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