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