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