xref: /AOO41X/main/accessibility/source/standard/vclxaccessibletabcontrol.cxx (revision 41163fb6bc5f228f840590e3b299c791cded5b6e)
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/standard/vclxaccessibletabcontrol.hxx>
27 #include <accessibility/standard/vclxaccessibletabpage.hxx>
28 
29 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
30 #include <com/sun/star/accessibility/AccessibleRole.hpp>
31 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
32 #include <unotools/accessiblestatesethelper.hxx>
33 #include <vcl/tabctrl.hxx>
34 #include <vcl/tabpage.hxx>
35 
36 #include <vector>
37 
38 using namespace ::com::sun::star;
39 using namespace ::com::sun::star::uno;
40 using namespace ::com::sun::star::lang;
41 using namespace ::com::sun::star::accessibility;
42 using namespace ::comphelper;
43 
44 
45 //  ----------------------------------------------------
46 //  class VCLXAccessibleTabControl
47 //  ----------------------------------------------------
48 
49 VCLXAccessibleTabControl::VCLXAccessibleTabControl( VCLXWindow* pVCLXWindow )
50     :VCLXAccessibleComponent( pVCLXWindow )
51 {
52     m_pTabControl = static_cast< TabControl* >( GetWindow() );
53 
54     if ( m_pTabControl )
55         m_aAccessibleChildren.assign( m_pTabControl->GetPageCount(), Reference< XAccessible >() );
56 }
57 
58 // -----------------------------------------------------------------------------
59 
60 VCLXAccessibleTabControl::~VCLXAccessibleTabControl()
61 {
62 }
63 
64 // -----------------------------------------------------------------------------
65 
66 void VCLXAccessibleTabControl::UpdateFocused()
67 {
68     for ( sal_uInt32 i = 0; i < m_aAccessibleChildren.size(); ++i )
69     {
70         Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
71         if ( xChild.is() )
72         {
73             VCLXAccessibleTabPage* pVCLXAccessibleTabPage = static_cast< VCLXAccessibleTabPage* >( xChild.get() );
74             if ( pVCLXAccessibleTabPage )
75                 pVCLXAccessibleTabPage->SetFocused( pVCLXAccessibleTabPage->IsFocused() );
76         }
77     }
78 }
79 
80 // -----------------------------------------------------------------------------
81 
82 void VCLXAccessibleTabControl::UpdateSelected( sal_Int32 i, bool bSelected )
83 {
84     //NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
85 
86     if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() )
87     {
88         Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
89         if ( xChild.is() )
90         {
91             VCLXAccessibleTabPage* pVCLXAccessibleTabPage = static_cast< VCLXAccessibleTabPage* >( xChild.get() );
92             if ( pVCLXAccessibleTabPage )
93                 pVCLXAccessibleTabPage->SetSelected( bSelected );
94         }
95     }
96 }
97 
98 // -----------------------------------------------------------------------------
99 
100 void VCLXAccessibleTabControl::UpdatePageText( sal_Int32 i )
101 {
102     if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() )
103     {
104         Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
105         if ( xChild.is() )
106         {
107             VCLXAccessibleTabPage* pVCLXAccessibleTabPage = static_cast< VCLXAccessibleTabPage* >( xChild.get() );
108             if ( pVCLXAccessibleTabPage )
109                 pVCLXAccessibleTabPage->SetPageText( pVCLXAccessibleTabPage->GetPageText() );
110         }
111     }
112 }
113 
114 // -----------------------------------------------------------------------------
115 
116 void VCLXAccessibleTabControl::UpdateTabPage( sal_Int32 i, bool bNew )
117 {
118     if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() )
119     {
120         Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
121         if ( xChild.is() )
122         {
123             VCLXAccessibleTabPage* pVCLXAccessibleTabPage = static_cast< VCLXAccessibleTabPage* >( xChild.get() );
124             if ( pVCLXAccessibleTabPage )
125                 pVCLXAccessibleTabPage->Update( bNew );
126         }
127     }
128 }
129 
130 // -----------------------------------------------------------------------------
131 
132 void VCLXAccessibleTabControl::InsertChild( sal_Int32 i )
133 {
134     if ( i >= 0 && i <= (sal_Int32)m_aAccessibleChildren.size() )
135     {
136         // insert entry in child list
137         m_aAccessibleChildren.insert( m_aAccessibleChildren.begin() + i, Reference< XAccessible >() );
138 
139         // send accessible child event
140         Reference< XAccessible > xChild( getAccessibleChild( i ) );
141         if ( xChild.is() )
142         {
143             Any aOldValue, aNewValue;
144             aNewValue <<= xChild;
145             NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
146         }
147     }
148 }
149 
150 // -----------------------------------------------------------------------------
151 
152 void VCLXAccessibleTabControl::RemoveChild( sal_Int32 i )
153 {
154     if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() )
155     {
156         // get the accessible of the removed page
157         Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
158 
159         // remove entry in child list
160         m_aAccessibleChildren.erase( m_aAccessibleChildren.begin() + i );
161 
162         // send accessible child event
163         if ( xChild.is() )
164         {
165             Any aOldValue, aNewValue;
166             aOldValue <<= xChild;
167             NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
168 
169             Reference< XComponent > xComponent( xChild, UNO_QUERY );
170             if ( xComponent.is() )
171                 xComponent->dispose();
172         }
173     }
174 }
175 
176 // -----------------------------------------------------------------------------
177 
178 void VCLXAccessibleTabControl::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
179 {
180     switch ( rVclWindowEvent.GetId() )
181     {
182         case VCLEVENT_TABPAGE_ACTIVATE:
183         case VCLEVENT_TABPAGE_DEACTIVATE:
184         {
185             if ( m_pTabControl )
186             {
187                 sal_uInt16 nPageId = (sal_uInt16)(sal_IntPtr) rVclWindowEvent.GetData();
188                 sal_uInt16 nPagePos = m_pTabControl->GetPagePos( nPageId );
189                 UpdateFocused();
190                 UpdateSelected( nPagePos, rVclWindowEvent.GetId() == VCLEVENT_TABPAGE_ACTIVATE );
191             }
192         }
193         break;
194         case VCLEVENT_TABPAGE_PAGETEXTCHANGED:
195         {
196             if ( m_pTabControl )
197             {
198                 sal_uInt16 nPageId = (sal_uInt16)(sal_IntPtr) rVclWindowEvent.GetData();
199                 sal_uInt16 nPagePos = m_pTabControl->GetPagePos( nPageId );
200                 UpdatePageText( nPagePos );
201             }
202         }
203         break;
204         case VCLEVENT_TABPAGE_INSERTED:
205         {
206             if ( m_pTabControl )
207             {
208                 sal_uInt16 nPageId = (sal_uInt16)(sal_IntPtr) rVclWindowEvent.GetData();
209                 sal_uInt16 nPagePos = m_pTabControl->GetPagePos( nPageId );
210                 InsertChild( nPagePos );
211             }
212         }
213         break;
214         case VCLEVENT_TABPAGE_REMOVED:
215         {
216             if ( m_pTabControl )
217             {
218                 sal_uInt16 nPageId = (sal_uInt16)(sal_IntPtr) rVclWindowEvent.GetData();
219                 for ( sal_Int32 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i )
220                 {
221                     Reference< XAccessible > xChild( getAccessibleChild( i ) );
222                     if ( xChild.is() )
223                     {
224                         VCLXAccessibleTabPage* pVCLXAccessibleTabPage = static_cast< VCLXAccessibleTabPage* >( xChild.get() );
225                         if ( pVCLXAccessibleTabPage && pVCLXAccessibleTabPage->GetPageId() == nPageId )
226                         {
227                             RemoveChild( i );
228                             break;
229                         }
230                     }
231                 }
232             }
233         }
234         break;
235         case VCLEVENT_TABPAGE_REMOVEDALL:
236         {
237             for ( sal_Int32 i = m_aAccessibleChildren.size() - 1; i >= 0; --i )
238                 RemoveChild( i );
239         }
240         break;
241         case VCLEVENT_WINDOW_GETFOCUS:
242         case VCLEVENT_WINDOW_LOSEFOCUS:
243         {
244             UpdateFocused();
245         }
246         break;
247         case VCLEVENT_OBJECT_DYING:
248         {
249             if ( m_pTabControl )
250             {
251                 m_pTabControl = NULL;
252 
253                 // dispose all tab pages
254                 for ( sal_uInt32 i = 0; i < m_aAccessibleChildren.size(); ++i )
255                 {
256                     Reference< XComponent > xComponent( m_aAccessibleChildren[i], UNO_QUERY );
257                     if ( xComponent.is() )
258                         xComponent->dispose();
259                 }
260                 m_aAccessibleChildren.clear();
261             }
262 
263             VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
264         }
265         break;
266         default:
267             VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
268    }
269 }
270 
271 // -----------------------------------------------------------------------------
272 
273 void VCLXAccessibleTabControl::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent )
274 {
275     switch ( rVclWindowEvent.GetId() )
276     {
277         case VCLEVENT_WINDOW_SHOW:
278         case VCLEVENT_WINDOW_HIDE:
279         {
280             if ( m_pTabControl )
281             {
282                 Window* pChild = static_cast< Window* >( rVclWindowEvent.GetData() );
283                 if ( pChild && pChild->GetType() == WINDOW_TABPAGE )
284                 {
285                     for ( sal_Int32 i = 0, nCount = m_pTabControl->GetPageCount(); i < nCount; ++i )
286                     {
287                         sal_uInt16 nPageId = m_pTabControl->GetPageId( (sal_uInt16)i );
288                         TabPage* pTabPage = m_pTabControl->GetTabPage( nPageId );
289                         if ( pTabPage == (TabPage*) pChild )
290                             UpdateTabPage( i, rVclWindowEvent.GetId() == VCLEVENT_WINDOW_SHOW );
291                     }
292                 }
293             }
294         }
295         break;
296         default:
297             VCLXAccessibleComponent::ProcessWindowChildEvent( rVclWindowEvent );
298     }
299 }
300 
301 
302 // -----------------------------------------------------------------------------
303 
304 void VCLXAccessibleTabControl::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
305 {
306     VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet );
307 
308     if ( m_pTabControl )
309         rStateSet.AddState( AccessibleStateType::FOCUSABLE );
310 }
311 
312 // -----------------------------------------------------------------------------
313 // XInterface
314 // -----------------------------------------------------------------------------
315 
316 IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleTabControl, VCLXAccessibleComponent, VCLXAccessibleTabControl_BASE )
317 
318 // -----------------------------------------------------------------------------
319 // XTypeProvider
320 // -----------------------------------------------------------------------------
321 
322 IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleTabControl, VCLXAccessibleComponent, VCLXAccessibleTabControl_BASE )
323 
324 // -----------------------------------------------------------------------------
325 // XComponent
326 // -----------------------------------------------------------------------------
327 
328 void VCLXAccessibleTabControl::disposing()
329 {
330     VCLXAccessibleComponent::disposing();
331 
332     if ( m_pTabControl )
333     {
334         m_pTabControl = NULL;
335 
336         // dispose all tab pages
337         for ( sal_uInt32 i = 0; i < m_aAccessibleChildren.size(); ++i )
338         {
339             Reference< XComponent > xComponent( m_aAccessibleChildren[i], UNO_QUERY );
340             if ( xComponent.is() )
341                 xComponent->dispose();
342         }
343         m_aAccessibleChildren.clear();
344     }
345 }
346 
347 // -----------------------------------------------------------------------------
348 // XServiceInfo
349 // -----------------------------------------------------------------------------
350 
351 ::rtl::OUString VCLXAccessibleTabControl::getImplementationName() throw (RuntimeException)
352 {
353     return ::rtl::OUString::createFromAscii( "com.sun.star.comp.toolkit.AccessibleTabControl" );
354 }
355 
356 // -----------------------------------------------------------------------------
357 
358 Sequence< ::rtl::OUString > VCLXAccessibleTabControl::getSupportedServiceNames() throw (RuntimeException)
359 {
360     Sequence< ::rtl::OUString > aNames(1);
361     aNames[0] = ::rtl::OUString::createFromAscii( "com.sun.star.awt.AccessibleTabControl" );
362     return aNames;
363 }
364 
365 // -----------------------------------------------------------------------------
366 // XAccessibleContext
367 // -----------------------------------------------------------------------------
368 
369 sal_Int32 VCLXAccessibleTabControl::getAccessibleChildCount() throw (RuntimeException)
370 {
371     OExternalLockGuard aGuard( this );
372 
373     return m_aAccessibleChildren.size();
374 }
375 
376 // -----------------------------------------------------------------------------
377 
378 Reference< XAccessible > VCLXAccessibleTabControl::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException, RuntimeException)
379 {
380     OExternalLockGuard aGuard( this );
381 
382     if ( i < 0 || i >= getAccessibleChildCount() )
383         throw IndexOutOfBoundsException();
384 
385     Reference< XAccessible > xChild = m_aAccessibleChildren[i];
386     if ( !xChild.is() )
387     {
388         if ( m_pTabControl )
389         {
390             sal_uInt16 nPageId = m_pTabControl->GetPageId( (sal_uInt16)i );
391 
392             xChild = new VCLXAccessibleTabPage( m_pTabControl, nPageId );
393 
394             // insert into tab page list
395             m_aAccessibleChildren[i] = xChild;
396         }
397     }
398 
399     return xChild;
400 }
401 
402 // -----------------------------------------------------------------------------
403 
404 sal_Int16 VCLXAccessibleTabControl::getAccessibleRole(  ) throw (RuntimeException)
405 {
406     OExternalLockGuard aGuard( this );
407 
408     return AccessibleRole::PAGE_TAB_LIST;
409 }
410 
411 // -----------------------------------------------------------------------------
412 
413 ::rtl::OUString VCLXAccessibleTabControl::getAccessibleName(  ) throw (RuntimeException)
414 {
415     OExternalLockGuard aGuard( this );
416 
417     return ::rtl::OUString();
418 }
419 
420 // -----------------------------------------------------------------------------
421 // XAccessibleSelection
422 // -----------------------------------------------------------------------------
423 
424 void VCLXAccessibleTabControl::selectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
425 {
426     OExternalLockGuard aGuard( this );
427 
428     if ( nChildIndex < 0 || nChildIndex >= getAccessibleChildCount() )
429         throw IndexOutOfBoundsException();
430 
431     if ( m_pTabControl )
432         m_pTabControl->SelectTabPage( m_pTabControl->GetPageId( (sal_uInt16)nChildIndex ) );
433 }
434 
435 // -----------------------------------------------------------------------------
436 
437 sal_Bool VCLXAccessibleTabControl::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
438 {
439     OExternalLockGuard aGuard( this );
440 
441     if ( nChildIndex < 0 || nChildIndex >= getAccessibleChildCount() )
442         throw IndexOutOfBoundsException();
443 
444     sal_Bool bSelected = sal_False;
445     if ( m_pTabControl && m_pTabControl->GetCurPageId() == m_pTabControl->GetPageId( (sal_uInt16)nChildIndex ) )
446         bSelected = sal_True;
447 
448     return bSelected;
449 }
450 
451 // -----------------------------------------------------------------------------
452 
453 void VCLXAccessibleTabControl::clearAccessibleSelection(  ) throw (RuntimeException)
454 {
455     // This method makes no sense in a tab control, and so does nothing.
456 }
457 
458 // -----------------------------------------------------------------------------
459 
460 void VCLXAccessibleTabControl::selectAllAccessibleChildren(  ) throw (RuntimeException)
461 {
462     OExternalLockGuard aGuard( this );
463 
464     selectAccessibleChild( 0 );
465 }
466 
467 // -----------------------------------------------------------------------------
468 
469 sal_Int32 VCLXAccessibleTabControl::getSelectedAccessibleChildCount(  ) throw (RuntimeException)
470 {
471     OExternalLockGuard aGuard( this );
472 
473     return 1;
474 }
475 
476 // -----------------------------------------------------------------------------
477 
478 Reference< XAccessible > VCLXAccessibleTabControl::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
479 {
480     OExternalLockGuard aGuard( this );
481 
482     if ( nSelectedChildIndex < 0 || nSelectedChildIndex >= getSelectedAccessibleChildCount() )
483         throw IndexOutOfBoundsException();
484 
485     Reference< XAccessible > xChild;
486 
487     for ( sal_Int32 i = 0, j = 0, nCount = getAccessibleChildCount(); i < nCount; i++ )
488     {
489         if ( isAccessibleChildSelected( i ) && ( j++ == nSelectedChildIndex ) )
490         {
491             xChild = getAccessibleChild( i );
492             break;
493         }
494     }
495 
496     return xChild;
497 }
498 
499 // -----------------------------------------------------------------------------
500 
501 void VCLXAccessibleTabControl::deselectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
502 {
503     OExternalLockGuard aGuard( this );
504 
505     if ( nChildIndex < 0 || nChildIndex >= getAccessibleChildCount() )
506         throw IndexOutOfBoundsException();
507 
508     // This method makes no sense in a tab control, and so does nothing.
509 }
510 
511 // -----------------------------------------------------------------------------
512