1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_accessibility.hxx"
30 #include "accessibility/extended/accessiblelistboxentry.hxx"
31 #include <svtools/svtreebx.hxx>
32 #include <svtools/stringtransfer.hxx>
33 #include <com/sun/star/awt/Point.hpp>
34 #include <com/sun/star/awt/Rectangle.hpp>
35 #include <com/sun/star/awt/Size.hpp>
36 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
37 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
38 #include <com/sun/star/accessibility/AccessibleRole.hpp>
39 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
40 #include <tools/debug.hxx>
41 #include <vcl/svapp.hxx>
42 #include <vcl/controllayout.hxx>
43 #include <toolkit/awt/vclxwindow.hxx>
44 #include <toolkit/helper/convert.hxx>
45 #include <unotools/accessiblestatesethelper.hxx>
46 #include <unotools/accessiblerelationsethelper.hxx>
47 #include <cppuhelper/typeprovider.hxx>
48 #include <comphelper/sequence.hxx>
49 #include <comphelper/accessibleeventnotifier.hxx>
50 #include <toolkit/helper/vclunohelper.hxx>
51 
52 #define ACCESSIBLE_ACTION_COUNT	1
53 
54 namespace
55 {
56 	void checkActionIndex_Impl( sal_Int32 _nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException)
57 	{
58 		if ( _nIndex < 0 || _nIndex >= ACCESSIBLE_ACTION_COUNT )
59 			// only three actions
60 			throw ::com::sun::star::lang::IndexOutOfBoundsException();
61 	}
62 }
63 
64 //........................................................................
65 namespace accessibility
66 {
67 	//........................................................................
68 	// class ALBSolarGuard ---------------------------------------------------------
69 
70 	/** Aquire the solar mutex. */
71 	class ALBSolarGuard : public ::vos::OGuard
72 	{
73 	public:
74     	inline ALBSolarGuard() : ::vos::OGuard( Application::GetSolarMutex() ) {}
75 	};
76 
77 	// class AccessibleListBoxEntry -----------------------------------------------------
78 
79 	using namespace ::com::sun::star::accessibility;
80 	using namespace ::com::sun::star::uno;
81 	using namespace ::com::sun::star::lang;
82 	using namespace ::com::sun::star;
83 
84 	DBG_NAME(AccessibleListBoxEntry)
85 
86 	// -----------------------------------------------------------------------------
87 	// Ctor() and Dtor()
88 	// -----------------------------------------------------------------------------
89 	AccessibleListBoxEntry::AccessibleListBoxEntry( SvTreeListBox& _rListBox,
90 													SvLBoxEntry* _pEntry,
91 													const Reference< XAccessible >& _xParent ) :
92 
93 		AccessibleListBoxEntry_BASE	( m_aMutex ),
94 		ListBoxAccessibleBase( _rListBox ),
95 
96         m_nClientId     ( 0 ),
97 		m_aParent		( _xParent )
98 
99 	{
100 		DBG_CTOR( AccessibleListBoxEntry, NULL );
101 
102 		_rListBox.FillEntryPath( _pEntry, m_aEntryPath );
103 	}
104 	// -----------------------------------------------------------------------------
105 	AccessibleListBoxEntry::~AccessibleListBoxEntry()
106 	{
107 		DBG_DTOR( AccessibleListBoxEntry, NULL );
108 
109 		if ( IsAlive_Impl() )
110 		{
111         	// increment ref count to prevent double call of Dtor
112         	osl_incrementInterlockedCount( &m_refCount );
113         	dispose();
114 		}
115 	}
116 
117 	// -----------------------------------------------------------------------------
118 	Rectangle AccessibleListBoxEntry::GetBoundingBox_Impl() const
119 	{
120 		Rectangle aRect;
121 		SvLBoxEntry* pEntry = getListBox()->GetEntryFromPath( m_aEntryPath );
122 		if ( pEntry )
123 		{
124 			aRect = getListBox()->GetBoundingRect( pEntry );
125 			SvLBoxEntry* pParent = getListBox()->GetParent( pEntry );
126 			if ( pParent )
127 			{
128 				// position relative to parent entry
129 				Point aTopLeft = aRect.TopLeft();
130     			aTopLeft -= getListBox()->GetBoundingRect( pParent ).TopLeft();
131 				aRect = Rectangle( aTopLeft, aRect.GetSize() );
132 			}
133 		}
134 
135 		return aRect;
136 	}
137 	// -----------------------------------------------------------------------------
138 	Rectangle AccessibleListBoxEntry::GetBoundingBoxOnScreen_Impl() const
139 	{
140 		Rectangle aRect;
141 		SvLBoxEntry* pEntry = getListBox()->GetEntryFromPath( m_aEntryPath );
142 		if ( pEntry )
143 		{
144 			aRect = getListBox()->GetBoundingRect( pEntry );
145 			Point aTopLeft = aRect.TopLeft();
146     		aTopLeft += getListBox()->GetWindowExtentsRelative( NULL ).TopLeft();
147 			aRect = Rectangle( aTopLeft, aRect.GetSize() );
148 		}
149 
150 		return aRect;
151 	}
152 	// -----------------------------------------------------------------------------
153 	sal_Bool AccessibleListBoxEntry::IsAlive_Impl() const
154 	{
155     	return ( !rBHelper.bDisposed && !rBHelper.bInDispose && isAlive() );
156 	}
157 	// -----------------------------------------------------------------------------
158 	sal_Bool AccessibleListBoxEntry::IsShowing_Impl() const
159 	{
160 		Reference< XAccessible > xParent = implGetParentAccessible( );
161 
162 		sal_Bool bShowing = sal_False;
163 		Reference< XAccessibleContext > m_xParentContext =
164 			xParent.is() ? xParent->getAccessibleContext() : Reference< XAccessibleContext >();
165     	if( m_xParentContext.is() )
166     	{
167         	Reference< XAccessibleComponent > xParentComp( m_xParentContext, uno::UNO_QUERY );
168         	if( xParentComp.is() )
169             	bShowing = GetBoundingBox_Impl().IsOver( VCLRectangle( xParentComp->getBounds() ) );
170     	}
171 
172 		return bShowing;
173 	}
174 	// -----------------------------------------------------------------------------
175 	Rectangle AccessibleListBoxEntry::GetBoundingBox() throw ( lang::DisposedException )
176 	{
177     	ALBSolarGuard aSolarGuard;
178 		::osl::MutexGuard aGuard( m_aMutex );
179 
180 		EnsureIsAlive();
181     	return GetBoundingBox_Impl();
182 	}
183 	// -----------------------------------------------------------------------------
184 	Rectangle AccessibleListBoxEntry::GetBoundingBoxOnScreen() throw ( lang::DisposedException )
185 	{
186     	ALBSolarGuard aSolarGuard;
187 		::osl::MutexGuard aGuard( m_aMutex );
188 
189 		EnsureIsAlive();
190     	return GetBoundingBoxOnScreen_Impl();
191 	}
192 	// -----------------------------------------------------------------------------
193 	void AccessibleListBoxEntry::EnsureIsAlive() const throw ( lang::DisposedException )
194 	{
195     	if ( !IsAlive_Impl() )
196         	throw lang::DisposedException();
197 	}
198 	// -----------------------------------------------------------------------------
199 	::rtl::OUString AccessibleListBoxEntry::implGetText()
200 	{
201 		::rtl::OUString sRet;
202 		SvLBoxEntry* pEntry = getListBox()->GetEntryFromPath( m_aEntryPath );
203 		if ( pEntry )
204 			sRet = getListBox()->SearchEntryText( pEntry );
205 		return sRet;
206 	}
207 	// -----------------------------------------------------------------------------
208 	Locale AccessibleListBoxEntry::implGetLocale()
209 	{
210     	Locale aLocale;
211 		aLocale = Application::GetSettings().GetUILocale();
212 
213     	return aLocale;
214 	}
215 	void AccessibleListBoxEntry::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
216 	{
217 		nStartIndex = 0;
218 		nEndIndex = 0;
219 	}
220 	// -----------------------------------------------------------------------------
221 	// XTypeProvider
222 	// -----------------------------------------------------------------------------
223 	// -----------------------------------------------------------------------------
224 	Sequence< sal_Int8 > AccessibleListBoxEntry::getImplementationId() throw (RuntimeException)
225 	{
226 		static ::cppu::OImplementationId* pId = NULL;
227 
228 		if ( !pId )
229 		{
230 			::osl::Guard< ::osl::Mutex > aGuard( m_aMutex );
231 
232 			if ( !pId )
233 			{
234 				static ::cppu::OImplementationId aId;
235 				pId = &aId;
236 			}
237 		}
238 		return pId->getImplementationId();
239 	}
240 
241 	// -----------------------------------------------------------------------------
242 	// XComponent/ListBoxAccessibleBase
243 	// -----------------------------------------------------------------------------
244 	void SAL_CALL AccessibleListBoxEntry::dispose() throw ( uno::RuntimeException )
245 	{
246 		AccessibleListBoxEntry_BASE::dispose();
247 	}
248 
249 	// -----------------------------------------------------------------------------
250 	// XComponent
251 	// -----------------------------------------------------------------------------
252 	void SAL_CALL AccessibleListBoxEntry::disposing()
253 	{
254 		ALBSolarGuard();
255 		::osl::MutexGuard aGuard( m_aMutex );
256 
257 		Reference< XAccessible > xKeepAlive( this );
258 
259         // Send a disposing to all listeners.
260 	    if ( m_nClientId )
261 	    {
262 			::comphelper::AccessibleEventNotifier::TClientId nId = m_nClientId;
263 		    m_nClientId =  0;
264             ::comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nId, *this );
265 	    }
266 
267 		// clean up
268 		{
269 
270 			ListBoxAccessibleBase::disposing();
271 		}
272 	    m_aParent = WeakReference< XAccessible >();
273 	}
274 	// -----------------------------------------------------------------------------
275 	// XServiceInfo
276 	// -----------------------------------------------------------------------------
277 	::rtl::OUString SAL_CALL AccessibleListBoxEntry::getImplementationName() throw(RuntimeException)
278 	{
279 		return getImplementationName_Static();
280 	}
281 	// -----------------------------------------------------------------------------
282 	Sequence< ::rtl::OUString > SAL_CALL AccessibleListBoxEntry::getSupportedServiceNames() throw(RuntimeException)
283 	{
284 		return getSupportedServiceNames_Static();
285 	}
286 	// -----------------------------------------------------------------------------
287 	sal_Bool SAL_CALL AccessibleListBoxEntry::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException)
288 	{
289 		Sequence< ::rtl::OUString > aSupported( getSupportedServiceNames() );
290 		const ::rtl::OUString* pSupported = aSupported.getConstArray();
291 		const ::rtl::OUString* pEnd = pSupported + aSupported.getLength();
292 		for ( ; pSupported != pEnd && !pSupported->equals(_rServiceName); ++pSupported )
293 			;
294 
295 		return pSupported != pEnd;
296 	}
297 	// -----------------------------------------------------------------------------
298 	// XServiceInfo - static methods
299 	// -----------------------------------------------------------------------------
300 	Sequence< ::rtl::OUString > AccessibleListBoxEntry::getSupportedServiceNames_Static(void) throw( RuntimeException )
301 	{
302 		Sequence< ::rtl::OUString > aSupported(3);
303 		aSupported[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.accessibility.AccessibleContext") );
304 		aSupported[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.accessibility.AccessibleComponent") );
305 		aSupported[2] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.AccessibleTreeListBoxEntry") );
306 		return aSupported;
307 	}
308 	// -----------------------------------------------------------------------------
309 	::rtl::OUString AccessibleListBoxEntry::getImplementationName_Static(void) throw( RuntimeException )
310 	{
311 		return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.svtools.AccessibleTreeListBoxEntry") );
312 	}
313 	// -----------------------------------------------------------------------------
314 	// XAccessible
315 	// -----------------------------------------------------------------------------
316 	Reference< XAccessibleContext > SAL_CALL AccessibleListBoxEntry::getAccessibleContext(  ) throw (RuntimeException)
317 	{
318 		EnsureIsAlive();
319 		return this;
320 	}
321 	// -----------------------------------------------------------------------------
322 	// XAccessibleContext
323 	// -----------------------------------------------------------------------------
324 	sal_Int32 SAL_CALL AccessibleListBoxEntry::getAccessibleChildCount(  ) throw (RuntimeException)
325 	{
326 		ALBSolarGuard aSolarGuard;
327 		::osl::MutexGuard aGuard( m_aMutex );
328 
329 		EnsureIsAlive();
330 		SvLBoxEntry* pEntry = getListBox()->GetEntryFromPath( m_aEntryPath );
331 		sal_Int32 nCount = 0;
332 		if ( pEntry )
333 			nCount = getListBox()->GetLevelChildCount( pEntry );
334 
335 		return nCount;
336 	}
337 	// -----------------------------------------------------------------------------
338 	Reference< XAccessible > SAL_CALL AccessibleListBoxEntry::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException,RuntimeException)
339 	{
340 		ALBSolarGuard aSolarGuard;
341 		::osl::MutexGuard aGuard( m_aMutex );
342 		EnsureIsAlive();
343 
344 		SvLBoxEntry* pParent = getListBox()->GetEntryFromPath( m_aEntryPath );
345 		SvLBoxEntry* pEntry = pParent ? getListBox()->GetEntry( pParent, i ) : NULL;
346 		if ( !pEntry )
347 			throw IndexOutOfBoundsException();
348 
349 		return new AccessibleListBoxEntry( *getListBox(), pEntry, this );
350 	}
351 
352 	// -----------------------------------------------------------------------------
353 	Reference< XAccessible > AccessibleListBoxEntry::implGetParentAccessible( ) const
354 	{
355 		Reference< XAccessible > xParent = (Reference< XAccessible >)m_aParent;
356 		if ( !xParent.is() )
357 		{
358 			DBG_ASSERT( m_aEntryPath.size(), "AccessibleListBoxEntry::getAccessibleParent: invalid path!" );
359 			if ( 1 == m_aEntryPath.size() )
360 			{	// we're a top level entry
361 				// -> our parent is the tree listbox itself
362 				if ( getListBox() )
363 					xParent = getListBox()->GetAccessible( );
364 			}
365 			else
366 			{	// we have a entry as parent -> get it's accessible
367 
368 				// shorten our access path by one
369 				::std::deque< sal_Int32 > aParentPath( m_aEntryPath );
370 				aParentPath.pop_back();
371 
372 				// get the entry for this shortened access path
373 				SvLBoxEntry* pParentEntry = getListBox()->GetEntryFromPath( m_aEntryPath );
374 				DBG_ASSERT( pParentEntry, "AccessibleListBoxEntry::implGetParentAccessible: could not obtain a parent entry!" );
375 
376 				if ( pParentEntry )
377 					xParent = new AccessibleListBoxEntry( *getListBox(), pParentEntry, NULL );
378 					// note that we pass NULL here as parent-accessible:
379 					// this is allowed, as the AccessibleListBoxEntry class will create it's parent
380 					// when needed
381 			}
382 		}
383 
384 		return xParent;
385 	}
386 
387 	// -----------------------------------------------------------------------------
388 	Reference< XAccessible > SAL_CALL AccessibleListBoxEntry::getAccessibleParent(  ) throw (RuntimeException)
389 	{
390     	ALBSolarGuard aSolarGuard;
391 		::osl::MutexGuard aGuard( m_aMutex );
392 		EnsureIsAlive();
393 
394 		return implGetParentAccessible( );
395 	}
396 	// -----------------------------------------------------------------------------
397 	sal_Int32 SAL_CALL AccessibleListBoxEntry::getAccessibleIndexInParent(  ) throw (RuntimeException)
398 	{
399 		::osl::MutexGuard aGuard( m_aMutex );
400 
401 		DBG_ASSERT( !m_aEntryPath.empty(), "empty path" );
402     	return m_aEntryPath.empty() ? -1 : m_aEntryPath.back();
403 	}
404 	// -----------------------------------------------------------------------------
405 	sal_Int16 SAL_CALL AccessibleListBoxEntry::getAccessibleRole(  ) throw (RuntimeException)
406 	{
407 		return AccessibleRole::LABEL;
408 	}
409 	// -----------------------------------------------------------------------------
410 	::rtl::OUString SAL_CALL AccessibleListBoxEntry::getAccessibleDescription(  ) throw (RuntimeException)
411 	{
412 		// no description for every item
413 		return ::rtl::OUString();
414 	}
415 	// -----------------------------------------------------------------------------
416 	::rtl::OUString SAL_CALL AccessibleListBoxEntry::getAccessibleName(  ) throw (RuntimeException)
417 	{
418 		::osl::MutexGuard aGuard( m_aMutex );
419 
420 		EnsureIsAlive();
421 		return implGetText();
422 	}
423 	// -----------------------------------------------------------------------------
424 	Reference< XAccessibleRelationSet > SAL_CALL AccessibleListBoxEntry::getAccessibleRelationSet(  ) throw (RuntimeException)
425 	{
426         Reference< XAccessibleRelationSet > xRelSet;
427         Reference< XAccessible > xParent;
428         if ( m_aEntryPath.size() > 1 ) // not a root entry
429             xParent = implGetParentAccessible();
430         if ( xParent.is() )
431         {
432             utl::AccessibleRelationSetHelper* pRelationSetHelper = new utl::AccessibleRelationSetHelper;
433             Sequence< Reference< XInterface > > aSequence(1);
434             aSequence[0] = xParent;
435             pRelationSetHelper->AddRelation(
436                 AccessibleRelation( AccessibleRelationType::NODE_CHILD_OF, aSequence ) );
437             xRelSet = pRelationSetHelper;
438         }
439         return xRelSet;
440 	}
441 	// -----------------------------------------------------------------------------
442 	Reference< XAccessibleStateSet > SAL_CALL AccessibleListBoxEntry::getAccessibleStateSet(  ) throw (RuntimeException)
443 	{
444 		::osl::MutexGuard aGuard( m_aMutex );
445 
446     	utl::AccessibleStateSetHelper* pStateSetHelper = new utl::AccessibleStateSetHelper;
447 		Reference< XAccessibleStateSet > xStateSet = pStateSetHelper;
448 
449 		if ( IsAlive_Impl() )
450 		{
451 	       	pStateSetHelper->AddState( AccessibleStateType::TRANSIENT );
452 	       	pStateSetHelper->AddState( AccessibleStateType::SELECTABLE );
453 	       	pStateSetHelper->AddState( AccessibleStateType::ENABLED );
454             pStateSetHelper->AddState( AccessibleStateType::SENSITIVE );
455 			if ( getListBox()->IsInplaceEditingEnabled() )
456 		       	pStateSetHelper->AddState( AccessibleStateType::EDITABLE );
457 			if ( IsShowing_Impl() )
458 	        	pStateSetHelper->AddState( AccessibleStateType::SHOWING );
459 			getListBox()->FillAccessibleEntryStateSet(
460 				getListBox()->GetEntryFromPath( m_aEntryPath ), *pStateSetHelper );
461 		}
462 		else
463         	pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
464 
465     	return xStateSet;
466 	}
467 	// -----------------------------------------------------------------------------
468 	Locale SAL_CALL AccessibleListBoxEntry::getLocale(  ) throw (IllegalAccessibleComponentStateException, RuntimeException)
469 	{
470 		ALBSolarGuard aSolarGuard;
471 		::osl::MutexGuard aGuard( m_aMutex );
472 
473 		return implGetLocale();
474 	}
475 	// -----------------------------------------------------------------------------
476 	// XAccessibleComponent
477 	// -----------------------------------------------------------------------------
478 	sal_Bool SAL_CALL AccessibleListBoxEntry::containsPoint( const awt::Point& rPoint ) throw (RuntimeException)
479 	{
480     	return Rectangle( Point(), GetBoundingBox().GetSize() ).IsInside( VCLPoint( rPoint ) );
481 	}
482 	// -----------------------------------------------------------------------------
483 	Reference< XAccessible > SAL_CALL AccessibleListBoxEntry::getAccessibleAtPoint( const awt::Point& _aPoint ) throw (RuntimeException)
484 	{
485 		ALBSolarGuard aSolarGuard;
486 		::osl::MutexGuard aGuard( m_aMutex );
487 
488 		EnsureIsAlive();
489 		SvLBoxEntry* pEntry = getListBox()->GetEntry( VCLPoint( _aPoint ) );
490 		if ( !pEntry )
491 			throw RuntimeException();
492 
493 		Reference< XAccessible > xAcc;
494 		AccessibleListBoxEntry* pAccEntry = new AccessibleListBoxEntry( *getListBox(), pEntry, this );
495 		Rectangle aRect = pAccEntry->GetBoundingBox_Impl();
496 		if ( aRect.IsInside( VCLPoint( _aPoint ) ) )
497 			xAcc = pAccEntry;
498 		return xAcc;
499 	}
500 	// -----------------------------------------------------------------------------
501 	awt::Rectangle SAL_CALL AccessibleListBoxEntry::getBounds(  ) throw (RuntimeException)
502 	{
503     	return AWTRectangle( GetBoundingBox() );
504 	}
505 	// -----------------------------------------------------------------------------
506 	awt::Point SAL_CALL AccessibleListBoxEntry::getLocation(  ) throw (RuntimeException)
507 	{
508     	return AWTPoint( GetBoundingBox().TopLeft() );
509 	}
510 	// -----------------------------------------------------------------------------
511 	awt::Point SAL_CALL AccessibleListBoxEntry::getLocationOnScreen(  ) throw (RuntimeException)
512 	{
513     	return AWTPoint( GetBoundingBoxOnScreen().TopLeft() );
514 	}
515 	// -----------------------------------------------------------------------------
516 	awt::Size SAL_CALL AccessibleListBoxEntry::getSize(  ) throw (RuntimeException)
517 	{
518     	return AWTSize( GetBoundingBox().GetSize() );
519 	}
520 	// -----------------------------------------------------------------------------
521 	void SAL_CALL AccessibleListBoxEntry::grabFocus(  ) throw (RuntimeException)
522 	{
523 		// do nothing, because no focus for each item
524 	}
525 	// -----------------------------------------------------------------------------
526 	sal_Int32 AccessibleListBoxEntry::getForeground(	) throw (RuntimeException)
527 	{
528     	ALBSolarGuard aSolarGuard;
529 		::osl::MutexGuard aGuard( m_aMutex );
530 
531 		sal_Int32 nColor = 0;
532 		Reference< XAccessible > xParent = getAccessibleParent();
533 		if ( xParent.is() )
534 		{
535 			Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
536 			if ( xParentComp.is() )
537 				nColor = xParentComp->getForeground();
538 		}
539 
540 		return nColor;
541 	}
542 	// -----------------------------------------------------------------------------
543 	sal_Int32 AccessibleListBoxEntry::getBackground(  ) throw (RuntimeException)
544 	{
545     	ALBSolarGuard aSolarGuard;
546 		::osl::MutexGuard aGuard( m_aMutex );
547 
548 		sal_Int32 nColor = 0;
549 		Reference< XAccessible > xParent = getAccessibleParent();
550 		if ( xParent.is() )
551 		{
552 			Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
553 			if ( xParentComp.is() )
554 				nColor = xParentComp->getBackground();
555 		}
556 
557 		return nColor;
558 	}
559 	// -----------------------------------------------------------------------------
560 	// XAccessibleText
561 	// -----------------------------------------------------------------------------
562 	// -----------------------------------------------------------------------------
563 	awt::Rectangle SAL_CALL AccessibleListBoxEntry::getCharacterBounds( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
564 	{
565     	ALBSolarGuard aSolarGuard;
566 		::osl::MutexGuard aGuard( m_aMutex );
567 
568 		EnsureIsAlive();
569 
570         if ( !implIsValidIndex( nIndex, implGetText().getLength() ) )
571             throw IndexOutOfBoundsException();
572 
573 		awt::Rectangle aBounds( 0, 0, 0, 0 );
574 		SvLBoxEntry* pEntry = getListBox()->GetEntryFromPath( m_aEntryPath );
575 		if ( pEntry )
576 		{
577 			::vcl::ControlLayoutData aLayoutData;
578 			Rectangle aItemRect = GetBoundingBox();
579 			getListBox()->RecordLayoutData( &aLayoutData, aItemRect );
580 			Rectangle aCharRect = aLayoutData.GetCharacterBounds( nIndex );
581 			aCharRect.Move( -aItemRect.Left(), -aItemRect.Top() );
582 			aBounds = AWTRectangle( aCharRect );
583 		}
584 
585 		return aBounds;
586 	}
587 	// -----------------------------------------------------------------------------
588 	sal_Int32 SAL_CALL AccessibleListBoxEntry::getIndexAtPoint( const awt::Point& aPoint ) throw (RuntimeException)
589 	{
590     	ALBSolarGuard aSolarGuard;
591 		::osl::MutexGuard aGuard( m_aMutex );
592 		EnsureIsAlive();
593 
594 		sal_Int32 nIndex = -1;
595 		SvLBoxEntry* pEntry = getListBox()->GetEntryFromPath( m_aEntryPath );
596 		if ( pEntry )
597 		{
598 			::vcl::ControlLayoutData aLayoutData;
599 			Rectangle aItemRect = GetBoundingBox();
600 			getListBox()->RecordLayoutData( &aLayoutData, aItemRect );
601 			Point aPnt( VCLPoint( aPoint ) );
602 			aPnt += aItemRect.TopLeft();
603 			nIndex = aLayoutData.GetIndexForPoint( aPnt );
604 		}
605 
606 	    return nIndex;
607 	}
608 	// -----------------------------------------------------------------------------
609 	sal_Bool SAL_CALL AccessibleListBoxEntry::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (IndexOutOfBoundsException, RuntimeException)
610 	{
611     	ALBSolarGuard aSolarGuard;
612 		::osl::MutexGuard aGuard( m_aMutex );
613 		EnsureIsAlive();
614 
615 		String sText = getText();
616 		if	( ( 0 > nStartIndex ) || ( sText.Len() <= nStartIndex )
617 			|| ( 0 > nEndIndex ) || ( sText.Len() <= nEndIndex ) )
618 			throw IndexOutOfBoundsException();
619 
620 		sal_Int32 nLen = nEndIndex - nStartIndex + 1;
621         ::svt::OStringTransfer::CopyString( sText.Copy( (sal_uInt16)nStartIndex, (sal_uInt16)nLen ), getListBox() );
622 
623 		return sal_True;
624 	}
625 	// -----------------------------------------------------------------------------
626 	// XAccessibleEventBroadcaster
627 	// -----------------------------------------------------------------------------
628 	void SAL_CALL AccessibleListBoxEntry::addEventListener( const Reference< XAccessibleEventListener >& xListener ) throw (RuntimeException)
629 	{
630 	    if (xListener.is())
631         {
632 			::osl::MutexGuard aGuard( m_aMutex );
633 		    if (!m_nClientId)
634                 m_nClientId = comphelper::AccessibleEventNotifier::registerClient( );
635 		    comphelper::AccessibleEventNotifier::addEventListener( m_nClientId, xListener );
636         }
637 	}
638 	// -----------------------------------------------------------------------------
639 	void SAL_CALL AccessibleListBoxEntry::removeEventListener( const Reference< XAccessibleEventListener >& xListener ) throw (RuntimeException)
640 	{
641 	    if (xListener.is())
642 	    {
643 			::osl::MutexGuard aGuard( m_aMutex );
644 
645             sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener( m_nClientId, xListener );
646 		    if ( !nListenerCount )
647 		    {
648 			    // no listeners anymore
649 			    // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
650 			    // and at least to us not firing any events anymore, in case somebody calls
651 			    // NotifyAccessibleEvent, again
652 				sal_Int32 nId = m_nClientId;
653 				m_nClientId = 0;
654 			    comphelper::AccessibleEventNotifier::revokeClient( nId );
655 
656 		    }
657 	    }
658 	}
659 	// -----------------------------------------------------------------------------
660 	// XAccessibleAction
661 	// -----------------------------------------------------------------------------
662     sal_Int32 SAL_CALL AccessibleListBoxEntry::getAccessibleActionCount(  ) throw (RuntimeException)
663 	{
664 		::osl::MutexGuard aGuard( m_aMutex );
665 
666 		// three actions supported
667 		return ACCESSIBLE_ACTION_COUNT;
668 	}
669 	// -----------------------------------------------------------------------------
670     sal_Bool SAL_CALL AccessibleListBoxEntry::doAccessibleAction( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
671 	{
672     	ALBSolarGuard aSolarGuard;
673 		::osl::MutexGuard aGuard( m_aMutex );
674 
675 		sal_Bool bRet = sal_False;
676 		checkActionIndex_Impl( nIndex );
677 		EnsureIsAlive();
678 
679 		SvLBoxEntry* pEntry = getListBox()->GetEntryFromPath( m_aEntryPath );
680 		if ( pEntry )
681 		{
682 			if ( getListBox()->IsExpanded( pEntry ) )
683 				getListBox()->Collapse( pEntry );
684 			else
685 				getListBox()->Expand( pEntry );
686 			bRet = sal_True;
687 		}
688 
689 		return bRet;
690 	}
691 	// -----------------------------------------------------------------------------
692     ::rtl::OUString SAL_CALL AccessibleListBoxEntry::getAccessibleActionDescription( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
693 	{
694     	ALBSolarGuard aSolarGuard;
695 		::osl::MutexGuard aGuard( m_aMutex );
696 
697 		checkActionIndex_Impl( nIndex );
698 		EnsureIsAlive();
699 
700 		static const ::rtl::OUString sActionDesc( RTL_CONSTASCII_USTRINGPARAM( "toggleExpand" ) );
701 		return sActionDesc;
702 	}
703 	// -----------------------------------------------------------------------------
704 	Reference< XAccessibleKeyBinding > AccessibleListBoxEntry::getAccessibleActionKeyBinding( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
705 	{
706 		::osl::MutexGuard aGuard( m_aMutex );
707 
708 		Reference< XAccessibleKeyBinding > xRet;
709 		checkActionIndex_Impl( nIndex );
710 		// ... which key?
711 		return xRet;
712 	}
713 	// -----------------------------------------------------------------------------
714 	// XAccessibleSelection
715 	// -----------------------------------------------------------------------------
716 	void SAL_CALL AccessibleListBoxEntry::selectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
717 	{
718     	ALBSolarGuard aSolarGuard;
719 		::osl::MutexGuard aGuard( m_aMutex );
720 
721 		EnsureIsAlive();
722 
723 		SvLBoxEntry* pParent = getListBox()->GetEntryFromPath( m_aEntryPath );
724 		SvLBoxEntry* pEntry = getListBox()->GetEntry( pParent, nChildIndex );
725 		if ( !pEntry )
726 			throw IndexOutOfBoundsException();
727 
728 		getListBox()->Select( pEntry, sal_True );
729 	}
730 	// -----------------------------------------------------------------------------
731 	sal_Bool SAL_CALL AccessibleListBoxEntry::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
732 	{
733     	ALBSolarGuard aSolarGuard;
734 		::osl::MutexGuard aGuard( m_aMutex );
735 
736 		EnsureIsAlive();
737 
738 		SvLBoxEntry* pParent = getListBox()->GetEntryFromPath( m_aEntryPath );
739 		SvLBoxEntry* pEntry = getListBox()->GetEntry( pParent, nChildIndex );
740 		if ( !pEntry )
741 			throw IndexOutOfBoundsException();
742 
743 		return getListBox()->IsSelected( pEntry );
744 	}
745 	// -----------------------------------------------------------------------------
746 	void SAL_CALL AccessibleListBoxEntry::clearAccessibleSelection(  ) throw (RuntimeException)
747 	{
748     	ALBSolarGuard aSolarGuard;
749 		::osl::MutexGuard aGuard( m_aMutex );
750 
751 		EnsureIsAlive();
752 
753 		SvLBoxEntry* pParent = getListBox()->GetEntryFromPath( m_aEntryPath );
754 		if ( !pParent )
755 			throw RuntimeException();
756     	sal_Int32 i, nCount = 0;
757 		nCount = getListBox()->GetLevelChildCount( pParent );
758 		for ( i = 0; i < nCount; ++i )
759 		{
760 			SvLBoxEntry* pEntry = getListBox()->GetEntry( pParent, i );
761 			if ( getListBox()->IsSelected( pEntry ) )
762 				getListBox()->Select( pEntry, sal_False );
763 		}
764 	}
765 	// -----------------------------------------------------------------------------
766 	void SAL_CALL AccessibleListBoxEntry::selectAllAccessibleChildren(  ) throw (RuntimeException)
767 	{
768     	ALBSolarGuard aSolarGuard;
769 		::osl::MutexGuard aGuard( m_aMutex );
770 
771 		EnsureIsAlive();
772 
773 		SvLBoxEntry* pParent = getListBox()->GetEntryFromPath( m_aEntryPath );
774 		if ( !pParent )
775 			throw RuntimeException();
776     	sal_Int32 i, nCount = 0;
777 		nCount = getListBox()->GetLevelChildCount( pParent );
778 		for ( i = 0; i < nCount; ++i )
779 		{
780 			SvLBoxEntry* pEntry = getListBox()->GetEntry( pParent, i );
781 			if ( !getListBox()->IsSelected( pEntry ) )
782 				getListBox()->Select( pEntry, sal_True );
783 		}
784 	}
785 	// -----------------------------------------------------------------------------
786 	sal_Int32 SAL_CALL AccessibleListBoxEntry::getSelectedAccessibleChildCount(  ) throw (RuntimeException)
787 	{
788     	ALBSolarGuard aSolarGuard;
789 		::osl::MutexGuard aGuard( m_aMutex );
790 
791 		EnsureIsAlive();
792 
793     	sal_Int32 i, nSelCount = 0, nCount = 0;
794 
795 		SvLBoxEntry* pParent = getListBox()->GetEntryFromPath( m_aEntryPath );
796 		if ( !pParent )
797 			throw RuntimeException();
798 		nCount = getListBox()->GetLevelChildCount( pParent );
799 		for ( i = 0; i < nCount; ++i )
800 		{
801 			SvLBoxEntry* pEntry = getListBox()->GetEntry( pParent, i );
802 			if ( getListBox()->IsSelected( pEntry ) )
803 				++nSelCount;
804 		}
805 
806     	return nSelCount;
807 	}
808 	// -----------------------------------------------------------------------------
809 	Reference< XAccessible > SAL_CALL AccessibleListBoxEntry::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
810 	{
811     	ALBSolarGuard aSolarGuard;
812 		::osl::MutexGuard aGuard( m_aMutex );
813 
814 		EnsureIsAlive();
815 
816 		if ( nSelectedChildIndex < 0 || nSelectedChildIndex >= getSelectedAccessibleChildCount() )
817 			throw IndexOutOfBoundsException();
818 
819 		Reference< XAccessible > xChild;
820     	sal_Int32 i, nSelCount = 0, nCount = 0;
821 
822 		SvLBoxEntry* pParent = getListBox()->GetEntryFromPath( m_aEntryPath );
823 		if ( !pParent )
824 			throw RuntimeException();
825 		nCount = getListBox()->GetLevelChildCount( pParent );
826 		for ( i = 0; i < nCount; ++i )
827 		{
828 			SvLBoxEntry* pEntry = getListBox()->GetEntry( pParent, i );
829 			if ( getListBox()->IsSelected( pEntry ) )
830 				++nSelCount;
831 
832 			if ( nSelCount == ( nSelectedChildIndex + 1 ) )
833 			{
834 				xChild = new AccessibleListBoxEntry( *getListBox(), pEntry, this );
835 				break;
836 			}
837 		}
838 
839 		return xChild;
840 	}
841 	// -----------------------------------------------------------------------------
842 	void SAL_CALL AccessibleListBoxEntry::deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
843 	{
844     	ALBSolarGuard aSolarGuard;
845 		::osl::MutexGuard aGuard( m_aMutex );
846 
847 		EnsureIsAlive();
848 
849 		SvLBoxEntry* pParent = getListBox()->GetEntryFromPath( m_aEntryPath );
850 		SvLBoxEntry* pEntry = getListBox()->GetEntry( pParent, nSelectedChildIndex );
851 		if ( !pEntry )
852 			throw IndexOutOfBoundsException();
853 
854 		getListBox()->Select( pEntry, sal_False );
855 	}
856 	sal_Int32 SAL_CALL AccessibleListBoxEntry::getCaretPosition(  ) throw (::com::sun::star::uno::RuntimeException)
857 	{
858 		return -1;
859 	}
860 	sal_Bool SAL_CALL AccessibleListBoxEntry::setCaretPosition ( sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
861 	{
862 		ALBSolarGuard aSolarGuard;
863 		::osl::MutexGuard aGuard( m_aMutex );
864 		EnsureIsAlive();
865 
866 		if ( !implIsValidRange( nIndex, nIndex, implGetText().getLength() ) )
867 			throw IndexOutOfBoundsException();
868 
869 		return sal_False;
870 	}
871 	sal_Unicode SAL_CALL AccessibleListBoxEntry::getCharacter( sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
872 	{
873 		ALBSolarGuard aSolarGuard;
874 		::osl::MutexGuard aGuard( m_aMutex );
875 		EnsureIsAlive();
876 		return OCommonAccessibleText::getCharacter( nIndex );
877 	}
878 	::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL AccessibleListBoxEntry::getCharacterAttributes( sal_Int32 nIndex, const ::com::sun::star::uno::Sequence< ::rtl::OUString >& ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
879 	{
880 		ALBSolarGuard aSolarGuard;
881 		::osl::MutexGuard aGuard( m_aMutex );
882 		EnsureIsAlive();
883 
884 		::rtl::OUString sText( implGetText() );
885 
886 		if ( !implIsValidIndex( nIndex, sText.getLength() ) )
887 			throw IndexOutOfBoundsException();
888 
889 		return ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >();
890 	}
891 	sal_Int32 SAL_CALL AccessibleListBoxEntry::getCharacterCount(  ) throw (::com::sun::star::uno::RuntimeException)
892 	{
893 		ALBSolarGuard aSolarGuard;
894 		::osl::MutexGuard aGuard( m_aMutex );
895 		EnsureIsAlive();
896 		return OCommonAccessibleText::getCharacterCount(  );
897 	}
898 
899 	::rtl::OUString SAL_CALL AccessibleListBoxEntry::getSelectedText(  ) throw (::com::sun::star::uno::RuntimeException)
900 	{
901 		ALBSolarGuard aSolarGuard;
902 		::osl::MutexGuard aGuard( m_aMutex );
903 		EnsureIsAlive();
904 		return OCommonAccessibleText::getSelectedText(  );
905 	}
906 	sal_Int32 SAL_CALL AccessibleListBoxEntry::getSelectionStart(  ) throw (::com::sun::star::uno::RuntimeException)
907 	{
908 		ALBSolarGuard aSolarGuard;
909 		::osl::MutexGuard aGuard( m_aMutex );
910 		EnsureIsAlive();
911 		return OCommonAccessibleText::getSelectionStart(  );
912 	}
913 	sal_Int32 SAL_CALL AccessibleListBoxEntry::getSelectionEnd(  ) throw (::com::sun::star::uno::RuntimeException)
914 	{
915 		ALBSolarGuard aSolarGuard;
916 		::osl::MutexGuard aGuard( m_aMutex );
917 		EnsureIsAlive();
918 		return OCommonAccessibleText::getSelectionEnd(  );
919 	}
920 	sal_Bool SAL_CALL AccessibleListBoxEntry::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
921 	{
922 		ALBSolarGuard aSolarGuard;
923 		::osl::MutexGuard aGuard( m_aMutex );
924 		EnsureIsAlive();
925 
926 		if ( !implIsValidRange( nStartIndex, nEndIndex, implGetText().getLength() ) )
927 			throw IndexOutOfBoundsException();
928 
929 		return sal_False;
930 	}
931 	::rtl::OUString SAL_CALL AccessibleListBoxEntry::getText(  ) throw (::com::sun::star::uno::RuntimeException)
932 	{
933 		ALBSolarGuard aSolarGuard;
934 		::osl::MutexGuard aGuard( m_aMutex );
935 		EnsureIsAlive();
936 		return OCommonAccessibleText::getText(  );
937 	}
938 	::rtl::OUString SAL_CALL AccessibleListBoxEntry::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
939 	{
940 		ALBSolarGuard aSolarGuard;
941 		::osl::MutexGuard aGuard( m_aMutex );
942 		EnsureIsAlive();
943 		return OCommonAccessibleText::getTextRange( nStartIndex, nEndIndex );
944 	}
945     ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleListBoxEntry::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
946 	{
947 		ALBSolarGuard aSolarGuard;
948 		::osl::MutexGuard aGuard( m_aMutex );
949 		EnsureIsAlive();
950 		return OCommonAccessibleText::getTextAtIndex( nIndex ,aTextType);
951 	}
952     ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleListBoxEntry::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
953 	{
954 		ALBSolarGuard aSolarGuard;
955 		::osl::MutexGuard aGuard( m_aMutex );
956 		EnsureIsAlive();
957 		return OCommonAccessibleText::getTextBeforeIndex( nIndex ,aTextType);
958 	}
959     ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleListBoxEntry::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
960 	{
961 		ALBSolarGuard aSolarGuard;
962 		::osl::MutexGuard aGuard( m_aMutex );
963 		EnsureIsAlive();
964 
965 		return OCommonAccessibleText::getTextBehindIndex( nIndex ,aTextType);
966 	}
967 //........................................................................
968 }// namespace accessibility
969 //........................................................................
970 
971