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