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