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