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