bump product version to 5.0.4.1
[LibreOffice.git] / sd / source / ui / accessibility / AccessibleSlideSorterView.cxx
blobb6531ee17f2766392263355fd8ff928f5a4725d5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "AccessibleSlideSorterView.hxx"
21 #include "AccessibleSlideSorterObject.hxx"
23 #include "SlideSorter.hxx"
24 #include "controller/SlideSorterController.hxx"
25 #include "controller/SlsPageSelector.hxx"
26 #include "controller/SlsFocusManager.hxx"
27 #include "controller/SlsSelectionManager.hxx"
28 #include "view/SlideSorterView.hxx"
29 #include "model/SlideSorterModel.hxx"
30 #include "model/SlsPageDescriptor.hxx"
31 #include "SlideSorterViewShell.hxx"
33 #include "ViewShellHint.hxx"
34 #include "sdpage.hxx"
35 #include "drawdoc.hxx"
37 #include "sdresid.hxx"
38 #include "accessibility.hrc"
39 #include <com/sun/star/accessibility/AccessibleRole.hpp>
40 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
41 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
42 #include <comphelper/accessibleeventnotifier.hxx>
43 #include <cppuhelper/supportsservice.hxx>
44 #include <unotools/accessiblestatesethelper.hxx>
45 #include <rtl/ref.hxx>
47 #include <vcl/settings.hxx>
48 #include <vcl/svapp.hxx>
50 using namespace ::com::sun::star;
51 using namespace ::com::sun::star::uno;
52 using namespace ::com::sun::star::accessibility;
54 namespace accessibility {
56 /** Inner implementation class of the AccessibleSlideSorterView.
58 Note that some event broadcasting is done asynchronously because
59 otherwise it could lead to deadlocks on (at least) some Solaris
60 machines. Probably (but unverified) this can happen on all GTK based
61 systems. The asynchronous broadcasting is just a workaround for a
62 poorly understood problem.
64 class AccessibleSlideSorterView::Implementation
65 : public SfxListener
67 public:
68 Implementation (
69 AccessibleSlideSorterView& rAccessibleSlideSorter,
70 ::sd::slidesorter::SlideSorter& rSlideSorter,
71 vcl::Window* pWindow);
72 virtual ~Implementation();
74 void RequestUpdateChildren();
75 void Clear();
76 sal_Int32 GetVisibleChildCount() const;
77 AccessibleSlideSorterObject* GetAccessibleChild (sal_Int32 nIndex);
78 AccessibleSlideSorterObject* GetVisibleChild (sal_Int32 nIndex);
80 void ConnectListeners();
81 void ReleaseListeners();
82 void Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint) SAL_OVERRIDE;
83 DECL_LINK(WindowEventListener, VclWindowEvent*);
84 DECL_LINK(SelectionChangeListener, void*);
85 DECL_LINK(BroadcastSelectionChange, void*);
86 DECL_LINK(FocusChangeListener, void*);
87 DECL_LINK(VisibilityChangeListener, void*);
88 DECL_LINK(UpdateChildrenCallback, void*);
90 void Activated();
91 private:
92 AccessibleSlideSorterView& mrAccessibleSlideSorter;
93 ::sd::slidesorter::SlideSorter& mrSlideSorter;
94 typedef ::std::vector<rtl::Reference<AccessibleSlideSorterObject> > PageObjectList;
95 PageObjectList maPageObjects;
96 sal_Int32 mnFirstVisibleChild;
97 sal_Int32 mnLastVisibleChild;
98 bool mbListeningToDocument;
99 VclPtr<vcl::Window> mpWindow;
100 sal_Int32 mnFocusedIndex;
101 bool mbModelChangeLocked;
102 ImplSVEvent * mnUpdateChildrenUserEventId;
103 ImplSVEvent * mnSelectionChangeUserEventId;
105 void UpdateChildren();
108 //===== AccessibleSlideSorterView =============================================
110 AccessibleSlideSorterView::AccessibleSlideSorterView(
111 ::sd::slidesorter::SlideSorter& rSlideSorter,
112 const Reference<XAccessible>& rxParent,
113 vcl::Window* pContentWindow)
114 : AccessibleSlideSorterViewBase(MutexOwner::maMutex),
115 mrSlideSorter(rSlideSorter),
116 mxParent(rxParent),
117 mnClientId(0),
118 mpContentWindow(pContentWindow)
122 void AccessibleSlideSorterView::Init()
124 mpImpl.reset(new Implementation(*this,mrSlideSorter,mpContentWindow));
127 AccessibleSlideSorterView::~AccessibleSlideSorterView()
129 Destroyed ();
132 void AccessibleSlideSorterView::FireAccessibleEvent (
133 short nEventId,
134 const uno::Any& rOldValue,
135 const uno::Any& rNewValue )
137 if (mnClientId != 0)
139 AccessibleEventObject aEventObject;
141 aEventObject.Source = Reference<XWeak>(this);
142 aEventObject.EventId = nEventId;
143 aEventObject.NewValue = rNewValue;
144 aEventObject.OldValue = rOldValue;
146 comphelper::AccessibleEventNotifier::addEvent (mnClientId, aEventObject);
150 void SAL_CALL AccessibleSlideSorterView::disposing()
152 if (mnClientId != 0)
154 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( mnClientId, *this );
155 mnClientId = 0;
157 mpImpl.reset();
160 AccessibleSlideSorterObject* AccessibleSlideSorterView::GetAccessibleChildImplementation (
161 sal_Int32 nIndex)
163 AccessibleSlideSorterObject* pResult = NULL;
164 ::osl::MutexGuard aGuard (maMutex);
166 if (nIndex>=0 && nIndex<mpImpl->GetVisibleChildCount())
167 pResult = mpImpl->GetVisibleChild(nIndex);
169 return pResult;
172 void AccessibleSlideSorterView::Destroyed()
174 ::osl::MutexGuard aGuard (maMutex);
176 // Send a disposing to all listeners.
177 if (mnClientId != 0)
179 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( mnClientId, *this );
180 mnClientId = 0;
184 //===== XAccessible =========================================================
186 Reference<XAccessibleContext > SAL_CALL
187 AccessibleSlideSorterView::getAccessibleContext()
188 throw (uno::RuntimeException, std::exception)
190 ThrowIfDisposed ();
191 return this;
194 //===== XAccessibleContext ==================================================
196 sal_Int32 SAL_CALL AccessibleSlideSorterView::getAccessibleChildCount()
197 throw (RuntimeException, std::exception)
199 ThrowIfDisposed();
200 ::osl::MutexGuard aGuard (maMutex);
201 return mpImpl->GetVisibleChildCount();
204 Reference<XAccessible > SAL_CALL
205 AccessibleSlideSorterView::getAccessibleChild (sal_Int32 nIndex)
206 throw (lang::IndexOutOfBoundsException, RuntimeException, std::exception)
208 ThrowIfDisposed();
209 ::osl::MutexGuard aGuard (maMutex);
211 if (nIndex<0 || nIndex>=mpImpl->GetVisibleChildCount())
212 throw lang::IndexOutOfBoundsException();
214 return mpImpl->GetVisibleChild(nIndex);
217 Reference<XAccessible > SAL_CALL AccessibleSlideSorterView::getAccessibleParent()
218 throw (uno::RuntimeException, std::exception)
220 ThrowIfDisposed();
221 const SolarMutexGuard aSolarGuard;
222 Reference<XAccessible> xParent;
224 if (mpContentWindow != nullptr)
226 vcl::Window* pParent = mpContentWindow->GetAccessibleParentWindow();
227 if (pParent != NULL)
228 xParent = pParent->GetAccessible();
231 return xParent;
234 sal_Int32 SAL_CALL AccessibleSlideSorterView::getAccessibleIndexInParent()
235 throw (uno::RuntimeException, std::exception)
237 OSL_ASSERT(getAccessibleParent().is());
238 ThrowIfDisposed();
239 const SolarMutexGuard aSolarGuard;
240 sal_Int32 nIndexInParent(-1);
242 Reference<XAccessibleContext> xParentContext (getAccessibleParent()->getAccessibleContext());
243 if (xParentContext.is())
245 sal_Int32 nChildCount (xParentContext->getAccessibleChildCount());
246 for (sal_Int32 i=0; i<nChildCount; ++i)
247 if (xParentContext->getAccessibleChild(i).get()
248 == static_cast<XAccessible*>(this))
250 nIndexInParent = i;
251 break;
255 return nIndexInParent;
258 sal_Int16 SAL_CALL AccessibleSlideSorterView::getAccessibleRole()
259 throw (uno::RuntimeException, std::exception)
261 ThrowIfDisposed();
262 static sal_Int16 nRole = AccessibleRole::DOCUMENT;
263 return nRole;
266 OUString SAL_CALL AccessibleSlideSorterView::getAccessibleDescription()
267 throw (uno::RuntimeException, std::exception)
269 ThrowIfDisposed();
270 SolarMutexGuard aGuard;
272 return SD_RESSTR(SID_SD_A11Y_I_SLIDEVIEW_D);
275 OUString SAL_CALL AccessibleSlideSorterView::getAccessibleName()
276 throw (uno::RuntimeException, std::exception)
278 ThrowIfDisposed();
279 SolarMutexGuard aGuard;
281 return SD_RESSTR(SID_SD_A11Y_I_SLIDEVIEW_N);
284 Reference<XAccessibleRelationSet> SAL_CALL
285 AccessibleSlideSorterView::getAccessibleRelationSet()
286 throw (uno::RuntimeException, std::exception)
288 return Reference<XAccessibleRelationSet>();
291 Reference<XAccessibleStateSet > SAL_CALL
292 AccessibleSlideSorterView::getAccessibleStateSet()
293 throw (uno::RuntimeException, std::exception)
295 ThrowIfDisposed();
296 const SolarMutexGuard aSolarGuard;
297 ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper();
299 pStateSet->AddState(AccessibleStateType::FOCUSABLE);
300 pStateSet->AddState(AccessibleStateType::SELECTABLE);
301 pStateSet->AddState(AccessibleStateType::ENABLED);
302 pStateSet->AddState(AccessibleStateType::ACTIVE);
303 pStateSet->AddState(AccessibleStateType::MULTI_SELECTABLE);
304 pStateSet->AddState(AccessibleStateType::OPAQUE);
305 if (mpContentWindow!=nullptr)
307 if (mpContentWindow->IsVisible())
308 pStateSet->AddState(AccessibleStateType::VISIBLE);
309 if (mpContentWindow->IsReallyVisible())
310 pStateSet->AddState(AccessibleStateType::SHOWING);
313 return pStateSet;
316 lang::Locale SAL_CALL AccessibleSlideSorterView::getLocale()
317 throw (IllegalAccessibleComponentStateException,
318 RuntimeException, std::exception)
320 ThrowIfDisposed ();
321 Reference<XAccessibleContext> xParentContext;
322 Reference<XAccessible> xParent (getAccessibleParent());
323 if (xParent.is())
324 xParentContext = xParent->getAccessibleContext();
326 if (xParentContext.is())
327 return xParentContext->getLocale();
328 else
329 // Strange, no parent! Anyway, return the default locale.
330 return Application::GetSettings().GetLanguageTag().getLocale();
333 void SAL_CALL AccessibleSlideSorterView::addAccessibleEventListener(
334 const Reference<XAccessibleEventListener >& rxListener)
335 throw (RuntimeException, std::exception)
337 if (rxListener.is())
339 const osl::MutexGuard aGuard(maMutex);
341 if (IsDisposed())
343 uno::Reference<uno::XInterface> x ((lang::XComponent *)this, uno::UNO_QUERY);
344 rxListener->disposing (lang::EventObject (x));
346 else
348 if ( ! mnClientId)
349 mnClientId = comphelper::AccessibleEventNotifier::registerClient();
350 comphelper::AccessibleEventNotifier::addEventListener(mnClientId, rxListener);
355 void SAL_CALL AccessibleSlideSorterView::removeAccessibleEventListener(
356 const Reference<XAccessibleEventListener >& rxListener)
357 throw (RuntimeException, std::exception)
359 ThrowIfDisposed();
360 if (rxListener.is())
362 const osl::MutexGuard aGuard(maMutex);
364 if (mnClientId != 0)
366 sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener(
367 mnClientId, rxListener );
368 if ( !nListenerCount )
370 // no listeners anymore -> revoke ourself. This may lead to
371 // the notifier thread dying (if we were the last client),
372 // and at least to us not firing any events anymore, in case
373 // somebody calls NotifyAccessibleEvent, again
374 comphelper::AccessibleEventNotifier::revokeClient( mnClientId );
375 mnClientId = 0;
381 //===== XAccessibleComponent ==================================================
383 sal_Bool SAL_CALL AccessibleSlideSorterView::containsPoint (const awt::Point& aPoint)
384 throw (RuntimeException, std::exception)
386 ThrowIfDisposed();
387 const awt::Rectangle aBBox (getBounds());
388 return (aPoint.X >= 0)
389 && (aPoint.X < aBBox.Width)
390 && (aPoint.Y >= 0)
391 && (aPoint.Y < aBBox.Height);
394 Reference<XAccessible> SAL_CALL
395 AccessibleSlideSorterView::getAccessibleAtPoint (const awt::Point& aPoint)
396 throw (RuntimeException, std::exception)
398 ThrowIfDisposed();
399 Reference<XAccessible> xAccessible;
400 const SolarMutexGuard aSolarGuard;
402 const Point aTestPoint (aPoint.X, aPoint.Y);
403 ::sd::slidesorter::model::SharedPageDescriptor pHitDescriptor (
404 mrSlideSorter.GetController().GetPageAt(aTestPoint));
405 if (pHitDescriptor.get() != NULL)
406 xAccessible = mpImpl->GetAccessibleChild(
407 (pHitDescriptor->GetPage()->GetPageNum()-1)/2);
409 return xAccessible;
412 awt::Rectangle SAL_CALL AccessibleSlideSorterView::getBounds()
413 throw (uno::RuntimeException, std::exception)
415 ThrowIfDisposed();
416 const SolarMutexGuard aSolarGuard;
417 awt::Rectangle aBBox;
419 if (mpContentWindow != nullptr)
421 const Point aPosition (mpContentWindow->GetPosPixel());
422 const Size aSize (mpContentWindow->GetOutputSizePixel());
424 aBBox.X = aPosition.X();
425 aBBox.Y = aPosition.Y();
426 aBBox.Width = aSize.Width();
427 aBBox.Height = aSize.Height();
430 return aBBox;
433 awt::Point SAL_CALL AccessibleSlideSorterView::getLocation()
434 throw (uno::RuntimeException, std::exception)
436 ThrowIfDisposed();
437 awt::Point aLocation;
439 if (mpContentWindow != nullptr)
441 const Point aPosition (mpContentWindow->GetPosPixel());
442 aLocation.X = aPosition.X();
443 aLocation.Y = aPosition.Y();
446 return aLocation;
449 /** Calculate the location on screen from the parent's location on screen
450 and our own relative location.
452 awt::Point SAL_CALL AccessibleSlideSorterView::getLocationOnScreen()
453 throw (uno::RuntimeException, std::exception)
455 ThrowIfDisposed();
456 const SolarMutexGuard aSolarGuard;
457 awt::Point aParentLocationOnScreen;
459 Reference<XAccessible> xParent (getAccessibleParent());
460 if (xParent.is())
462 Reference<XAccessibleComponent> xParentComponent (
463 xParent->getAccessibleContext(), uno::UNO_QUERY);
464 if (xParentComponent.is())
465 aParentLocationOnScreen = xParentComponent->getLocationOnScreen();
468 awt::Point aLocationOnScreen (getLocation());
469 aLocationOnScreen.X += aParentLocationOnScreen.X;
470 aLocationOnScreen.Y += aParentLocationOnScreen.Y;
472 return aLocationOnScreen;
475 awt::Size SAL_CALL AccessibleSlideSorterView::getSize()
476 throw (uno::RuntimeException, std::exception)
478 ThrowIfDisposed();
479 awt::Size aSize;
481 if (mpContentWindow != nullptr)
483 const Size aOutputSize (mpContentWindow->GetOutputSizePixel());
484 aSize.Width = aOutputSize.Width();
485 aSize.Height = aOutputSize.Height();
488 return aSize;
491 void SAL_CALL AccessibleSlideSorterView::grabFocus()
492 throw (uno::RuntimeException, std::exception)
494 ThrowIfDisposed();
495 const SolarMutexGuard aSolarGuard;
497 if (mpContentWindow)
498 mpContentWindow->GrabFocus();
501 sal_Int32 SAL_CALL AccessibleSlideSorterView::getForeground()
502 throw (RuntimeException, std::exception)
504 ThrowIfDisposed();
505 svtools::ColorConfig aColorConfig;
506 sal_uInt32 nColor = aColorConfig.GetColorValue( svtools::FONTCOLOR ).nColor;
507 return static_cast<sal_Int32>(nColor);
510 sal_Int32 SAL_CALL AccessibleSlideSorterView::getBackground()
511 throw (RuntimeException, std::exception)
513 ThrowIfDisposed();
514 sal_uInt32 nColor = Application::GetSettings().GetStyleSettings().GetWindowColor().GetColor();
515 return static_cast<sal_Int32>(nColor);
518 //===== XAccessibleSelection ==================================================
520 void SAL_CALL AccessibleSlideSorterView::selectAccessibleChild (sal_Int32 nChildIndex)
521 throw (lang::IndexOutOfBoundsException,
522 RuntimeException, std::exception)
524 ThrowIfDisposed();
525 const SolarMutexGuard aSolarGuard;
527 AccessibleSlideSorterObject* pChild = mpImpl->GetAccessibleChild(nChildIndex);
528 if (pChild != NULL)
529 mrSlideSorter.GetController().GetPageSelector().SelectPage(pChild->GetPageNumber());
530 else
531 throw lang::IndexOutOfBoundsException();
534 sal_Bool SAL_CALL AccessibleSlideSorterView::isAccessibleChildSelected (sal_Int32 nChildIndex)
535 throw (lang::IndexOutOfBoundsException,
536 RuntimeException, std::exception)
538 ThrowIfDisposed();
539 bool bIsSelected = false;
540 const SolarMutexGuard aSolarGuard;
542 AccessibleSlideSorterObject* pChild = mpImpl->GetAccessibleChild(nChildIndex);
543 if (pChild != NULL)
544 bIsSelected = mrSlideSorter.GetController().GetPageSelector().IsPageSelected(
545 pChild->GetPageNumber());
546 else
547 throw lang::IndexOutOfBoundsException();
549 return bIsSelected;
552 void SAL_CALL AccessibleSlideSorterView::clearAccessibleSelection()
553 throw (uno::RuntimeException, std::exception)
555 ThrowIfDisposed();
556 const SolarMutexGuard aSolarGuard;
558 mrSlideSorter.GetController().GetPageSelector().DeselectAllPages();
561 void SAL_CALL AccessibleSlideSorterView::selectAllAccessibleChildren()
562 throw (uno::RuntimeException, std::exception)
564 ThrowIfDisposed();
565 const SolarMutexGuard aSolarGuard;
567 mrSlideSorter.GetController().GetPageSelector().SelectAllPages();
570 sal_Int32 SAL_CALL AccessibleSlideSorterView::getSelectedAccessibleChildCount()
571 throw (uno::RuntimeException, std::exception)
573 ThrowIfDisposed ();
574 const SolarMutexGuard aSolarGuard;
575 return mrSlideSorter.GetController().GetPageSelector().GetSelectedPageCount();
578 Reference<XAccessible > SAL_CALL
579 AccessibleSlideSorterView::getSelectedAccessibleChild (sal_Int32 nSelectedChildIndex )
580 throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
582 ThrowIfDisposed ();
583 const SolarMutexGuard aSolarGuard;
584 Reference<XAccessible> xChild;
586 ::sd::slidesorter::controller::PageSelector& rSelector (
587 mrSlideSorter.GetController().GetPageSelector());
588 sal_Int32 nPageCount(rSelector.GetPageCount());
589 sal_Int32 nSelectedCount = 0;
590 for (sal_Int32 i=0; i<nPageCount; i++)
591 if (rSelector.IsPageSelected(i))
593 if (nSelectedCount == nSelectedChildIndex)
595 xChild = mpImpl->GetAccessibleChild(i);
596 break;
598 ++nSelectedCount;
601 if ( ! xChild.is() )
602 throw lang::IndexOutOfBoundsException();
604 return xChild;
607 void SAL_CALL AccessibleSlideSorterView::deselectAccessibleChild (sal_Int32 nChildIndex)
608 throw (lang::IndexOutOfBoundsException,
609 RuntimeException, std::exception)
611 ThrowIfDisposed();
612 const SolarMutexGuard aSolarGuard;
614 AccessibleSlideSorterObject* pChild = mpImpl->GetAccessibleChild(nChildIndex);
615 if (pChild != NULL)
616 mrSlideSorter.GetController().GetPageSelector().DeselectPage(pChild->GetPageNumber());
617 else
618 throw lang::IndexOutOfBoundsException();
621 // XServiceInfo
622 OUString SAL_CALL
623 AccessibleSlideSorterView::getImplementationName()
624 throw (::com::sun::star::uno::RuntimeException, std::exception)
626 return OUString("AccessibleSlideSorterView");
629 sal_Bool SAL_CALL AccessibleSlideSorterView::supportsService (const OUString& sServiceName)
630 throw (::com::sun::star::uno::RuntimeException, std::exception)
632 return cppu::supportsService(this, sServiceName);
635 uno::Sequence< OUString> SAL_CALL
636 AccessibleSlideSorterView::getSupportedServiceNames()
637 throw (::com::sun::star::uno::RuntimeException, std::exception)
639 ThrowIfDisposed ();
641 static const OUString sServiceNames[3] = {
642 OUString("com.sun.star.accessibility.Accessible"),
643 OUString("com.sun.star.accessibility.AccessibleContext"),
644 OUString("com.sun.star.drawing.AccessibleSlideSorterView")
646 return uno::Sequence<OUString> (sServiceNames, 3);
649 void AccessibleSlideSorterView::ThrowIfDisposed()
650 throw (lang::DisposedException)
652 if (rBHelper.bDisposed || rBHelper.bInDispose)
654 OSL_TRACE ("Calling disposed object. Throwing exception:");
655 throw lang::DisposedException ("object has been already disposed",
656 static_cast<uno::XWeak*>(this));
660 bool AccessibleSlideSorterView::IsDisposed()
662 return (rBHelper.bDisposed || rBHelper.bInDispose);
665 //===== AccessibleSlideSorterView::Implementation =============================
667 AccessibleSlideSorterView::Implementation::Implementation (
668 AccessibleSlideSorterView& rAccessibleSlideSorter,
669 ::sd::slidesorter::SlideSorter& rSlideSorter,
670 vcl::Window* pWindow)
671 : mrAccessibleSlideSorter(rAccessibleSlideSorter),
672 mrSlideSorter(rSlideSorter),
673 maPageObjects(),
674 mnFirstVisibleChild(0),
675 mnLastVisibleChild(-1),
676 mbListeningToDocument(false),
677 mpWindow(pWindow),
678 mnFocusedIndex(-1),
679 mbModelChangeLocked(false),
680 mnUpdateChildrenUserEventId(0),
681 mnSelectionChangeUserEventId(0)
683 ConnectListeners();
684 UpdateChildren();
687 AccessibleSlideSorterView::Implementation::~Implementation()
689 if (mnUpdateChildrenUserEventId != 0)
690 Application::RemoveUserEvent(mnUpdateChildrenUserEventId);
691 if (mnSelectionChangeUserEventId != 0)
692 Application::RemoveUserEvent(mnSelectionChangeUserEventId);
693 ReleaseListeners();
694 Clear();
697 void AccessibleSlideSorterView::Implementation::RequestUpdateChildren()
699 if (mnUpdateChildrenUserEventId == 0)
700 mnUpdateChildrenUserEventId = Application::PostUserEvent(
701 LINK(this, AccessibleSlideSorterView::Implementation,
702 UpdateChildrenCallback));
705 void AccessibleSlideSorterView::Implementation::UpdateChildren()
707 //By default, all children should be accessible. So here workaround is to make all children visible.
708 // MT: THis was in UpdateVisibility, which has some similarity, and hg merge automatically has put it here. Correct?!
709 // In the IA2 CWS, also setting mnFirst/LastVisibleChild was commented out!
710 mnLastVisibleChild = maPageObjects.size();
712 if (mbModelChangeLocked)
714 // Do nothing right now. When the flag is reset, this method is
715 // called again.
716 return;
719 const Pair aRange (mrSlideSorter.GetView().GetVisiblePageRange());
720 mnFirstVisibleChild = aRange.A();
721 mnLastVisibleChild = aRange.B();
723 // Release all children.
724 Clear();
726 // Create new children for the modified visible range.
727 maPageObjects.resize(mrSlideSorter.GetModel().GetPageCount());
729 // No Visible children
730 if (mnFirstVisibleChild == -1 && mnLastVisibleChild == -1)
731 return;
733 for (sal_Int32 nIndex(mnFirstVisibleChild); nIndex<=mnLastVisibleChild; ++nIndex)
734 GetAccessibleChild(nIndex);
737 void AccessibleSlideSorterView::Implementation::Clear()
739 PageObjectList::iterator iPageObject;
740 PageObjectList::iterator iEnd = maPageObjects.end();
741 for (iPageObject=maPageObjects.begin(); iPageObject!=iEnd; ++iPageObject)
742 if (*iPageObject != NULL)
744 mrAccessibleSlideSorter.FireAccessibleEvent(
745 AccessibleEventId::CHILD,
746 Any(Reference<XAccessible>(iPageObject->get())),
747 Any());
749 Reference<XComponent> xComponent (Reference<XWeak>(iPageObject->get()), UNO_QUERY);
750 if (xComponent.is())
751 xComponent->dispose();
752 *iPageObject = NULL;
754 maPageObjects.clear();
757 sal_Int32 AccessibleSlideSorterView::Implementation::GetVisibleChildCount() const
759 if (mnFirstVisibleChild<=mnLastVisibleChild && mnFirstVisibleChild>=0)
760 return mnLastVisibleChild - mnFirstVisibleChild + 1;
761 else
762 return 0;
765 AccessibleSlideSorterObject* AccessibleSlideSorterView::Implementation::GetVisibleChild (
766 sal_Int32 nIndex)
768 assert(nIndex>=0 && nIndex<GetVisibleChildCount());
770 return GetAccessibleChild(nIndex+mnFirstVisibleChild);
773 AccessibleSlideSorterObject* AccessibleSlideSorterView::Implementation::GetAccessibleChild (
774 sal_Int32 nIndex)
776 AccessibleSlideSorterObject* pChild = NULL;
778 if (nIndex>=0 && (sal_uInt32)nIndex<maPageObjects.size())
780 if (maPageObjects[nIndex] == NULL)
782 ::sd::slidesorter::model::SharedPageDescriptor pDescriptor(
783 mrSlideSorter.GetModel().GetPageDescriptor(nIndex));
784 if (pDescriptor.get() != NULL)
786 maPageObjects[nIndex] = new AccessibleSlideSorterObject(
787 &mrAccessibleSlideSorter,
788 mrSlideSorter,
789 (pDescriptor->GetPage()->GetPageNum()-1)/2);
791 mrAccessibleSlideSorter.FireAccessibleEvent(
792 AccessibleEventId::CHILD,
793 Any(),
794 Any(Reference<XAccessible>(maPageObjects[nIndex].get())));
799 pChild = maPageObjects[nIndex].get();
801 else
803 OSL_ASSERT(nIndex>=0 && (sal_uInt32)nIndex<maPageObjects.size());
806 return pChild;
809 void AccessibleSlideSorterView::Implementation::ConnectListeners()
811 StartListening (*mrSlideSorter.GetModel().GetDocument());
812 if (mrSlideSorter.GetViewShell() != NULL)
813 StartListening (*mrSlideSorter.GetViewShell());
814 mbListeningToDocument = true;
816 if (mpWindow != nullptr)
817 mpWindow->AddEventListener(
818 LINK(this,AccessibleSlideSorterView::Implementation,WindowEventListener));
820 mrSlideSorter.GetController().GetSelectionManager()->AddSelectionChangeListener(
821 LINK(this,AccessibleSlideSorterView::Implementation,SelectionChangeListener));
822 mrSlideSorter.GetController().GetFocusManager().AddFocusChangeListener(
823 LINK(this,AccessibleSlideSorterView::Implementation,FocusChangeListener));
824 mrSlideSorter.GetView().AddVisibilityChangeListener(
825 LINK(this,AccessibleSlideSorterView::Implementation,VisibilityChangeListener));
828 void AccessibleSlideSorterView::Implementation::ReleaseListeners()
830 mrSlideSorter.GetController().GetFocusManager().RemoveFocusChangeListener(
831 LINK(this,AccessibleSlideSorterView::Implementation,FocusChangeListener));
832 mrSlideSorter.GetController().GetSelectionManager()->RemoveSelectionChangeListener(
833 LINK(this,AccessibleSlideSorterView::Implementation,SelectionChangeListener));
834 mrSlideSorter.GetView().RemoveVisibilityChangeListener(
835 LINK(this,AccessibleSlideSorterView::Implementation,VisibilityChangeListener));
837 if (mpWindow != nullptr)
838 mpWindow->RemoveEventListener(
839 LINK(this,AccessibleSlideSorterView::Implementation,WindowEventListener));
841 if (mbListeningToDocument)
843 if (mrSlideSorter.GetViewShell() != NULL)
844 StartListening(*mrSlideSorter.GetViewShell());
845 EndListening (*mrSlideSorter.GetModel().GetDocument());
846 mbListeningToDocument = false;
850 void AccessibleSlideSorterView::Implementation::Notify (
851 SfxBroadcaster&,
852 const SfxHint& rHint)
854 const SdrHint* pSdrHint = dynamic_cast<const SdrHint*>(&rHint);
855 if (pSdrHint)
857 switch (pSdrHint->GetKind())
859 case HINT_PAGEORDERCHG:
860 RequestUpdateChildren();
861 break;
862 default:
863 break;
866 else if (dynamic_cast<const sd::ViewShellHint*>(&rHint))
868 const sd::ViewShellHint& rViewShellHint = static_cast<const sd::ViewShellHint&>(rHint);
869 switch (rViewShellHint.GetHintId())
871 case sd::ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_START:
872 mbModelChangeLocked = true;
873 break;
875 case sd::ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_END:
876 mbModelChangeLocked = false;
877 RequestUpdateChildren();
878 break;
879 default:
880 break;
885 void AccessibleSlideSorterView::SwitchViewActivated()
887 // Firstly, set focus to view
888 this->FireAccessibleEvent(AccessibleEventId::STATE_CHANGED,
889 Any(),
890 Any(AccessibleStateType::FOCUSED));
892 mpImpl->Activated();
895 void AccessibleSlideSorterView::Implementation::Activated()
897 mrSlideSorter.GetController().GetFocusManager().ShowFocus();
901 IMPL_LINK(AccessibleSlideSorterView::Implementation, WindowEventListener, VclWindowEvent*, pEvent)
903 switch (pEvent->GetId())
905 case VCLEVENT_WINDOW_MOVE:
906 case VCLEVENT_WINDOW_RESIZE:
907 RequestUpdateChildren();
908 break;
910 case VCLEVENT_WINDOW_GETFOCUS:
911 case VCLEVENT_WINDOW_LOSEFOCUS:
912 mrAccessibleSlideSorter.FireAccessibleEvent(
913 AccessibleEventId::SELECTION_CHANGED,
914 Any(),
915 Any());
916 break;
917 default:
918 break;
920 return 1;
923 IMPL_LINK_NOARG(AccessibleSlideSorterView::Implementation, SelectionChangeListener)
925 if (mnSelectionChangeUserEventId == 0)
926 mnSelectionChangeUserEventId = Application::PostUserEvent(
927 LINK(this, AccessibleSlideSorterView::Implementation, BroadcastSelectionChange));
928 return 1;
931 IMPL_LINK_NOARG(AccessibleSlideSorterView::Implementation, BroadcastSelectionChange)
933 mnSelectionChangeUserEventId = 0;
934 mrAccessibleSlideSorter.FireAccessibleEvent(
935 AccessibleEventId::SELECTION_CHANGED,
936 Any(),
937 Any());
938 return 1;
941 IMPL_LINK_NOARG(AccessibleSlideSorterView::Implementation, FocusChangeListener)
943 sal_Int32 nNewFocusedIndex (
944 mrSlideSorter.GetController().GetFocusManager().GetFocusedPageIndex());
946 bool bHasFocus = mrSlideSorter.GetController().GetFocusManager().IsFocusShowing();
947 if (!bHasFocus)
948 nNewFocusedIndex = -1;
950 // add a checker whether the focus event is sent out. Only after sent, the mnFocusedIndex should be updated.
951 bool bSentFocus = false;
952 if (nNewFocusedIndex != mnFocusedIndex)
954 if (mnFocusedIndex >= 0)
956 AccessibleSlideSorterObject* pObject = GetAccessibleChild(mnFocusedIndex);
957 if (pObject != NULL)
959 pObject->FireAccessibleEvent(
960 AccessibleEventId::STATE_CHANGED,
961 Any(AccessibleStateType::FOCUSED),
962 Any());
963 bSentFocus = true;
966 if (nNewFocusedIndex >= 0)
968 AccessibleSlideSorterObject* pObject = GetAccessibleChild(nNewFocusedIndex);
969 if (pObject != NULL)
971 pObject->FireAccessibleEvent(
972 AccessibleEventId::STATE_CHANGED,
973 Any(),
974 Any(AccessibleStateType::FOCUSED));
975 bSentFocus = true;
978 if (bSentFocus)
979 mnFocusedIndex = nNewFocusedIndex;
981 return 1;
984 IMPL_LINK_NOARG(AccessibleSlideSorterView::Implementation, UpdateChildrenCallback)
986 mnUpdateChildrenUserEventId = 0;
987 UpdateChildren();
989 return 1;
992 IMPL_LINK_NOARG(AccessibleSlideSorterView::Implementation, VisibilityChangeListener)
994 UpdateChildren();
995 return 1;
998 } // end of namespace ::accessibility
1000 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */