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