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