1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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
72 AccessibleSlideSorterView
& rAccessibleSlideSorter
,
73 ::sd::slidesorter::SlideSorter
& rSlideSorter
,
74 vcl::Window
* pWindow
);
75 virtual ~Implementation() override
;
77 void RequestUpdateChildren();
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);
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
),
119 mpContentWindow(pContentWindow
)
123 void AccessibleSlideSorterView::Init()
125 mpImpl
.reset(new Implementation(*this,mrSlideSorter
,mpContentWindow
));
128 AccessibleSlideSorterView::~AccessibleSlideSorterView()
133 void AccessibleSlideSorterView::FireAccessibleEvent (
135 const uno::Any
& rOldValue
,
136 const uno::Any
& rNewValue
)
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()
156 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( mnClientId
, *this );
162 AccessibleSlideSorterObject
* AccessibleSlideSorterView::GetAccessibleChildImplementation (
165 AccessibleSlideSorterObject
* pResult
= nullptr;
166 ::osl::MutexGuard
aGuard (m_aMutex
);
168 if (nIndex
>=0 && nIndex
<mpImpl
->GetVisibleChildCount())
169 pResult
= mpImpl
->GetVisibleChild(nIndex
);
174 void AccessibleSlideSorterView::Destroyed()
176 ::osl::MutexGuard
aGuard (m_aMutex
);
178 // Send a disposing to all listeners.
181 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( mnClientId
, *this );
186 //===== XAccessible =========================================================
188 Reference
<XAccessibleContext
> SAL_CALL
189 AccessibleSlideSorterView::getAccessibleContext()
195 //===== XAccessibleContext ==================================================
197 sal_Int64 SAL_CALL
AccessibleSlideSorterView::getAccessibleChildCount()
200 ::osl::MutexGuard
aGuard (m_aMutex
);
201 return mpImpl
->GetVisibleChildCount();
204 Reference
<XAccessible
> SAL_CALL
205 AccessibleSlideSorterView::getAccessibleChild (sal_Int64 nIndex
)
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()
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();
232 sal_Int64 SAL_CALL
AccessibleSlideSorterView::getAccessibleIndexInParent()
234 OSL_ASSERT(getAccessibleParent().is());
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))
252 return nIndexInParent
;
255 sal_Int16 SAL_CALL
AccessibleSlideSorterView::getAccessibleRole()
258 return AccessibleRole::DOCUMENT
;
261 OUString SAL_CALL
AccessibleSlideSorterView::getAccessibleDescription()
264 SolarMutexGuard aGuard
;
266 return SdResId(SID_SD_A11Y_I_SLIDEVIEW_D
);
269 OUString SAL_CALL
AccessibleSlideSorterView::getAccessibleName()
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()
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
;
306 lang::Locale SAL_CALL
AccessibleSlideSorterView::getLocale()
309 Reference
<XAccessibleContext
> xParentContext
;
310 Reference
<XAccessible
> xParent (getAccessibleParent());
312 xParentContext
= xParent
->getAccessibleContext();
314 if (xParentContext
.is())
315 return xParentContext
->getLocale();
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())
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
));
337 mnClientId
= comphelper::AccessibleEventNotifier::registerClient();
338 comphelper::AccessibleEventNotifier::addEventListener(mnClientId
, rxListener
);
342 void SAL_CALL
AccessibleSlideSorterView::removeAccessibleEventListener(
343 const Reference
<XAccessibleEventListener
>& rxListener
)
346 if (!rxListener
.is())
349 const osl::MutexGuard
aGuard(m_aMutex
);
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
);
367 //===== XAccessibleComponent ==================================================
369 sal_Bool SAL_CALL
AccessibleSlideSorterView::containsPoint (const awt::Point
& aPoint
)
372 const awt::Rectangle
aBBox (getBounds());
373 return (aPoint
.X
>= 0)
374 && (aPoint
.X
< aBBox
.Width
)
376 && (aPoint
.Y
< aBBox
.Height
);
379 Reference
<XAccessible
> SAL_CALL
380 AccessibleSlideSorterView::getAccessibleAtPoint (const awt::Point
& aPoint
)
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
));
390 xAccessible
= mpImpl
->GetAccessibleChild(
391 (pHitDescriptor
->GetPage()->GetPageNum()-1)/2);
396 awt::Rectangle SAL_CALL
AccessibleSlideSorterView::getBounds()
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();
416 awt::Point SAL_CALL
AccessibleSlideSorterView::getLocation()
419 awt::Point aLocation
;
421 if (mpContentWindow
!= nullptr)
423 const Point
aPosition (mpContentWindow
->GetPosPixel());
424 aLocation
.X
= aPosition
.X();
425 aLocation
.Y
= aPosition
.Y();
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()
437 const SolarMutexGuard aSolarGuard
;
438 awt::Point aParentLocationOnScreen
;
440 Reference
<XAccessible
> xParent (getAccessibleParent());
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()
461 if (mpContentWindow
!= nullptr)
463 const Size
aOutputSize (mpContentWindow
->GetOutputSizePixel());
464 aSize
.Width
= aOutputSize
.Width();
465 aSize
.Height
= aOutputSize
.Height();
471 void SAL_CALL
AccessibleSlideSorterView::grabFocus()
474 const SolarMutexGuard aSolarGuard
;
477 mpContentWindow
->GrabFocus();
480 sal_Int32 SAL_CALL
AccessibleSlideSorterView::getForeground()
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()
491 Color nColor
= Application::GetSettings().GetStyleSettings().GetWindowColor();
492 return sal_Int32(nColor
);
495 //===== XAccessibleSelection ==================================================
497 void SAL_CALL
AccessibleSlideSorterView::selectAccessibleChild (sal_Int64 nChildIndex
)
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
)
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());
531 void SAL_CALL
AccessibleSlideSorterView::clearAccessibleSelection()
534 const SolarMutexGuard aSolarGuard
;
536 mrSlideSorter
.GetController().GetPageSelector().DeselectAllPages();
539 void SAL_CALL
AccessibleSlideSorterView::selectAllAccessibleChildren()
542 const SolarMutexGuard aSolarGuard
;
544 mrSlideSorter
.GetController().GetPageSelector().SelectAllPages();
547 sal_Int64 SAL_CALL
AccessibleSlideSorterView::getSelectedAccessibleChildCount()
550 const SolarMutexGuard aSolarGuard
;
551 return mrSlideSorter
.GetController().GetPageSelector().GetSelectedPageCount();
554 Reference
<XAccessible
> SAL_CALL
555 AccessibleSlideSorterView::getSelectedAccessibleChild (sal_Int64 nSelectedChildIndex
)
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
);
581 throw lang::IndexOutOfBoundsException();
586 void SAL_CALL
AccessibleSlideSorterView::deselectAccessibleChild (sal_Int64 nChildIndex
)
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());
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()
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),
648 mbModelChangeLocked(false),
649 mnUpdateChildrenUserEventId(nullptr),
650 mnSelectionChangeUserEventId(nullptr)
656 AccessibleSlideSorterView::Implementation::~Implementation()
658 if (mnUpdateChildrenUserEventId
!= nullptr)
659 Application::RemoveUserEvent(mnUpdateChildrenUserEventId
);
660 if (mnSelectionChangeUserEventId
!= nullptr)
661 Application::RemoveUserEvent(mnSelectionChangeUserEventId
);
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
688 const Range
aRange (mrSlideSorter
.GetView().GetVisiblePageRange());
689 mnFirstVisibleChild
= aRange
.Min();
690 mnLastVisibleChild
= aRange
.Max();
692 // Release all children.
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)
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
)),
716 Reference
<XComponent
> xComponent (Reference
<XWeak
>(rxPageObject
), UNO_QUERY
);
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;
732 AccessibleSlideSorterObject
* AccessibleSlideSorterView::Implementation::GetVisibleChild (
735 assert(nIndex
>=0 && nIndex
<GetVisibleChildCount());
737 return GetAccessibleChild(nIndex
+mnFirstVisibleChild
);
740 AccessibleSlideSorterObject
* AccessibleSlideSorterView::Implementation::GetAccessibleChild (
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
));
753 maPageObjects
[nIndex
] = new AccessibleSlideSorterObject(
754 &mrAccessibleSlideSorter
,
756 (pDescriptor
->GetPage()->GetPageNum()-1)/2);
758 mrAccessibleSlideSorter
.FireAccessibleEvent(
759 AccessibleEventId::CHILD
,
761 Any(Reference
<XAccessible
>(maPageObjects
[nIndex
])));
766 pChild
= maPageObjects
[nIndex
].get();
770 OSL_ASSERT(nIndex
>=0 && o3tl::make_unsigned(nIndex
)<maPageObjects
.size());
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 (
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();
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;
845 case sd::ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_END
:
846 mbModelChangeLocked
= false;
847 RequestUpdateChildren();
855 void AccessibleSlideSorterView::SwitchViewActivated()
857 // Firstly, set focus to view
858 FireAccessibleEvent(AccessibleEventId::STATE_CHANGED
,
860 Any(AccessibleStateType::FOCUSED
));
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();
880 case VclEventId::WindowGetFocus
:
881 case VclEventId::WindowLoseFocus
:
882 mrAccessibleSlideSorter
.FireAccessibleEvent(
883 AccessibleEventId::SELECTION_CHANGED
,
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
,
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();
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
)
922 if (mnFocusedIndex
>= 0)
924 AccessibleSlideSorterObject
* pObject
= GetAccessibleChild(mnFocusedIndex
);
925 if (pObject
!= nullptr)
927 pObject
->FireAccessibleEvent(
928 AccessibleEventId::STATE_CHANGED
,
929 Any(AccessibleStateType::FOCUSED
),
934 if (nNewFocusedIndex
>= 0)
936 AccessibleSlideSorterObject
* pObject
= GetAccessibleChild(nNewFocusedIndex
);
937 if (pObject
!= nullptr)
939 pObject
->FireAccessibleEvent(
940 AccessibleEventId::STATE_CHANGED
,
942 Any(AccessibleStateType::FOCUSED
));
947 mnFocusedIndex
= nNewFocusedIndex
;
950 IMPL_LINK_NOARG(AccessibleSlideSorterView::Implementation
, UpdateChildrenCallback
, void*, void)
952 mnUpdateChildrenUserEventId
= nullptr;
956 IMPL_LINK_NOARG(AccessibleSlideSorterView::Implementation
, VisibilityChangeListener
, LinkParamNone
*, void)
961 } // end of namespace ::accessibility
963 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */