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