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 //IAccessibility2 Implementation 2009----- 655 return AccessibleRole::SHAPE/*LIST_ITEM*/; // #i73747# role SHAPE seems more appropriate, but is not read 656 //-----IAccessibility2 Implementation 2009 657 } 658 659 Reference< XAccessibleRelationSet > SAL_CALL AccessibleBase::getAccessibleRelationSet() 660 throw (RuntimeException) 661 { 662 Reference< XAccessibleRelationSet > aResult; 663 return aResult; 664 } 665 666 Reference< XAccessibleStateSet > SAL_CALL AccessibleBase::getAccessibleStateSet() 667 throw (RuntimeException) 668 { 669 if( ! m_bStateSetInitialized ) 670 { 671 Reference< view::XSelectionSupplier > xSelSupp( GetInfo().m_xSelectionSupplier ); 672 if ( xSelSupp.is() ) 673 { 674 ObjectIdentifier aOID( xSelSupp->getSelection() ); 675 if ( aOID.isValid() && GetId() == aOID ) 676 { 677 AddState( AccessibleStateType::SELECTED ); 678 AddState( AccessibleStateType::FOCUSED ); 679 } 680 } 681 m_bStateSetInitialized = true; 682 } 683 684 return m_aStateSet; 685 } 686 687 688 lang::Locale SAL_CALL AccessibleBase::getLocale() 689 throw (IllegalAccessibleComponentStateException, RuntimeException) 690 { 691 CheckDisposeState(); 692 693 return Application::GetSettings().GetLocale(); 694 } 695 696 // ________ AccessibleBase::XAccessibleComponent ________ 697 sal_Bool SAL_CALL AccessibleBase::containsPoint( const awt::Point& aPoint ) 698 throw (RuntimeException) 699 { 700 awt::Rectangle aRect( getBounds() ); 701 702 // contains() works with relative coordinates 703 aRect.X = 0; 704 aRect.Y = 0; 705 706 return ( aPoint.X >= aRect.X && 707 aPoint.Y >= aRect.Y && 708 aPoint.X < (aRect.X + aRect.Width) && 709 aPoint.Y < (aRect.Y + aRect.Height) ); 710 } 711 712 Reference< XAccessible > SAL_CALL AccessibleBase::getAccessibleAtPoint( const awt::Point& aPoint ) 713 throw (RuntimeException) 714 { 715 CheckDisposeState(); 716 Reference< XAccessible > aResult; 717 awt::Rectangle aRect( getBounds()); 718 719 // children are positioned relative to this object, so translate bound rect 720 aRect.X = 0; 721 aRect.Y = 0; 722 723 // children must be inside the own bound rect 724 if( ( aRect.X <= aPoint.X && aPoint.X <= (aRect.X + aRect.Width) ) && 725 ( aRect.Y <= aPoint.Y && aPoint.Y <= (aRect.Y + aRect.Height))) 726 { 727 // /-- 728 ClearableMutexGuard aGuard( GetMutex() ); 729 ChildListVectorType aLocalChildList( m_aChildList ); 730 aGuard.clear(); 731 // \-- 732 733 Reference< XAccessibleComponent > aComp; 734 for( ChildListVectorType::const_iterator aIter = aLocalChildList.begin(); 735 aIter != aLocalChildList.end(); ++aIter ) 736 { 737 aComp.set( *aIter, UNO_QUERY ); 738 if( aComp.is()) 739 { 740 aRect = aComp->getBounds(); 741 if( ( aRect.X <= aPoint.X && aPoint.X <= (aRect.X + aRect.Width) ) && 742 ( aRect.Y <= aPoint.Y && aPoint.Y <= (aRect.Y + aRect.Height))) 743 { 744 aResult = (*aIter); 745 break; 746 } 747 } 748 } 749 } 750 751 return aResult; 752 } 753 754 awt::Rectangle SAL_CALL AccessibleBase::getBounds() 755 throw (RuntimeException) 756 { 757 ExplicitValueProvider *pExplicitValueProvider( 758 ExplicitValueProvider::getExplicitValueProvider( m_aAccInfo.m_xView )); 759 if( pExplicitValueProvider ) 760 { 761 Window* pWindow( VCLUnoHelper::GetWindow( m_aAccInfo.m_xWindow )); 762 awt::Rectangle aLogicRect( pExplicitValueProvider->getRectangleOfObject( m_aAccInfo.m_aOID.getObjectCID() )); 763 if( pWindow ) 764 { 765 Rectangle aRect( aLogicRect.X, aLogicRect.Y, 766 aLogicRect.X + aLogicRect.Width, 767 aLogicRect.Y + aLogicRect.Height ); 768 // /-- solar 769 ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); 770 aRect = pWindow->LogicToPixel( aRect ); 771 772 // aLogicRect ist relative to the page, but we need a value relative 773 // to the parent object 774 awt::Point aParentLocOnScreen; 775 uno::Reference< XAccessibleComponent > xParent( getAccessibleParent(), uno::UNO_QUERY ); 776 if( xParent.is() ) 777 aParentLocOnScreen = xParent->getLocationOnScreen(); 778 779 // aOffset = aParentLocOnScreen - GetUpperLeftOnScreen() 780 awt::Point aULOnScreen = GetUpperLeftOnScreen(); 781 awt::Point aOffset( aParentLocOnScreen.X - aULOnScreen.X, 782 aParentLocOnScreen.Y - aULOnScreen.Y ); 783 784 return awt::Rectangle( aRect.getX() - aOffset.X, aRect.getY() - aOffset.Y, 785 aRect.getWidth(), aRect.getHeight()); 786 // \-- solar 787 } 788 } 789 790 return awt::Rectangle(); 791 } 792 793 awt::Point SAL_CALL AccessibleBase::getLocation() 794 throw (RuntimeException) 795 { 796 CheckDisposeState(); 797 awt::Rectangle aBBox( getBounds() ); 798 return awt::Point( aBBox.X, aBBox.Y ); 799 } 800 801 awt::Point SAL_CALL AccessibleBase::getLocationOnScreen() 802 throw (RuntimeException) 803 { 804 CheckDisposeState(); 805 806 if( m_aAccInfo.m_pParent != NULL ) 807 { 808 AccessibleBase * pParent = m_aAccInfo.m_pParent; 809 awt::Point aLocThisRel( getLocation()); 810 awt::Point aUpperLeft; 811 812 if( pParent != NULL ) 813 aUpperLeft = pParent->getLocationOnScreen(); 814 815 return awt::Point( aUpperLeft.X + aLocThisRel.X, 816 aUpperLeft.Y + aLocThisRel.Y ); 817 } 818 else 819 return getLocation(); 820 } 821 822 awt::Size SAL_CALL AccessibleBase::getSize() 823 throw (RuntimeException) 824 { 825 CheckDisposeState(); 826 awt::Rectangle aBBox( getBounds() ); 827 return awt::Size( aBBox.Width, aBBox.Height ); 828 } 829 830 void SAL_CALL AccessibleBase::grabFocus() 831 throw (RuntimeException) 832 { 833 CheckDisposeState(); 834 835 Reference< view::XSelectionSupplier > xSelSupp( GetInfo().m_xSelectionSupplier ); 836 if ( xSelSupp.is() ) 837 { 838 xSelSupp->select( GetId().getAny() ); 839 } 840 } 841 842 sal_Int32 SAL_CALL AccessibleBase::getForeground() 843 throw (RuntimeException) 844 { 845 return getColor( ACC_BASE_FOREGROUND ); 846 } 847 848 sal_Int32 SAL_CALL AccessibleBase::getBackground() 849 throw (RuntimeException) 850 { 851 return getColor( ACC_BASE_BACKGROUND ); 852 } 853 854 sal_Int32 AccessibleBase::getColor( eColorType eColType ) 855 { 856 sal_Int32 nResult = static_cast< sal_Int32 >( Color( COL_TRANSPARENT ).GetColor()); 857 if( m_bAlwaysTransparent ) 858 return nResult; 859 860 ObjectIdentifier aOID( m_aAccInfo.m_aOID ); 861 ObjectType eType( aOID.getObjectType() ); 862 Reference< beans::XPropertySet > xObjProp; 863 OUString aObjectCID = aOID.getObjectCID(); 864 if( eType == OBJECTTYPE_LEGEND_ENTRY ) 865 { 866 // for colors get the data series/point properties 867 OUString aParentParticle( ObjectIdentifier::getFullParentParticle( aObjectCID )); 868 aObjectCID = ObjectIdentifier::createClassifiedIdentifierForParticle( aParentParticle ); 869 } 870 871 xObjProp.set( 872 ObjectIdentifier::getObjectPropertySet( 873 aObjectCID, Reference< chart2::XChartDocument >( m_aAccInfo.m_xChartDocument )), uno::UNO_QUERY ); 874 if( xObjProp.is()) 875 { 876 try 877 { 878 OUString aPropName; 879 OUString aStylePropName; 880 881 switch( eType ) 882 { 883 case OBJECTTYPE_LEGEND_ENTRY: 884 case OBJECTTYPE_DATA_SERIES: 885 case OBJECTTYPE_DATA_POINT: 886 if( eColType == ACC_BASE_FOREGROUND ) 887 { 888 aPropName = C2U("BorderColor"); 889 aStylePropName = C2U("BorderTransparency"); 890 } 891 else 892 { 893 aPropName = C2U("Color"); 894 aStylePropName = C2U("Transparency"); 895 } 896 break; 897 default: 898 if( eColType == ACC_BASE_FOREGROUND ) 899 { 900 aPropName = C2U("LineColor"); 901 aStylePropName = C2U("LineTransparence"); 902 } 903 else 904 { 905 aPropName = C2U("FillColor"); 906 aStylePropName = C2U("FillTransparence"); 907 } 908 break; 909 } 910 911 bool bTransparent = m_bAlwaysTransparent; 912 Reference< beans::XPropertySetInfo > xInfo( xObjProp->getPropertySetInfo(), uno::UNO_QUERY ); 913 if( xInfo.is() && 914 xInfo->hasPropertyByName( aStylePropName )) 915 { 916 if( eColType == ACC_BASE_FOREGROUND ) 917 { 918 drawing::LineStyle aLStyle; 919 if( xObjProp->getPropertyValue( aStylePropName ) >>= aLStyle ) 920 bTransparent = (aLStyle == drawing::LineStyle_NONE); 921 } 922 else 923 { 924 drawing::FillStyle aFStyle; 925 if( xObjProp->getPropertyValue( aStylePropName ) >>= aFStyle ) 926 bTransparent = (aFStyle == drawing::FillStyle_NONE); 927 } 928 } 929 930 if( !bTransparent && 931 xInfo.is() && 932 xInfo->hasPropertyByName( aPropName )) 933 { 934 xObjProp->getPropertyValue( aPropName ) >>= nResult; 935 } 936 } 937 catch( const uno::Exception & ex ) 938 { 939 ASSERT_EXCEPTION( ex ); 940 } 941 } 942 943 return nResult; 944 } 945 946 // ________ AccessibleBase::XServiceInfo ________ 947 OUString SAL_CALL AccessibleBase::getImplementationName() 948 throw (RuntimeException) 949 { 950 return OUString( RTL_CONSTASCII_USTRINGPARAM( "AccessibleBase" )); 951 } 952 953 sal_Bool SAL_CALL AccessibleBase::supportsService( const OUString& ServiceName ) 954 throw (RuntimeException) 955 { 956 return comphelper::ServiceInfoHelper::supportsService( ServiceName, getSupportedServiceNames() ); 957 } 958 959 uno::Sequence< OUString > SAL_CALL AccessibleBase::getSupportedServiceNames() 960 throw (RuntimeException) 961 { 962 uno::Sequence< ::rtl::OUString > aSeq( 2 ); 963 ::rtl::OUString* pStr = aSeq.getArray(); 964 pStr[ 0 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.accessibility.Accessible" )); 965 pStr[ 1 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.accessibility.AccessibleContext" )); 966 967 return aSeq; 968 } 969 970 // ________ AccessibleBase::XEventListener ________ 971 void SAL_CALL AccessibleBase::disposing( const lang::EventObject& /*Source*/ ) 972 throw (RuntimeException) 973 { 974 } 975 976 // ________ XAccessibleEventBroadcasters ________ 977 void SAL_CALL AccessibleBase::addEventListener( const Reference< XAccessibleEventListener >& xListener ) 978 throw (RuntimeException) 979 { 980 MutexGuard aGuard( GetMutex() ); 981 982 if ( xListener.is() ) 983 { 984 if ( !m_nEventNotifierId ) 985 m_nEventNotifierId = ::comphelper::AccessibleEventNotifier::registerClient(); 986 987 ::comphelper::AccessibleEventNotifier::addEventListener( m_nEventNotifierId, xListener ); 988 } 989 } 990 991 void SAL_CALL AccessibleBase::removeEventListener( const Reference< XAccessibleEventListener >& xListener ) 992 throw (RuntimeException) 993 { 994 MutexGuard aGuard( GetMutex() ); 995 996 if ( xListener.is() ) 997 { 998 sal_Int32 nListenerCount = ::comphelper::AccessibleEventNotifier::removeEventListener( m_nEventNotifierId, xListener ); 999 if ( !nListenerCount ) 1000 { 1001 // no listeners anymore 1002 ::comphelper::AccessibleEventNotifier::revokeClient( m_nEventNotifierId ); 1003 m_nEventNotifierId = 0; 1004 } 1005 } 1006 } 1007 1008 } // namespace chart 1009