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 : #include <string.h>
20 :
21 : #include <accessibility/standard/vclxaccessibletoolbox.hxx>
22 : #include <accessibility/standard/vclxaccessibletoolboxitem.hxx>
23 : #include <toolkit/helper/convert.hxx>
24 :
25 : #include <unotools/accessiblestatesethelper.hxx>
26 : #include <com/sun/star/accessibility/AccessibleEventId.hpp>
27 : #include <com/sun/star/accessibility/AccessibleStateType.hpp>
28 : #include <com/sun/star/lang/XUnoTunnel.hpp>
29 : #include <vcl/toolbox.hxx>
30 : #include <comphelper/accessiblewrapper.hxx>
31 : #include <comphelper/processfactory.hxx>
32 :
33 : using namespace ::comphelper;
34 : using namespace ::com::sun::star;
35 : using namespace ::com::sun::star::uno;
36 : using namespace ::com::sun::star::lang;
37 : using namespace ::com::sun::star::accessibility;
38 :
39 : namespace
40 : {
41 :
42 : // = OToolBoxWindowItemContext
43 :
44 : /** XAccessibleContext implementation for a toolbox item which is represented by a VCL Window
45 : */
46 16 : class OToolBoxWindowItemContext : public OAccessibleContextWrapper
47 : {
48 : sal_Int32 m_nIndexInParent;
49 : public:
50 8 : OToolBoxWindowItemContext(sal_Int32 _nIndexInParent,
51 : const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& _rxContext,
52 : const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >& _rxInnerAccessibleContext,
53 : const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& _rxOwningAccessible,
54 : const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& _rxParentAccessible
55 : ) : OAccessibleContextWrapper(
56 : _rxContext,
57 : _rxInnerAccessibleContext,
58 : _rxOwningAccessible,
59 : _rxParentAccessible )
60 8 : ,m_nIndexInParent(_nIndexInParent)
61 : {
62 8 : }
63 : virtual sal_Int32 SAL_CALL getAccessibleIndexInParent( ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
64 : };
65 :
66 :
67 1 : sal_Int32 SAL_CALL OToolBoxWindowItemContext::getAccessibleIndexInParent( ) throw (::com::sun::star::uno::RuntimeException, std::exception)
68 : {
69 1 : ::osl::MutexGuard aGuard( m_aMutex );
70 1 : return m_nIndexInParent;
71 : }
72 :
73 :
74 : // = OToolBoxWindowItem
75 :
76 : typedef ::cppu::ImplHelper1 < XUnoTunnel
77 : > OToolBoxWindowItem_Base;
78 :
79 : /** XAccessible implementation for a toolbox item which is represented by a VCL Window
80 : */
81 0 : class OToolBoxWindowItem
82 : :public OAccessibleWrapper
83 : ,public OToolBoxWindowItem_Base
84 : {
85 : private:
86 : sal_Int32 m_nIndexInParent;
87 :
88 : public:
89 0 : inline sal_Int32 getIndexInParent() const { return m_nIndexInParent; }
90 0 : inline void setIndexInParent( sal_Int32 _nNewIndex ) { m_nIndexInParent = _nNewIndex; }
91 :
92 : static bool isWindowItem( const Reference< XAccessible >& _rxAcc, OToolBoxWindowItem** /* [out] */ _ppImplementation = NULL );
93 :
94 : public:
95 12 : OToolBoxWindowItem(sal_Int32 _nIndexInParent,
96 : const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& _rxContext,
97 : const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& _rxInnerAccessible,
98 : const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& _rxParentAccessible
99 : ) : OAccessibleWrapper(
100 : _rxContext,
101 : _rxInnerAccessible,
102 : _rxParentAccessible)
103 12 : ,m_nIndexInParent(_nIndexInParent)
104 : {
105 12 : }
106 :
107 : protected:
108 : // XInterface
109 : DECLARE_XINTERFACE( )
110 : DECLARE_XTYPEPROVIDER( )
111 :
112 : // OAccessibleWrapper
113 : virtual OAccessibleContextWrapper* createAccessibleContext(
114 : const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >& _rxInnerContext
115 : ) SAL_OVERRIDE;
116 :
117 : // XUnoTunnel
118 : virtual sal_Int64 SAL_CALL getSomething( const Sequence< sal_Int8 >& aIdentifier ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
119 : static Sequence< sal_Int8 > getUnoTunnelImplementationId();
120 : };
121 :
122 727 : IMPLEMENT_FORWARD_XINTERFACE2( OToolBoxWindowItem, OAccessibleWrapper, OToolBoxWindowItem_Base )
123 0 : IMPLEMENT_FORWARD_XTYPEPROVIDER2( OToolBoxWindowItem, OAccessibleWrapper, OToolBoxWindowItem_Base )
124 :
125 8 : OAccessibleContextWrapper* OToolBoxWindowItem::createAccessibleContext(
126 : const Reference< XAccessibleContext >& _rxInnerContext )
127 : {
128 8 : return new OToolBoxWindowItemContext( m_nIndexInParent, getComponentContext(), _rxInnerContext, this, getParent() );
129 : }
130 :
131 796 : bool OToolBoxWindowItem::isWindowItem( const Reference< XAccessible >& _rxAcc, OToolBoxWindowItem** /* [out] */ _ppImplementation )
132 : {
133 796 : OToolBoxWindowItem* pImplementation = NULL;
134 :
135 796 : Reference< XUnoTunnel > xTunnel( _rxAcc, UNO_QUERY );
136 796 : if ( xTunnel.is() )
137 0 : pImplementation = reinterpret_cast< OToolBoxWindowItem* >( xTunnel->getSomething( getUnoTunnelImplementationId() ) );
138 :
139 796 : if ( _ppImplementation )
140 796 : *_ppImplementation = pImplementation;
141 :
142 796 : return NULL != pImplementation;
143 : }
144 :
145 0 : Sequence< sal_Int8 > OToolBoxWindowItem::getUnoTunnelImplementationId()
146 : {
147 : static ::cppu::OImplementationId * pId = 0;
148 0 : if (! pId)
149 : {
150 0 : ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
151 0 : if (! pId)
152 : {
153 0 : static ::cppu::OImplementationId aId;
154 0 : pId = &aId;
155 0 : }
156 : }
157 0 : return pId->getImplementationId();
158 : }
159 :
160 0 : sal_Int64 SAL_CALL OToolBoxWindowItem::getSomething( const Sequence< sal_Int8 >& _rId ) throw (RuntimeException, std::exception)
161 : {
162 0 : if ( ( 16 == _rId.getLength() )
163 0 : && ( 0 == memcmp( getUnoTunnelImplementationId().getConstArray(), _rId.getConstArray(), 16 ) )
164 : )
165 0 : return reinterpret_cast< sal_Int64>( this );
166 :
167 0 : return 0;
168 : }
169 : }
170 :
171 : // VCLXAccessibleToolBox
172 :
173 12 : VCLXAccessibleToolBox::VCLXAccessibleToolBox( VCLXWindow* pVCLXWindow ) :
174 :
175 12 : VCLXAccessibleComponent( pVCLXWindow )
176 :
177 : {
178 12 : }
179 :
180 24 : VCLXAccessibleToolBox::~VCLXAccessibleToolBox()
181 : {
182 24 : }
183 :
184 3 : VCLXAccessibleToolBoxItem* VCLXAccessibleToolBox::GetItem_Impl( sal_Int32 _nPos, bool _bMustHaveFocus )
185 : {
186 3 : VCLXAccessibleToolBoxItem* pItem = NULL;
187 3 : VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
188 3 : if ( pToolBox && ( !_bMustHaveFocus || pToolBox->HasFocus() ) )
189 : {
190 3 : ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.find( _nPos );
191 : // returns only toolbox buttons, not windows
192 3 : if ( aIter != m_aAccessibleChildren.end() && aIter->second.is())
193 3 : pItem = static_cast< VCLXAccessibleToolBoxItem* >( aIter->second.get() );
194 : }
195 :
196 3 : return pItem;
197 : }
198 :
199 1 : void VCLXAccessibleToolBox::UpdateFocus_Impl()
200 : {
201 1 : VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
202 1 : if( !pToolBox )
203 1 : return;
204 :
205 : // submit events only if toolbox has the focus to avoid sending events due to mouse move
206 1 : bool bHasFocus = false;
207 1 : if ( pToolBox->HasFocus() )
208 1 : bHasFocus = true;
209 : else
210 : {
211 : // check for subtoolbar, i.e. check if our parent is a toolbar
212 0 : ToolBox* pToolBoxParent = dynamic_cast< ToolBox* >( pToolBox->GetParent() );
213 : // subtoolbars never get the focus as key input is just forwarded, so check if the parent toolbar has it
214 0 : if ( pToolBoxParent && pToolBoxParent->HasFocus() )
215 0 : bHasFocus = true;
216 : }
217 :
218 1 : if ( bHasFocus )
219 : {
220 1 : sal_uInt16 nHighlightItemId = pToolBox->GetHighlightItemId();
221 1 : sal_uInt16 nFocusCount = 0;
222 12 : for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
223 8 : aIter != m_aAccessibleChildren.end(); ++aIter )
224 : {
225 3 : sal_uInt16 nItemId = pToolBox->GetItemId( (sal_uInt16)aIter->first );
226 :
227 3 : if ( aIter->second.is() )
228 : {
229 : VCLXAccessibleToolBoxItem* pItem =
230 3 : static_cast< VCLXAccessibleToolBoxItem* >( aIter->second.get() );
231 3 : if ( pItem->HasFocus() && nItemId != nHighlightItemId )
232 : {
233 : // reset the old focused item
234 0 : pItem->SetFocus( false );
235 0 : nFocusCount++;
236 : }
237 3 : if ( nItemId == nHighlightItemId )
238 : {
239 : // set the new focused item
240 1 : pItem->SetFocus( true );
241 1 : nFocusCount++;
242 : }
243 : }
244 : // both items changed?
245 3 : if ( nFocusCount > 1 )
246 0 : break;
247 : }
248 1 : }
249 : }
250 :
251 0 : void VCLXAccessibleToolBox::ReleaseFocus_Impl( sal_Int32 _nPos )
252 : {
253 0 : VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
254 0 : if ( pToolBox ) // #107124#, do not check for focus because this message is also handled in losefocus
255 : {
256 0 : ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.find( _nPos );
257 0 : if ( aIter != m_aAccessibleChildren.end() && aIter->second.is() )
258 : {
259 : VCLXAccessibleToolBoxItem* pItem =
260 0 : static_cast< VCLXAccessibleToolBoxItem* >( aIter->second.get() );
261 0 : if ( pItem->HasFocus() )
262 0 : pItem->SetFocus( false );
263 : }
264 0 : }
265 0 : }
266 :
267 4 : void VCLXAccessibleToolBox::UpdateChecked_Impl( sal_Int32 _nPos )
268 : {
269 4 : VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
270 4 : if ( pToolBox )
271 : {
272 4 : sal_uInt16 nFocusId = pToolBox->GetItemId( (sal_uInt16)_nPos );
273 4 : VCLXAccessibleToolBoxItem* pFocusItem = NULL;
274 :
275 96 : for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
276 64 : aIter != m_aAccessibleChildren.end(); ++aIter )
277 : {
278 28 : sal_uInt16 nItemId = pToolBox->GetItemId( (sal_uInt16)aIter->first );
279 :
280 : VCLXAccessibleToolBoxItem* pItem =
281 28 : static_cast< VCLXAccessibleToolBoxItem* >( aIter->second.get() );
282 28 : pItem->SetChecked( pToolBox->IsItemChecked( nItemId ) );
283 28 : if ( nItemId == nFocusId )
284 4 : pFocusItem = pItem;
285 : }
286 : //Solution:If the position is not a child item,the focus should not be called
287 4 : if ( pFocusItem && (sal_uInt16)_nPos != TOOLBOX_ITEM_NOTFOUND )
288 4 : pFocusItem->SetFocus( true );
289 4 : }
290 4 : }
291 :
292 4 : void VCLXAccessibleToolBox::UpdateIndeterminate_Impl( sal_Int32 _nPos )
293 : {
294 4 : VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
295 4 : if ( pToolBox )
296 : {
297 4 : sal_uInt16 nItemId = pToolBox->GetItemId( (sal_uInt16)_nPos );
298 :
299 4 : ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.find( _nPos );
300 4 : if ( aIter != m_aAccessibleChildren.end() && aIter->second.is() )
301 : {
302 : VCLXAccessibleToolBoxItem* pItem =
303 4 : static_cast< VCLXAccessibleToolBoxItem* >( aIter->second.get() );
304 4 : if ( pItem )
305 4 : pItem->SetIndeterminate( pToolBox->GetItemState( nItemId ) == TRISTATE_INDET );
306 : }
307 4 : }
308 4 : }
309 :
310 796 : void VCLXAccessibleToolBox::implReleaseToolboxItem( ToolBoxItemsMap::iterator& _rMapPos,
311 : bool _bNotifyRemoval, bool _bDispose )
312 : {
313 796 : Reference< XAccessible > xItemAcc( _rMapPos->second );
314 796 : if ( !xItemAcc.is() )
315 796 : return;
316 :
317 796 : if ( _bNotifyRemoval )
318 : {
319 75 : NotifyAccessibleEvent( AccessibleEventId::CHILD, makeAny( xItemAcc ), Any() );
320 : }
321 :
322 796 : OToolBoxWindowItem* pWindowItem = NULL;
323 796 : if ( !OToolBoxWindowItem::isWindowItem( xItemAcc, &pWindowItem ) )
324 : {
325 796 : static_cast< VCLXAccessibleToolBoxItem* >( xItemAcc.get() )->ReleaseToolBox();
326 796 : if ( _bDispose )
327 796 : ::comphelper::disposeComponent( xItemAcc );
328 : }
329 : else
330 : {
331 0 : if ( _bDispose )
332 : {
333 0 : if ( pWindowItem )
334 : {
335 0 : Reference< XAccessibleContext > xContext( pWindowItem->getContextNoCreate() );
336 0 : ::comphelper::disposeComponent( xContext );
337 : }
338 : }
339 796 : }
340 : }
341 :
342 0 : void VCLXAccessibleToolBox::UpdateItem_Impl( sal_Int32 _nPos, bool _bItemAdded )
343 : {
344 0 : if ( _nPos < sal_Int32( m_aAccessibleChildren.size() ) )
345 : {
346 0 : UpdateAllItems_Impl();
347 0 : return;
348 : }
349 :
350 0 : VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
351 0 : if ( pToolBox )
352 : {
353 0 : if ( !_bItemAdded )
354 : { // the item was removed
355 : // -> destroy the old item
356 0 : ToolBoxItemsMap::iterator aItemPos = m_aAccessibleChildren.find( _nPos );
357 0 : if ( m_aAccessibleChildren.end() != aItemPos )
358 : {
359 0 : implReleaseToolboxItem( aItemPos, true, true );
360 0 : m_aAccessibleChildren.erase( aItemPos );
361 : }
362 : }
363 :
364 : // adjust the "index-in-parent"s
365 0 : ToolBoxItemsMap::iterator aIndexAdjust = m_aAccessibleChildren.upper_bound( _nPos );
366 0 : while ( m_aAccessibleChildren.end() != aIndexAdjust )
367 : {
368 0 : Reference< XAccessible > xItemAcc( aIndexAdjust->second );
369 :
370 0 : OToolBoxWindowItem* pWindowItem = NULL;
371 0 : if ( !OToolBoxWindowItem::isWindowItem( xItemAcc, &pWindowItem ) )
372 : {
373 0 : VCLXAccessibleToolBoxItem* pItem = static_cast< VCLXAccessibleToolBoxItem* >( xItemAcc.get() );
374 0 : if ( pItem )
375 : {
376 0 : sal_Int32 nIndex = pItem->getIndexInParent( );
377 0 : nIndex += (_bItemAdded ? +1 : -1);
378 0 : pItem->setIndexInParent( nIndex );
379 : }
380 : }
381 : else
382 : {
383 0 : if ( pWindowItem )
384 : {
385 0 : sal_Int32 nIndex = pWindowItem->getIndexInParent( );
386 0 : nIndex += (_bItemAdded ? +1 : -1);
387 0 : pWindowItem->setIndexInParent( nIndex );
388 : }
389 : }
390 :
391 0 : ++aIndexAdjust;
392 0 : }
393 :
394 0 : if ( _bItemAdded )
395 : {
396 : // TODO: we should make this dependent on the existence of event listeners
397 : // with the current implementation, we always create accessible object
398 0 : Any aNewChild = makeAny( getAccessibleChild( (sal_Int32)_nPos ) );
399 0 : NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), aNewChild );
400 : }
401 0 : }
402 : }
403 :
404 3 : void VCLXAccessibleToolBox::UpdateAllItems_Impl()
405 : {
406 3 : VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
407 3 : if ( pToolBox )
408 : {
409 : // deregister the old items
410 234 : for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
411 156 : aIter != m_aAccessibleChildren.end(); ++aIter )
412 : {
413 75 : implReleaseToolboxItem( aIter, true, true );
414 : }
415 3 : m_aAccessibleChildren.clear();
416 :
417 : // register the new items
418 3 : sal_uInt16 i, nCount = pToolBox->GetItemCount();
419 3 : for ( i = 0; i < nCount; ++i )
420 : {
421 0 : Any aNewValue;
422 0 : aNewValue <<= getAccessibleChild( (sal_Int32)i );;
423 0 : NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), aNewValue );
424 0 : }
425 3 : }
426 3 : }
427 :
428 0 : void VCLXAccessibleToolBox::UpdateCustomPopupItemp_Impl( vcl::Window* pWindow, bool bOpen )
429 : {
430 0 : VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
431 0 : if( pWindow && pToolBox )
432 : {
433 0 : const sal_uInt16 nDownItem = pToolBox->GetDownItemId();
434 0 : if ( !nDownItem )
435 : // Items with ItemId == 0 are not allowed in ToolBox, which means that currently no item is in down state.
436 : // Moreover, running GetItemPos with 0 could find a separator item if there is any.
437 0 : return;
438 :
439 0 : Reference< XAccessible > xChild( pWindow->GetAccessible() );
440 0 : if( xChild.is() )
441 : {
442 0 : Reference< XAccessible > xChildItem( getAccessibleChild( static_cast< sal_Int32 >( pToolBox->GetItemPos( nDownItem ) ) ) );
443 0 : VCLXAccessibleToolBoxItem* pItem = static_cast< VCLXAccessibleToolBoxItem* >( xChildItem.get() );
444 :
445 0 : pItem->SetChild( xChild );
446 0 : pItem->NotifyChildEvent( xChild, bOpen );
447 0 : }
448 0 : }
449 : }
450 :
451 0 : void VCLXAccessibleToolBox::UpdateItemName_Impl( sal_Int32 _nPos )
452 : {
453 0 : VCLXAccessibleToolBoxItem* pItem = GetItem_Impl( _nPos, false );
454 0 : if ( pItem )
455 0 : pItem->NameChanged();
456 0 : }
457 :
458 3 : void VCLXAccessibleToolBox::UpdateItemEnabled_Impl( sal_Int32 _nPos )
459 : {
460 3 : VCLXAccessibleToolBoxItem* pItem = GetItem_Impl( _nPos, false );
461 3 : if ( pItem )
462 3 : pItem->ToggleEnableState();
463 3 : }
464 :
465 6 : void VCLXAccessibleToolBox::HandleSubToolBarEvent( const VclWindowEvent& rVclWindowEvent, bool _bShow )
466 : {
467 6 : vcl::Window* pChildWindow = static_cast<vcl::Window *>(rVclWindowEvent.GetData());
468 6 : VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
469 6 : if ( pChildWindow
470 4 : && pToolBox
471 4 : && pToolBox == pChildWindow->GetParent()
472 6 : && pChildWindow->GetType() == WINDOW_TOOLBOX )
473 : {
474 0 : sal_Int32 nIndex = pToolBox->GetItemPos( pToolBox->GetCurItemId() );
475 0 : Reference< XAccessible > xItem = getAccessibleChild( nIndex );
476 0 : if ( xItem.is() )
477 : {
478 0 : Reference< XAccessible > xChild = pChildWindow->GetAccessible();
479 : VCLXAccessibleToolBoxItem* pItem =
480 0 : static_cast< VCLXAccessibleToolBoxItem* >( xItem.get() );
481 0 : pItem->SetChild( xChild );
482 0 : pItem->NotifyChildEvent( xChild, _bShow );
483 0 : }
484 6 : }
485 6 : }
486 :
487 0 : void VCLXAccessibleToolBox::ReleaseSubToolBox( ToolBox* _pSubToolBox )
488 : {
489 0 : VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
490 0 : if ( !pToolBox )
491 0 : return;
492 :
493 0 : sal_Int32 nIndex = pToolBox->GetItemPos( pToolBox->GetCurItemId() );
494 0 : if ( nIndex == SAL_MAX_UINT16 )
495 0 : return; // not found
496 :
497 0 : Reference< XAccessible > xItem = getAccessibleChild( nIndex );
498 0 : if ( !xItem.is() )
499 0 : return;
500 :
501 0 : Reference< XAccessible > xChild = _pSubToolBox->GetAccessible();
502 : VCLXAccessibleToolBoxItem* pItem =
503 0 : static_cast< VCLXAccessibleToolBoxItem* >( xItem.get() );
504 0 : if ( pItem->GetChild() == xChild )
505 : {
506 0 : pItem->SetChild( Reference< XAccessible >() );
507 0 : pItem->NotifyChildEvent( xChild, false );
508 0 : }
509 : }
510 :
511 11 : void VCLXAccessibleToolBox::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
512 : {
513 11 : VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet );
514 :
515 11 : VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
516 11 : if ( pToolBox )
517 : {
518 11 : rStateSet.AddState( AccessibleStateType::FOCUSABLE );
519 11 : if ( pToolBox->IsHorizontal() )
520 11 : rStateSet.AddState( AccessibleStateType::HORIZONTAL );
521 : else
522 0 : rStateSet.AddState( AccessibleStateType::VERTICAL );
523 11 : }
524 11 : }
525 :
526 860 : void VCLXAccessibleToolBox::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
527 : {
528 : // to prevent an early release of the toolbox (VCLEVENT_OBJECT_DYING)
529 860 : Reference< XAccessibleContext > xTemp = this;
530 :
531 860 : switch ( rVclWindowEvent.GetId() )
532 : {
533 : case VCLEVENT_TOOLBOX_CLICK:
534 : case VCLEVENT_TOOLBOX_SELECT:
535 : {
536 4 : VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
537 4 : if ( rVclWindowEvent.GetData() )
538 : {
539 0 : UpdateChecked_Impl( (sal_Int32)reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()) );
540 0 : UpdateIndeterminate_Impl( (sal_Int32)reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()) );
541 : }
542 4 : else if( pToolBox->GetItemPos(pToolBox->GetCurItemId()) != TOOLBOX_ITEM_NOTFOUND )
543 : {
544 4 : UpdateChecked_Impl( pToolBox->GetItemPos(pToolBox->GetCurItemId()) );
545 4 : UpdateIndeterminate_Impl( pToolBox->GetItemPos(pToolBox->GetCurItemId()) );
546 : }
547 4 : break;
548 : }
549 : case VCLEVENT_TOOLBOX_DOUBLECLICK:
550 : case VCLEVENT_TOOLBOX_ACTIVATE:
551 : case VCLEVENT_TOOLBOX_DEACTIVATE:
552 : //case VCLEVENT_TOOLBOX_SELECT:
553 4 : break;
554 :
555 : case VCLEVENT_TOOLBOX_ITEMUPDATED:
556 : {
557 0 : if ( rVclWindowEvent.GetData() )
558 : {
559 0 : UpdateChecked_Impl( TOOLBOX_ITEM_NOTFOUND );
560 0 : UpdateIndeterminate_Impl( (sal_Int32)reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()) );
561 : }
562 0 : break;
563 : }
564 :
565 : case VCLEVENT_TOOLBOX_HIGHLIGHT:
566 1 : UpdateFocus_Impl();
567 1 : break;
568 :
569 : case VCLEVENT_TOOLBOX_HIGHLIGHTOFF:
570 0 : ReleaseFocus_Impl( (sal_Int32)reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()) );
571 0 : break;
572 :
573 : case VCLEVENT_TOOLBOX_ITEMADDED :
574 0 : UpdateItem_Impl( (sal_Int32)reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()), true );
575 0 : break;
576 :
577 : case VCLEVENT_TOOLBOX_ITEMREMOVED :
578 : case VCLEVENT_TOOLBOX_ALLITEMSCHANGED :
579 : {
580 3 : UpdateAllItems_Impl();
581 3 : break;
582 : }
583 :
584 : case VCLEVENT_TOOLBOX_ITEMWINDOWCHANGED:
585 : {
586 398 : sal_Int32 nPos = (sal_Int32)reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData());
587 398 : ToolBoxItemsMap::iterator aAccessiblePos( m_aAccessibleChildren.find( nPos ) );
588 398 : if ( m_aAccessibleChildren.end() != aAccessiblePos )
589 : {
590 315 : implReleaseToolboxItem( aAccessiblePos, false, true );
591 315 : m_aAccessibleChildren.erase (aAccessiblePos);
592 : }
593 :
594 398 : Any aNewValue;
595 398 : aNewValue <<= getAccessibleChild(nPos);
596 398 : NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), aNewValue );
597 398 : break;
598 : }
599 : case VCLEVENT_TOOLBOX_ITEMTEXTCHANGED :
600 0 : UpdateItemName_Impl( (sal_Int32)reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()) );
601 0 : break;
602 :
603 : case VCLEVENT_TOOLBOX_ITEMENABLED :
604 : case VCLEVENT_TOOLBOX_ITEMDISABLED :
605 : {
606 3 : UpdateItemEnabled_Impl( (sal_Int32)reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()) );
607 3 : break;
608 : }
609 :
610 : case VCLEVENT_DROPDOWN_OPEN:
611 : case VCLEVENT_DROPDOWN_CLOSE:
612 : {
613 0 : UpdateCustomPopupItemp_Impl( static_cast< vcl::Window* >( rVclWindowEvent.GetData() ), rVclWindowEvent.GetId() == VCLEVENT_DROPDOWN_OPEN );
614 0 : break;
615 : }
616 :
617 : case VCLEVENT_OBJECT_DYING :
618 : {
619 : // if this toolbox is a subtoolbox, we have to relese it from its parent
620 12 : VclPtr< vcl::Window > pWin = GetAs< vcl::Window >();
621 24 : if ( pWin && pWin->GetParent() &&
622 12 : pWin->GetParent()->GetType() == WINDOW_TOOLBOX )
623 : {
624 : VCLXAccessibleToolBox* pParent = static_cast< VCLXAccessibleToolBox* >(
625 0 : pWin->GetParent()->GetAccessible()->getAccessibleContext().get() );
626 0 : if ( pParent )
627 0 : pParent->ReleaseSubToolBox(static_cast<ToolBox *>(pWin.get()));
628 : }
629 :
630 : // dispose all items
631 1254 : for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
632 836 : aIter != m_aAccessibleChildren.end(); ++aIter )
633 : {
634 406 : implReleaseToolboxItem( aIter, false, true );
635 : }
636 12 : m_aAccessibleChildren.clear();
637 :
638 : //!!! no break to call base class
639 : }
640 :
641 : default:
642 447 : VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
643 860 : }
644 860 : }
645 :
646 1135 : void VCLXAccessibleToolBox::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent )
647 : {
648 1135 : switch ( rVclWindowEvent.GetId() )
649 : {
650 : case VCLEVENT_WINDOW_SHOW: // send create on show for direct accessible children
651 : {
652 6 : Reference< XAccessible > xReturn = GetItemWindowAccessible(rVclWindowEvent);
653 6 : if ( xReturn.is() )
654 0 : NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), makeAny(xReturn) );
655 : else
656 6 : HandleSubToolBarEvent( rVclWindowEvent, true );
657 : }
658 6 : break;
659 :
660 : default:
661 1129 : VCLXAccessibleComponent::ProcessWindowChildEvent( rVclWindowEvent );
662 :
663 : }
664 1135 : }
665 :
666 : // XInterface
667 4404 : IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleToolBox, VCLXAccessibleComponent, VCLXAccessibleToolBox_BASE )
668 :
669 : // XTypeProvider
670 0 : IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleToolBox, VCLXAccessibleComponent, VCLXAccessibleToolBox_BASE )
671 :
672 : // XComponent
673 12 : void SAL_CALL VCLXAccessibleToolBox::disposing()
674 : {
675 12 : VCLXAccessibleComponent::disposing();
676 :
677 : // release the items
678 36 : for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
679 24 : aIter != m_aAccessibleChildren.end(); ++aIter )
680 : {
681 0 : implReleaseToolboxItem( aIter, false, true );
682 : }
683 12 : m_aAccessibleChildren.clear();
684 12 : }
685 :
686 : // XServiceInfo
687 1 : OUString VCLXAccessibleToolBox::getImplementationName() throw (RuntimeException, std::exception)
688 : {
689 1 : return OUString( "com.sun.star.comp.toolkit.AccessibleToolBox" );
690 : }
691 :
692 0 : Sequence< OUString > VCLXAccessibleToolBox::getSupportedServiceNames() throw (RuntimeException, std::exception)
693 : {
694 0 : Sequence< OUString > aNames = VCLXAccessibleComponent::getSupportedServiceNames();
695 0 : sal_Int32 nLength = aNames.getLength();
696 0 : aNames.realloc( nLength + 1 );
697 0 : aNames[nLength] = "com.sun.star.accessibility.AccessibleToolBox";
698 0 : return aNames;
699 : }
700 :
701 : // XAccessibleContext
702 828 : sal_Int32 SAL_CALL VCLXAccessibleToolBox::getAccessibleChildCount( ) throw (RuntimeException, std::exception)
703 : {
704 828 : comphelper::OExternalLockGuard aGuard( this );
705 :
706 828 : sal_Int32 nCount = 0;
707 1656 : VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
708 828 : if ( pToolBox )
709 828 : nCount = pToolBox->GetItemCount();
710 :
711 1656 : return nCount;
712 : }
713 :
714 800 : Reference< XAccessible > SAL_CALL VCLXAccessibleToolBox::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
715 : {
716 800 : if ( i < 0 || i >= getAccessibleChildCount() )
717 0 : throw IndexOutOfBoundsException();
718 :
719 800 : comphelper::OExternalLockGuard aGuard( this );
720 :
721 1600 : VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
722 800 : if ( pToolBox )
723 : {
724 800 : Reference< XAccessible > xChild;
725 : // search for the child
726 800 : ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.find(i);
727 800 : if ( m_aAccessibleChildren.end() == aIter )
728 : {
729 796 : sal_uInt16 nItemId = pToolBox->GetItemId( (sal_uInt16)i );
730 796 : sal_uInt16 nHighlightItemId = pToolBox->GetHighlightItemId();
731 796 : vcl::Window* pItemWindow = pToolBox->GetItemWindow( nItemId );
732 : // not found -> create a new child
733 796 : VCLXAccessibleToolBoxItem* pChild = new VCLXAccessibleToolBoxItem( pToolBox, i );
734 796 : Reference< XAccessible> xParent = pChild;
735 796 : if ( pItemWindow )
736 : {
737 12 : xChild = new OToolBoxWindowItem(0,::comphelper::getProcessComponentContext(),pItemWindow->GetAccessible(),xParent);
738 12 : pItemWindow->SetAccessible(xChild);
739 12 : pChild->SetChild( xChild );
740 : }
741 796 : xChild = pChild;
742 796 : if ( nHighlightItemId > 0 && nItemId == nHighlightItemId )
743 3 : pChild->SetFocus( true );
744 796 : if ( pToolBox->IsItemChecked( nItemId ) )
745 39 : pChild->SetChecked( true );
746 796 : if ( pToolBox->GetItemState( nItemId ) == TRISTATE_INDET )
747 0 : pChild->SetIndeterminate( true );
748 796 : m_aAccessibleChildren.insert( ToolBoxItemsMap::value_type( i, xChild ) );
749 : }
750 : else
751 : {
752 : // found it
753 4 : xChild = aIter->second;
754 : }
755 800 : return xChild;
756 : }
757 :
758 800 : return NULL;
759 : }
760 :
761 0 : Reference< XAccessible > SAL_CALL VCLXAccessibleToolBox::getAccessibleAtPoint( const awt::Point& _rPoint ) throw (RuntimeException, std::exception)
762 : {
763 0 : comphelper::OExternalLockGuard aGuard( this );
764 :
765 0 : Reference< XAccessible > xAccessible;
766 0 : VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
767 0 : if ( pToolBox )
768 : {
769 0 : sal_uInt16 nItemPos = pToolBox->GetItemPos( VCLPoint( _rPoint ) );
770 0 : if ( nItemPos != TOOLBOX_ITEM_NOTFOUND )
771 0 : xAccessible = getAccessibleChild( nItemPos );
772 : }
773 :
774 0 : return xAccessible;
775 : }
776 :
777 108 : Reference< XAccessible > VCLXAccessibleToolBox::GetItemWindowAccessible( const VclWindowEvent& rVclWindowEvent )
778 : {
779 108 : Reference< XAccessible > xReturn;
780 108 : vcl::Window* pChildWindow = static_cast<vcl::Window *>(rVclWindowEvent.GetData());
781 216 : VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
782 108 : if ( pChildWindow && pToolBox )
783 : {
784 59 : sal_uInt16 nCount = pToolBox->GetItemCount();
785 2481 : for (sal_uInt16 i = 0 ; i < nCount && !xReturn.is() ; ++i)
786 : {
787 2422 : sal_uInt16 nItemId = pToolBox->GetItemId( i );
788 2422 : vcl::Window* pItemWindow = pToolBox->GetItemWindow( nItemId );
789 2422 : if ( pItemWindow == pChildWindow )
790 8 : xReturn = getAccessibleChild(i);
791 : }
792 : }
793 216 : return xReturn;
794 : }
795 :
796 102 : Reference< XAccessible > VCLXAccessibleToolBox::GetChildAccessible( const VclWindowEvent& rVclWindowEvent )
797 : {
798 102 : Reference< XAccessible > xReturn = GetItemWindowAccessible(rVclWindowEvent);
799 :
800 102 : if ( !xReturn.is() )
801 94 : xReturn = VCLXAccessibleComponent::GetChildAccessible(rVclWindowEvent);
802 102 : return xReturn;
803 : }
804 :
805 : // XAccessibleSelection
806 0 : void VCLXAccessibleToolBox::selectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
807 : {
808 0 : OExternalLockGuard aGuard( this );
809 0 : if ( nChildIndex < 0 || nChildIndex >= getAccessibleChildCount() )
810 0 : throw IndexOutOfBoundsException();
811 0 : VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
812 0 : sal_uInt16 nPos = static_cast < sal_uInt16 > (nChildIndex);
813 0 : pToolBox->ChangeHighlight( nPos );
814 0 : }
815 :
816 0 : sal_Bool VCLXAccessibleToolBox::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
817 : {
818 0 : OExternalLockGuard aGuard( this );
819 0 : if ( nChildIndex < 0 || nChildIndex >= getAccessibleChildCount() )
820 0 : throw IndexOutOfBoundsException();
821 0 : VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
822 0 : sal_uInt16 nPos = static_cast < sal_uInt16 > (nChildIndex);
823 0 : if ( pToolBox && pToolBox->GetHighlightItemId() == pToolBox->GetItemId( nPos ) )
824 0 : return true;
825 : else
826 0 : return false;
827 : }
828 :
829 0 : void VCLXAccessibleToolBox::clearAccessibleSelection( ) throw (RuntimeException, std::exception)
830 : {
831 0 : OExternalLockGuard aGuard( this );
832 0 : VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
833 0 : pToolBox -> LoseFocus();
834 0 : }
835 :
836 0 : void VCLXAccessibleToolBox::selectAllAccessibleChildren( ) throw (RuntimeException, std::exception)
837 : {
838 0 : OExternalLockGuard aGuard( this );
839 : // intentionally empty. makes no sense for a toolbox
840 0 : }
841 :
842 0 : sal_Int32 VCLXAccessibleToolBox::getSelectedAccessibleChildCount( ) throw (RuntimeException, std::exception)
843 : {
844 0 : OExternalLockGuard aGuard( this );
845 0 : sal_Int32 nRet = 0;
846 0 : for ( sal_Int32 i = 0, nCount = getAccessibleChildCount(); i < nCount; i++ )
847 : {
848 0 : if ( isAccessibleChildSelected( i ) )
849 : {
850 0 : nRet = 1;
851 0 : break; // a toolbox can only have (n)one selected child
852 : }
853 : }
854 0 : return nRet;
855 : }
856 :
857 0 : Reference< XAccessible > VCLXAccessibleToolBox::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
858 : {
859 0 : OExternalLockGuard aGuard( this );
860 0 : if ( nSelectedChildIndex < 0 || nSelectedChildIndex >= getSelectedAccessibleChildCount() )
861 0 : throw IndexOutOfBoundsException();
862 0 : Reference< XAccessible > xChild;
863 0 : for ( sal_Int32 i = 0, j = 0, nCount = getAccessibleChildCount(); i < nCount; i++ )
864 : {
865 0 : if ( isAccessibleChildSelected( i ) && ( j++ == nSelectedChildIndex ) )
866 : {
867 0 : xChild = getAccessibleChild( i );
868 0 : break;
869 : }
870 : }
871 0 : return xChild;
872 : }
873 :
874 0 : void VCLXAccessibleToolBox::deselectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
875 : {
876 0 : OExternalLockGuard aGuard( this );
877 0 : if ( nChildIndex < 0 || nChildIndex >= getAccessibleChildCount() )
878 0 : throw IndexOutOfBoundsException();
879 0 : clearAccessibleSelection(); // a toolbox can only have (n)one selected child
880 0 : }
881 :
882 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|