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/accessiblelistbox.hxx>
27 #include <accessibility/extended/accessiblelistboxentry.hxx>
28 #include <svtools/svtreebx.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/AccessibleRole.hpp>
34 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
35 #include <tools/debug.hxx>
36 #include <vcl/svapp.hxx>
37 #include <toolkit/awt/vclxwindow.hxx>
38 #include <toolkit/helper/convert.hxx>
39 #include <unotools/accessiblestatesethelper.hxx>
40 
41 //........................................................................
42 namespace accessibility
43 {
44 //........................................................................
45 
46 	// class AccessibleListBox -----------------------------------------------------
47 
48 	using namespace ::com::sun::star::accessibility;
49 	using namespace ::com::sun::star::uno;
50 	using namespace ::com::sun::star::lang;
51 	using namespace ::com::sun::star;
52 
53 	DBG_NAME(AccessibleListBox)
54 
55 	// -----------------------------------------------------------------------------
56 	// Ctor() and Dtor()
57 	// -----------------------------------------------------------------------------
58 	AccessibleListBox::AccessibleListBox( SvTreeListBox& _rListBox, const Reference< XAccessible >& _xParent ) :
59 
60 		VCLXAccessibleComponent( _rListBox.GetWindowPeer() ),
61 		m_xParent( _xParent )
62 	{
63 		DBG_CTOR( AccessibleListBox, NULL );
64 	}
65 	// -----------------------------------------------------------------------------
66 	AccessibleListBox::~AccessibleListBox()
67 	{
68 		DBG_DTOR( AccessibleListBox, NULL );
69 		if ( isAlive() )
70 		{
71 			// increment ref count to prevent double call of Dtor
72         	osl_incrementInterlockedCount( &m_refCount );
73         	dispose();
74 		}
75 	}
76 	IMPLEMENT_FORWARD_XINTERFACE2(AccessibleListBox, VCLXAccessibleComponent, AccessibleListBox_BASE)
77 	IMPLEMENT_FORWARD_XTYPEPROVIDER2(AccessibleListBox, VCLXAccessibleComponent, AccessibleListBox_BASE)
78 	// -----------------------------------------------------------------------------
79 	SvTreeListBox* AccessibleListBox::getListBox() const
80 	{
81 		return	static_cast< SvTreeListBox* >( const_cast<AccessibleListBox*>(this)->GetWindow() );
82 	}
83 	// -----------------------------------------------------------------------------
84 	void AccessibleListBox::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
85 	{
86     	if ( isAlive() )
87 		{
88 			switch ( rVclWindowEvent.GetId() )
89 			{
90 				case  VCLEVENT_CHECKBOX_TOGGLE :
91 				{
92 					if ( !getListBox() || !getListBox()->HasFocus() )
93 					{
94 						return;
95 					}
96 					AccessibleListBoxEntry* pCurOpEntry = GetCurEventEntry(rVclWindowEvent);
97 					if(!pCurOpEntry)
98 					{
99 						return ;
100 					}
101 					uno::Any aValue;
102 					aValue <<= AccessibleStateType::CHECKED;
103 
104 					if ( getListBox()->GetCheckButtonState( pCurOpEntry->GetSvLBoxEntry() ) == SV_BUTTON_CHECKED )
105 					{
106 						pCurOpEntry->NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, uno::Any(), aValue );
107 					}
108 					else
109 					{
110 						pCurOpEntry->NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aValue,uno::Any() );
111 					}
112 					break;
113 				}
114 
115 				case VCLEVENT_LISTBOX_SELECT :
116 				{
117                     // First send an event that tells the listeners of a
118                     // modified selection.  The active descendant event is
119                     // send after that so that the receiving AT has time to
120                     // read the text or name of the active child.
121 //                    NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
122 					OSL_ASSERT(0 && "Debug: Treelist shouldn't use VCLEVENT_LISTBOX_SELECT");
123 				}
124 				case VCLEVENT_LISTBOX_TREESELECT:
125 					{
126 						if ( getListBox() && getListBox()->HasFocus() )
127 						{
128 							AccessibleListBoxEntry* pEntry =static_cast< AccessibleListBoxEntry* >(m_xFocusedChild.get());
129 							if (pEntry)
130 							{
131 								pEntry->NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
132 							}
133 						}
134 					}
135 					break;
136 				case VCLEVENT_LISTBOX_TREEFOCUS:
137 					{
138 						SvTreeListBox* pBox = getListBox();
139 						sal_Bool bNeedFocus = sal_False;
140 						if (pBox)
141 						{
142 							Window* pParent = ((Window*)pBox)->GetParent();
143 							if (pParent && pParent->GetType() == WINDOW_FLOATINGWINDOW)
144 							{
145 								// MT: ImplGetAppSVData shouldn't be exported from VCL.
146 								// In which scenario is this needed?
147 								// If needed, we need to find an other solution
148 								/*
149 								ImplSVData* pSVData = ImplGetAppSVData();
150 								if (pSVData && pSVData->maWinData.mpFirstFloat == (FloatingWindow*)pParent)
151 									bNeedFocus = sal_True;
152 								*/
153 							}
154 						}
155 						if( pBox && (pBox->HasFocus() || bNeedFocus) )
156 						{
157 							uno::Any aOldValue, aNewValue;
158 							SvLBoxEntry* pEntry = static_cast< SvLBoxEntry* >( rVclWindowEvent.GetData() );
159 							if ( pEntry )
160 							{
161 								AccessibleListBoxEntry* pEntryFocus =static_cast< AccessibleListBoxEntry* >(m_xFocusedChild.get());
162 								if (pEntryFocus && pEntryFocus->GetSvLBoxEntry() == pEntry)
163 								{
164 									aOldValue <<= uno::Any();
165 									aNewValue <<= m_xFocusedChild;
166 									NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldValue, aNewValue );
167 									return ;
168 								}
169 
170 								aOldValue <<= m_xFocusedChild;
171 
172 								MAP_ENTRY::iterator mi = m_mapEntry.find(pEntry);
173 								if(mi != m_mapEntry.end())
174 								{
175 									OSL_ASSERT(mi->second.get() != NULL);
176 									m_xFocusedChild = mi->second;
177 								}
178 								else
179 								{
180 									AccessibleListBoxEntry *pEntNew = new AccessibleListBoxEntry( *getListBox(), pEntry, NULL );
181 									m_xFocusedChild = pEntNew;
182 									m_mapEntry.insert(MAP_ENTRY::value_type(pEntry,pEntNew));
183 								}
184 
185 								aNewValue <<= m_xFocusedChild;
186 								NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldValue, aNewValue );
187 							}
188 							else
189 							{
190 								aOldValue <<= uno::Any();
191 								aNewValue <<= AccessibleStateType::FOCUSED;
192 								NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
193 							}
194 						}
195 					}
196 					break;
197 				case VCLEVENT_LISTBOX_ITEMREMOVED:
198 					{
199 						SvLBoxEntry* pEntry = static_cast< SvLBoxEntry* >( rVclWindowEvent.GetData() );
200 						if ( pEntry )
201 						{
202 							RemoveChildEntries(pEntry);
203 						}
204 						else
205 						{
206 							// NULL means Clear()
207 							MAP_ENTRY::iterator mi = m_mapEntry.begin();
208 							for ( ; mi != m_mapEntry.end() ; ++mi)
209 							{
210 								uno::Any aNewValue;
211 								uno::Any aOldValue;
212 								aOldValue <<= mi->second;
213 								NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
214 							}
215 							m_mapEntry.clear();
216 						}
217 
218 
219 					}
220 					break;
221 
222                 // --> OD 2009-04-01 #i92103#
223                 case VCLEVENT_ITEM_EXPANDED :
224                 case VCLEVENT_ITEM_COLLAPSED :
225                 {
226                     SvLBoxEntry* pEntry = static_cast< SvLBoxEntry* >( rVclWindowEvent.GetData() );
227                     if ( pEntry )
228                     {
229                         AccessibleListBoxEntry* pAccListBoxEntry =
230                             new AccessibleListBoxEntry( *getListBox(), pEntry, this );
231                         Reference< XAccessible > xChild = pAccListBoxEntry;
232                         const short nAccEvent =
233                                 ( rVclWindowEvent.GetId() == VCLEVENT_ITEM_EXPANDED )
234                                 ? AccessibleEventId::LISTBOX_ENTRY_EXPANDED
235                                 : AccessibleEventId::LISTBOX_ENTRY_COLLAPSED;
236                         uno::Any aListBoxEntry;
237                         aListBoxEntry <<= xChild;
238                         NotifyAccessibleEvent( nAccEvent, Any(), aListBoxEntry );
239                         if ( getListBox() && getListBox()->HasFocus() )
240                         {
241                             NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, Any(), aListBoxEntry );
242                         }
243                     }
244                 }
245                 break;
246                 // <--
247 				default:
248 					VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent);
249 			}
250 		}
251 	}
252 
253 	AccessibleListBoxEntry* AccessibleListBox::GetCurEventEntry( const VclWindowEvent& rVclWindowEvent )
254 	{
255 		SvLBoxEntry* pEntry = static_cast< SvLBoxEntry* >( rVclWindowEvent.GetData() );
256 		if ( !pEntry )
257 			pEntry = getListBox()->GetCurEntry();
258 
259 		AccessibleListBoxEntry* pEntryFocus =static_cast< AccessibleListBoxEntry* >(m_xFocusedChild.get());
260 		if (pEntryFocus && pEntry && pEntry != pEntryFocus->GetSvLBoxEntry())
261 		{
262 			AccessibleListBoxEntry *pAccCurOptionEntry =NULL;
263 			MAP_ENTRY::iterator mi = m_mapEntry.find(pEntry);
264 			if (mi != m_mapEntry.end())
265 			{
266 				pAccCurOptionEntry= static_cast< AccessibleListBoxEntry* >(mi->second.get());
267 			}
268 			else
269 			{
270 				pAccCurOptionEntry =new AccessibleListBoxEntry( *getListBox(), pEntry, NULL );
271 				std::pair<MAP_ENTRY::iterator, bool> pairMi =  m_mapEntry.insert(MAP_ENTRY::value_type(pAccCurOptionEntry->GetSvLBoxEntry(),pAccCurOptionEntry));
272 				mi = pairMi.first;
273 			}
274 
275 			uno::Any aNewValue;
276 			aNewValue <<= mi->second;//xAcc
277 			NotifyAccessibleEvent( AccessibleEventId::CHILD, uno::Any(), aNewValue );//Add
278 
279 			return pAccCurOptionEntry;
280 		}
281 		else
282 		{
283 			return pEntryFocus;
284 		}
285 		return NULL;
286 	}
287 
288 	void AccessibleListBox::RemoveChildEntries(SvLBoxEntry* pEntry)
289 	{
290 		MAP_ENTRY::iterator mi = m_mapEntry.find(pEntry);
291 		if ( mi != m_mapEntry.end() )
292 		{
293 			uno::Any aNewValue;
294 			uno::Any aOldValue;
295 			aOldValue <<= mi->second;
296 			NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
297 
298 			m_mapEntry.erase(mi);
299 		}
300 
301 		SvTreeListBox* pBox = getListBox();
302 		SvLBoxEntry* pEntryChild = pBox->FirstChild(pEntry);
303 		while (pEntryChild)
304 		{
305 			RemoveChildEntries(pEntryChild);
306 			pEntryChild = pBox->NextSibling(pEntryChild);
307 		}
308 	}
309 
310 	// -----------------------------------------------------------------------------
311     void AccessibleListBox::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent )
312     {
313         switch ( rVclWindowEvent.GetId() )
314         {
315             case VCLEVENT_WINDOW_SHOW:
316             case VCLEVENT_WINDOW_HIDE:
317             {
318             }
319             break;
320             default:
321             {
322                 VCLXAccessibleComponent::ProcessWindowChildEvent( rVclWindowEvent );
323             }
324             break;
325         }
326     }
327 
328 	// -----------------------------------------------------------------------------
329 	// XComponent
330 	// -----------------------------------------------------------------------------
331 	void SAL_CALL AccessibleListBox::disposing()
332 	{
333 		::osl::MutexGuard aGuard( m_aMutex );
334 
335 		m_mapEntry.clear();
336 		VCLXAccessibleComponent::disposing();
337 	    m_xParent = NULL;
338 	}
339 	// -----------------------------------------------------------------------------
340 	// XServiceInfo
341 	// -----------------------------------------------------------------------------
342 	::rtl::OUString SAL_CALL AccessibleListBox::getImplementationName() throw(RuntimeException)
343 	{
344 		return getImplementationName_Static();
345 	}
346 	// -----------------------------------------------------------------------------
347 	Sequence< ::rtl::OUString > SAL_CALL AccessibleListBox::getSupportedServiceNames() throw(RuntimeException)
348 	{
349 		return getSupportedServiceNames_Static();
350 	}
351 	// -----------------------------------------------------------------------------
352 	sal_Bool SAL_CALL AccessibleListBox::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException)
353 	{
354 		Sequence< ::rtl::OUString > aSupported( getSupportedServiceNames() );
355 		const ::rtl::OUString* pSupported = aSupported.getConstArray();
356 		const ::rtl::OUString* pEnd = pSupported + aSupported.getLength();
357 		for ( ; pSupported != pEnd && !pSupported->equals(_rServiceName); ++pSupported )
358 			;
359 
360 		return pSupported != pEnd;
361 	}
362 	// -----------------------------------------------------------------------------
363 	// XServiceInfo - static methods
364 	// -----------------------------------------------------------------------------
365 	Sequence< ::rtl::OUString > AccessibleListBox::getSupportedServiceNames_Static(void) throw( RuntimeException )
366 	{
367 		Sequence< ::rtl::OUString > aSupported(3);
368 		aSupported[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.accessibility.AccessibleContext") );
369 		aSupported[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.accessibility.AccessibleComponent") );
370 		aSupported[2] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.AccessibleTreeListBox") );
371 		return aSupported;
372 	}
373 	// -----------------------------------------------------------------------------
374 	::rtl::OUString AccessibleListBox::getImplementationName_Static(void) throw( RuntimeException )
375 	{
376 		return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.svtools.AccessibleTreeListBox") );
377 	}
378 	// -----------------------------------------------------------------------------
379 	// XAccessible
380 	// -----------------------------------------------------------------------------
381 	Reference< XAccessibleContext > SAL_CALL AccessibleListBox::getAccessibleContext(  ) throw (RuntimeException)
382 	{
383 		ensureAlive();
384 		return this;
385 	}
386 	// -----------------------------------------------------------------------------
387 	// XAccessibleContext
388 	// -----------------------------------------------------------------------------
389 	sal_Int32 SAL_CALL AccessibleListBox::getAccessibleChildCount(  ) throw (RuntimeException)
390 	{
391 		::comphelper::OExternalLockGuard aGuard( this );
392 
393 		ensureAlive();
394 
395         sal_Int32 nCount = 0;
396         SvTreeListBox* pSvTreeListBox = getListBox();
397         if ( pSvTreeListBox )
398             nCount = pSvTreeListBox->GetLevelChildCount( NULL );
399 
400         return nCount;
401 	}
402 	// -----------------------------------------------------------------------------
403 	Reference< XAccessible > SAL_CALL AccessibleListBox::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException,RuntimeException)
404 	{
405 		::comphelper::OExternalLockGuard aGuard( this );
406 
407 		ensureAlive();
408 		SvLBoxEntry* pEntry = getListBox()->GetEntry(i);
409 		if ( !pEntry )
410 			throw IndexOutOfBoundsException();
411 
412 		// Solution: Set the parameter of the parent to null to let entry determine the parent by itself
413 		//return new AccessibleListBoxEntry( *getListBox(), pEntry, this );
414 		return new AccessibleListBoxEntry( *getListBox(), pEntry, NULL );
415 	}
416 	// -----------------------------------------------------------------------------
417 	Reference< XAccessible > SAL_CALL AccessibleListBox::getAccessibleParent(  ) throw (RuntimeException)
418 	{
419 		::osl::MutexGuard aGuard( m_aMutex );
420 
421 		ensureAlive();
422 		return m_xParent;
423 	}
424 	// -----------------------------------------------------------------------------
425 	sal_Int32 SAL_CALL AccessibleListBox::getRoleType()
426 	{
427 		sal_Int32 nCase = 0;
428 		SvLBoxEntry* pEntry = getListBox()->GetEntry(0);
429 		if ( pEntry )
430 		{
431 			if( pEntry->HasChildsOnDemand() || getListBox()->GetChildCount(pEntry) > 0  )
432 			//end add by duan mei hua, 2007/01/27, for sodc_6862
433 			{
434 				nCase = 1;
435 				return nCase;
436 			}
437 		}
438 
439 		sal_Bool bHasButtons = (getListBox()->GetStyle() & WB_HASBUTTONS)!=0;
440 		if( !(getListBox()->GetTreeFlags() & TREEFLAG_CHKBTN) )
441 		{
442 			if( bHasButtons )
443 				nCase = 1;
444 		}
445 		else
446 		{
447 			if( bHasButtons )
448 				nCase = 2;
449 			 else
450 				nCase = 3;
451 		}
452 		return nCase;
453 	}
454 	sal_Int16 SAL_CALL AccessibleListBox::getAccessibleRole(  ) throw (RuntimeException)
455 	{
456 		if(getListBox())
457 		{
458 			short nType = getListBox()->GetAllEntriesAccessibleRoleType();
459 			if( nType == TREEBOX_ALLITEM_ACCROLE_TYPE_TREE)
460 					return AccessibleRole::TREE;
461 			else if( nType == TREEBOX_ALLITEM_ACCROLE_TYPE_LIST)
462 					return AccessibleRole::LIST;
463 		}
464 
465 		//o is: return AccessibleRole::TREE;
466 		sal_Bool bHasButtons = (getListBox()->GetStyle() & WB_HASBUTTONS)!=0;
467 		if(!bHasButtons && (getListBox()->GetTreeFlags() & TREEFLAG_CHKBTN))
468 			return AccessibleRole::LIST;
469 		else
470 			if(getRoleType() == 0)
471 				return AccessibleRole::LIST;
472 			else
473 			return AccessibleRole::TREE;
474 	}
475 	// -----------------------------------------------------------------------------
476 	::rtl::OUString SAL_CALL AccessibleListBox::getAccessibleDescription(  ) throw (RuntimeException)
477 	{
478 		::comphelper::OExternalLockGuard aGuard( this );
479 
480 		ensureAlive();
481 		return getListBox()->GetAccessibleDescription();
482 	}
483 	// -----------------------------------------------------------------------------
484 	::rtl::OUString SAL_CALL AccessibleListBox::getAccessibleName(  ) throw (RuntimeException)
485 	{
486 		::comphelper::OExternalLockGuard aGuard( this );
487 
488 		ensureAlive();
489 		return getListBox()->GetAccessibleName();
490 	}
491 	// -----------------------------------------------------------------------------
492 	// XAccessibleSelection
493 	// -----------------------------------------------------------------------------
494 	void SAL_CALL AccessibleListBox::selectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
495 	{
496     	::comphelper::OExternalLockGuard aGuard( this );
497 
498 		ensureAlive();
499 
500 		SvLBoxEntry* pEntry = getListBox()->GetEntry( nChildIndex );
501 		if ( !pEntry )
502 			throw IndexOutOfBoundsException();
503 
504 		getListBox()->Select( pEntry, sal_True );
505 	}
506 	// -----------------------------------------------------------------------------
507 	sal_Bool SAL_CALL AccessibleListBox::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
508 	{
509     	::comphelper::OExternalLockGuard aGuard( this );
510 
511 		ensureAlive();
512 
513 		SvLBoxEntry* pEntry = getListBox()->GetEntry( nChildIndex );
514 		if ( !pEntry )
515 			throw IndexOutOfBoundsException();
516 
517 		return getListBox()->IsSelected( pEntry );
518 	}
519 	// -----------------------------------------------------------------------------
520 	void SAL_CALL AccessibleListBox::clearAccessibleSelection(  ) throw (RuntimeException)
521 	{
522     	::comphelper::OExternalLockGuard aGuard( this );
523 
524 		ensureAlive();
525 
526     	sal_Int32 i, nCount = 0;
527 		nCount = getListBox()->GetLevelChildCount( NULL );
528 		for ( i = 0; i < nCount; ++i )
529 		{
530 			SvLBoxEntry* pEntry = getListBox()->GetEntry( i );
531 			if ( getListBox()->IsSelected( pEntry ) )
532 				getListBox()->Select( pEntry, sal_False );
533 		}
534 	}
535 	// -----------------------------------------------------------------------------
536 	void SAL_CALL AccessibleListBox::selectAllAccessibleChildren(  ) throw (RuntimeException)
537 	{
538     	::comphelper::OExternalLockGuard aGuard( this );
539 
540 		ensureAlive();
541 
542     	sal_Int32 i, nCount = 0;
543 		nCount = getListBox()->GetLevelChildCount( NULL );
544 		for ( i = 0; i < nCount; ++i )
545 		{
546 			SvLBoxEntry* pEntry = getListBox()->GetEntry( i );
547 			if ( !getListBox()->IsSelected( pEntry ) )
548 				getListBox()->Select( pEntry, sal_True );
549 		}
550 	}
551 	// -----------------------------------------------------------------------------
552 	sal_Int32 SAL_CALL AccessibleListBox::getSelectedAccessibleChildCount(  ) throw (RuntimeException)
553 	{
554     	::comphelper::OExternalLockGuard aGuard( this );
555 
556 		ensureAlive();
557 
558 
559 //     	sal_Int32 i, nSelCount = 0, nCount = 0;
560 // 		nCount = getListBox()->GetLevelChildCount( NULL );
561 // 		for ( i = 0; i < nCount; ++i )
562 // 		{
563 // 			SvLBoxEntry* pEntry = getListBox()->GetEntry( i );
564 // 			if ( getListBox()->IsSelected( pEntry ) )
565 // 				++nSelCount;
566 // 		}
567 //    	return nSelCount;
568 
569 		int nTestCount =  getListBox()->GetSelectionCount();
570 		return nTestCount;
571 	}
572 	// -----------------------------------------------------------------------------
573 	Reference< XAccessible > SAL_CALL AccessibleListBox::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
574 	{
575     	::comphelper::OExternalLockGuard aGuard( this );
576 
577 		ensureAlive();
578 
579 		if ( nSelectedChildIndex < 0 || nSelectedChildIndex >= getSelectedAccessibleChildCount() )
580 			throw IndexOutOfBoundsException();
581 
582 		Reference< XAccessible > xChild;
583     	sal_Int32 i, nSelCount = 0, nCount = 0;
584 		nCount = getListBox()->GetLevelChildCount( NULL );
585 		for ( i = 0; i < nCount; ++i )
586 		{
587 			SvLBoxEntry* pEntry = getListBox()->GetEntry( i );
588 			if ( getListBox()->IsSelected( pEntry ) )
589 				++nSelCount;
590 
591 			if ( nSelCount == ( nSelectedChildIndex + 1 ) )
592 			{
593 				// Solution: Set the parameter of the parent to null to let entry determine the parent by itself
594 				//xChild = new AccessibleListBoxEntry( *getListBox(), pEntry, this );
595 				xChild = new AccessibleListBoxEntry( *getListBox(), pEntry, NULL );
596 				break;
597 			}
598 		}
599 
600 		return xChild;
601 	}
602 	// -----------------------------------------------------------------------------
603 	void SAL_CALL AccessibleListBox::deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
604 	{
605     	::comphelper::OExternalLockGuard aGuard( this );
606 
607 		ensureAlive();
608 
609 		SvLBoxEntry* pEntry = getListBox()->GetEntry( nSelectedChildIndex );
610 		if ( !pEntry )
611 			throw IndexOutOfBoundsException();
612 
613 		getListBox()->Select( pEntry, sal_False );
614 	}
615 	// -----------------------------------------------------------------------------
616 	void AccessibleListBox::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
617 	{
618 		VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet );
619 		if ( getListBox() && isAlive() )
620 		{
621 			rStateSet.AddState( AccessibleStateType::FOCUSABLE );
622 			rStateSet.AddState( AccessibleStateType::MANAGES_DESCENDANTS );
623 			if ( getListBox()->GetSelectionMode() == MULTIPLE_SELECTION )
624 				rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE );
625 		}
626 	}
627 
628 
629 //........................................................................
630 }// namespace accessibility
631 //........................................................................
632 
633