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