xref: /trunk/main/accessibility/source/extended/accessiblelistbox.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_accessibility.hxx"
30 #include <accessibility/extended/accessiblelistbox.hxx>
31 #include <accessibility/extended/accessiblelistboxentry.hxx>
32 #include <svtools/svtreebx.hxx>
33 #include <com/sun/star/awt/Point.hpp>
34 #include <com/sun/star/awt/Rectangle.hpp>
35 #include <com/sun/star/awt/Size.hpp>
36 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
37 #include <com/sun/star/accessibility/AccessibleRole.hpp>
38 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
39 #include <tools/debug.hxx>
40 #include <vcl/svapp.hxx>
41 #include <toolkit/awt/vclxwindow.hxx>
42 #include <toolkit/helper/convert.hxx>
43 #include <unotools/accessiblestatesethelper.hxx>
44 
45 //........................................................................
46 namespace accessibility
47 {
48 //........................................................................
49 
50     // class AccessibleListBox -----------------------------------------------------
51 
52     using namespace ::com::sun::star::accessibility;
53     using namespace ::com::sun::star::uno;
54     using namespace ::com::sun::star::lang;
55     using namespace ::com::sun::star;
56 
57     DBG_NAME(AccessibleListBox)
58 
59     // -----------------------------------------------------------------------------
60     // Ctor() and Dtor()
61     // -----------------------------------------------------------------------------
62     AccessibleListBox::AccessibleListBox( SvTreeListBox& _rListBox, const Reference< XAccessible >& _xParent ) :
63 
64         VCLXAccessibleComponent( _rListBox.GetWindowPeer() ),
65         m_xParent( _xParent )
66     {
67         DBG_CTOR( AccessibleListBox, NULL );
68     }
69     // -----------------------------------------------------------------------------
70     AccessibleListBox::~AccessibleListBox()
71     {
72         DBG_DTOR( AccessibleListBox, NULL );
73         if ( isAlive() )
74         {
75             // increment ref count to prevent double call of Dtor
76             osl_incrementInterlockedCount( &m_refCount );
77             dispose();
78         }
79     }
80     IMPLEMENT_FORWARD_XINTERFACE2(AccessibleListBox, VCLXAccessibleComponent, AccessibleListBox_BASE)
81     IMPLEMENT_FORWARD_XTYPEPROVIDER2(AccessibleListBox, VCLXAccessibleComponent, AccessibleListBox_BASE)
82     // -----------------------------------------------------------------------------
83     SvTreeListBox* AccessibleListBox::getListBox() const
84     {
85         return  static_cast< SvTreeListBox* >( const_cast<AccessibleListBox*>(this)->GetWindow() );
86     }
87     // -----------------------------------------------------------------------------
88     void AccessibleListBox::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
89     {
90         if ( isAlive() )
91         {
92             switch ( rVclWindowEvent.GetId() )
93             {
94                 case  VCLEVENT_CHECKBOX_TOGGLE :
95                 {
96                     if ( getListBox() && getListBox()->HasFocus() )
97                     {
98                         SvLBoxEntry* pEntry = static_cast< SvLBoxEntry* >( rVclWindowEvent.GetData() );
99                         if ( !pEntry )
100                             pEntry = getListBox()->GetCurEntry();
101 
102                         if ( pEntry )
103                         {
104                             Reference< XAccessible > xChild = new AccessibleListBoxEntry( *getListBox(), pEntry, this );
105                             uno::Any aOldValue, aNewValue;
106                             aNewValue <<= xChild;
107                             NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldValue, aNewValue );
108                         }
109                     }
110                     break;
111                 }
112 
113                 case VCLEVENT_LISTBOX_SELECT :
114                 {
115                     // First send an event that tells the listeners of a
116                     // modified selection.  The active descendant event is
117                     // send after that so that the receiving AT has time to
118                     // read the text or name of the active child.
119                     NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
120                     if ( getListBox() && getListBox()->HasFocus() )
121                     {
122                         SvLBoxEntry* pEntry = static_cast< SvLBoxEntry* >( rVclWindowEvent.GetData() );
123                         if ( pEntry )
124                         {
125                             Reference< XAccessible > xChild = new AccessibleListBoxEntry( *getListBox(), pEntry, this );
126                             uno::Any aOldValue, aNewValue;
127                             aNewValue <<= xChild;
128                             NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldValue, aNewValue );
129                         }
130                     }
131                     break;
132 
133                 // --> OD 2009-04-01 #i92103#
134                 case VCLEVENT_ITEM_EXPANDED :
135                 case VCLEVENT_ITEM_COLLAPSED :
136                 {
137                     SvLBoxEntry* pEntry = static_cast< SvLBoxEntry* >( rVclWindowEvent.GetData() );
138                     if ( pEntry )
139                     {
140                         AccessibleListBoxEntry* pAccListBoxEntry =
141                             new AccessibleListBoxEntry( *getListBox(), pEntry, this );
142                         Reference< XAccessible > xChild = pAccListBoxEntry;
143                         const short nAccEvent =
144                                 ( rVclWindowEvent.GetId() == VCLEVENT_ITEM_EXPANDED )
145                                 ? AccessibleEventId::LISTBOX_ENTRY_EXPANDED
146                                 : AccessibleEventId::LISTBOX_ENTRY_COLLAPSED;
147                         uno::Any aListBoxEntry;
148                         aListBoxEntry <<= xChild;
149                         NotifyAccessibleEvent( nAccEvent, Any(), aListBoxEntry );
150                         if ( getListBox() && getListBox()->HasFocus() )
151                         {
152                             NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, Any(), aListBoxEntry );
153                         }
154                     }
155                     break;
156                 }
157                 // <--
158                 }
159                 default:
160                     VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent);
161             }
162         }
163     }
164     // -----------------------------------------------------------------------------
165     void AccessibleListBox::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent )
166     {
167         switch ( rVclWindowEvent.GetId() )
168         {
169             case VCLEVENT_WINDOW_SHOW:
170             case VCLEVENT_WINDOW_HIDE:
171             {
172             }
173             break;
174             default:
175             {
176                 VCLXAccessibleComponent::ProcessWindowChildEvent( rVclWindowEvent );
177             }
178             break;
179         }
180     }
181 
182     // -----------------------------------------------------------------------------
183     // XComponent
184     // -----------------------------------------------------------------------------
185     void SAL_CALL AccessibleListBox::disposing()
186     {
187         ::osl::MutexGuard aGuard( m_aMutex );
188 
189         VCLXAccessibleComponent::disposing();
190         m_xParent = NULL;
191     }
192     // -----------------------------------------------------------------------------
193     // XServiceInfo
194     // -----------------------------------------------------------------------------
195     ::rtl::OUString SAL_CALL AccessibleListBox::getImplementationName() throw(RuntimeException)
196     {
197         return getImplementationName_Static();
198     }
199     // -----------------------------------------------------------------------------
200     Sequence< ::rtl::OUString > SAL_CALL AccessibleListBox::getSupportedServiceNames() throw(RuntimeException)
201     {
202         return getSupportedServiceNames_Static();
203     }
204     // -----------------------------------------------------------------------------
205     sal_Bool SAL_CALL AccessibleListBox::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException)
206     {
207         Sequence< ::rtl::OUString > aSupported( getSupportedServiceNames() );
208         const ::rtl::OUString* pSupported = aSupported.getConstArray();
209         const ::rtl::OUString* pEnd = pSupported + aSupported.getLength();
210         for ( ; pSupported != pEnd && !pSupported->equals(_rServiceName); ++pSupported )
211             ;
212 
213         return pSupported != pEnd;
214     }
215     // -----------------------------------------------------------------------------
216     // XServiceInfo - static methods
217     // -----------------------------------------------------------------------------
218     Sequence< ::rtl::OUString > AccessibleListBox::getSupportedServiceNames_Static(void) throw( RuntimeException )
219     {
220         Sequence< ::rtl::OUString > aSupported(3);
221         aSupported[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.accessibility.AccessibleContext") );
222         aSupported[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.accessibility.AccessibleComponent") );
223         aSupported[2] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.AccessibleTreeListBox") );
224         return aSupported;
225     }
226     // -----------------------------------------------------------------------------
227     ::rtl::OUString AccessibleListBox::getImplementationName_Static(void) throw( RuntimeException )
228     {
229         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.svtools.AccessibleTreeListBox") );
230     }
231     // -----------------------------------------------------------------------------
232     // XAccessible
233     // -----------------------------------------------------------------------------
234     Reference< XAccessibleContext > SAL_CALL AccessibleListBox::getAccessibleContext(  ) throw (RuntimeException)
235     {
236         ensureAlive();
237         return this;
238     }
239     // -----------------------------------------------------------------------------
240     // XAccessibleContext
241     // -----------------------------------------------------------------------------
242     sal_Int32 SAL_CALL AccessibleListBox::getAccessibleChildCount(  ) throw (RuntimeException)
243     {
244         ::comphelper::OExternalLockGuard aGuard( this );
245 
246         ensureAlive();
247 
248         sal_Int32 nCount = 0;
249         SvTreeListBox* pSvTreeListBox = getListBox();
250         if ( pSvTreeListBox )
251             nCount = pSvTreeListBox->GetLevelChildCount( NULL );
252 
253         return nCount;
254     }
255     // -----------------------------------------------------------------------------
256     Reference< XAccessible > SAL_CALL AccessibleListBox::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException,RuntimeException)
257     {
258         ::comphelper::OExternalLockGuard aGuard( this );
259 
260         ensureAlive();
261         SvLBoxEntry* pEntry = getListBox()->GetEntry(i);
262         if ( !pEntry )
263             throw IndexOutOfBoundsException();
264 
265         return new AccessibleListBoxEntry( *getListBox(), pEntry, this );
266     }
267     // -----------------------------------------------------------------------------
268     Reference< XAccessible > SAL_CALL AccessibleListBox::getAccessibleParent(  ) throw (RuntimeException)
269     {
270         ::osl::MutexGuard aGuard( m_aMutex );
271 
272         ensureAlive();
273         return m_xParent;
274     }
275     // -----------------------------------------------------------------------------
276     sal_Int16 SAL_CALL AccessibleListBox::getAccessibleRole(  ) throw (RuntimeException)
277     {
278         return AccessibleRole::TREE;
279     }
280     // -----------------------------------------------------------------------------
281     ::rtl::OUString SAL_CALL AccessibleListBox::getAccessibleDescription(  ) throw (RuntimeException)
282     {
283         ::comphelper::OExternalLockGuard aGuard( this );
284 
285         ensureAlive();
286         return getListBox()->GetAccessibleDescription();
287     }
288     // -----------------------------------------------------------------------------
289     ::rtl::OUString SAL_CALL AccessibleListBox::getAccessibleName(  ) throw (RuntimeException)
290     {
291         ::comphelper::OExternalLockGuard aGuard( this );
292 
293         ensureAlive();
294         return getListBox()->GetAccessibleName();
295     }
296     // -----------------------------------------------------------------------------
297     // XAccessibleSelection
298     // -----------------------------------------------------------------------------
299     void SAL_CALL AccessibleListBox::selectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
300     {
301         ::comphelper::OExternalLockGuard aGuard( this );
302 
303         ensureAlive();
304 
305         SvLBoxEntry* pEntry = getListBox()->GetEntry( nChildIndex );
306         if ( !pEntry )
307             throw IndexOutOfBoundsException();
308 
309         getListBox()->Select( pEntry, sal_True );
310     }
311     // -----------------------------------------------------------------------------
312     sal_Bool SAL_CALL AccessibleListBox::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
313     {
314         ::comphelper::OExternalLockGuard aGuard( this );
315 
316         ensureAlive();
317 
318         SvLBoxEntry* pEntry = getListBox()->GetEntry( nChildIndex );
319         if ( !pEntry )
320             throw IndexOutOfBoundsException();
321 
322         return getListBox()->IsSelected( pEntry );
323     }
324     // -----------------------------------------------------------------------------
325     void SAL_CALL AccessibleListBox::clearAccessibleSelection(  ) throw (RuntimeException)
326     {
327         ::comphelper::OExternalLockGuard aGuard( this );
328 
329         ensureAlive();
330 
331         sal_Int32 i, nCount = 0;
332         nCount = getListBox()->GetLevelChildCount( NULL );
333         for ( i = 0; i < nCount; ++i )
334         {
335             SvLBoxEntry* pEntry = getListBox()->GetEntry( i );
336             if ( getListBox()->IsSelected( pEntry ) )
337                 getListBox()->Select( pEntry, sal_False );
338         }
339     }
340     // -----------------------------------------------------------------------------
341     void SAL_CALL AccessibleListBox::selectAllAccessibleChildren(  ) throw (RuntimeException)
342     {
343         ::comphelper::OExternalLockGuard aGuard( this );
344 
345         ensureAlive();
346 
347         sal_Int32 i, nCount = 0;
348         nCount = getListBox()->GetLevelChildCount( NULL );
349         for ( i = 0; i < nCount; ++i )
350         {
351             SvLBoxEntry* pEntry = getListBox()->GetEntry( i );
352             if ( !getListBox()->IsSelected( pEntry ) )
353                 getListBox()->Select( pEntry, sal_True );
354         }
355     }
356     // -----------------------------------------------------------------------------
357     sal_Int32 SAL_CALL AccessibleListBox::getSelectedAccessibleChildCount(  ) throw (RuntimeException)
358     {
359         ::comphelper::OExternalLockGuard aGuard( this );
360 
361         ensureAlive();
362 
363         sal_Int32 i, nSelCount = 0, nCount = 0;
364         nCount = getListBox()->GetLevelChildCount( NULL );
365         for ( i = 0; i < nCount; ++i )
366         {
367             SvLBoxEntry* pEntry = getListBox()->GetEntry( i );
368             if ( getListBox()->IsSelected( pEntry ) )
369                 ++nSelCount;
370         }
371 
372         return nSelCount;
373     }
374     // -----------------------------------------------------------------------------
375     Reference< XAccessible > SAL_CALL AccessibleListBox::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
376     {
377         ::comphelper::OExternalLockGuard aGuard( this );
378 
379         ensureAlive();
380 
381         if ( nSelectedChildIndex < 0 || nSelectedChildIndex >= getSelectedAccessibleChildCount() )
382             throw IndexOutOfBoundsException();
383 
384         Reference< XAccessible > xChild;
385         sal_Int32 i, nSelCount = 0, nCount = 0;
386         nCount = getListBox()->GetLevelChildCount( NULL );
387         for ( i = 0; i < nCount; ++i )
388         {
389             SvLBoxEntry* pEntry = getListBox()->GetEntry( i );
390             if ( getListBox()->IsSelected( pEntry ) )
391                 ++nSelCount;
392 
393             if ( nSelCount == ( nSelectedChildIndex + 1 ) )
394             {
395                 xChild = new AccessibleListBoxEntry( *getListBox(), pEntry, this );
396                 break;
397             }
398         }
399 
400         return xChild;
401     }
402     // -----------------------------------------------------------------------------
403     void SAL_CALL AccessibleListBox::deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
404     {
405         ::comphelper::OExternalLockGuard aGuard( this );
406 
407         ensureAlive();
408 
409         SvLBoxEntry* pEntry = getListBox()->GetEntry( nSelectedChildIndex );
410         if ( !pEntry )
411             throw IndexOutOfBoundsException();
412 
413         getListBox()->Select( pEntry, sal_False );
414     }
415     // -----------------------------------------------------------------------------
416     void AccessibleListBox::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
417     {
418         VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet );
419         if ( getListBox() && isAlive() )
420         {
421             rStateSet.AddState( AccessibleStateType::FOCUSABLE );
422             rStateSet.AddState( AccessibleStateType::MANAGES_DESCENDANTS );
423             if ( getListBox()->GetSelectionMode() == MULTIPLE_SELECTION )
424                 rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE );
425         }
426     }
427 
428 
429 //........................................................................
430 }// namespace accessibility
431 //........................................................................
432 
433