Branch libreoffice-5-0-4
[LibreOffice.git] / accessibility / source / standard / vclxaccessibletoolbox.cxx
blobbbb4e26f2efa2cf03a947d71e0edc82732c17066
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
19 #include <string.h>
21 #include <accessibility/standard/vclxaccessibletoolbox.hxx>
22 #include <accessibility/standard/vclxaccessibletoolboxitem.hxx>
23 #include <toolkit/helper/convert.hxx>
25 #include <unotools/accessiblestatesethelper.hxx>
26 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
27 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
28 #include <com/sun/star/lang/XUnoTunnel.hpp>
29 #include <vcl/toolbox.hxx>
30 #include <comphelper/accessiblewrapper.hxx>
31 #include <comphelper/processfactory.hxx>
33 using namespace ::comphelper;
34 using namespace ::com::sun::star;
35 using namespace ::com::sun::star::uno;
36 using namespace ::com::sun::star::lang;
37 using namespace ::com::sun::star::accessibility;
39 namespace
42 // = OToolBoxWindowItemContext
44 /** XAccessibleContext implementation for a toolbox item which is represented by a VCL Window
46 class OToolBoxWindowItemContext : public OAccessibleContextWrapper
48 sal_Int32 m_nIndexInParent;
49 public:
50 OToolBoxWindowItemContext(sal_Int32 _nIndexInParent,
51 const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& _rxContext,
52 const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >& _rxInnerAccessibleContext,
53 const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& _rxOwningAccessible,
54 const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& _rxParentAccessible
55 ) : OAccessibleContextWrapper(
56 _rxContext,
57 _rxInnerAccessibleContext,
58 _rxOwningAccessible,
59 _rxParentAccessible )
60 ,m_nIndexInParent(_nIndexInParent)
63 virtual sal_Int32 SAL_CALL getAccessibleIndexInParent( ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
67 sal_Int32 SAL_CALL OToolBoxWindowItemContext::getAccessibleIndexInParent( ) throw (::com::sun::star::uno::RuntimeException, std::exception)
69 ::osl::MutexGuard aGuard( m_aMutex );
70 return m_nIndexInParent;
74 // = OToolBoxWindowItem
76 typedef ::cppu::ImplHelper1 < XUnoTunnel
77 > OToolBoxWindowItem_Base;
79 /** XAccessible implementation for a toolbox item which is represented by a VCL Window
81 class OToolBoxWindowItem
82 :public OAccessibleWrapper
83 ,public OToolBoxWindowItem_Base
85 private:
86 sal_Int32 m_nIndexInParent;
88 public:
89 inline sal_Int32 getIndexInParent() const { return m_nIndexInParent; }
90 inline void setIndexInParent( sal_Int32 _nNewIndex ) { m_nIndexInParent = _nNewIndex; }
92 static bool isWindowItem( const Reference< XAccessible >& _rxAcc, OToolBoxWindowItem** /* [out] */ _ppImplementation = NULL );
94 public:
95 OToolBoxWindowItem(sal_Int32 _nIndexInParent,
96 const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& _rxContext,
97 const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& _rxInnerAccessible,
98 const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& _rxParentAccessible
99 ) : OAccessibleWrapper(
100 _rxContext,
101 _rxInnerAccessible,
102 _rxParentAccessible)
103 ,m_nIndexInParent(_nIndexInParent)
107 protected:
108 // XInterface
109 DECLARE_XINTERFACE( )
110 DECLARE_XTYPEPROVIDER( )
112 // OAccessibleWrapper
113 virtual OAccessibleContextWrapper* createAccessibleContext(
114 const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >& _rxInnerContext
115 ) SAL_OVERRIDE;
117 // XUnoTunnel
118 virtual sal_Int64 SAL_CALL getSomething( const Sequence< sal_Int8 >& aIdentifier ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
119 static Sequence< sal_Int8 > getUnoTunnelImplementationId();
122 IMPLEMENT_FORWARD_XINTERFACE2( OToolBoxWindowItem, OAccessibleWrapper, OToolBoxWindowItem_Base )
123 IMPLEMENT_FORWARD_XTYPEPROVIDER2( OToolBoxWindowItem, OAccessibleWrapper, OToolBoxWindowItem_Base )
125 OAccessibleContextWrapper* OToolBoxWindowItem::createAccessibleContext(
126 const Reference< XAccessibleContext >& _rxInnerContext )
128 return new OToolBoxWindowItemContext( m_nIndexInParent, getComponentContext(), _rxInnerContext, this, getParent() );
131 bool OToolBoxWindowItem::isWindowItem( const Reference< XAccessible >& _rxAcc, OToolBoxWindowItem** /* [out] */ _ppImplementation )
133 OToolBoxWindowItem* pImplementation = NULL;
135 Reference< XUnoTunnel > xTunnel( _rxAcc, UNO_QUERY );
136 if ( xTunnel.is() )
137 pImplementation = reinterpret_cast< OToolBoxWindowItem* >( xTunnel->getSomething( getUnoTunnelImplementationId() ) );
139 if ( _ppImplementation )
140 *_ppImplementation = pImplementation;
142 return NULL != pImplementation;
145 Sequence< sal_Int8 > OToolBoxWindowItem::getUnoTunnelImplementationId()
147 static ::cppu::OImplementationId * pId = 0;
148 if (! pId)
150 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
151 if (! pId)
153 static ::cppu::OImplementationId aId;
154 pId = &aId;
157 return pId->getImplementationId();
160 sal_Int64 SAL_CALL OToolBoxWindowItem::getSomething( const Sequence< sal_Int8 >& _rId ) throw (RuntimeException, std::exception)
162 if ( ( 16 == _rId.getLength() )
163 && ( 0 == memcmp( getUnoTunnelImplementationId().getConstArray(), _rId.getConstArray(), 16 ) )
165 return reinterpret_cast< sal_Int64>( this );
167 return 0;
171 // VCLXAccessibleToolBox
173 VCLXAccessibleToolBox::VCLXAccessibleToolBox( VCLXWindow* pVCLXWindow ) :
175 VCLXAccessibleComponent( pVCLXWindow )
180 VCLXAccessibleToolBox::~VCLXAccessibleToolBox()
184 VCLXAccessibleToolBoxItem* VCLXAccessibleToolBox::GetItem_Impl( sal_Int32 _nPos, bool _bMustHaveFocus )
186 VCLXAccessibleToolBoxItem* pItem = NULL;
187 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
188 if ( pToolBox && ( !_bMustHaveFocus || pToolBox->HasFocus() ) )
190 ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.find( _nPos );
191 // returns only toolbox buttons, not windows
192 if ( aIter != m_aAccessibleChildren.end() && aIter->second.is())
193 pItem = static_cast< VCLXAccessibleToolBoxItem* >( aIter->second.get() );
196 return pItem;
199 void VCLXAccessibleToolBox::UpdateFocus_Impl()
201 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
202 if( !pToolBox )
203 return;
205 // submit events only if toolbox has the focus to avoid sending events due to mouse move
206 bool bHasFocus = false;
207 if ( pToolBox->HasFocus() )
208 bHasFocus = true;
209 else
211 // check for subtoolbar, i.e. check if our parent is a toolbar
212 ToolBox* pToolBoxParent = dynamic_cast< ToolBox* >( pToolBox->GetParent() );
213 // subtoolbars never get the focus as key input is just forwarded, so check if the parent toolbar has it
214 if ( pToolBoxParent && pToolBoxParent->HasFocus() )
215 bHasFocus = true;
218 if ( bHasFocus )
220 sal_uInt16 nHighlightItemId = pToolBox->GetHighlightItemId();
221 sal_uInt16 nFocusCount = 0;
222 for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
223 aIter != m_aAccessibleChildren.end(); ++aIter )
225 sal_uInt16 nItemId = pToolBox->GetItemId( (sal_uInt16)aIter->first );
227 if ( aIter->second.is() )
229 VCLXAccessibleToolBoxItem* pItem =
230 static_cast< VCLXAccessibleToolBoxItem* >( aIter->second.get() );
231 if ( pItem->HasFocus() && nItemId != nHighlightItemId )
233 // reset the old focused item
234 pItem->SetFocus( false );
235 nFocusCount++;
237 if ( nItemId == nHighlightItemId )
239 // set the new focused item
240 pItem->SetFocus( true );
241 nFocusCount++;
244 // both items changed?
245 if ( nFocusCount > 1 )
246 break;
251 void VCLXAccessibleToolBox::ReleaseFocus_Impl( sal_Int32 _nPos )
253 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
254 if ( pToolBox ) // #107124#, do not check for focus because this message is also handled in losefocus
256 ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.find( _nPos );
257 if ( aIter != m_aAccessibleChildren.end() && aIter->second.is() )
259 VCLXAccessibleToolBoxItem* pItem =
260 static_cast< VCLXAccessibleToolBoxItem* >( aIter->second.get() );
261 if ( pItem->HasFocus() )
262 pItem->SetFocus( false );
267 void VCLXAccessibleToolBox::UpdateChecked_Impl( sal_Int32 _nPos )
269 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
270 if ( pToolBox )
272 sal_uInt16 nFocusId = pToolBox->GetItemId( (sal_uInt16)_nPos );
273 VCLXAccessibleToolBoxItem* pFocusItem = NULL;
275 for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
276 aIter != m_aAccessibleChildren.end(); ++aIter )
278 sal_uInt16 nItemId = pToolBox->GetItemId( (sal_uInt16)aIter->first );
280 VCLXAccessibleToolBoxItem* pItem =
281 static_cast< VCLXAccessibleToolBoxItem* >( aIter->second.get() );
282 pItem->SetChecked( pToolBox->IsItemChecked( nItemId ) );
283 if ( nItemId == nFocusId )
284 pFocusItem = pItem;
286 //Solution:If the position is not a child item,the focus should not be called
287 if ( pFocusItem && (sal_uInt16)_nPos != TOOLBOX_ITEM_NOTFOUND )
288 pFocusItem->SetFocus( true );
292 void VCLXAccessibleToolBox::UpdateIndeterminate_Impl( sal_Int32 _nPos )
294 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
295 if ( pToolBox )
297 sal_uInt16 nItemId = pToolBox->GetItemId( (sal_uInt16)_nPos );
299 ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.find( _nPos );
300 if ( aIter != m_aAccessibleChildren.end() && aIter->second.is() )
302 VCLXAccessibleToolBoxItem* pItem =
303 static_cast< VCLXAccessibleToolBoxItem* >( aIter->second.get() );
304 if ( pItem )
305 pItem->SetIndeterminate( pToolBox->GetItemState( nItemId ) == TRISTATE_INDET );
310 void VCLXAccessibleToolBox::implReleaseToolboxItem( ToolBoxItemsMap::iterator& _rMapPos,
311 bool _bNotifyRemoval, bool _bDispose )
313 Reference< XAccessible > xItemAcc( _rMapPos->second );
314 if ( !xItemAcc.is() )
315 return;
317 if ( _bNotifyRemoval )
319 NotifyAccessibleEvent( AccessibleEventId::CHILD, makeAny( xItemAcc ), Any() );
322 OToolBoxWindowItem* pWindowItem = NULL;
323 if ( !OToolBoxWindowItem::isWindowItem( xItemAcc, &pWindowItem ) )
325 static_cast< VCLXAccessibleToolBoxItem* >( xItemAcc.get() )->ReleaseToolBox();
326 if ( _bDispose )
327 ::comphelper::disposeComponent( xItemAcc );
329 else
331 if ( _bDispose )
333 if ( pWindowItem )
335 Reference< XAccessibleContext > xContext( pWindowItem->getContextNoCreate() );
336 ::comphelper::disposeComponent( xContext );
342 void VCLXAccessibleToolBox::UpdateItem_Impl( sal_Int32 _nPos, bool _bItemAdded )
344 if ( _nPos < sal_Int32( m_aAccessibleChildren.size() ) )
346 UpdateAllItems_Impl();
347 return;
350 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
351 if ( pToolBox )
353 if ( !_bItemAdded )
354 { // the item was removed
355 // -> destroy the old item
356 ToolBoxItemsMap::iterator aItemPos = m_aAccessibleChildren.find( _nPos );
357 if ( m_aAccessibleChildren.end() != aItemPos )
359 implReleaseToolboxItem( aItemPos, true, true );
360 m_aAccessibleChildren.erase( aItemPos );
364 // adjust the "index-in-parent"s
365 ToolBoxItemsMap::iterator aIndexAdjust = m_aAccessibleChildren.upper_bound( _nPos );
366 while ( m_aAccessibleChildren.end() != aIndexAdjust )
368 Reference< XAccessible > xItemAcc( aIndexAdjust->second );
370 OToolBoxWindowItem* pWindowItem = NULL;
371 if ( !OToolBoxWindowItem::isWindowItem( xItemAcc, &pWindowItem ) )
373 VCLXAccessibleToolBoxItem* pItem = static_cast< VCLXAccessibleToolBoxItem* >( xItemAcc.get() );
374 if ( pItem )
376 sal_Int32 nIndex = pItem->getIndexInParent( );
377 nIndex += (_bItemAdded ? +1 : -1);
378 pItem->setIndexInParent( nIndex );
381 else
383 if ( pWindowItem )
385 sal_Int32 nIndex = pWindowItem->getIndexInParent( );
386 nIndex += (_bItemAdded ? +1 : -1);
387 pWindowItem->setIndexInParent( nIndex );
391 ++aIndexAdjust;
394 if ( _bItemAdded )
396 // TODO: we should make this dependent on the existence of event listeners
397 // with the current implementation, we always create accessible object
398 Any aNewChild = makeAny( getAccessibleChild( (sal_Int32)_nPos ) );
399 NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), aNewChild );
404 void VCLXAccessibleToolBox::UpdateAllItems_Impl()
406 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
407 if ( pToolBox )
409 // deregister the old items
410 for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
411 aIter != m_aAccessibleChildren.end(); ++aIter )
413 implReleaseToolboxItem( aIter, true, true );
415 m_aAccessibleChildren.clear();
417 // register the new items
418 sal_uInt16 i, nCount = pToolBox->GetItemCount();
419 for ( i = 0; i < nCount; ++i )
421 Any aNewValue;
422 aNewValue <<= getAccessibleChild( (sal_Int32)i );;
423 NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), aNewValue );
428 void VCLXAccessibleToolBox::UpdateCustomPopupItemp_Impl( vcl::Window* pWindow, bool bOpen )
430 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
431 if( pWindow && pToolBox )
433 const sal_uInt16 nDownItem = pToolBox->GetDownItemId();
434 if ( !nDownItem )
435 // Items with ItemId == 0 are not allowed in ToolBox, which means that currently no item is in down state.
436 // Moreover, running GetItemPos with 0 could find a separator item if there is any.
437 return;
439 Reference< XAccessible > xChild( pWindow->GetAccessible() );
440 if( xChild.is() )
442 Reference< XAccessible > xChildItem( getAccessibleChild( static_cast< sal_Int32 >( pToolBox->GetItemPos( nDownItem ) ) ) );
443 VCLXAccessibleToolBoxItem* pItem = static_cast< VCLXAccessibleToolBoxItem* >( xChildItem.get() );
445 pItem->SetChild( xChild );
446 pItem->NotifyChildEvent( xChild, bOpen );
451 void VCLXAccessibleToolBox::UpdateItemName_Impl( sal_Int32 _nPos )
453 VCLXAccessibleToolBoxItem* pItem = GetItem_Impl( _nPos, false );
454 if ( pItem )
455 pItem->NameChanged();
458 void VCLXAccessibleToolBox::UpdateItemEnabled_Impl( sal_Int32 _nPos )
460 VCLXAccessibleToolBoxItem* pItem = GetItem_Impl( _nPos, false );
461 if ( pItem )
462 pItem->ToggleEnableState();
465 void VCLXAccessibleToolBox::HandleSubToolBarEvent( const VclWindowEvent& rVclWindowEvent, bool _bShow )
467 vcl::Window* pChildWindow = static_cast<vcl::Window *>(rVclWindowEvent.GetData());
468 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
469 if ( pChildWindow
470 && pToolBox
471 && pToolBox == pChildWindow->GetParent()
472 && pChildWindow->GetType() == WINDOW_TOOLBOX )
474 sal_Int32 nIndex = pToolBox->GetItemPos( pToolBox->GetCurItemId() );
475 Reference< XAccessible > xItem = getAccessibleChild( nIndex );
476 if ( xItem.is() )
478 Reference< XAccessible > xChild = pChildWindow->GetAccessible();
479 VCLXAccessibleToolBoxItem* pItem =
480 static_cast< VCLXAccessibleToolBoxItem* >( xItem.get() );
481 pItem->SetChild( xChild );
482 pItem->NotifyChildEvent( xChild, _bShow );
487 void VCLXAccessibleToolBox::ReleaseSubToolBox( ToolBox* _pSubToolBox )
489 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
490 if ( !pToolBox )
491 return;
493 sal_Int32 nIndex = pToolBox->GetItemPos( pToolBox->GetCurItemId() );
494 if ( nIndex == SAL_MAX_UINT16 )
495 return; // not found
497 Reference< XAccessible > xItem = getAccessibleChild( nIndex );
498 if ( !xItem.is() )
499 return;
501 Reference< XAccessible > xChild = _pSubToolBox->GetAccessible();
502 VCLXAccessibleToolBoxItem* pItem =
503 static_cast< VCLXAccessibleToolBoxItem* >( xItem.get() );
504 if ( pItem->GetChild() == xChild )
506 pItem->SetChild( Reference< XAccessible >() );
507 pItem->NotifyChildEvent( xChild, false );
511 void VCLXAccessibleToolBox::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
513 VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet );
515 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
516 if ( pToolBox )
518 rStateSet.AddState( AccessibleStateType::FOCUSABLE );
519 if ( pToolBox->IsHorizontal() )
520 rStateSet.AddState( AccessibleStateType::HORIZONTAL );
521 else
522 rStateSet.AddState( AccessibleStateType::VERTICAL );
526 void VCLXAccessibleToolBox::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
528 // to prevent an early release of the toolbox (VCLEVENT_OBJECT_DYING)
529 Reference< XAccessibleContext > xTemp = this;
531 switch ( rVclWindowEvent.GetId() )
533 case VCLEVENT_TOOLBOX_CLICK:
534 case VCLEVENT_TOOLBOX_SELECT:
536 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
537 if ( rVclWindowEvent.GetData() )
539 UpdateChecked_Impl( (sal_Int32)reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()) );
540 UpdateIndeterminate_Impl( (sal_Int32)reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()) );
542 else if( pToolBox->GetItemPos(pToolBox->GetCurItemId()) != TOOLBOX_ITEM_NOTFOUND )
544 UpdateChecked_Impl( pToolBox->GetItemPos(pToolBox->GetCurItemId()) );
545 UpdateIndeterminate_Impl( pToolBox->GetItemPos(pToolBox->GetCurItemId()) );
547 break;
549 case VCLEVENT_TOOLBOX_DOUBLECLICK:
550 case VCLEVENT_TOOLBOX_ACTIVATE:
551 case VCLEVENT_TOOLBOX_DEACTIVATE:
552 //case VCLEVENT_TOOLBOX_SELECT:
553 break;
555 case VCLEVENT_TOOLBOX_ITEMUPDATED:
557 if ( rVclWindowEvent.GetData() )
559 UpdateChecked_Impl( TOOLBOX_ITEM_NOTFOUND );
560 UpdateIndeterminate_Impl( (sal_Int32)reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()) );
562 break;
565 case VCLEVENT_TOOLBOX_HIGHLIGHT:
566 UpdateFocus_Impl();
567 break;
569 case VCLEVENT_TOOLBOX_HIGHLIGHTOFF:
570 ReleaseFocus_Impl( (sal_Int32)reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()) );
571 break;
573 case VCLEVENT_TOOLBOX_ITEMADDED :
574 UpdateItem_Impl( (sal_Int32)reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()), true );
575 break;
577 case VCLEVENT_TOOLBOX_ITEMREMOVED :
578 case VCLEVENT_TOOLBOX_ALLITEMSCHANGED :
580 UpdateAllItems_Impl();
581 break;
584 case VCLEVENT_TOOLBOX_ITEMWINDOWCHANGED:
586 sal_Int32 nPos = (sal_Int32)reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData());
587 ToolBoxItemsMap::iterator aAccessiblePos( m_aAccessibleChildren.find( nPos ) );
588 if ( m_aAccessibleChildren.end() != aAccessiblePos )
590 implReleaseToolboxItem( aAccessiblePos, false, true );
591 m_aAccessibleChildren.erase (aAccessiblePos);
594 Any aNewValue;
595 aNewValue <<= getAccessibleChild(nPos);
596 NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), aNewValue );
597 break;
599 case VCLEVENT_TOOLBOX_ITEMTEXTCHANGED :
600 UpdateItemName_Impl( (sal_Int32)reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()) );
601 break;
603 case VCLEVENT_TOOLBOX_ITEMENABLED :
604 case VCLEVENT_TOOLBOX_ITEMDISABLED :
606 UpdateItemEnabled_Impl( (sal_Int32)reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()) );
607 break;
610 case VCLEVENT_DROPDOWN_OPEN:
611 case VCLEVENT_DROPDOWN_CLOSE:
613 UpdateCustomPopupItemp_Impl( static_cast< vcl::Window* >( rVclWindowEvent.GetData() ), rVclWindowEvent.GetId() == VCLEVENT_DROPDOWN_OPEN );
614 break;
617 case VCLEVENT_OBJECT_DYING :
619 // if this toolbox is a subtoolbox, we have to relese it from its parent
620 VclPtr< vcl::Window > pWin = GetAs< vcl::Window >();
621 if ( pWin && pWin->GetParent() &&
622 pWin->GetParent()->GetType() == WINDOW_TOOLBOX )
624 VCLXAccessibleToolBox* pParent = static_cast< VCLXAccessibleToolBox* >(
625 pWin->GetParent()->GetAccessible()->getAccessibleContext().get() );
626 if ( pParent )
627 pParent->ReleaseSubToolBox(static_cast<ToolBox *>(pWin.get()));
630 // dispose all items
631 for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
632 aIter != m_aAccessibleChildren.end(); ++aIter )
634 implReleaseToolboxItem( aIter, false, true );
636 m_aAccessibleChildren.clear();
638 //!!! no break to call base class
641 default:
642 VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
646 void VCLXAccessibleToolBox::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent )
648 switch ( rVclWindowEvent.GetId() )
650 case VCLEVENT_WINDOW_SHOW: // send create on show for direct accessible children
652 Reference< XAccessible > xReturn = GetItemWindowAccessible(rVclWindowEvent);
653 if ( xReturn.is() )
654 NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), makeAny(xReturn) );
655 else
656 HandleSubToolBarEvent( rVclWindowEvent, true );
658 break;
660 default:
661 VCLXAccessibleComponent::ProcessWindowChildEvent( rVclWindowEvent );
666 // XInterface
667 IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleToolBox, VCLXAccessibleComponent, VCLXAccessibleToolBox_BASE )
669 // XTypeProvider
670 IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleToolBox, VCLXAccessibleComponent, VCLXAccessibleToolBox_BASE )
672 // XComponent
673 void SAL_CALL VCLXAccessibleToolBox::disposing()
675 VCLXAccessibleComponent::disposing();
677 // release the items
678 for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
679 aIter != m_aAccessibleChildren.end(); ++aIter )
681 implReleaseToolboxItem( aIter, false, true );
683 m_aAccessibleChildren.clear();
686 // XServiceInfo
687 OUString VCLXAccessibleToolBox::getImplementationName() throw (RuntimeException, std::exception)
689 return OUString( "com.sun.star.comp.toolkit.AccessibleToolBox" );
692 Sequence< OUString > VCLXAccessibleToolBox::getSupportedServiceNames() throw (RuntimeException, std::exception)
694 Sequence< OUString > aNames = VCLXAccessibleComponent::getSupportedServiceNames();
695 sal_Int32 nLength = aNames.getLength();
696 aNames.realloc( nLength + 1 );
697 aNames[nLength] = "com.sun.star.accessibility.AccessibleToolBox";
698 return aNames;
701 // XAccessibleContext
702 sal_Int32 SAL_CALL VCLXAccessibleToolBox::getAccessibleChildCount( ) throw (RuntimeException, std::exception)
704 comphelper::OExternalLockGuard aGuard( this );
706 sal_Int32 nCount = 0;
707 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
708 if ( pToolBox )
709 nCount = pToolBox->GetItemCount();
711 return nCount;
714 Reference< XAccessible > SAL_CALL VCLXAccessibleToolBox::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
716 if ( i < 0 || i >= getAccessibleChildCount() )
717 throw IndexOutOfBoundsException();
719 comphelper::OExternalLockGuard aGuard( this );
721 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
722 if ( pToolBox )
724 Reference< XAccessible > xChild;
725 // search for the child
726 ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.find(i);
727 if ( m_aAccessibleChildren.end() == aIter )
729 sal_uInt16 nItemId = pToolBox->GetItemId( (sal_uInt16)i );
730 sal_uInt16 nHighlightItemId = pToolBox->GetHighlightItemId();
731 vcl::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 )
737 xChild = new OToolBoxWindowItem(0,::comphelper::getProcessComponentContext(),pItemWindow->GetAccessible(),xParent);
738 pItemWindow->SetAccessible(xChild);
739 pChild->SetChild( xChild );
741 xChild = pChild;
742 if ( nHighlightItemId > 0 && nItemId == nHighlightItemId )
743 pChild->SetFocus( true );
744 if ( pToolBox->IsItemChecked( nItemId ) )
745 pChild->SetChecked( true );
746 if ( pToolBox->GetItemState( nItemId ) == TRISTATE_INDET )
747 pChild->SetIndeterminate( true );
748 m_aAccessibleChildren.insert( ToolBoxItemsMap::value_type( i, xChild ) );
750 else
752 // found it
753 xChild = aIter->second;
755 return xChild;
758 return NULL;
761 Reference< XAccessible > SAL_CALL VCLXAccessibleToolBox::getAccessibleAtPoint( const awt::Point& _rPoint ) throw (RuntimeException, std::exception)
763 comphelper::OExternalLockGuard aGuard( this );
765 Reference< XAccessible > xAccessible;
766 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
767 if ( pToolBox )
769 sal_uInt16 nItemPos = pToolBox->GetItemPos( VCLPoint( _rPoint ) );
770 if ( nItemPos != TOOLBOX_ITEM_NOTFOUND )
771 xAccessible = getAccessibleChild( nItemPos );
774 return xAccessible;
777 Reference< XAccessible > VCLXAccessibleToolBox::GetItemWindowAccessible( const VclWindowEvent& rVclWindowEvent )
779 Reference< XAccessible > xReturn;
780 vcl::Window* pChildWindow = static_cast<vcl::Window *>(rVclWindowEvent.GetData());
781 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
782 if ( pChildWindow && pToolBox )
784 sal_uInt16 nCount = pToolBox->GetItemCount();
785 for (sal_uInt16 i = 0 ; i < nCount && !xReturn.is() ; ++i)
787 sal_uInt16 nItemId = pToolBox->GetItemId( i );
788 vcl::Window* pItemWindow = pToolBox->GetItemWindow( nItemId );
789 if ( pItemWindow == pChildWindow )
790 xReturn = getAccessibleChild(i);
793 return xReturn;
796 Reference< XAccessible > VCLXAccessibleToolBox::GetChildAccessible( const VclWindowEvent& rVclWindowEvent )
798 Reference< XAccessible > xReturn = GetItemWindowAccessible(rVclWindowEvent);
800 if ( !xReturn.is() )
801 xReturn = VCLXAccessibleComponent::GetChildAccessible(rVclWindowEvent);
802 return xReturn;
805 // XAccessibleSelection
806 void VCLXAccessibleToolBox::selectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
808 OExternalLockGuard aGuard( this );
809 if ( nChildIndex < 0 || nChildIndex >= getAccessibleChildCount() )
810 throw IndexOutOfBoundsException();
811 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
812 sal_uInt16 nPos = static_cast < sal_uInt16 > (nChildIndex);
813 pToolBox->ChangeHighlight( nPos );
816 sal_Bool VCLXAccessibleToolBox::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
818 OExternalLockGuard aGuard( this );
819 if ( nChildIndex < 0 || nChildIndex >= getAccessibleChildCount() )
820 throw IndexOutOfBoundsException();
821 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
822 sal_uInt16 nPos = static_cast < sal_uInt16 > (nChildIndex);
823 if ( pToolBox && pToolBox->GetHighlightItemId() == pToolBox->GetItemId( nPos ) )
824 return true;
825 else
826 return false;
829 void VCLXAccessibleToolBox::clearAccessibleSelection( ) throw (RuntimeException, std::exception)
831 OExternalLockGuard aGuard( this );
832 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
833 pToolBox -> LoseFocus();
836 void VCLXAccessibleToolBox::selectAllAccessibleChildren( ) throw (RuntimeException, std::exception)
838 OExternalLockGuard aGuard( this );
839 // intentionally empty. makes no sense for a toolbox
842 sal_Int32 VCLXAccessibleToolBox::getSelectedAccessibleChildCount( ) throw (RuntimeException, std::exception)
844 OExternalLockGuard aGuard( this );
845 sal_Int32 nRet = 0;
846 for ( sal_Int32 i = 0, nCount = getAccessibleChildCount(); i < nCount; i++ )
848 if ( isAccessibleChildSelected( i ) )
850 nRet = 1;
851 break; // a toolbox can only have (n)one selected child
854 return nRet;
857 Reference< XAccessible > VCLXAccessibleToolBox::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
859 OExternalLockGuard aGuard( this );
860 if ( nSelectedChildIndex < 0 || nSelectedChildIndex >= getSelectedAccessibleChildCount() )
861 throw IndexOutOfBoundsException();
862 Reference< XAccessible > xChild;
863 for ( sal_Int32 i = 0, j = 0, nCount = getAccessibleChildCount(); i < nCount; i++ )
865 if ( isAccessibleChildSelected( i ) && ( j++ == nSelectedChildIndex ) )
867 xChild = getAccessibleChild( i );
868 break;
871 return xChild;
874 void VCLXAccessibleToolBox::deselectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
876 OExternalLockGuard aGuard( this );
877 if ( nChildIndex < 0 || nChildIndex >= getAccessibleChildCount() )
878 throw IndexOutOfBoundsException();
879 clearAccessibleSelection(); // a toolbox can only have (n)one selected child
882 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */