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