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 #include "precompiled_sd.hxx" 29 30 #include "AccessibleSlideSorterView.hxx" 31 #include "AccessibleSlideSorterObject.hxx" 32 33 #include "SlideSorter.hxx" 34 #include "controller/SlideSorterController.hxx" 35 #include "controller/SlsPageSelector.hxx" 36 #include "controller/SlsFocusManager.hxx" 37 #include "controller/SlsSelectionManager.hxx" 38 #include "view/SlideSorterView.hxx" 39 #include "model/SlideSorterModel.hxx" 40 #include "model/SlsPageDescriptor.hxx" 41 #include "SlideSorterViewShell.hxx" 42 43 #include "ViewShellHint.hxx" 44 #include "sdpage.hxx" 45 #include "drawdoc.hxx" 46 47 #include "sdresid.hxx" 48 #include "accessibility.hrc" 49 #include <com/sun/star/accessibility/AccessibleRole.hpp> 50 #include <com/sun/star/accessibility/AccessibleEventId.hpp> 51 #include <com/sun/star/accessibility/AccessibleStateType.hpp> 52 #include <comphelper/accessibleeventnotifier.hxx> 53 #include <unotools/accessiblestatesethelper.hxx> 54 #include <rtl/ref.hxx> 55 #include <vcl/svapp.hxx> 56 57 using ::rtl::OUString; 58 using namespace ::com::sun::star; 59 using namespace ::com::sun::star::uno; 60 using namespace ::com::sun::star::accessibility; 61 62 namespace accessibility { 63 64 65 /** Inner implementation class of the AccessibleSlideSorterView. 66 67 Note that some event broadcasting is done asynchronously because 68 otherwise it could lead to deadlocks on (at least) some Solaris 69 machines. Probably (but unverified) this can happen on all GTK based 70 systems. The asynchronous broadcasting is just a workaround for a 71 poorly understood problem. 72 */ 73 class AccessibleSlideSorterView::Implementation 74 : public SfxListener 75 { 76 public: 77 Implementation ( 78 AccessibleSlideSorterView& rAccessibleSlideSorter, 79 ::sd::slidesorter::SlideSorter& rSlideSorter, 80 ::Window* pWindow); 81 ~Implementation (void); 82 83 void RequestUpdateChildren (void); 84 void Clear (void); 85 sal_Int32 GetVisibleChildCount (void) const; 86 AccessibleSlideSorterObject* GetAccessibleChild (sal_Int32 nIndex); 87 AccessibleSlideSorterObject* GetVisibleChild (sal_Int32 nIndex); 88 89 void ConnectListeners (void); 90 void ReleaseListeners (void); 91 void Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint); 92 DECL_LINK(WindowEventListener, VclWindowEvent*); 93 DECL_LINK(SelectionChangeListener, void*); 94 DECL_LINK(BroadcastSelectionChange, void*); 95 DECL_LINK(FocusChangeListener, void*); 96 DECL_LINK(UpdateChildrenCallback, void*); 97 98 private: 99 AccessibleSlideSorterView& mrAccessibleSlideSorter; 100 ::sd::slidesorter::SlideSorter& mrSlideSorter; 101 typedef ::std::vector<rtl::Reference<AccessibleSlideSorterObject> > PageObjectList; 102 PageObjectList maPageObjects; 103 sal_Int32 mnFirstVisibleChild; 104 sal_Int32 mnLastVisibleChild; 105 bool mbListeningToDocument; 106 ::Window* mpWindow; 107 sal_Int32 mnFocusedIndex; 108 bool mbModelChangeLocked; 109 sal_uLong mnUpdateChildrenUserEventId; 110 sal_uLong mnSelectionChangeUserEventId; 111 112 void UpdateChildren (void); 113 }; 114 115 116 117 118 //===== AccessibleSlideSorterView ============================================= 119 120 AccessibleSlideSorterView::AccessibleSlideSorterView( 121 ::sd::slidesorter::SlideSorter& rSlideSorter, 122 const Reference<XAccessible>& rxParent, 123 ::Window* pContentWindow) 124 : AccessibleSlideSorterViewBase(MutexOwner::maMutex), 125 mpImpl(new Implementation(*this,rSlideSorter,pContentWindow)), 126 mrSlideSorter(rSlideSorter), 127 mxParent(rxParent), 128 mnClientId(0), 129 mpContentWindow(pContentWindow) 130 { 131 } 132 133 134 135 136 AccessibleSlideSorterView::~AccessibleSlideSorterView (void) 137 { 138 Destroyed (); 139 } 140 141 142 143 144 void AccessibleSlideSorterView::FireAccessibleEvent ( 145 short nEventId, 146 const uno::Any& rOldValue, 147 const uno::Any& rNewValue ) 148 { 149 if (mnClientId != 0) 150 { 151 AccessibleEventObject aEventObject; 152 153 aEventObject.Source = Reference<XWeak>(this); 154 aEventObject.EventId = nEventId; 155 aEventObject.NewValue = rNewValue; 156 aEventObject.OldValue = rOldValue; 157 158 comphelper::AccessibleEventNotifier::addEvent (mnClientId, aEventObject); 159 } 160 } 161 162 163 164 165 void SAL_CALL AccessibleSlideSorterView::disposing (void) 166 { 167 if (mnClientId != 0) 168 { 169 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( mnClientId, *this ); 170 mnClientId = 0; 171 } 172 mpImpl.reset(NULL); 173 } 174 175 176 177 178 AccessibleSlideSorterObject* AccessibleSlideSorterView::GetAccessibleChildImplementation ( 179 sal_Int32 nIndex) 180 { 181 AccessibleSlideSorterObject* pResult = NULL; 182 ::osl::MutexGuard aGuard (maMutex); 183 184 if (nIndex>=0 && nIndex<mpImpl->GetVisibleChildCount()) 185 pResult = mpImpl->GetVisibleChild(nIndex); 186 187 return pResult; 188 } 189 190 void AccessibleSlideSorterView::Destroyed (void) 191 { 192 ::osl::MutexGuard aGuard (maMutex); 193 194 // Send a disposing to all listeners. 195 if (mnClientId != 0) 196 { 197 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( mnClientId, *this ); 198 mnClientId = 0; 199 } 200 } 201 202 //===== XAccessible ========================================================= 203 204 Reference<XAccessibleContext > SAL_CALL 205 AccessibleSlideSorterView::getAccessibleContext (void) 206 throw (uno::RuntimeException) 207 { 208 ThrowIfDisposed (); 209 return this; 210 } 211 212 //===== XAccessibleContext ================================================== 213 214 sal_Int32 SAL_CALL AccessibleSlideSorterView::getAccessibleChildCount (void) 215 throw (RuntimeException) 216 { 217 ThrowIfDisposed(); 218 ::osl::MutexGuard aGuard (maMutex); 219 return mpImpl->GetVisibleChildCount(); 220 } 221 222 Reference<XAccessible > SAL_CALL 223 AccessibleSlideSorterView::getAccessibleChild (sal_Int32 nIndex) 224 throw (lang::IndexOutOfBoundsException, RuntimeException) 225 { 226 ThrowIfDisposed(); 227 ::osl::MutexGuard aGuard (maMutex); 228 229 if (nIndex<0 || nIndex>=mpImpl->GetVisibleChildCount()) 230 throw lang::IndexOutOfBoundsException(); 231 232 return mpImpl->GetVisibleChild(nIndex); 233 } 234 235 Reference<XAccessible > SAL_CALL AccessibleSlideSorterView::getAccessibleParent (void) 236 throw (uno::RuntimeException) 237 { 238 ThrowIfDisposed(); 239 const vos::OGuard aSolarGuard (Application::GetSolarMutex()); 240 Reference<XAccessible> xParent; 241 242 if (mpContentWindow != NULL) 243 { 244 ::Window* pParent = mpContentWindow->GetAccessibleParentWindow(); 245 if (pParent != NULL) 246 xParent = pParent->GetAccessible(); 247 } 248 249 return xParent; 250 } 251 252 sal_Int32 SAL_CALL AccessibleSlideSorterView::getAccessibleIndexInParent (void) 253 throw (uno::RuntimeException) 254 { 255 OSL_ASSERT(getAccessibleParent().is()); 256 ThrowIfDisposed(); 257 const vos::OGuard aSolarGuard (Application::GetSolarMutex()); 258 sal_Int32 nIndexInParent(-1); 259 260 261 Reference<XAccessibleContext> xParentContext (getAccessibleParent()->getAccessibleContext()); 262 if (xParentContext.is()) 263 { 264 sal_Int32 nChildCount (xParentContext->getAccessibleChildCount()); 265 for (sal_Int32 i=0; i<nChildCount; ++i) 266 if (xParentContext->getAccessibleChild(i).get() 267 == static_cast<XAccessible*>(this)) 268 { 269 nIndexInParent = i; 270 break; 271 } 272 } 273 274 return nIndexInParent; 275 } 276 277 278 279 280 sal_Int16 SAL_CALL AccessibleSlideSorterView::getAccessibleRole (void) 281 throw (uno::RuntimeException) 282 { 283 ThrowIfDisposed(); 284 static sal_Int16 nRole = AccessibleRole::DOCUMENT; 285 return nRole; 286 } 287 288 289 290 291 ::rtl::OUString SAL_CALL AccessibleSlideSorterView::getAccessibleDescription (void) 292 throw (uno::RuntimeException) 293 { 294 ThrowIfDisposed(); 295 ::vos::OGuard aGuard (Application::GetSolarMutex()); 296 297 return String(SdResId(SID_SD_A11Y_I_SLIDEVIEW_D)); 298 } 299 300 301 302 303 ::rtl::OUString SAL_CALL AccessibleSlideSorterView::getAccessibleName (void) 304 throw (uno::RuntimeException) 305 { 306 ThrowIfDisposed(); 307 ::vos::OGuard aGuard (Application::GetSolarMutex()); 308 309 return String(SdResId(SID_SD_A11Y_I_SLIDEVIEW_N)); 310 } 311 312 313 314 315 Reference<XAccessibleRelationSet> SAL_CALL 316 AccessibleSlideSorterView::getAccessibleRelationSet (void) 317 throw (uno::RuntimeException) 318 { 319 return Reference<XAccessibleRelationSet>(); 320 } 321 322 323 324 325 Reference<XAccessibleStateSet > SAL_CALL 326 AccessibleSlideSorterView::getAccessibleStateSet (void) 327 throw (uno::RuntimeException) 328 { 329 ThrowIfDisposed(); 330 const vos::OGuard aSolarGuard (Application::GetSolarMutex()); 331 ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper(); 332 333 pStateSet->AddState(AccessibleStateType::FOCUSABLE); 334 pStateSet->AddState(AccessibleStateType::SELECTABLE); 335 pStateSet->AddState(AccessibleStateType::ENABLED); 336 pStateSet->AddState(AccessibleStateType::ACTIVE); 337 pStateSet->AddState(AccessibleStateType::MULTI_SELECTABLE); 338 pStateSet->AddState(AccessibleStateType::OPAQUE); 339 if (mpContentWindow!=NULL) 340 { 341 if (mpContentWindow->IsVisible()) 342 pStateSet->AddState(AccessibleStateType::VISIBLE); 343 if (mpContentWindow->IsReallyVisible()) 344 pStateSet->AddState(AccessibleStateType::SHOWING); 345 } 346 347 return pStateSet; 348 } 349 350 351 352 353 lang::Locale SAL_CALL AccessibleSlideSorterView::getLocale (void) 354 throw (IllegalAccessibleComponentStateException, 355 RuntimeException) 356 { 357 ThrowIfDisposed (); 358 Reference<XAccessibleContext> xParentContext; 359 Reference<XAccessible> xParent (getAccessibleParent()); 360 if (xParent.is()) 361 xParentContext = xParent->getAccessibleContext(); 362 363 if (xParentContext.is()) 364 return xParentContext->getLocale(); 365 else 366 // Strange, no parent! Anyway, return the default locale. 367 return Application::GetSettings().GetLocale(); 368 } 369 370 371 372 373 void SAL_CALL AccessibleSlideSorterView::addEventListener( 374 const Reference<XAccessibleEventListener >& rxListener) 375 throw (RuntimeException) 376 { 377 if (rxListener.is()) 378 { 379 const osl::MutexGuard aGuard(maMutex); 380 381 if (IsDisposed()) 382 { 383 uno::Reference<uno::XInterface> x ((lang::XComponent *)this, uno::UNO_QUERY); 384 rxListener->disposing (lang::EventObject (x)); 385 } 386 else 387 { 388 if ( ! mnClientId) 389 mnClientId = comphelper::AccessibleEventNotifier::registerClient(); 390 comphelper::AccessibleEventNotifier::addEventListener(mnClientId, rxListener); 391 } 392 } 393 } 394 395 396 397 398 void SAL_CALL AccessibleSlideSorterView::removeEventListener( 399 const Reference<XAccessibleEventListener >& rxListener) 400 throw (RuntimeException) 401 { 402 ThrowIfDisposed(); 403 if (rxListener.is()) 404 { 405 const osl::MutexGuard aGuard(maMutex); 406 407 if (mnClientId != 0) 408 { 409 sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener( 410 mnClientId, rxListener ); 411 if ( !nListenerCount ) 412 { 413 // no listeners anymore -> revoke ourself. This may lead to 414 // the notifier thread dying (if we were the last client), 415 // and at least to us not firing any events anymore, in case 416 // somebody calls NotifyAccessibleEvent, again 417 comphelper::AccessibleEventNotifier::revokeClient( mnClientId ); 418 mnClientId = 0; 419 } 420 } 421 } 422 } 423 424 425 426 427 //===== XAccessibleComponent ================================================== 428 429 sal_Bool SAL_CALL AccessibleSlideSorterView::containsPoint (const awt::Point& aPoint) 430 throw (RuntimeException) 431 { 432 ThrowIfDisposed(); 433 const awt::Rectangle aBBox (getBounds()); 434 return (aPoint.X >= 0) 435 && (aPoint.X < aBBox.Width) 436 && (aPoint.Y >= 0) 437 && (aPoint.Y < aBBox.Height); 438 } 439 440 441 442 443 Reference<XAccessible> SAL_CALL 444 AccessibleSlideSorterView::getAccessibleAtPoint (const awt::Point& aPoint) 445 throw (RuntimeException) 446 { 447 ThrowIfDisposed(); 448 Reference<XAccessible> xAccessible; 449 const vos::OGuard aSolarGuard (Application::GetSolarMutex()); 450 451 const Point aTestPoint (aPoint.X, aPoint.Y); 452 ::sd::slidesorter::model::SharedPageDescriptor pHitDescriptor ( 453 mrSlideSorter.GetController().GetPageAt(aTestPoint)); 454 if (pHitDescriptor.get() != NULL) 455 xAccessible = mpImpl->GetAccessibleChild( 456 (pHitDescriptor->GetPage()->GetPageNum()-1)/2); 457 458 return xAccessible; 459 } 460 461 462 463 464 awt::Rectangle SAL_CALL AccessibleSlideSorterView::getBounds (void) 465 throw (uno::RuntimeException) 466 { 467 ThrowIfDisposed(); 468 const vos::OGuard aSolarGuard (Application::GetSolarMutex()); 469 awt::Rectangle aBBox; 470 471 if (mpContentWindow != NULL) 472 { 473 const Point aPosition (mpContentWindow->GetPosPixel()); 474 const Size aSize (mpContentWindow->GetOutputSizePixel()); 475 476 aBBox.X = aPosition.X(); 477 aBBox.Y = aPosition.Y(); 478 aBBox.Width = aSize.Width(); 479 aBBox.Height = aSize.Height(); 480 } 481 482 return aBBox; 483 } 484 485 486 487 488 awt::Point SAL_CALL AccessibleSlideSorterView::getLocation (void) 489 throw (uno::RuntimeException) 490 { 491 ThrowIfDisposed(); 492 awt::Point aLocation; 493 494 if (mpContentWindow != NULL) 495 { 496 const Point aPosition (mpContentWindow->GetPosPixel()); 497 aLocation.X = aPosition.X(); 498 aLocation.Y = aPosition.Y(); 499 } 500 501 return aLocation; 502 } 503 504 505 506 507 /** Calculate the location on screen from the parent's location on screen 508 and our own relative location. 509 */ 510 awt::Point SAL_CALL AccessibleSlideSorterView::getLocationOnScreen() 511 throw (uno::RuntimeException) 512 { 513 ThrowIfDisposed(); 514 const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); 515 awt::Point aParentLocationOnScreen; 516 517 Reference<XAccessible> xParent (getAccessibleParent()); 518 if (xParent.is()) 519 { 520 Reference<XAccessibleComponent> xParentComponent ( 521 xParent->getAccessibleContext(), uno::UNO_QUERY); 522 if (xParentComponent.is()) 523 aParentLocationOnScreen = xParentComponent->getLocationOnScreen(); 524 } 525 526 awt::Point aLocationOnScreen (getLocation()); 527 aLocationOnScreen.X += aParentLocationOnScreen.X; 528 aLocationOnScreen.Y += aParentLocationOnScreen.Y; 529 530 return aLocationOnScreen; 531 } 532 533 534 535 536 awt::Size SAL_CALL AccessibleSlideSorterView::getSize (void) 537 throw (uno::RuntimeException) 538 { 539 ThrowIfDisposed(); 540 awt::Size aSize; 541 542 if (mpContentWindow != NULL) 543 { 544 const Size aOutputSize (mpContentWindow->GetOutputSizePixel()); 545 aSize.Width = aOutputSize.Width(); 546 aSize.Height = aOutputSize.Height(); 547 } 548 549 return aSize; 550 } 551 552 553 554 555 void SAL_CALL AccessibleSlideSorterView::grabFocus (void) 556 throw (uno::RuntimeException) 557 { 558 ThrowIfDisposed(); 559 const vos::OGuard aSolarGuard (Application::GetSolarMutex()); 560 561 if (mpContentWindow) 562 mpContentWindow->GrabFocus(); 563 } 564 565 566 567 568 sal_Int32 SAL_CALL AccessibleSlideSorterView::getForeground (void) 569 throw (RuntimeException) 570 { 571 ThrowIfDisposed(); 572 svtools::ColorConfig aColorConfig; 573 sal_uInt32 nColor = aColorConfig.GetColorValue( svtools::FONTCOLOR ).nColor; 574 return static_cast<sal_Int32>(nColor); 575 } 576 577 578 579 580 sal_Int32 SAL_CALL AccessibleSlideSorterView::getBackground (void) 581 throw (RuntimeException) 582 { 583 ThrowIfDisposed(); 584 sal_uInt32 nColor = Application::GetSettings().GetStyleSettings().GetWindowColor().GetColor(); 585 return static_cast<sal_Int32>(nColor); 586 } 587 588 589 590 591 //===== XAccessibleSelection ================================================== 592 593 void SAL_CALL AccessibleSlideSorterView::selectAccessibleChild (sal_Int32 nChildIndex) 594 throw (lang::IndexOutOfBoundsException, 595 RuntimeException) 596 { 597 ThrowIfDisposed(); 598 const vos::OGuard aSolarGuard (Application::GetSolarMutex()); 599 600 AccessibleSlideSorterObject* pChild = mpImpl->GetAccessibleChild(nChildIndex); 601 if (pChild != NULL) 602 mrSlideSorter.GetController().GetPageSelector().SelectPage(pChild->GetPageNumber()); 603 else 604 throw lang::IndexOutOfBoundsException(); 605 } 606 607 608 609 610 sal_Bool SAL_CALL AccessibleSlideSorterView::isAccessibleChildSelected (sal_Int32 nChildIndex) 611 throw (lang::IndexOutOfBoundsException, 612 RuntimeException) 613 { 614 ThrowIfDisposed(); 615 sal_Bool bIsSelected = sal_False; 616 const vos::OGuard aSolarGuard (Application::GetSolarMutex()); 617 618 AccessibleSlideSorterObject* pChild = mpImpl->GetAccessibleChild(nChildIndex); 619 if (pChild != NULL) 620 bIsSelected = mrSlideSorter.GetController().GetPageSelector().IsPageSelected( 621 pChild->GetPageNumber()); 622 else 623 throw lang::IndexOutOfBoundsException(); 624 625 return bIsSelected; 626 } 627 628 629 630 631 void SAL_CALL AccessibleSlideSorterView::clearAccessibleSelection (void) 632 throw (uno::RuntimeException) 633 { 634 ThrowIfDisposed(); 635 const vos::OGuard aSolarGuard (Application::GetSolarMutex()); 636 637 mrSlideSorter.GetController().GetPageSelector().DeselectAllPages(); 638 } 639 640 641 642 643 void SAL_CALL AccessibleSlideSorterView::selectAllAccessibleChildren (void) 644 throw (uno::RuntimeException) 645 { 646 ThrowIfDisposed(); 647 const vos::OGuard aSolarGuard (Application::GetSolarMutex()); 648 649 mrSlideSorter.GetController().GetPageSelector().SelectAllPages(); 650 } 651 652 653 654 655 sal_Int32 SAL_CALL AccessibleSlideSorterView::getSelectedAccessibleChildCount (void) 656 throw (uno::RuntimeException) 657 { 658 ThrowIfDisposed (); 659 const vos::OGuard aSolarGuard (Application::GetSolarMutex()); 660 return mrSlideSorter.GetController().GetPageSelector().GetSelectedPageCount(); 661 } 662 663 664 665 666 Reference<XAccessible > SAL_CALL 667 AccessibleSlideSorterView::getSelectedAccessibleChild (sal_Int32 nSelectedChildIndex ) 668 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 669 { 670 ThrowIfDisposed (); 671 const vos::OGuard aSolarGuard (Application::GetSolarMutex()); 672 Reference<XAccessible> xChild; 673 674 ::sd::slidesorter::controller::PageSelector& rSelector ( 675 mrSlideSorter.GetController().GetPageSelector()); 676 sal_Int32 nPageCount(rSelector.GetPageCount()); 677 sal_Int32 nSelectedCount = 0; 678 for (sal_Int32 i=0; i<nPageCount; i++) 679 if (rSelector.IsPageSelected(i)) 680 { 681 if (nSelectedCount == nSelectedChildIndex) 682 { 683 xChild = mpImpl->GetAccessibleChild(i); 684 break; 685 } 686 ++nSelectedCount; 687 } 688 689 690 if ( ! xChild.is() ) 691 throw lang::IndexOutOfBoundsException(); 692 693 return xChild; 694 } 695 696 697 698 699 void SAL_CALL AccessibleSlideSorterView::deselectAccessibleChild (sal_Int32 nChildIndex) 700 throw (lang::IndexOutOfBoundsException, 701 RuntimeException) 702 { 703 ThrowIfDisposed(); 704 const vos::OGuard aSolarGuard (Application::GetSolarMutex()); 705 706 AccessibleSlideSorterObject* pChild = mpImpl->GetAccessibleChild(nChildIndex); 707 if (pChild != NULL) 708 mrSlideSorter.GetController().GetPageSelector().DeselectPage(pChild->GetPageNumber()); 709 else 710 throw lang::IndexOutOfBoundsException(); 711 } 712 713 714 715 716 //===== XServiceInfo ======================================================== 717 718 ::rtl::OUString SAL_CALL 719 AccessibleSlideSorterView::getImplementationName (void) 720 throw (::com::sun::star::uno::RuntimeException) 721 { 722 return OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleSlideSorterView")); 723 } 724 725 726 727 728 sal_Bool SAL_CALL 729 AccessibleSlideSorterView::supportsService (const OUString& sServiceName) 730 throw (::com::sun::star::uno::RuntimeException) 731 { 732 ThrowIfDisposed (); 733 734 // Iterate over all supported service names and return true if on of them 735 // matches the given name. 736 uno::Sequence< ::rtl::OUString> aSupportedServices ( 737 getSupportedServiceNames ()); 738 for (int i=0; i<aSupportedServices.getLength(); i++) 739 if (sServiceName == aSupportedServices[i]) 740 return sal_True; 741 return sal_False; 742 } 743 744 745 746 747 uno::Sequence< ::rtl::OUString> SAL_CALL 748 AccessibleSlideSorterView::getSupportedServiceNames (void) 749 throw (::com::sun::star::uno::RuntimeException) 750 { 751 ThrowIfDisposed (); 752 753 static const OUString sServiceNames[3] = { 754 OUString(RTL_CONSTASCII_USTRINGPARAM( 755 "com.sun.star.accessibility.Accessible")), 756 OUString(RTL_CONSTASCII_USTRINGPARAM( 757 "com.sun.star.accessibility.AccessibleContext")), 758 OUString(RTL_CONSTASCII_USTRINGPARAM( 759 "com.sun.star.drawing.AccessibleSlideSorterView")) 760 }; 761 return uno::Sequence<OUString> (sServiceNames, 3); 762 } 763 764 765 766 767 void AccessibleSlideSorterView::ThrowIfDisposed (void) 768 throw (lang::DisposedException) 769 { 770 if (rBHelper.bDisposed || rBHelper.bInDispose) 771 { 772 OSL_TRACE ("Calling disposed object. Throwing exception:"); 773 throw lang::DisposedException ( 774 OUString(RTL_CONSTASCII_USTRINGPARAM("object has been already disposed")), 775 static_cast<uno::XWeak*>(this)); 776 } 777 } 778 779 780 781 sal_Bool AccessibleSlideSorterView::IsDisposed (void) 782 { 783 return (rBHelper.bDisposed || rBHelper.bInDispose); 784 } 785 786 787 788 789 //===== AccessibleSlideSorterView::Implementation ============================= 790 791 AccessibleSlideSorterView::Implementation::Implementation ( 792 AccessibleSlideSorterView& rAccessibleSlideSorter, 793 ::sd::slidesorter::SlideSorter& rSlideSorter, 794 ::Window* pWindow) 795 : mrAccessibleSlideSorter(rAccessibleSlideSorter), 796 mrSlideSorter(rSlideSorter), 797 maPageObjects(), 798 mnFirstVisibleChild(0), 799 mnLastVisibleChild(-1), 800 mbListeningToDocument(false), 801 mpWindow(pWindow), 802 mnFocusedIndex(-1), 803 mbModelChangeLocked(false), 804 mnUpdateChildrenUserEventId(0), 805 mnSelectionChangeUserEventId(0) 806 { 807 ConnectListeners(); 808 UpdateChildren(); 809 } 810 811 812 813 814 AccessibleSlideSorterView::Implementation::~Implementation (void) 815 { 816 if (mnUpdateChildrenUserEventId != 0) 817 Application::RemoveUserEvent(mnUpdateChildrenUserEventId); 818 if (mnSelectionChangeUserEventId != 0) 819 Application::RemoveUserEvent(mnSelectionChangeUserEventId); 820 ReleaseListeners(); 821 Clear(); 822 } 823 824 825 826 827 void AccessibleSlideSorterView::Implementation::RequestUpdateChildren (void) 828 { 829 if (mnUpdateChildrenUserEventId == 0) 830 mnUpdateChildrenUserEventId = Application::PostUserEvent( 831 LINK(this, AccessibleSlideSorterView::Implementation, 832 UpdateChildrenCallback)); 833 } 834 835 836 837 838 void AccessibleSlideSorterView::Implementation::UpdateChildren (void) 839 { 840 if (mbModelChangeLocked) 841 { 842 // Do nothing right now. When the flag is reset, this method is 843 // called again. 844 return; 845 } 846 847 const Pair aRange (mrSlideSorter.GetView().GetVisiblePageRange()); 848 mnFirstVisibleChild = aRange.A(); 849 mnLastVisibleChild = aRange.B(); 850 851 // Release all children. 852 Clear(); 853 854 // Create new children for the modified visible range. 855 maPageObjects.resize(mrSlideSorter.GetModel().GetPageCount()); 856 for (sal_Int32 nIndex(mnFirstVisibleChild); nIndex<=mnLastVisibleChild; ++nIndex) 857 GetAccessibleChild(nIndex); 858 } 859 860 861 862 863 void AccessibleSlideSorterView::Implementation::Clear (void) 864 { 865 PageObjectList::iterator iPageObject; 866 PageObjectList::iterator iEnd = maPageObjects.end(); 867 for (iPageObject=maPageObjects.begin(); iPageObject!=iEnd; ++iPageObject) 868 if (*iPageObject != NULL) 869 { 870 mrAccessibleSlideSorter.FireAccessibleEvent( 871 AccessibleEventId::CHILD, 872 Any(Reference<XAccessible>(iPageObject->get())), 873 Any()); 874 875 Reference<XComponent> xComponent (Reference<XWeak>(iPageObject->get()), UNO_QUERY); 876 if (xComponent.is()) 877 xComponent->dispose(); 878 *iPageObject = NULL; 879 } 880 maPageObjects.clear(); 881 } 882 883 884 885 886 sal_Int32 AccessibleSlideSorterView::Implementation::GetVisibleChildCount (void) const 887 { 888 if (mnFirstVisibleChild<=mnLastVisibleChild && mnFirstVisibleChild>=0) 889 return mnLastVisibleChild - mnFirstVisibleChild + 1; 890 else 891 return 0; 892 } 893 894 895 896 897 AccessibleSlideSorterObject* AccessibleSlideSorterView::Implementation::GetVisibleChild ( 898 sal_Int32 nIndex) 899 { 900 assert(nIndex>=0 && nIndex<GetVisibleChildCount()); 901 902 return GetAccessibleChild(nIndex+mnFirstVisibleChild); 903 } 904 905 906 907 908 AccessibleSlideSorterObject* AccessibleSlideSorterView::Implementation::GetAccessibleChild ( 909 sal_Int32 nIndex) 910 { 911 AccessibleSlideSorterObject* pChild = NULL; 912 913 if (nIndex>=0 && (sal_uInt32)nIndex<maPageObjects.size()) 914 { 915 if (maPageObjects[nIndex] == NULL) 916 { 917 ::sd::slidesorter::model::SharedPageDescriptor pDescriptor( 918 mrSlideSorter.GetModel().GetPageDescriptor(nIndex)); 919 if (pDescriptor.get() != NULL) 920 { 921 maPageObjects[nIndex] = new AccessibleSlideSorterObject( 922 &mrAccessibleSlideSorter, 923 mrSlideSorter, 924 (pDescriptor->GetPage()->GetPageNum()-1)/2); 925 926 mrAccessibleSlideSorter.FireAccessibleEvent( 927 AccessibleEventId::CHILD, 928 Any(), 929 Any(Reference<XAccessible>(maPageObjects[nIndex].get()))); 930 } 931 932 } 933 934 pChild = maPageObjects[nIndex].get(); 935 } 936 else 937 { 938 OSL_ASSERT(nIndex>=0 && (sal_uInt32)nIndex<maPageObjects.size()); 939 } 940 941 return pChild; 942 } 943 944 945 946 947 void AccessibleSlideSorterView::Implementation::ConnectListeners (void) 948 { 949 StartListening (*mrSlideSorter.GetModel().GetDocument()); 950 if (mrSlideSorter.GetViewShell() != NULL) 951 StartListening (*mrSlideSorter.GetViewShell()); 952 mbListeningToDocument = true; 953 954 if (mpWindow != NULL) 955 mpWindow->AddEventListener( 956 LINK(this,AccessibleSlideSorterView::Implementation,WindowEventListener)); 957 958 mrSlideSorter.GetController().GetSelectionManager()->AddSelectionChangeListener( 959 LINK(this,AccessibleSlideSorterView::Implementation,SelectionChangeListener)); 960 mrSlideSorter.GetController().GetFocusManager().AddFocusChangeListener( 961 LINK(this,AccessibleSlideSorterView::Implementation,FocusChangeListener)); 962 mrSlideSorter.GetView().AddVisibilityChangeListener( 963 LINK(this,AccessibleSlideSorterView::Implementation,UpdateChildrenCallback)); 964 } 965 966 967 968 969 void AccessibleSlideSorterView::Implementation::ReleaseListeners (void) 970 { 971 mrSlideSorter.GetController().GetFocusManager().RemoveFocusChangeListener( 972 LINK(this,AccessibleSlideSorterView::Implementation,FocusChangeListener)); 973 mrSlideSorter.GetController().GetSelectionManager()->RemoveSelectionChangeListener( 974 LINK(this,AccessibleSlideSorterView::Implementation,SelectionChangeListener)); 975 mrSlideSorter.GetView().RemoveVisibilityChangeListener( 976 LINK(this,AccessibleSlideSorterView::Implementation,UpdateChildrenCallback)); 977 978 if (mpWindow != NULL) 979 mpWindow->RemoveEventListener( 980 LINK(this,AccessibleSlideSorterView::Implementation,WindowEventListener)); 981 982 if (mbListeningToDocument) 983 { 984 if (mrSlideSorter.GetViewShell() != NULL) 985 StartListening(*mrSlideSorter.GetViewShell()); 986 EndListening (*mrSlideSorter.GetModel().GetDocument()); 987 mbListeningToDocument = false; 988 } 989 } 990 991 992 993 994 void AccessibleSlideSorterView::Implementation::Notify ( 995 SfxBroadcaster&, 996 const SfxHint& rHint) 997 { 998 if (rHint.ISA(SdrHint)) 999 { 1000 SdrHint& rSdrHint (*PTR_CAST(SdrHint,&rHint)); 1001 switch (rSdrHint.GetKind()) 1002 { 1003 case HINT_PAGEORDERCHG: 1004 RequestUpdateChildren(); 1005 break; 1006 default: 1007 break; 1008 } 1009 } 1010 else if (rHint.ISA(sd::ViewShellHint)) 1011 { 1012 sd::ViewShellHint& rViewShellHint (*PTR_CAST(sd::ViewShellHint, &rHint)); 1013 switch (rViewShellHint.GetHintId()) 1014 { 1015 case sd::ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_START: 1016 mbModelChangeLocked = true; 1017 break; 1018 1019 case sd::ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_END: 1020 mbModelChangeLocked = false; 1021 RequestUpdateChildren(); 1022 break; 1023 default: 1024 break; 1025 } 1026 } 1027 } 1028 1029 1030 1031 1032 IMPL_LINK(AccessibleSlideSorterView::Implementation, WindowEventListener, VclWindowEvent*, pEvent) 1033 { 1034 switch (pEvent->GetId()) 1035 { 1036 case VCLEVENT_WINDOW_MOVE: 1037 case VCLEVENT_WINDOW_RESIZE: 1038 RequestUpdateChildren(); 1039 break; 1040 1041 case VCLEVENT_WINDOW_GETFOCUS: 1042 case VCLEVENT_WINDOW_LOSEFOCUS: 1043 mrAccessibleSlideSorter.FireAccessibleEvent( 1044 AccessibleEventId::SELECTION_CHANGED, 1045 Any(), 1046 Any()); 1047 break; 1048 default: 1049 break; 1050 } 1051 return 1; 1052 } 1053 1054 1055 1056 1057 IMPL_LINK(AccessibleSlideSorterView::Implementation, SelectionChangeListener, void*, EMPTYARG ) 1058 { 1059 if (mnSelectionChangeUserEventId == 0) 1060 mnSelectionChangeUserEventId = Application::PostUserEvent( 1061 LINK(this, AccessibleSlideSorterView::Implementation, BroadcastSelectionChange)); 1062 return 1; 1063 } 1064 1065 1066 1067 1068 IMPL_LINK(AccessibleSlideSorterView::Implementation, BroadcastSelectionChange, void*, EMPTYARG ) 1069 { 1070 mnSelectionChangeUserEventId = 0; 1071 mrAccessibleSlideSorter.FireAccessibleEvent( 1072 AccessibleEventId::SELECTION_CHANGED, 1073 Any(), 1074 Any()); 1075 return 1; 1076 } 1077 1078 1079 1080 1081 IMPL_LINK(AccessibleSlideSorterView::Implementation, FocusChangeListener, void*, EMPTYARG ) 1082 { 1083 sal_Int32 nNewFocusedIndex ( 1084 mrSlideSorter.GetController().GetFocusManager().GetFocusedPageIndex()); 1085 1086 if (nNewFocusedIndex != mnFocusedIndex) 1087 { 1088 if (mnFocusedIndex >= 0) 1089 { 1090 AccessibleSlideSorterObject* pObject = GetAccessibleChild(mnFocusedIndex); 1091 if (pObject != NULL) 1092 pObject->FireAccessibleEvent( 1093 AccessibleEventId::STATE_CHANGED, 1094 Any(AccessibleStateType::FOCUSED), 1095 Any()); 1096 } 1097 if (nNewFocusedIndex >= 0) 1098 { 1099 AccessibleSlideSorterObject* pObject = GetAccessibleChild(nNewFocusedIndex); 1100 if (pObject != NULL) 1101 pObject->FireAccessibleEvent( 1102 AccessibleEventId::STATE_CHANGED, 1103 Any(), 1104 Any(AccessibleStateType::FOCUSED)); 1105 } 1106 mnFocusedIndex = nNewFocusedIndex; 1107 } 1108 return 1; 1109 } 1110 1111 1112 1113 1114 IMPL_LINK(AccessibleSlideSorterView::Implementation, UpdateChildrenCallback, void*, EMPTYARG ) 1115 { 1116 mnUpdateChildrenUserEventId = 0; 1117 UpdateChildren(); 1118 1119 return 1; 1120 } 1121 1122 1123 1124 1125 } // end of namespace ::accessibility 1126