xref: /AOO41X/main/accessibility/source/extended/accessiblelistbox.cxx (revision 8809db7a87f97847b57a57f4cd2b0104b2b83182)
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                         SvLBoxEntry* pEntry = static_cast< SvLBoxEntry* >( rVclWindowEvent.GetData() );
95                         if ( !pEntry )
96                             pEntry = getListBox()->GetCurEntry();
97 
98                         if ( pEntry )
99                         {
100                             Reference< XAccessible > xChild = new AccessibleListBoxEntry( *getListBox(), pEntry, this );
101                             uno::Any aOldValue, aNewValue;
102                             aNewValue <<= xChild;
103                             NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldValue, aNewValue );
104                         }
105                     }
106                     break;
107                 }
108 
109                 case VCLEVENT_LISTBOX_SELECT :
110                 {
111                     // First send an event that tells the listeners of a
112                     // modified selection.  The active descendant event is
113                     // send after that so that the receiving AT has time to
114                     // read the text or name of the active child.
115                     NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
116                     if ( getListBox() && getListBox()->HasFocus() )
117                     {
118                         SvLBoxEntry* pEntry = static_cast< SvLBoxEntry* >( rVclWindowEvent.GetData() );
119                         if ( pEntry )
120                         {
121                             Reference< XAccessible > xChild = new AccessibleListBoxEntry( *getListBox(), pEntry, this );
122                             uno::Any aOldValue, aNewValue;
123                             aNewValue <<= xChild;
124                             NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldValue, aNewValue );
125                         }
126                     }
127                     break;
128 
129                 // --> OD 2009-04-01 #i92103#
130                 case VCLEVENT_ITEM_EXPANDED :
131                 case VCLEVENT_ITEM_COLLAPSED :
132                 {
133                     SvLBoxEntry* pEntry = static_cast< SvLBoxEntry* >( rVclWindowEvent.GetData() );
134                     if ( pEntry )
135                     {
136                         AccessibleListBoxEntry* pAccListBoxEntry =
137                             new AccessibleListBoxEntry( *getListBox(), pEntry, this );
138                         Reference< XAccessible > xChild = pAccListBoxEntry;
139                         const short nAccEvent =
140                                 ( rVclWindowEvent.GetId() == VCLEVENT_ITEM_EXPANDED )
141                                 ? AccessibleEventId::LISTBOX_ENTRY_EXPANDED
142                                 : AccessibleEventId::LISTBOX_ENTRY_COLLAPSED;
143                         uno::Any aListBoxEntry;
144                         aListBoxEntry <<= xChild;
145                         NotifyAccessibleEvent( nAccEvent, Any(), aListBoxEntry );
146                         if ( getListBox() && getListBox()->HasFocus() )
147                         {
148                             NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, Any(), aListBoxEntry );
149                         }
150                     }
151                     break;
152                 }
153                 // <--
154                 }
155                 default:
156                     VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent);
157             }
158         }
159     }
160     // -----------------------------------------------------------------------------
161     void AccessibleListBox::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent )
162     {
163         switch ( rVclWindowEvent.GetId() )
164         {
165             case VCLEVENT_WINDOW_SHOW:
166             case VCLEVENT_WINDOW_HIDE:
167             {
168             }
169             break;
170             default:
171             {
172                 VCLXAccessibleComponent::ProcessWindowChildEvent( rVclWindowEvent );
173             }
174             break;
175         }
176     }
177 
178     // -----------------------------------------------------------------------------
179     // XComponent
180     // -----------------------------------------------------------------------------
181     void SAL_CALL AccessibleListBox::disposing()
182     {
183         ::osl::MutexGuard aGuard( m_aMutex );
184 
185         VCLXAccessibleComponent::disposing();
186         m_xParent = NULL;
187     }
188     // -----------------------------------------------------------------------------
189     // XServiceInfo
190     // -----------------------------------------------------------------------------
191     ::rtl::OUString SAL_CALL AccessibleListBox::getImplementationName() throw(RuntimeException)
192     {
193         return getImplementationName_Static();
194     }
195     // -----------------------------------------------------------------------------
196     Sequence< ::rtl::OUString > SAL_CALL AccessibleListBox::getSupportedServiceNames() throw(RuntimeException)
197     {
198         return getSupportedServiceNames_Static();
199     }
200     // -----------------------------------------------------------------------------
201     sal_Bool SAL_CALL AccessibleListBox::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException)
202     {
203         Sequence< ::rtl::OUString > aSupported( getSupportedServiceNames() );
204         const ::rtl::OUString* pSupported = aSupported.getConstArray();
205         const ::rtl::OUString* pEnd = pSupported + aSupported.getLength();
206         for ( ; pSupported != pEnd && !pSupported->equals(_rServiceName); ++pSupported )
207             ;
208 
209         return pSupported != pEnd;
210     }
211     // -----------------------------------------------------------------------------
212     // XServiceInfo - static methods
213     // -----------------------------------------------------------------------------
214     Sequence< ::rtl::OUString > AccessibleListBox::getSupportedServiceNames_Static(void) throw( RuntimeException )
215     {
216         Sequence< ::rtl::OUString > aSupported(3);
217         aSupported[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.accessibility.AccessibleContext") );
218         aSupported[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.accessibility.AccessibleComponent") );
219         aSupported[2] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.AccessibleTreeListBox") );
220         return aSupported;
221     }
222     // -----------------------------------------------------------------------------
223     ::rtl::OUString AccessibleListBox::getImplementationName_Static(void) throw( RuntimeException )
224     {
225         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.svtools.AccessibleTreeListBox") );
226     }
227     // -----------------------------------------------------------------------------
228     // XAccessible
229     // -----------------------------------------------------------------------------
230     Reference< XAccessibleContext > SAL_CALL AccessibleListBox::getAccessibleContext(  ) throw (RuntimeException)
231     {
232         ensureAlive();
233         return this;
234     }
235     // -----------------------------------------------------------------------------
236     // XAccessibleContext
237     // -----------------------------------------------------------------------------
238     sal_Int32 SAL_CALL AccessibleListBox::getAccessibleChildCount(  ) throw (RuntimeException)
239     {
240         ::comphelper::OExternalLockGuard aGuard( this );
241 
242         ensureAlive();
243 
244         sal_Int32 nCount = 0;
245         SvTreeListBox* pSvTreeListBox = getListBox();
246         if ( pSvTreeListBox )
247             nCount = pSvTreeListBox->GetLevelChildCount( NULL );
248 
249         return nCount;
250     }
251     // -----------------------------------------------------------------------------
252     Reference< XAccessible > SAL_CALL AccessibleListBox::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException,RuntimeException)
253     {
254         ::comphelper::OExternalLockGuard aGuard( this );
255 
256         ensureAlive();
257         SvLBoxEntry* pEntry = getListBox()->GetEntry(i);
258         if ( !pEntry )
259             throw IndexOutOfBoundsException();
260 
261         return new AccessibleListBoxEntry( *getListBox(), pEntry, this );
262     }
263     // -----------------------------------------------------------------------------
264     Reference< XAccessible > SAL_CALL AccessibleListBox::getAccessibleParent(  ) throw (RuntimeException)
265     {
266         ::osl::MutexGuard aGuard( m_aMutex );
267 
268         ensureAlive();
269         return m_xParent;
270     }
271     // -----------------------------------------------------------------------------
272     sal_Int16 SAL_CALL AccessibleListBox::getAccessibleRole(  ) throw (RuntimeException)
273     {
274         return AccessibleRole::TREE;
275     }
276     // -----------------------------------------------------------------------------
277     ::rtl::OUString SAL_CALL AccessibleListBox::getAccessibleDescription(  ) throw (RuntimeException)
278     {
279         ::comphelper::OExternalLockGuard aGuard( this );
280 
281         ensureAlive();
282         return getListBox()->GetAccessibleDescription();
283     }
284     // -----------------------------------------------------------------------------
285     ::rtl::OUString SAL_CALL AccessibleListBox::getAccessibleName(  ) throw (RuntimeException)
286     {
287         ::comphelper::OExternalLockGuard aGuard( this );
288 
289         ensureAlive();
290         return getListBox()->GetAccessibleName();
291     }
292     // -----------------------------------------------------------------------------
293     // XAccessibleSelection
294     // -----------------------------------------------------------------------------
295     void SAL_CALL AccessibleListBox::selectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
296     {
297         ::comphelper::OExternalLockGuard aGuard( this );
298 
299         ensureAlive();
300 
301         SvLBoxEntry* pEntry = getListBox()->GetEntry( nChildIndex );
302         if ( !pEntry )
303             throw IndexOutOfBoundsException();
304 
305         getListBox()->Select( pEntry, sal_True );
306     }
307     // -----------------------------------------------------------------------------
308     sal_Bool SAL_CALL AccessibleListBox::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
309     {
310         ::comphelper::OExternalLockGuard aGuard( this );
311 
312         ensureAlive();
313 
314         SvLBoxEntry* pEntry = getListBox()->GetEntry( nChildIndex );
315         if ( !pEntry )
316             throw IndexOutOfBoundsException();
317 
318         return getListBox()->IsSelected( pEntry );
319     }
320     // -----------------------------------------------------------------------------
321     void SAL_CALL AccessibleListBox::clearAccessibleSelection(  ) throw (RuntimeException)
322     {
323         ::comphelper::OExternalLockGuard aGuard( this );
324 
325         ensureAlive();
326 
327         sal_Int32 i, nCount = 0;
328         nCount = getListBox()->GetLevelChildCount( NULL );
329         for ( i = 0; i < nCount; ++i )
330         {
331             SvLBoxEntry* pEntry = getListBox()->GetEntry( i );
332             if ( getListBox()->IsSelected( pEntry ) )
333                 getListBox()->Select( pEntry, sal_False );
334         }
335     }
336     // -----------------------------------------------------------------------------
337     void SAL_CALL AccessibleListBox::selectAllAccessibleChildren(  ) throw (RuntimeException)
338     {
339         ::comphelper::OExternalLockGuard aGuard( this );
340 
341         ensureAlive();
342 
343         sal_Int32 i, nCount = 0;
344         nCount = getListBox()->GetLevelChildCount( NULL );
345         for ( i = 0; i < nCount; ++i )
346         {
347             SvLBoxEntry* pEntry = getListBox()->GetEntry( i );
348             if ( !getListBox()->IsSelected( pEntry ) )
349                 getListBox()->Select( pEntry, sal_True );
350         }
351     }
352     // -----------------------------------------------------------------------------
353     sal_Int32 SAL_CALL AccessibleListBox::getSelectedAccessibleChildCount(  ) throw (RuntimeException)
354     {
355         ::comphelper::OExternalLockGuard aGuard( this );
356 
357         ensureAlive();
358 
359         sal_Int32 i, nSelCount = 0, nCount = 0;
360         nCount = getListBox()->GetLevelChildCount( NULL );
361         for ( i = 0; i < nCount; ++i )
362         {
363             SvLBoxEntry* pEntry = getListBox()->GetEntry( i );
364             if ( getListBox()->IsSelected( pEntry ) )
365                 ++nSelCount;
366         }
367 
368         return nSelCount;
369     }
370     // -----------------------------------------------------------------------------
371     Reference< XAccessible > SAL_CALL AccessibleListBox::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
372     {
373         ::comphelper::OExternalLockGuard aGuard( this );
374 
375         ensureAlive();
376 
377         if ( nSelectedChildIndex < 0 || nSelectedChildIndex >= getSelectedAccessibleChildCount() )
378             throw IndexOutOfBoundsException();
379 
380         Reference< XAccessible > xChild;
381         sal_Int32 i, nSelCount = 0, nCount = 0;
382         nCount = getListBox()->GetLevelChildCount( NULL );
383         for ( i = 0; i < nCount; ++i )
384         {
385             SvLBoxEntry* pEntry = getListBox()->GetEntry( i );
386             if ( getListBox()->IsSelected( pEntry ) )
387                 ++nSelCount;
388 
389             if ( nSelCount == ( nSelectedChildIndex + 1 ) )
390             {
391                 xChild = new AccessibleListBoxEntry( *getListBox(), pEntry, this );
392                 break;
393             }
394         }
395 
396         return xChild;
397     }
398     // -----------------------------------------------------------------------------
399     void SAL_CALL AccessibleListBox::deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
400     {
401         ::comphelper::OExternalLockGuard aGuard( this );
402 
403         ensureAlive();
404 
405         SvLBoxEntry* pEntry = getListBox()->GetEntry( nSelectedChildIndex );
406         if ( !pEntry )
407             throw IndexOutOfBoundsException();
408 
409         getListBox()->Select( pEntry, sal_False );
410     }
411     // -----------------------------------------------------------------------------
412     void AccessibleListBox::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
413     {
414         VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet );
415         if ( getListBox() && isAlive() )
416         {
417             rStateSet.AddState( AccessibleStateType::FOCUSABLE );
418             rStateSet.AddState( AccessibleStateType::MANAGES_DESCENDANTS );
419             if ( getListBox()->GetSelectionMode() == MULTIPLE_SELECTION )
420                 rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE );
421         }
422     }
423 
424 
425 //........................................................................
426 }// namespace accessibility
427 //........................................................................
428 
429