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