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