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 
DBG_NAME(AccessibleListBox)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 	// -----------------------------------------------------------------------------
~AccessibleListBox()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 	}
IMPLEMENT_FORWARD_XINTERFACE2(AccessibleListBox,VCLXAccessibleComponent,AccessibleListBox_BASE)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 	// -----------------------------------------------------------------------------
ProcessWindowEvent(const VclWindowEvent & rVclWindowEvent)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 
GetCurEventEntry(const VclWindowEvent & rVclWindowEvent)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 
RemoveChildEntries(SvLBoxEntry * pEntry)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 	// -----------------------------------------------------------------------------
ProcessWindowChildEvent(const VclWindowEvent & rVclWindowEvent)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 	// -----------------------------------------------------------------------------
disposing()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 	// -----------------------------------------------------------------------------
getImplementationName()342 	::rtl::OUString SAL_CALL AccessibleListBox::getImplementationName() throw(RuntimeException)
343 	{
344 		return getImplementationName_Static();
345 	}
346 	// -----------------------------------------------------------------------------
getSupportedServiceNames()347 	Sequence< ::rtl::OUString > SAL_CALL AccessibleListBox::getSupportedServiceNames() throw(RuntimeException)
348 	{
349 		return getSupportedServiceNames_Static();
350 	}
351 	// -----------------------------------------------------------------------------
supportsService(const::rtl::OUString & _rServiceName)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 	// -----------------------------------------------------------------------------
getSupportedServiceNames_Static(void)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 	// -----------------------------------------------------------------------------
getImplementationName_Static(void)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 	// -----------------------------------------------------------------------------
getAccessibleContext()381 	Reference< XAccessibleContext > SAL_CALL AccessibleListBox::getAccessibleContext(  ) throw (RuntimeException)
382 	{
383 		ensureAlive();
384 		return this;
385 	}
386 	// -----------------------------------------------------------------------------
387 	// XAccessibleContext
388 	// -----------------------------------------------------------------------------
getAccessibleChildCount()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 	// -----------------------------------------------------------------------------
getAccessibleChild(sal_Int32 i)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 	// -----------------------------------------------------------------------------
getAccessibleParent()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 	// -----------------------------------------------------------------------------
getRoleType()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 			{
433 				nCase = 1;
434 				return nCase;
435 			}
436 		}
437 
438 		sal_Bool bHasButtons = (getListBox()->GetStyle() & WB_HASBUTTONS)!=0;
439 		if( !(getListBox()->GetTreeFlags() & TREEFLAG_CHKBTN) )
440 		{
441 			if( bHasButtons )
442 				nCase = 1;
443 		}
444 		else
445 		{
446 			if( bHasButtons )
447 				nCase = 2;
448 			 else
449 				nCase = 3;
450 		}
451 		return nCase;
452 	}
getAccessibleRole()453 	sal_Int16 SAL_CALL AccessibleListBox::getAccessibleRole(  ) throw (RuntimeException)
454 	{
455 		if(getListBox())
456 		{
457 			short nType = getListBox()->GetAllEntriesAccessibleRoleType();
458 			if( nType == TREEBOX_ALLITEM_ACCROLE_TYPE_TREE)
459 					return AccessibleRole::TREE;
460 			else if( nType == TREEBOX_ALLITEM_ACCROLE_TYPE_LIST)
461 					return AccessibleRole::LIST;
462 		}
463 
464 		//o is: return AccessibleRole::TREE;
465 		sal_Bool bHasButtons = (getListBox()->GetStyle() & WB_HASBUTTONS)!=0;
466 		if(!bHasButtons && (getListBox()->GetTreeFlags() & TREEFLAG_CHKBTN))
467 			return AccessibleRole::LIST;
468 		else
469 			if(getRoleType() == 0)
470 				return AccessibleRole::LIST;
471 			else
472 			return AccessibleRole::TREE;
473 	}
474 	// -----------------------------------------------------------------------------
getAccessibleDescription()475 	::rtl::OUString SAL_CALL AccessibleListBox::getAccessibleDescription(  ) throw (RuntimeException)
476 	{
477 		::comphelper::OExternalLockGuard aGuard( this );
478 
479 		ensureAlive();
480 		return getListBox()->GetAccessibleDescription();
481 	}
482 	// -----------------------------------------------------------------------------
getAccessibleName()483 	::rtl::OUString SAL_CALL AccessibleListBox::getAccessibleName(  ) throw (RuntimeException)
484 	{
485 		::comphelper::OExternalLockGuard aGuard( this );
486 
487 		ensureAlive();
488 		return getListBox()->GetAccessibleName();
489 	}
490 	// -----------------------------------------------------------------------------
491 	// XAccessibleSelection
492 	// -----------------------------------------------------------------------------
selectAccessibleChild(sal_Int32 nChildIndex)493 	void SAL_CALL AccessibleListBox::selectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
494 	{
495     	::comphelper::OExternalLockGuard aGuard( this );
496 
497 		ensureAlive();
498 
499 		SvLBoxEntry* pEntry = getListBox()->GetEntry( nChildIndex );
500 		if ( !pEntry )
501 			throw IndexOutOfBoundsException();
502 
503 		getListBox()->Select( pEntry, sal_True );
504 	}
505 	// -----------------------------------------------------------------------------
isAccessibleChildSelected(sal_Int32 nChildIndex)506 	sal_Bool SAL_CALL AccessibleListBox::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
507 	{
508     	::comphelper::OExternalLockGuard aGuard( this );
509 
510 		ensureAlive();
511 
512 		SvLBoxEntry* pEntry = getListBox()->GetEntry( nChildIndex );
513 		if ( !pEntry )
514 			throw IndexOutOfBoundsException();
515 
516 		return getListBox()->IsSelected( pEntry );
517 	}
518 	// -----------------------------------------------------------------------------
clearAccessibleSelection()519 	void SAL_CALL AccessibleListBox::clearAccessibleSelection(  ) throw (RuntimeException)
520 	{
521     	::comphelper::OExternalLockGuard aGuard( this );
522 
523 		ensureAlive();
524 
525     	sal_Int32 i, nCount = 0;
526 		nCount = getListBox()->GetLevelChildCount( NULL );
527 		for ( i = 0; i < nCount; ++i )
528 		{
529 			SvLBoxEntry* pEntry = getListBox()->GetEntry( i );
530 			if ( getListBox()->IsSelected( pEntry ) )
531 				getListBox()->Select( pEntry, sal_False );
532 		}
533 	}
534 	// -----------------------------------------------------------------------------
selectAllAccessibleChildren()535 	void SAL_CALL AccessibleListBox::selectAllAccessibleChildren(  ) throw (RuntimeException)
536 	{
537     	::comphelper::OExternalLockGuard aGuard( this );
538 
539 		ensureAlive();
540 
541     	sal_Int32 i, nCount = 0;
542 		nCount = getListBox()->GetLevelChildCount( NULL );
543 		for ( i = 0; i < nCount; ++i )
544 		{
545 			SvLBoxEntry* pEntry = getListBox()->GetEntry( i );
546 			if ( !getListBox()->IsSelected( pEntry ) )
547 				getListBox()->Select( pEntry, sal_True );
548 		}
549 	}
550 	// -----------------------------------------------------------------------------
getSelectedAccessibleChildCount()551 	sal_Int32 SAL_CALL AccessibleListBox::getSelectedAccessibleChildCount(  ) throw (RuntimeException)
552 	{
553     	::comphelper::OExternalLockGuard aGuard( this );
554 
555 		ensureAlive();
556 
557 
558 //     	sal_Int32 i, nSelCount = 0, nCount = 0;
559 // 		nCount = getListBox()->GetLevelChildCount( NULL );
560 // 		for ( i = 0; i < nCount; ++i )
561 // 		{
562 // 			SvLBoxEntry* pEntry = getListBox()->GetEntry( i );
563 // 			if ( getListBox()->IsSelected( pEntry ) )
564 // 				++nSelCount;
565 // 		}
566 //    	return nSelCount;
567 
568 		int nTestCount =  getListBox()->GetSelectionCount();
569 		return nTestCount;
570 	}
571 	// -----------------------------------------------------------------------------
getSelectedAccessibleChild(sal_Int32 nSelectedChildIndex)572 	Reference< XAccessible > SAL_CALL AccessibleListBox::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
573 	{
574     	::comphelper::OExternalLockGuard aGuard( this );
575 
576 		ensureAlive();
577 
578 		if ( nSelectedChildIndex < 0 || nSelectedChildIndex >= getSelectedAccessibleChildCount() )
579 			throw IndexOutOfBoundsException();
580 
581 		Reference< XAccessible > xChild;
582     	sal_Int32 i, nSelCount = 0, nCount = 0;
583 		nCount = getListBox()->GetLevelChildCount( NULL );
584 		for ( i = 0; i < nCount; ++i )
585 		{
586 			SvLBoxEntry* pEntry = getListBox()->GetEntry( i );
587 			if ( getListBox()->IsSelected( pEntry ) )
588 				++nSelCount;
589 
590 			if ( nSelCount == ( nSelectedChildIndex + 1 ) )
591 			{
592 				// Solution: Set the parameter of the parent to null to let entry determine the parent by itself
593 				//xChild = new AccessibleListBoxEntry( *getListBox(), pEntry, this );
594 				xChild = new AccessibleListBoxEntry( *getListBox(), pEntry, NULL );
595 				break;
596 			}
597 		}
598 
599 		return xChild;
600 	}
601 	// -----------------------------------------------------------------------------
deselectAccessibleChild(sal_Int32 nSelectedChildIndex)602 	void SAL_CALL AccessibleListBox::deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
603 	{
604     	::comphelper::OExternalLockGuard aGuard( this );
605 
606 		ensureAlive();
607 
608 		SvLBoxEntry* pEntry = getListBox()->GetEntry( nSelectedChildIndex );
609 		if ( !pEntry )
610 			throw IndexOutOfBoundsException();
611 
612 		getListBox()->Select( pEntry, sal_False );
613 	}
614 	// -----------------------------------------------------------------------------
FillAccessibleStateSet(utl::AccessibleStateSetHelper & rStateSet)615 	void AccessibleListBox::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
616 	{
617 		VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet );
618 		if ( getListBox() && isAlive() )
619 		{
620 			rStateSet.AddState( AccessibleStateType::FOCUSABLE );
621 			rStateSet.AddState( AccessibleStateType::MANAGES_DESCENDANTS );
622 			if ( getListBox()->GetSelectionMode() == MULTIPLE_SELECTION )
623 				rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE );
624 		}
625 	}
626 
627 
628 //........................................................................
629 }// namespace accessibility
630 //........................................................................
631 
632