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