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_chart2.hxx" 30 31 #include "AccessibleBase.hxx" 32 #include "AccessibleChartShape.hxx" 33 #include "ObjectHierarchy.hxx" 34 #include "ObjectIdentifier.hxx" 35 #include "chartview/ExplicitValueProvider.hxx" 36 #include "macros.hxx" 37 38 #include <com/sun/star/awt/XDevice.hpp> 39 #include <com/sun/star/accessibility/AccessibleEventId.hpp> 40 #include <com/sun/star/accessibility/AccessibleEventObject.hpp> 41 #include <com/sun/star/accessibility/AccessibleStateType.hpp> 42 #include <com/sun/star/accessibility/AccessibleRole.hpp> 43 #include <comphelper/serviceinfohelper.hxx> 44 #include <com/sun/star/drawing/LineStyle.hpp> 45 #include <com/sun/star/drawing/FillStyle.hpp> 46 #include <rtl/ustrbuf.hxx> 47 // for SolarMutex 48 #include <vcl/svapp.hxx> 49 #include <rtl/uuid.h> 50 #include <cppuhelper/queryinterface.hxx> 51 #include <svl/itemset.hxx> 52 #include <editeng/unofdesc.hxx> 53 #include <editeng/outliner.hxx> 54 #include <svx/svdoutl.hxx> 55 #include <svx/svdetc.hxx> 56 #include <svx/unoshape.hxx> 57 #include <svx/unoprov.hxx> 58 #include <vcl/unohelp.hxx> 59 #include <toolkit/helper/vclunohelper.hxx> 60 #include <vcl/window.hxx> 61 62 #include <algorithm> 63 64 #include "ChartElementFactory.hxx" 65 66 using namespace ::com::sun::star; 67 using namespace ::com::sun::star::accessibility; 68 69 using ::com::sun::star::uno::UNO_QUERY; 70 using ::rtl::OUString; 71 using ::rtl::OUStringBuffer; 72 using ::com::sun::star::uno::Reference; 73 using ::osl::MutexGuard; 74 using ::osl::ClearableMutexGuard; 75 using ::osl::ResettableMutexGuard; 76 using ::com::sun::star::uno::RuntimeException; 77 using ::com::sun::star::uno::Any; 78 79 namespace chart 80 { 81 82 /** @param bMayHaveChildren is false per default 83 */ 84 AccessibleBase::AccessibleBase( 85 const AccessibleElementInfo & rAccInfo, 86 bool bMayHaveChildren, 87 bool bAlwaysTransparent /* default: false */ ) : 88 impl::AccessibleBase_Base( m_aMutex ), 89 m_bIsDisposed( false ), 90 m_bMayHaveChildren( bMayHaveChildren ), 91 m_bChildrenInitialized( false ), 92 m_nEventNotifierId(0), 93 m_pStateSetHelper( new ::utl::AccessibleStateSetHelper() ), 94 m_aStateSet( m_pStateSetHelper ), 95 m_aAccInfo( rAccInfo ), 96 m_bAlwaysTransparent( bAlwaysTransparent ), 97 m_bStateSetInitialized( false ) 98 { 99 // initialize some states 100 OSL_ASSERT( m_pStateSetHelper ); 101 m_pStateSetHelper->AddState( AccessibleStateType::ENABLED ); 102 m_pStateSetHelper->AddState( AccessibleStateType::SHOWING ); 103 m_pStateSetHelper->AddState( AccessibleStateType::VISIBLE ); 104 m_pStateSetHelper->AddState( AccessibleStateType::SELECTABLE ); 105 m_pStateSetHelper->AddState( AccessibleStateType::FOCUSABLE ); 106 } 107 108 AccessibleBase::~AccessibleBase() 109 { 110 OSL_ASSERT( m_bIsDisposed ); 111 } 112 113 // ________ public ________ 114 115 bool AccessibleBase::CheckDisposeState( bool bThrowException /* default: true */ ) const 116 throw (lang::DisposedException) 117 { 118 if( bThrowException && 119 m_bIsDisposed ) 120 { 121 throw lang::DisposedException( 122 C2U("component has state DEFUNC" ), 123 static_cast< uno::XWeak * >( const_cast< AccessibleBase * >( this ))); 124 } 125 return m_bIsDisposed; 126 } 127 128 bool AccessibleBase::NotifyEvent( EventType eEventType, const AccessibleUniqueId & rId ) 129 { 130 if( GetId() == rId ) 131 { 132 // event is addressed to this object 133 134 ::com::sun::star::uno::Any aEmpty; 135 ::com::sun::star::uno::Any aSelected; 136 aSelected <<= AccessibleStateType::SELECTED; 137 switch( eEventType ) 138 { 139 case OBJECT_CHANGE: 140 { 141 BroadcastAccEvent( AccessibleEventId::VISIBLE_DATA_CHANGED, aEmpty, aEmpty ); 142 #if OSL_DEBUG_LEVEL > 1 143 OSL_TRACE( 144 ::rtl::OUStringToOString( 145 OUString( RTL_CONSTASCII_USTRINGPARAM( 146 "Visible data event sent by: " )) + 147 getAccessibleName(), 148 RTL_TEXTENCODING_ASCII_US ).getStr() ); 149 #endif 150 } 151 break; 152 153 case GOT_SELECTION: 154 { 155 AddState( AccessibleStateType::SELECTED ); 156 BroadcastAccEvent( AccessibleEventId::STATE_CHANGED, aSelected, aEmpty ); 157 158 AddState( AccessibleStateType::FOCUSED ); 159 aSelected <<= AccessibleStateType::FOCUSED; 160 BroadcastAccEvent( AccessibleEventId::STATE_CHANGED, aSelected, aEmpty, true ); 161 #if OSL_DEBUG_LEVEL > 1 162 OSL_TRACE( 163 ::rtl::OUStringToOString( 164 OUString( RTL_CONSTASCII_USTRINGPARAM( 165 "Selection acquired by: " )) + 166 getAccessibleName(), 167 RTL_TEXTENCODING_ASCII_US ).getStr() ); 168 #endif 169 } 170 break; 171 172 case LOST_SELECTION: 173 { 174 RemoveState( AccessibleStateType::SELECTED ); 175 BroadcastAccEvent( AccessibleEventId::STATE_CHANGED, aEmpty, aSelected ); 176 177 AddState( AccessibleStateType::FOCUSED ); 178 aSelected <<= AccessibleStateType::FOCUSED; 179 BroadcastAccEvent( AccessibleEventId::STATE_CHANGED, aEmpty, aSelected, true ); 180 #if OSL_DEBUG_LEVEL > 1 181 OSL_TRACE( 182 ::rtl::OUStringToOString( 183 OUString( RTL_CONSTASCII_USTRINGPARAM( 184 "Selection lost by: " )) + 185 getAccessibleName(), 186 RTL_TEXTENCODING_ASCII_US ).getStr() ); 187 #endif 188 } 189 break; 190 191 case PROPERTY_CHANGE: 192 { 193 //not implemented --> rebuild all 194 } 195 break; 196 } 197 return true; 198 } 199 else if( m_bMayHaveChildren ) 200 { 201 bool bStop = false; 202 // /-- 203 ClearableMutexGuard aGuard( GetMutex() ); 204 // make local copy for notification 205 ChildListVectorType aLocalChildList( m_aChildList ); 206 aGuard.clear(); 207 // \-- 208 209 ChildListVectorType::iterator aEndIter = aLocalChildList.end(); 210 for( ChildListVectorType::iterator aIter = aLocalChildList.begin() ; 211 ( aIter != aEndIter ) && ( ! bStop ) ; 212 ++aIter ) 213 { 214 // Note: at this place we must be sure to have an AccessibleBase 215 // object in the UNO reference to XAccessible ! 216 bStop = (*static_cast< AccessibleBase * > 217 ( (*aIter).get() )).NotifyEvent( eEventType, rId ); 218 } 219 return bStop; 220 } 221 222 return false; 223 } 224 225 void AccessibleBase::AddState( sal_Int16 aState ) 226 throw (RuntimeException) 227 { 228 CheckDisposeState(); 229 OSL_ASSERT( m_pStateSetHelper ); 230 m_pStateSetHelper->AddState( aState ); 231 } 232 233 void AccessibleBase::RemoveState( sal_Int16 aState ) 234 throw (RuntimeException) 235 { 236 CheckDisposeState(); 237 OSL_ASSERT( m_pStateSetHelper ); 238 m_pStateSetHelper->RemoveState( aState ); 239 } 240 241 // ________ protected ________ 242 243 bool AccessibleBase::UpdateChildren() 244 { 245 bool bMustUpdateChildren = false; 246 { 247 // /-- 248 MutexGuard aGuard( GetMutex() ); 249 if( ! m_bMayHaveChildren || 250 m_bIsDisposed ) 251 return false; 252 253 bMustUpdateChildren = ( m_bMayHaveChildren && 254 ! m_bChildrenInitialized ); 255 // \-- 256 } 257 258 // update unguarded 259 if( bMustUpdateChildren ) 260 m_bChildrenInitialized = ImplUpdateChildren(); 261 262 return m_bChildrenInitialized; 263 } 264 265 bool AccessibleBase::ImplUpdateChildren() 266 { 267 bool bResult = false; 268 269 if( m_aAccInfo.m_spObjectHierarchy ) 270 { 271 ObjectHierarchy::tChildContainer aModelChildren( 272 m_aAccInfo.m_spObjectHierarchy->getChildren( GetId() )); 273 ::std::vector< ChildOIDMap::key_type > aAccChildren; 274 aAccChildren.reserve( aModelChildren.size()); 275 ::std::transform( m_aChildOIDMap.begin(), m_aChildOIDMap.end(), 276 ::std::back_inserter( aAccChildren ), 277 ::std::select1st< ChildOIDMap::value_type >()); 278 279 ::std::sort( aModelChildren.begin(), aModelChildren.end()); 280 281 ::std::vector< ObjectHierarchy::tOID > aChildrenToRemove, aChildrenToAdd; 282 ::std::set_difference( aModelChildren.begin(), aModelChildren.end(), 283 aAccChildren.begin(), aAccChildren.end(), 284 ::std::back_inserter( aChildrenToAdd )); 285 ::std::set_difference( aAccChildren.begin(), aAccChildren.end(), 286 aModelChildren.begin(), aModelChildren.end(), 287 ::std::back_inserter( aChildrenToRemove )); 288 289 ::std::vector< ObjectHierarchy::tOID >::const_iterator aIt( aChildrenToRemove.begin()); 290 for( ; aIt != aChildrenToRemove.end(); ++aIt ) 291 { 292 RemoveChildByOId( *aIt ); 293 } 294 295 AccessibleElementInfo aAccInfo( GetInfo()); 296 aAccInfo.m_pParent = this; 297 298 for( aIt = aChildrenToAdd.begin(); aIt != aChildrenToAdd.end(); ++aIt ) 299 { 300 aAccInfo.m_aOID = *aIt; 301 if ( aIt->isAutoGeneratedObject() ) 302 { 303 AddChild( ChartElementFactory::CreateChartElement( aAccInfo ) ); 304 } 305 else if ( aIt->isAdditionalShape() ) 306 { 307 AddChild( new AccessibleChartShape( aAccInfo, true, false ) ); 308 } 309 } 310 bResult = true; 311 } 312 313 return bResult; 314 } 315 316 void AccessibleBase::AddChild( AccessibleBase * pChild ) 317 { 318 OSL_ENSURE( pChild != NULL, "Invalid Child" ); 319 if( pChild ) 320 { 321 // /-- 322 ClearableMutexGuard aGuard( GetMutex() ); 323 324 Reference< XAccessible > xChild( pChild ); 325 m_aChildList.push_back( xChild ); 326 327 m_aChildOIDMap[ pChild->GetId() ] = xChild; 328 329 // inform listeners of new child 330 if( m_bChildrenInitialized ) 331 { 332 Any aEmpty, aNew; 333 aNew <<= xChild; 334 335 aGuard.clear(); 336 // \-- (1st) 337 BroadcastAccEvent( AccessibleEventId::CHILD, aNew, aEmpty ); 338 } 339 // \-- (2nd) 340 } 341 } 342 343 /** in this method we imply that the Reference< XAccessible > elements in the 344 vector are AccessibleBase objects ! 345 */ 346 void AccessibleBase::RemoveChildByOId( const ObjectIdentifier& rOId ) 347 { 348 // /-- 349 ClearableMutexGuard aGuard( GetMutex() ); 350 351 ChildOIDMap::iterator aIt( m_aChildOIDMap.find( rOId )); 352 if( aIt != m_aChildOIDMap.end()) 353 { 354 Reference< XAccessible > xChild( aIt->second ); 355 356 // remove from map 357 m_aChildOIDMap.erase( aIt ); 358 359 // search child in vector 360 ChildListVectorType::iterator aVecIter = 361 ::std::find( m_aChildList.begin(), m_aChildList.end(), xChild ); 362 363 OSL_ENSURE( aVecIter != m_aChildList.end(), 364 "Inconsistent ChildMap" ); 365 366 // remove child from vector 367 m_aChildList.erase( aVecIter ); 368 bool bInitialized = m_bChildrenInitialized; 369 370 // call listeners unguarded 371 aGuard.clear(); 372 // \-- (1st) 373 374 // inform listeners of removed child 375 if( bInitialized ) 376 { 377 Any aEmpty, aOld; 378 aOld <<= xChild; 379 380 BroadcastAccEvent( AccessibleEventId::CHILD, aEmpty, aOld ); 381 } 382 383 // dispose the child 384 Reference< lang::XComponent > xComp( xChild, UNO_QUERY ); 385 if( xComp.is()) 386 xComp->dispose(); 387 } 388 } 389 390 awt::Point AccessibleBase::GetUpperLeftOnScreen() const 391 { 392 awt::Point aResult; 393 if( m_aAccInfo.m_pParent ) 394 { 395 // /-- 396 ClearableMutexGuard aGuard( GetMutex() ); 397 AccessibleBase * pParent = m_aAccInfo.m_pParent; 398 aGuard.clear(); 399 // \-- 400 401 if( pParent ) 402 { 403 aResult = pParent->GetUpperLeftOnScreen(); 404 } 405 else 406 OSL_ENSURE( false, "Default position used is probably incorrect." ); 407 } 408 409 return aResult; 410 } 411 412 void AccessibleBase::BroadcastAccEvent( 413 sal_Int16 nId, 414 const Any & rNew, 415 const Any & rOld, 416 bool bSendGlobally ) const 417 { 418 // /-- 419 ClearableMutexGuard aGuard( GetMutex() ); 420 421 if ( !m_nEventNotifierId && !bSendGlobally ) 422 return; 423 // if we don't have a client id for the notifier, then we don't have listeners, then 424 // we don't need to notify anything 425 //except SendGlobally for focus handling? 426 427 // the const cast is needed, because UNO parameters are never const 428 const AccessibleEventObject aEvent( 429 const_cast< uno::XWeak * >( static_cast< const uno::XWeak * >( this )), 430 nId, rNew, rOld ); 431 432 if ( m_nEventNotifierId ) // let the notifier handle this event 433 ::comphelper::AccessibleEventNotifier::addEvent( m_nEventNotifierId, aEvent ); 434 435 aGuard.clear(); 436 // \-- 437 438 // send event to global message queue 439 if( bSendGlobally ) 440 { 441 ::vcl::unohelper::NotifyAccessibleStateEventGlobally( aEvent ); 442 } 443 } 444 445 void AccessibleBase::KillAllChildren() 446 { 447 // /-- 448 ClearableMutexGuard aGuard( GetMutex() ); 449 450 // make local copy for notification 451 ChildListVectorType aLocalChildList( m_aChildList ); 452 453 // remove all children 454 m_aChildList.clear(); 455 m_aChildOIDMap.clear(); 456 457 aGuard.clear(); 458 // \-- 459 460 // call dispose for all children 461 // and notify listeners 462 Reference< lang::XComponent > xComp; 463 Any aEmpty, aOld; 464 ChildListVectorType::const_iterator aEndIter = aLocalChildList.end(); 465 for( ChildListVectorType::const_iterator aIter = aLocalChildList.begin(); 466 aIter != aEndIter; ++aIter ) 467 { 468 aOld <<= (*aIter); 469 BroadcastAccEvent( AccessibleEventId::CHILD, aEmpty, aOld ); 470 471 xComp.set( *aIter, UNO_QUERY ); 472 if( xComp.is()) 473 xComp->dispose(); 474 } 475 m_bChildrenInitialized = false; 476 } 477 478 AccessibleElementInfo AccessibleBase::GetInfo() const 479 { 480 return m_aAccInfo; 481 } 482 483 void AccessibleBase::SetInfo( const AccessibleElementInfo & rNewInfo ) 484 { 485 m_aAccInfo = rNewInfo; 486 if( m_bMayHaveChildren ) 487 { 488 KillAllChildren(); 489 } 490 BroadcastAccEvent( AccessibleEventId::INVALIDATE_ALL_CHILDREN, uno::Any(), uno::Any(), 491 true /* global notification */ ); 492 } 493 494 AccessibleUniqueId AccessibleBase::GetId() const 495 { 496 return m_aAccInfo.m_aOID; 497 } 498 499 // ____________________________________ 500 // ____________________________________ 501 // 502 // Interfaces 503 // ____________________________________ 504 // ____________________________________ 505 506 // ________ (XComponent::dispose) ________ 507 void SAL_CALL AccessibleBase::disposing() 508 { 509 // /-- 510 ClearableMutexGuard aGuard( GetMutex() ); 511 OSL_ENSURE( ! m_bIsDisposed, "dispose() called twice" ); 512 513 // notify disposing to all AccessibleEvent listeners asynchron 514 if ( m_nEventNotifierId ) 515 { 516 ::comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( m_nEventNotifierId, *this ); 517 m_nEventNotifierId = 0; 518 } 519 520 // reset pointers 521 m_aAccInfo.m_pParent = NULL; 522 523 // invalidate implementation for helper, but keep UNO reference to still 524 // allow a tool to query the DEFUNC state. 525 // Note: The object will be deleted when the last reference is released 526 m_pStateSetHelper = NULL; 527 528 // attach new empty state set helper to member reference 529 ::utl::AccessibleStateSetHelper * pHelper = new ::utl::AccessibleStateSetHelper(); 530 pHelper->AddState( AccessibleStateType::DEFUNC ); 531 // release old helper and attach new one 532 m_aStateSet.set( pHelper ); 533 534 m_bIsDisposed = true; 535 536 // call listeners unguarded 537 aGuard.clear(); 538 // \-- 539 540 if( m_bMayHaveChildren ) 541 { 542 KillAllChildren(); 543 } 544 else 545 OSL_ENSURE( m_aChildList.empty(), "Child list should be empty" ); 546 } 547 548 // ________ XAccessible ________ 549 Reference< XAccessibleContext > SAL_CALL AccessibleBase::getAccessibleContext() 550 throw (RuntimeException) 551 { 552 return this; 553 } 554 555 // ________ AccessibleBase::XAccessibleContext ________ 556 sal_Int32 SAL_CALL AccessibleBase::getAccessibleChildCount() 557 throw (RuntimeException) 558 { 559 // /-- 560 ClearableMutexGuard aGuard( GetMutex() ); 561 if( ! m_bMayHaveChildren || 562 m_bIsDisposed ) 563 return 0; 564 565 bool bMustUpdateChildren = ( m_bMayHaveChildren && 566 ! m_bChildrenInitialized ); 567 568 aGuard.clear(); 569 // \-- 570 571 // update unguarded 572 if( bMustUpdateChildren ) 573 UpdateChildren(); 574 575 return ImplGetAccessibleChildCount(); 576 } 577 578 sal_Int32 AccessibleBase::ImplGetAccessibleChildCount() const 579 throw (RuntimeException) 580 { 581 return m_aChildList.size(); 582 } 583 584 Reference< XAccessible > SAL_CALL AccessibleBase::getAccessibleChild( sal_Int32 i ) 585 throw (lang::IndexOutOfBoundsException, RuntimeException) 586 { 587 CheckDisposeState(); 588 Reference< XAccessible > xResult; 589 590 // /-- 591 ResettableMutexGuard aGuard( GetMutex() ); 592 bool bMustUpdateChildren = ( m_bMayHaveChildren && 593 ! m_bChildrenInitialized ); 594 595 aGuard.clear(); 596 // \-- 597 598 if( bMustUpdateChildren ) 599 UpdateChildren(); 600 601 xResult.set( ImplGetAccessibleChildById( i )); 602 603 return xResult; 604 // \-- 605 } 606 607 Reference< XAccessible > AccessibleBase::ImplGetAccessibleChildById( sal_Int32 i ) const 608 throw (lang::IndexOutOfBoundsException, RuntimeException) 609 { 610 Reference< XAccessible > xResult; 611 // /-- 612 MutexGuard aGuard( GetMutex()); 613 if( ! m_bMayHaveChildren || 614 i < 0 || 615 static_cast< ChildListVectorType::size_type >( i ) >= m_aChildList.size() ) 616 { 617 OUStringBuffer aBuf; 618 aBuf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "Index " )); 619 aBuf.append( i ); 620 aBuf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " is invalid for range [ 0, " )); 621 aBuf.append( static_cast< sal_Int32 >( m_aChildList.size() - 1 ) ); 622 aBuf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " ]" ) ); 623 lang::IndexOutOfBoundsException aEx( aBuf.makeStringAndClear(), 624 const_cast< ::cppu::OWeakObject * >( 625 static_cast< const ::cppu::OWeakObject * >( this ))); 626 throw aEx; 627 } 628 else 629 xResult.set( m_aChildList[ i ] ); 630 631 return xResult; 632 } 633 634 Reference< XAccessible > SAL_CALL AccessibleBase::getAccessibleParent() 635 throw (RuntimeException) 636 { 637 CheckDisposeState(); 638 Reference< XAccessible > aResult; 639 if( m_aAccInfo.m_pParent ) 640 aResult.set( m_aAccInfo.m_pParent ); 641 642 return aResult; 643 } 644 645 sal_Int32 SAL_CALL AccessibleBase::getAccessibleIndexInParent() 646 throw (RuntimeException) 647 { 648 CheckDisposeState(); 649 650 if( m_aAccInfo.m_spObjectHierarchy ) 651 return m_aAccInfo.m_spObjectHierarchy->getIndexInParent( GetId() ); 652 return -1; 653 } 654 655 sal_Int16 SAL_CALL AccessibleBase::getAccessibleRole() 656 throw (RuntimeException) 657 { 658 return AccessibleRole::LIST_ITEM; // #i73747# role SHAPE seems more appropriate, but is not read 659 } 660 661 Reference< XAccessibleRelationSet > SAL_CALL AccessibleBase::getAccessibleRelationSet() 662 throw (RuntimeException) 663 { 664 Reference< XAccessibleRelationSet > aResult; 665 return aResult; 666 } 667 668 Reference< XAccessibleStateSet > SAL_CALL AccessibleBase::getAccessibleStateSet() 669 throw (RuntimeException) 670 { 671 if( ! m_bStateSetInitialized ) 672 { 673 Reference< view::XSelectionSupplier > xSelSupp( GetInfo().m_xSelectionSupplier ); 674 if ( xSelSupp.is() ) 675 { 676 ObjectIdentifier aOID( xSelSupp->getSelection() ); 677 if ( aOID.isValid() && GetId() == aOID ) 678 { 679 AddState( AccessibleStateType::SELECTED ); 680 AddState( AccessibleStateType::FOCUSED ); 681 } 682 } 683 m_bStateSetInitialized = true; 684 } 685 686 return m_aStateSet; 687 } 688 689 690 lang::Locale SAL_CALL AccessibleBase::getLocale() 691 throw (IllegalAccessibleComponentStateException, RuntimeException) 692 { 693 CheckDisposeState(); 694 695 return Application::GetSettings().GetLocale(); 696 } 697 698 // ________ AccessibleBase::XAccessibleComponent ________ 699 sal_Bool SAL_CALL AccessibleBase::containsPoint( const awt::Point& aPoint ) 700 throw (RuntimeException) 701 { 702 awt::Rectangle aRect( getBounds() ); 703 704 // contains() works with relative coordinates 705 aRect.X = 0; 706 aRect.Y = 0; 707 708 return ( aPoint.X >= aRect.X && 709 aPoint.Y >= aRect.Y && 710 aPoint.X < (aRect.X + aRect.Width) && 711 aPoint.Y < (aRect.Y + aRect.Height) ); 712 } 713 714 Reference< XAccessible > SAL_CALL AccessibleBase::getAccessibleAtPoint( const awt::Point& aPoint ) 715 throw (RuntimeException) 716 { 717 CheckDisposeState(); 718 Reference< XAccessible > aResult; 719 awt::Rectangle aRect( getBounds()); 720 721 // children are positioned relative to this object, so translate bound rect 722 aRect.X = 0; 723 aRect.Y = 0; 724 725 // children must be inside the own bound rect 726 if( ( aRect.X <= aPoint.X && aPoint.X <= (aRect.X + aRect.Width) ) && 727 ( aRect.Y <= aPoint.Y && aPoint.Y <= (aRect.Y + aRect.Height))) 728 { 729 // /-- 730 ClearableMutexGuard aGuard( GetMutex() ); 731 ChildListVectorType aLocalChildList( m_aChildList ); 732 aGuard.clear(); 733 // \-- 734 735 Reference< XAccessibleComponent > aComp; 736 for( ChildListVectorType::const_iterator aIter = aLocalChildList.begin(); 737 aIter != aLocalChildList.end(); ++aIter ) 738 { 739 aComp.set( *aIter, UNO_QUERY ); 740 if( aComp.is()) 741 { 742 aRect = aComp->getBounds(); 743 if( ( aRect.X <= aPoint.X && aPoint.X <= (aRect.X + aRect.Width) ) && 744 ( aRect.Y <= aPoint.Y && aPoint.Y <= (aRect.Y + aRect.Height))) 745 { 746 aResult = (*aIter); 747 break; 748 } 749 } 750 } 751 } 752 753 return aResult; 754 } 755 756 awt::Rectangle SAL_CALL AccessibleBase::getBounds() 757 throw (RuntimeException) 758 { 759 ExplicitValueProvider *pExplicitValueProvider( 760 ExplicitValueProvider::getExplicitValueProvider( m_aAccInfo.m_xView )); 761 if( pExplicitValueProvider ) 762 { 763 Window* pWindow( VCLUnoHelper::GetWindow( m_aAccInfo.m_xWindow )); 764 awt::Rectangle aLogicRect( pExplicitValueProvider->getRectangleOfObject( m_aAccInfo.m_aOID.getObjectCID() )); 765 if( pWindow ) 766 { 767 Rectangle aRect( aLogicRect.X, aLogicRect.Y, 768 aLogicRect.X + aLogicRect.Width, 769 aLogicRect.Y + aLogicRect.Height ); 770 // /-- solar 771 ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); 772 aRect = pWindow->LogicToPixel( aRect ); 773 774 // aLogicRect ist relative to the page, but we need a value relative 775 // to the parent object 776 awt::Point aParentLocOnScreen; 777 uno::Reference< XAccessibleComponent > xParent( getAccessibleParent(), uno::UNO_QUERY ); 778 if( xParent.is() ) 779 aParentLocOnScreen = xParent->getLocationOnScreen(); 780 781 // aOffset = aParentLocOnScreen - GetUpperLeftOnScreen() 782 awt::Point aULOnScreen = GetUpperLeftOnScreen(); 783 awt::Point aOffset( aParentLocOnScreen.X - aULOnScreen.X, 784 aParentLocOnScreen.Y - aULOnScreen.Y ); 785 786 return awt::Rectangle( aRect.getX() - aOffset.X, aRect.getY() - aOffset.Y, 787 aRect.getWidth(), aRect.getHeight()); 788 // \-- solar 789 } 790 } 791 792 return awt::Rectangle(); 793 } 794 795 awt::Point SAL_CALL AccessibleBase::getLocation() 796 throw (RuntimeException) 797 { 798 CheckDisposeState(); 799 awt::Rectangle aBBox( getBounds() ); 800 return awt::Point( aBBox.X, aBBox.Y ); 801 } 802 803 awt::Point SAL_CALL AccessibleBase::getLocationOnScreen() 804 throw (RuntimeException) 805 { 806 CheckDisposeState(); 807 808 if( m_aAccInfo.m_pParent != NULL ) 809 { 810 AccessibleBase * pParent = m_aAccInfo.m_pParent; 811 awt::Point aLocThisRel( getLocation()); 812 awt::Point aUpperLeft; 813 814 if( pParent != NULL ) 815 aUpperLeft = pParent->getLocationOnScreen(); 816 817 return awt::Point( aUpperLeft.X + aLocThisRel.X, 818 aUpperLeft.Y + aLocThisRel.Y ); 819 } 820 else 821 return getLocation(); 822 } 823 824 awt::Size SAL_CALL AccessibleBase::getSize() 825 throw (RuntimeException) 826 { 827 CheckDisposeState(); 828 awt::Rectangle aBBox( getBounds() ); 829 return awt::Size( aBBox.Width, aBBox.Height ); 830 } 831 832 void SAL_CALL AccessibleBase::grabFocus() 833 throw (RuntimeException) 834 { 835 CheckDisposeState(); 836 837 Reference< view::XSelectionSupplier > xSelSupp( GetInfo().m_xSelectionSupplier ); 838 if ( xSelSupp.is() ) 839 { 840 xSelSupp->select( GetId().getAny() ); 841 } 842 } 843 844 sal_Int32 SAL_CALL AccessibleBase::getForeground() 845 throw (RuntimeException) 846 { 847 return getColor( ACC_BASE_FOREGROUND ); 848 } 849 850 sal_Int32 SAL_CALL AccessibleBase::getBackground() 851 throw (RuntimeException) 852 { 853 return getColor( ACC_BASE_BACKGROUND ); 854 } 855 856 sal_Int32 AccessibleBase::getColor( eColorType eColType ) 857 { 858 sal_Int32 nResult = static_cast< sal_Int32 >( Color( COL_TRANSPARENT ).GetColor()); 859 if( m_bAlwaysTransparent ) 860 return nResult; 861 862 ObjectIdentifier aOID( m_aAccInfo.m_aOID ); 863 ObjectType eType( aOID.getObjectType() ); 864 Reference< beans::XPropertySet > xObjProp; 865 OUString aObjectCID = aOID.getObjectCID(); 866 if( eType == OBJECTTYPE_LEGEND_ENTRY ) 867 { 868 // for colors get the data series/point properties 869 OUString aParentParticle( ObjectIdentifier::getFullParentParticle( aObjectCID )); 870 aObjectCID = ObjectIdentifier::createClassifiedIdentifierForParticle( aParentParticle ); 871 } 872 873 xObjProp.set( 874 ObjectIdentifier::getObjectPropertySet( 875 aObjectCID, Reference< chart2::XChartDocument >( m_aAccInfo.m_xChartDocument )), uno::UNO_QUERY ); 876 if( xObjProp.is()) 877 { 878 try 879 { 880 OUString aPropName; 881 OUString aStylePropName; 882 883 switch( eType ) 884 { 885 case OBJECTTYPE_LEGEND_ENTRY: 886 case OBJECTTYPE_DATA_SERIES: 887 case OBJECTTYPE_DATA_POINT: 888 if( eColType == ACC_BASE_FOREGROUND ) 889 { 890 aPropName = C2U("BorderColor"); 891 aStylePropName = C2U("BorderTransparency"); 892 } 893 else 894 { 895 aPropName = C2U("Color"); 896 aStylePropName = C2U("Transparency"); 897 } 898 break; 899 default: 900 if( eColType == ACC_BASE_FOREGROUND ) 901 { 902 aPropName = C2U("LineColor"); 903 aStylePropName = C2U("LineTransparence"); 904 } 905 else 906 { 907 aPropName = C2U("FillColor"); 908 aStylePropName = C2U("FillTransparence"); 909 } 910 break; 911 } 912 913 bool bTransparent = m_bAlwaysTransparent; 914 Reference< beans::XPropertySetInfo > xInfo( xObjProp->getPropertySetInfo(), uno::UNO_QUERY ); 915 if( xInfo.is() && 916 xInfo->hasPropertyByName( aStylePropName )) 917 { 918 if( eColType == ACC_BASE_FOREGROUND ) 919 { 920 drawing::LineStyle aLStyle; 921 if( xObjProp->getPropertyValue( aStylePropName ) >>= aLStyle ) 922 bTransparent = (aLStyle == drawing::LineStyle_NONE); 923 } 924 else 925 { 926 drawing::FillStyle aFStyle; 927 if( xObjProp->getPropertyValue( aStylePropName ) >>= aFStyle ) 928 bTransparent = (aFStyle == drawing::FillStyle_NONE); 929 } 930 } 931 932 if( !bTransparent && 933 xInfo.is() && 934 xInfo->hasPropertyByName( aPropName )) 935 { 936 xObjProp->getPropertyValue( aPropName ) >>= nResult; 937 } 938 } 939 catch( const uno::Exception & ex ) 940 { 941 ASSERT_EXCEPTION( ex ); 942 } 943 } 944 945 return nResult; 946 } 947 948 // ________ AccessibleBase::XServiceInfo ________ 949 OUString SAL_CALL AccessibleBase::getImplementationName() 950 throw (RuntimeException) 951 { 952 return OUString( RTL_CONSTASCII_USTRINGPARAM( "AccessibleBase" )); 953 } 954 955 sal_Bool SAL_CALL AccessibleBase::supportsService( const OUString& ServiceName ) 956 throw (RuntimeException) 957 { 958 return comphelper::ServiceInfoHelper::supportsService( ServiceName, getSupportedServiceNames() ); 959 } 960 961 uno::Sequence< OUString > SAL_CALL AccessibleBase::getSupportedServiceNames() 962 throw (RuntimeException) 963 { 964 uno::Sequence< ::rtl::OUString > aSeq( 2 ); 965 ::rtl::OUString* pStr = aSeq.getArray(); 966 pStr[ 0 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.accessibility.Accessible" )); 967 pStr[ 1 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.accessibility.AccessibleContext" )); 968 969 return aSeq; 970 } 971 972 // ________ AccessibleBase::XEventListener ________ 973 void SAL_CALL AccessibleBase::disposing( const lang::EventObject& /*Source*/ ) 974 throw (RuntimeException) 975 { 976 } 977 978 // ________ XAccessibleEventBroadcasters ________ 979 void SAL_CALL AccessibleBase::addEventListener( const Reference< XAccessibleEventListener >& xListener ) 980 throw (RuntimeException) 981 { 982 MutexGuard aGuard( GetMutex() ); 983 984 if ( xListener.is() ) 985 { 986 if ( !m_nEventNotifierId ) 987 m_nEventNotifierId = ::comphelper::AccessibleEventNotifier::registerClient(); 988 989 ::comphelper::AccessibleEventNotifier::addEventListener( m_nEventNotifierId, xListener ); 990 } 991 } 992 993 void SAL_CALL AccessibleBase::removeEventListener( const Reference< XAccessibleEventListener >& xListener ) 994 throw (RuntimeException) 995 { 996 MutexGuard aGuard( GetMutex() ); 997 998 if ( xListener.is() ) 999 { 1000 sal_Int32 nListenerCount = ::comphelper::AccessibleEventNotifier::removeEventListener( m_nEventNotifierId, xListener ); 1001 if ( !nListenerCount ) 1002 { 1003 // no listeners anymore 1004 ::comphelper::AccessibleEventNotifier::revokeClient( m_nEventNotifierId ); 1005 m_nEventNotifierId = 0; 1006 } 1007 } 1008 } 1009 1010 } // namespace chart 1011