xref: /trunk/main/accessibility/source/extended/accessiblelistbox.cxx (revision ca62e2c2083b5d0995f1245bad6c2edfb455fbec)
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