tdf#154285 Check upper bound of arguments in SbRtl_Minute function
[LibreOffice.git] / sd / source / ui / accessibility / AccessibleSlideSorterView.cxx
blobac5d06f9a1ee451685f3b1ae9b79ffa2acd07ce1
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>
32 #include <ViewShell.hxx>
33 #include <ViewShellHint.hxx>
34 #include <sdpage.hxx>
35 #include <drawdoc.hxx>
37 #include <sdresid.hxx>
38 #include <strings.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 <com/sun/star/lang/IndexOutOfBoundsException.hpp>
43 #include <comphelper/accessibleeventnotifier.hxx>
44 #include <cppuhelper/supportsservice.hxx>
45 #include <o3tl/safeint.hxx>
46 #include <rtl/ref.hxx>
47 #include <sal/log.hxx>
48 #include <i18nlangtag/languagetag.hxx>
50 #include <vcl/settings.hxx>
51 #include <vcl/svapp.hxx>
53 using namespace ::com::sun::star;
54 using namespace ::com::sun::star::uno;
55 using namespace ::com::sun::star::accessibility;
57 namespace accessibility {
59 /** Inner implementation class of the AccessibleSlideSorterView.
61 Note that some event broadcasting is done asynchronously because
62 otherwise it could lead to deadlocks on (at least) some Solaris
63 machines. Probably (but unverified) this can happen on all GTK based
64 systems. The asynchronous broadcasting is just a workaround for a
65 poorly understood problem.
67 class AccessibleSlideSorterView::Implementation
68 : public SfxListener
70 public:
71 Implementation (
72 AccessibleSlideSorterView& rAccessibleSlideSorter,
73 ::sd::slidesorter::SlideSorter& rSlideSorter,
74 vcl::Window* pWindow);
75 virtual ~Implementation() override;
77 void RequestUpdateChildren();
78 void Clear();
79 sal_Int32 GetVisibleChildCount() const;
80 AccessibleSlideSorterObject* GetAccessibleChild (sal_Int32 nIndex);
81 AccessibleSlideSorterObject* GetVisibleChild (sal_Int32 nIndex);
83 void ConnectListeners();
84 void ReleaseListeners();
85 void Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint) override;
86 DECL_LINK(WindowEventListener, VclWindowEvent&, void);
87 DECL_LINK(SelectionChangeListener, LinkParamNone*, void);
88 DECL_LINK(BroadcastSelectionChange, void*, void);
89 DECL_LINK(FocusChangeListener, LinkParamNone*, void);
90 DECL_LINK(VisibilityChangeListener, LinkParamNone*, void);
91 DECL_LINK(UpdateChildrenCallback, void*, void);
93 void Activated();
94 private:
95 AccessibleSlideSorterView& mrAccessibleSlideSorter;
96 ::sd::slidesorter::SlideSorter& mrSlideSorter;
97 typedef ::std::vector<rtl::Reference<AccessibleSlideSorterObject> > PageObjectList;
98 PageObjectList maPageObjects;
99 sal_Int32 mnFirstVisibleChild;
100 sal_Int32 mnLastVisibleChild;
101 bool mbListeningToDocument;
102 VclPtr<vcl::Window> mpWindow;
103 sal_Int32 mnFocusedIndex;
104 bool mbModelChangeLocked;
105 ImplSVEvent * mnUpdateChildrenUserEventId;
106 ImplSVEvent * mnSelectionChangeUserEventId;
108 void UpdateChildren();
111 //===== AccessibleSlideSorterView =============================================
113 AccessibleSlideSorterView::AccessibleSlideSorterView(
114 ::sd::slidesorter::SlideSorter& rSlideSorter,
115 vcl::Window* pContentWindow)
116 : AccessibleSlideSorterViewBase(m_aMutex),
117 mrSlideSorter(rSlideSorter),
118 mnClientId(0),
119 mpContentWindow(pContentWindow)
123 void AccessibleSlideSorterView::Init()
125 mpImpl.reset(new Implementation(*this,mrSlideSorter,mpContentWindow));
128 AccessibleSlideSorterView::~AccessibleSlideSorterView()
130 Destroyed ();
133 void AccessibleSlideSorterView::FireAccessibleEvent (
134 short nEventId,
135 const uno::Any& rOldValue,
136 const uno::Any& rNewValue )
138 if (mnClientId != 0)
140 AccessibleEventObject aEventObject;
142 aEventObject.Source = Reference<XWeak>(this);
143 aEventObject.EventId = nEventId;
144 aEventObject.NewValue = rNewValue;
145 aEventObject.OldValue = rOldValue;
146 aEventObject.IndexHint = -1;
148 comphelper::AccessibleEventNotifier::addEvent (mnClientId, aEventObject);
152 void SAL_CALL AccessibleSlideSorterView::disposing()
154 if (mnClientId != 0)
156 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( mnClientId, *this );
157 mnClientId = 0;
159 mpImpl.reset();
162 AccessibleSlideSorterObject* AccessibleSlideSorterView::GetAccessibleChildImplementation (
163 sal_Int32 nIndex)
165 AccessibleSlideSorterObject* pResult = nullptr;
166 ::osl::MutexGuard aGuard (m_aMutex);
168 if (nIndex>=0 && nIndex<mpImpl->GetVisibleChildCount())
169 pResult = mpImpl->GetVisibleChild(nIndex);
171 return pResult;
174 void AccessibleSlideSorterView::Destroyed()
176 ::osl::MutexGuard aGuard (m_aMutex);
178 // Send a disposing to all listeners.
179 if (mnClientId != 0)
181 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( mnClientId, *this );
182 mnClientId = 0;
186 //===== XAccessible =========================================================
188 Reference<XAccessibleContext > SAL_CALL
189 AccessibleSlideSorterView::getAccessibleContext()
191 ThrowIfDisposed ();
192 return this;
195 //===== XAccessibleContext ==================================================
197 sal_Int64 SAL_CALL AccessibleSlideSorterView::getAccessibleChildCount()
199 ThrowIfDisposed();
200 ::osl::MutexGuard aGuard (m_aMutex);
201 return mpImpl->GetVisibleChildCount();
204 Reference<XAccessible > SAL_CALL
205 AccessibleSlideSorterView::getAccessibleChild (sal_Int64 nIndex)
207 ThrowIfDisposed();
208 ::osl::MutexGuard aGuard (m_aMutex);
210 if (nIndex<0 || nIndex>=mpImpl->GetVisibleChildCount())
211 throw lang::IndexOutOfBoundsException();
213 return mpImpl->GetVisibleChild(nIndex);
216 Reference<XAccessible > SAL_CALL AccessibleSlideSorterView::getAccessibleParent()
218 ThrowIfDisposed();
219 const SolarMutexGuard aSolarGuard;
220 Reference<XAccessible> xParent;
222 if (mpContentWindow != nullptr)
224 vcl::Window* pParent = mpContentWindow->GetAccessibleParentWindow();
225 if (pParent != nullptr)
226 xParent = pParent->GetAccessible();
229 return xParent;
232 sal_Int64 SAL_CALL AccessibleSlideSorterView::getAccessibleIndexInParent()
234 OSL_ASSERT(getAccessibleParent().is());
235 ThrowIfDisposed();
236 const SolarMutexGuard aSolarGuard;
237 sal_Int64 nIndexInParent(-1);
239 Reference<XAccessibleContext> xParentContext (getAccessibleParent()->getAccessibleContext());
240 if (xParentContext.is())
242 sal_Int64 nChildCount (xParentContext->getAccessibleChildCount());
243 for (sal_Int64 i=0; i<nChildCount; ++i)
244 if (xParentContext->getAccessibleChild(i).get()
245 == static_cast<XAccessible*>(this))
247 nIndexInParent = i;
248 break;
252 return nIndexInParent;
255 sal_Int16 SAL_CALL AccessibleSlideSorterView::getAccessibleRole()
257 ThrowIfDisposed();
258 return AccessibleRole::DOCUMENT;
261 OUString SAL_CALL AccessibleSlideSorterView::getAccessibleDescription()
263 ThrowIfDisposed();
264 SolarMutexGuard aGuard;
266 return SdResId(SID_SD_A11Y_I_SLIDEVIEW_D);
269 OUString SAL_CALL AccessibleSlideSorterView::getAccessibleName()
271 ThrowIfDisposed();
272 SolarMutexGuard aGuard;
274 return SdResId(SID_SD_A11Y_I_SLIDEVIEW_N);
277 Reference<XAccessibleRelationSet> SAL_CALL
278 AccessibleSlideSorterView::getAccessibleRelationSet()
280 return Reference<XAccessibleRelationSet>();
283 sal_Int64 SAL_CALL AccessibleSlideSorterView::getAccessibleStateSet()
285 ThrowIfDisposed();
286 const SolarMutexGuard aSolarGuard;
287 sal_Int64 nStateSet = 0;
289 nStateSet |= AccessibleStateType::FOCUSABLE;
290 nStateSet |= AccessibleStateType::SELECTABLE;
291 nStateSet |= AccessibleStateType::ENABLED;
292 nStateSet |= AccessibleStateType::ACTIVE;
293 nStateSet |= AccessibleStateType::MULTI_SELECTABLE;
294 nStateSet |= AccessibleStateType::OPAQUE;
295 if (mpContentWindow!=nullptr)
297 if (mpContentWindow->IsVisible())
298 nStateSet |= AccessibleStateType::VISIBLE;
299 if (mpContentWindow->IsReallyVisible())
300 nStateSet |= AccessibleStateType::SHOWING;
303 return nStateSet;
306 lang::Locale SAL_CALL AccessibleSlideSorterView::getLocale()
308 ThrowIfDisposed ();
309 Reference<XAccessibleContext> xParentContext;
310 Reference<XAccessible> xParent (getAccessibleParent());
311 if (xParent.is())
312 xParentContext = xParent->getAccessibleContext();
314 if (xParentContext.is())
315 return xParentContext->getLocale();
316 else
317 // Strange, no parent! Anyway, return the default locale.
318 return Application::GetSettings().GetLanguageTag().getLocale();
321 void SAL_CALL AccessibleSlideSorterView::addAccessibleEventListener(
322 const Reference<XAccessibleEventListener >& rxListener)
324 if (!rxListener.is())
325 return;
327 const osl::MutexGuard aGuard(m_aMutex);
329 if (rBHelper.bDisposed || rBHelper.bInDispose)
331 uno::Reference<uno::XInterface> x (static_cast<lang::XComponent *>(this), uno::UNO_QUERY);
332 rxListener->disposing (lang::EventObject (x));
334 else
336 if ( ! mnClientId)
337 mnClientId = comphelper::AccessibleEventNotifier::registerClient();
338 comphelper::AccessibleEventNotifier::addEventListener(mnClientId, rxListener);
342 void SAL_CALL AccessibleSlideSorterView::removeAccessibleEventListener(
343 const Reference<XAccessibleEventListener >& rxListener)
345 ThrowIfDisposed();
346 if (!rxListener.is())
347 return;
349 const osl::MutexGuard aGuard(m_aMutex);
351 if (mnClientId == 0)
352 return;
354 sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener(
355 mnClientId, rxListener );
356 if ( !nListenerCount )
358 // no listeners anymore -> revoke ourself. This may lead to
359 // the notifier thread dying (if we were the last client),
360 // and at least to us not firing any events anymore, in case
361 // somebody calls NotifyAccessibleEvent, again
362 comphelper::AccessibleEventNotifier::revokeClient( mnClientId );
363 mnClientId = 0;
367 //===== XAccessibleComponent ==================================================
369 sal_Bool SAL_CALL AccessibleSlideSorterView::containsPoint (const awt::Point& aPoint)
371 ThrowIfDisposed();
372 const awt::Rectangle aBBox (getBounds());
373 return (aPoint.X >= 0)
374 && (aPoint.X < aBBox.Width)
375 && (aPoint.Y >= 0)
376 && (aPoint.Y < aBBox.Height);
379 Reference<XAccessible> SAL_CALL
380 AccessibleSlideSorterView::getAccessibleAtPoint (const awt::Point& aPoint)
382 ThrowIfDisposed();
383 Reference<XAccessible> xAccessible;
384 const SolarMutexGuard aSolarGuard;
386 const Point aTestPoint (aPoint.X, aPoint.Y);
387 ::sd::slidesorter::model::SharedPageDescriptor pHitDescriptor (
388 mrSlideSorter.GetController().GetPageAt(aTestPoint));
389 if (pHitDescriptor)
390 xAccessible = mpImpl->GetAccessibleChild(
391 (pHitDescriptor->GetPage()->GetPageNum()-1)/2);
393 return xAccessible;
396 awt::Rectangle SAL_CALL AccessibleSlideSorterView::getBounds()
398 ThrowIfDisposed();
399 const SolarMutexGuard aSolarGuard;
400 awt::Rectangle aBBox;
402 if (mpContentWindow != nullptr)
404 const Point aPosition (mpContentWindow->GetPosPixel());
405 const Size aSize (mpContentWindow->GetOutputSizePixel());
407 aBBox.X = aPosition.X();
408 aBBox.Y = aPosition.Y();
409 aBBox.Width = aSize.Width();
410 aBBox.Height = aSize.Height();
413 return aBBox;
416 awt::Point SAL_CALL AccessibleSlideSorterView::getLocation()
418 ThrowIfDisposed();
419 awt::Point aLocation;
421 if (mpContentWindow != nullptr)
423 const Point aPosition (mpContentWindow->GetPosPixel());
424 aLocation.X = aPosition.X();
425 aLocation.Y = aPosition.Y();
428 return aLocation;
431 /** Calculate the location on screen from the parent's location on screen
432 and our own relative location.
434 awt::Point SAL_CALL AccessibleSlideSorterView::getLocationOnScreen()
436 ThrowIfDisposed();
437 const SolarMutexGuard aSolarGuard;
438 awt::Point aParentLocationOnScreen;
440 Reference<XAccessible> xParent (getAccessibleParent());
441 if (xParent.is())
443 Reference<XAccessibleComponent> xParentComponent (
444 xParent->getAccessibleContext(), uno::UNO_QUERY);
445 if (xParentComponent.is())
446 aParentLocationOnScreen = xParentComponent->getLocationOnScreen();
449 awt::Point aLocationOnScreen (getLocation());
450 aLocationOnScreen.X += aParentLocationOnScreen.X;
451 aLocationOnScreen.Y += aParentLocationOnScreen.Y;
453 return aLocationOnScreen;
456 awt::Size SAL_CALL AccessibleSlideSorterView::getSize()
458 ThrowIfDisposed();
459 awt::Size aSize;
461 if (mpContentWindow != nullptr)
463 const Size aOutputSize (mpContentWindow->GetOutputSizePixel());
464 aSize.Width = aOutputSize.Width();
465 aSize.Height = aOutputSize.Height();
468 return aSize;
471 void SAL_CALL AccessibleSlideSorterView::grabFocus()
473 ThrowIfDisposed();
474 const SolarMutexGuard aSolarGuard;
476 if (mpContentWindow)
477 mpContentWindow->GrabFocus();
480 sal_Int32 SAL_CALL AccessibleSlideSorterView::getForeground()
482 ThrowIfDisposed();
483 svtools::ColorConfig aColorConfig;
484 Color nColor = aColorConfig.GetColorValue( svtools::FONTCOLOR ).nColor;
485 return static_cast<sal_Int32>(nColor);
488 sal_Int32 SAL_CALL AccessibleSlideSorterView::getBackground()
490 ThrowIfDisposed();
491 Color nColor = Application::GetSettings().GetStyleSettings().GetWindowColor();
492 return sal_Int32(nColor);
495 //===== XAccessibleSelection ==================================================
497 void SAL_CALL AccessibleSlideSorterView::selectAccessibleChild (sal_Int64 nChildIndex)
499 ThrowIfDisposed();
500 const SolarMutexGuard aSolarGuard;
502 if (nChildIndex < 0 || nChildIndex >= getAccessibleChildCount())
503 throw lang::IndexOutOfBoundsException();
505 AccessibleSlideSorterObject* pChild = mpImpl->GetAccessibleChild(nChildIndex);
506 if (pChild == nullptr)
507 throw lang::IndexOutOfBoundsException();
509 mrSlideSorter.GetController().GetPageSelector().SelectPage(pChild->GetPageNumber());
512 sal_Bool SAL_CALL AccessibleSlideSorterView::isAccessibleChildSelected (sal_Int64 nChildIndex)
514 ThrowIfDisposed();
515 bool bIsSelected = false;
516 const SolarMutexGuard aSolarGuard;
518 if (nChildIndex < 0 || nChildIndex >= getAccessibleChildCount())
519 throw lang::IndexOutOfBoundsException();
521 AccessibleSlideSorterObject* pChild = mpImpl->GetAccessibleChild(nChildIndex);
522 if (pChild == nullptr)
523 throw lang::IndexOutOfBoundsException();
525 bIsSelected = mrSlideSorter.GetController().GetPageSelector().IsPageSelected(
526 pChild->GetPageNumber());
528 return bIsSelected;
531 void SAL_CALL AccessibleSlideSorterView::clearAccessibleSelection()
533 ThrowIfDisposed();
534 const SolarMutexGuard aSolarGuard;
536 mrSlideSorter.GetController().GetPageSelector().DeselectAllPages();
539 void SAL_CALL AccessibleSlideSorterView::selectAllAccessibleChildren()
541 ThrowIfDisposed();
542 const SolarMutexGuard aSolarGuard;
544 mrSlideSorter.GetController().GetPageSelector().SelectAllPages();
547 sal_Int64 SAL_CALL AccessibleSlideSorterView::getSelectedAccessibleChildCount()
549 ThrowIfDisposed ();
550 const SolarMutexGuard aSolarGuard;
551 return mrSlideSorter.GetController().GetPageSelector().GetSelectedPageCount();
554 Reference<XAccessible > SAL_CALL
555 AccessibleSlideSorterView::getSelectedAccessibleChild (sal_Int64 nSelectedChildIndex )
557 ThrowIfDisposed ();
558 const SolarMutexGuard aSolarGuard;
560 if (nSelectedChildIndex < 0 || nSelectedChildIndex >= getSelectedAccessibleChildCount())
561 throw lang::IndexOutOfBoundsException();
563 Reference<XAccessible> xChild;
565 ::sd::slidesorter::controller::PageSelector& rSelector (
566 mrSlideSorter.GetController().GetPageSelector());
567 sal_Int32 nPageCount(rSelector.GetPageCount());
568 sal_Int32 nSelectedCount = 0;
569 for (sal_Int32 i=0; i<nPageCount; i++)
570 if (rSelector.IsPageSelected(i))
572 if (nSelectedCount == nSelectedChildIndex)
574 xChild = mpImpl->GetAccessibleChild(i);
575 break;
577 ++nSelectedCount;
580 if ( ! xChild.is() )
581 throw lang::IndexOutOfBoundsException();
583 return xChild;
586 void SAL_CALL AccessibleSlideSorterView::deselectAccessibleChild (sal_Int64 nChildIndex)
588 ThrowIfDisposed();
589 const SolarMutexGuard aSolarGuard;
591 if (nChildIndex < 0 || nChildIndex >= getAccessibleChildCount())
592 throw lang::IndexOutOfBoundsException();
594 AccessibleSlideSorterObject* pChild = mpImpl->GetAccessibleChild(nChildIndex);
595 if (pChild == nullptr)
596 throw lang::IndexOutOfBoundsException();
598 mrSlideSorter.GetController().GetPageSelector().DeselectPage(pChild->GetPageNumber());
601 // XServiceInfo
602 OUString SAL_CALL
603 AccessibleSlideSorterView::getImplementationName()
605 return u"AccessibleSlideSorterView"_ustr;
608 sal_Bool SAL_CALL AccessibleSlideSorterView::supportsService (const OUString& sServiceName)
610 return cppu::supportsService(this, sServiceName);
613 uno::Sequence< OUString> SAL_CALL
614 AccessibleSlideSorterView::getSupportedServiceNames()
616 ThrowIfDisposed ();
618 return uno::Sequence<OUString> {
619 u"com.sun.star.accessibility.Accessible"_ustr,
620 u"com.sun.star.accessibility.AccessibleContext"_ustr,
621 u"com.sun.star.drawing.AccessibleSlideSorterView"_ustr
625 void AccessibleSlideSorterView::ThrowIfDisposed()
627 if (rBHelper.bDisposed || rBHelper.bInDispose)
629 SAL_WARN("sd", "Calling disposed object. Throwing exception:");
630 throw lang::DisposedException (u"object has been already disposed"_ustr,
631 static_cast<uno::XWeak*>(this));
635 //===== AccessibleSlideSorterView::Implementation =============================
637 AccessibleSlideSorterView::Implementation::Implementation (
638 AccessibleSlideSorterView& rAccessibleSlideSorter,
639 ::sd::slidesorter::SlideSorter& rSlideSorter,
640 vcl::Window* pWindow)
641 : mrAccessibleSlideSorter(rAccessibleSlideSorter),
642 mrSlideSorter(rSlideSorter),
643 mnFirstVisibleChild(0),
644 mnLastVisibleChild(-1),
645 mbListeningToDocument(false),
646 mpWindow(pWindow),
647 mnFocusedIndex(-1),
648 mbModelChangeLocked(false),
649 mnUpdateChildrenUserEventId(nullptr),
650 mnSelectionChangeUserEventId(nullptr)
652 ConnectListeners();
653 UpdateChildren();
656 AccessibleSlideSorterView::Implementation::~Implementation()
658 if (mnUpdateChildrenUserEventId != nullptr)
659 Application::RemoveUserEvent(mnUpdateChildrenUserEventId);
660 if (mnSelectionChangeUserEventId != nullptr)
661 Application::RemoveUserEvent(mnSelectionChangeUserEventId);
662 ReleaseListeners();
663 Clear();
666 void AccessibleSlideSorterView::Implementation::RequestUpdateChildren()
668 if (mnUpdateChildrenUserEventId == nullptr)
669 mnUpdateChildrenUserEventId = Application::PostUserEvent(
670 LINK(this, AccessibleSlideSorterView::Implementation,
671 UpdateChildrenCallback));
674 void AccessibleSlideSorterView::Implementation::UpdateChildren()
676 //By default, all children should be accessible. So here workaround is to make all children visible.
677 // MT: This was in UpdateVisibility, which has some similarity, and hg merge automatically has put it here. Correct?!
678 // In the IA2 CWS, also setting mnFirst/LastVisibleChild was commented out!
679 mnLastVisibleChild = maPageObjects.size();
681 if (mbModelChangeLocked)
683 // Do nothing right now. When the flag is reset, this method is
684 // called again.
685 return;
688 const Range aRange (mrSlideSorter.GetView().GetVisiblePageRange());
689 mnFirstVisibleChild = aRange.Min();
690 mnLastVisibleChild = aRange.Max();
692 // Release all children.
693 Clear();
695 // Create new children for the modified visible range.
696 maPageObjects.resize(mrSlideSorter.GetModel().GetPageCount());
698 // No Visible children
699 if (mnFirstVisibleChild == -1 && mnLastVisibleChild == -1)
700 return;
702 for (sal_Int32 nIndex(mnFirstVisibleChild); nIndex<=mnLastVisibleChild; ++nIndex)
703 GetAccessibleChild(nIndex);
706 void AccessibleSlideSorterView::Implementation::Clear()
708 for (auto& rxPageObject : maPageObjects)
709 if (rxPageObject != nullptr)
711 mrAccessibleSlideSorter.FireAccessibleEvent(
712 AccessibleEventId::CHILD,
713 Any(Reference<XAccessible>(rxPageObject)),
714 Any());
716 Reference<XComponent> xComponent (Reference<XWeak>(rxPageObject), UNO_QUERY);
717 if (xComponent.is())
718 xComponent->dispose();
719 rxPageObject = nullptr;
721 maPageObjects.clear();
724 sal_Int32 AccessibleSlideSorterView::Implementation::GetVisibleChildCount() const
726 if (mnFirstVisibleChild<=mnLastVisibleChild && mnFirstVisibleChild>=0)
727 return mnLastVisibleChild - mnFirstVisibleChild + 1;
728 else
729 return 0;
732 AccessibleSlideSorterObject* AccessibleSlideSorterView::Implementation::GetVisibleChild (
733 sal_Int32 nIndex)
735 assert(nIndex>=0 && nIndex<GetVisibleChildCount());
737 return GetAccessibleChild(nIndex+mnFirstVisibleChild);
740 AccessibleSlideSorterObject* AccessibleSlideSorterView::Implementation::GetAccessibleChild (
741 sal_Int32 nIndex)
743 AccessibleSlideSorterObject* pChild = nullptr;
745 if (nIndex>=0 && o3tl::make_unsigned(nIndex)<maPageObjects.size())
747 if (maPageObjects[nIndex] == nullptr)
749 ::sd::slidesorter::model::SharedPageDescriptor pDescriptor(
750 mrSlideSorter.GetModel().GetPageDescriptor(nIndex));
751 if (pDescriptor)
753 maPageObjects[nIndex] = new AccessibleSlideSorterObject(
754 &mrAccessibleSlideSorter,
755 mrSlideSorter,
756 (pDescriptor->GetPage()->GetPageNum()-1)/2);
758 mrAccessibleSlideSorter.FireAccessibleEvent(
759 AccessibleEventId::CHILD,
760 Any(),
761 Any(Reference<XAccessible>(maPageObjects[nIndex])));
766 pChild = maPageObjects[nIndex].get();
768 else
770 OSL_ASSERT(nIndex>=0 && o3tl::make_unsigned(nIndex)<maPageObjects.size());
773 return pChild;
776 void AccessibleSlideSorterView::Implementation::ConnectListeners()
778 StartListening (*mrSlideSorter.GetModel().GetDocument());
779 if (mrSlideSorter.GetViewShell() != nullptr)
780 StartListening (*mrSlideSorter.GetViewShell());
781 mbListeningToDocument = true;
783 if (mpWindow != nullptr)
784 mpWindow->AddEventListener(
785 LINK(this,AccessibleSlideSorterView::Implementation,WindowEventListener));
787 mrSlideSorter.GetController().GetSelectionManager()->AddSelectionChangeListener(
788 LINK(this,AccessibleSlideSorterView::Implementation,SelectionChangeListener));
789 mrSlideSorter.GetController().GetFocusManager().AddFocusChangeListener(
790 LINK(this,AccessibleSlideSorterView::Implementation,FocusChangeListener));
791 mrSlideSorter.GetView().AddVisibilityChangeListener(
792 LINK(this,AccessibleSlideSorterView::Implementation,VisibilityChangeListener));
795 void AccessibleSlideSorterView::Implementation::ReleaseListeners()
797 mrSlideSorter.GetController().GetFocusManager().RemoveFocusChangeListener(
798 LINK(this,AccessibleSlideSorterView::Implementation,FocusChangeListener));
799 mrSlideSorter.GetController().GetSelectionManager()->RemoveSelectionChangeListener(
800 LINK(this,AccessibleSlideSorterView::Implementation,SelectionChangeListener));
801 mrSlideSorter.GetView().RemoveVisibilityChangeListener(
802 LINK(this,AccessibleSlideSorterView::Implementation,VisibilityChangeListener));
804 if (mpWindow != nullptr)
805 mpWindow->RemoveEventListener(
806 LINK(this,AccessibleSlideSorterView::Implementation,WindowEventListener));
808 if (mbListeningToDocument)
810 if (mrSlideSorter.GetViewShell() != nullptr && !IsListening(*mrSlideSorter.GetViewShell()))
811 { // ??? is it even possible that ConnectListeners is called with no
812 // view shell and this one with a view shell?
813 StartListening(*mrSlideSorter.GetViewShell());
815 EndListening (*mrSlideSorter.GetModel().GetDocument());
816 mbListeningToDocument = false;
820 void AccessibleSlideSorterView::Implementation::Notify (
821 SfxBroadcaster&,
822 const SfxHint& rHint)
824 if (rHint.GetId() == SfxHintId::ThisIsAnSdrHint)
826 const SdrHint* pSdrHint = static_cast<const SdrHint*>(&rHint);
827 switch (pSdrHint->GetKind())
829 case SdrHintKind::PageOrderChange:
830 RequestUpdateChildren();
831 break;
832 default:
833 break;
836 else if (rHint.GetId() == SfxHintId::SdViewShell)
838 auto pViewShellHint = static_cast<const sd::ViewShellHint*>(&rHint);
839 switch (pViewShellHint->GetHintId())
841 case sd::ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_START:
842 mbModelChangeLocked = true;
843 break;
845 case sd::ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_END:
846 mbModelChangeLocked = false;
847 RequestUpdateChildren();
848 break;
849 default:
850 break;
855 void AccessibleSlideSorterView::SwitchViewActivated()
857 // Firstly, set focus to view
858 FireAccessibleEvent(AccessibleEventId::STATE_CHANGED,
859 Any(),
860 Any(AccessibleStateType::FOCUSED));
862 mpImpl->Activated();
865 void AccessibleSlideSorterView::Implementation::Activated()
867 mrSlideSorter.GetController().GetFocusManager().ShowFocus();
871 IMPL_LINK(AccessibleSlideSorterView::Implementation, WindowEventListener, VclWindowEvent&, rEvent, void)
873 switch (rEvent.GetId())
875 case VclEventId::WindowMove:
876 case VclEventId::WindowResize:
877 RequestUpdateChildren();
878 break;
880 case VclEventId::WindowGetFocus:
881 case VclEventId::WindowLoseFocus:
882 mrAccessibleSlideSorter.FireAccessibleEvent(
883 AccessibleEventId::SELECTION_CHANGED,
884 Any(),
885 Any());
886 break;
887 default:
888 break;
892 IMPL_LINK_NOARG(AccessibleSlideSorterView::Implementation, SelectionChangeListener, LinkParamNone*, void)
894 if (mnSelectionChangeUserEventId == nullptr)
895 mnSelectionChangeUserEventId = Application::PostUserEvent(
896 LINK(this, AccessibleSlideSorterView::Implementation, BroadcastSelectionChange));
899 IMPL_LINK_NOARG(AccessibleSlideSorterView::Implementation, BroadcastSelectionChange, void*, void)
901 mnSelectionChangeUserEventId = nullptr;
902 mrAccessibleSlideSorter.FireAccessibleEvent(
903 AccessibleEventId::SELECTION_CHANGED,
904 Any(),
905 Any());
908 IMPL_LINK_NOARG(AccessibleSlideSorterView::Implementation, FocusChangeListener, LinkParamNone*, void)
910 sal_Int32 nNewFocusedIndex (
911 mrSlideSorter.GetController().GetFocusManager().GetFocusedPageIndex());
913 bool bHasFocus = mrSlideSorter.GetController().GetFocusManager().IsFocusShowing();
914 if (!bHasFocus)
915 nNewFocusedIndex = -1;
917 // add a checker whether the focus event is sent out. Only after sent, the mnFocusedIndex should be updated.
918 bool bSentFocus = false;
919 if (nNewFocusedIndex == mnFocusedIndex)
920 return;
922 if (mnFocusedIndex >= 0)
924 AccessibleSlideSorterObject* pObject = GetAccessibleChild(mnFocusedIndex);
925 if (pObject != nullptr)
927 pObject->FireAccessibleEvent(
928 AccessibleEventId::STATE_CHANGED,
929 Any(AccessibleStateType::FOCUSED),
930 Any());
931 bSentFocus = true;
934 if (nNewFocusedIndex >= 0)
936 AccessibleSlideSorterObject* pObject = GetAccessibleChild(nNewFocusedIndex);
937 if (pObject != nullptr)
939 pObject->FireAccessibleEvent(
940 AccessibleEventId::STATE_CHANGED,
941 Any(),
942 Any(AccessibleStateType::FOCUSED));
943 bSentFocus = true;
946 if (bSentFocus)
947 mnFocusedIndex = nNewFocusedIndex;
950 IMPL_LINK_NOARG(AccessibleSlideSorterView::Implementation, UpdateChildrenCallback, void*, void)
952 mnUpdateChildrenUserEventId = nullptr;
953 UpdateChildren();
956 IMPL_LINK_NOARG(AccessibleSlideSorterView::Implementation, VisibilityChangeListener, LinkParamNone*, void)
958 UpdateChildren();
961 } // end of namespace ::accessibility
963 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */