xref: /trunk/main/sd/source/ui/accessibility/AccessibleSlideSorterView.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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 
AccessibleSlideSorterView(::sd::slidesorter::SlideSorter & rSlideSorter,const Reference<XAccessible> & rxParent,::Window * pContentWindow)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 
~AccessibleSlideSorterView(void)133 AccessibleSlideSorterView::~AccessibleSlideSorterView (void)
134 {
135     Destroyed ();
136 }
137 
138 
139 
140 
FireAccessibleEvent(short nEventId,const uno::Any & rOldValue,const uno::Any & rNewValue)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 
disposing(void)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 
GetAccessibleChildImplementation(sal_Int32 nIndex)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 
Destroyed(void)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
getAccessibleContext(void)202     AccessibleSlideSorterView::getAccessibleContext (void)
203 {
204     ThrowIfDisposed ();
205     return this;
206 }
207 
208 //=====  XAccessibleContext  ==================================================
209 
getAccessibleChildCount(void)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
getAccessibleChild(sal_Int32 nIndex)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 
getAccessibleParent(void)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 
getAccessibleIndexInParent(void)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 
getAccessibleRole(void)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 
getAccessibleDescription(void)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 
getAccessibleName(void)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
getAccessibleRelationSet(void)305     AccessibleSlideSorterView::getAccessibleRelationSet (void)
306 {
307     return Reference<XAccessibleRelationSet>();
308 }
309 
310 
311 
312 
313 Reference<XAccessibleStateSet > SAL_CALL
getAccessibleStateSet(void)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 
getLocale(void)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 
addEventListener(const Reference<XAccessibleEventListener> & rxListener)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 
removeEventListener(const Reference<XAccessibleEventListener> & rxListener)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 
containsPoint(const awt::Point & aPoint)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
getAccessibleAtPoint(const awt::Point & aPoint)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 
getBounds(void)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 
getLocation(void)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 */
getLocationOnScreen()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 
getSize(void)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 
grabFocus(void)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 
getForeground(void)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 
getBackground(void)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 
selectAccessibleChild(sal_Int32 nChildIndex)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 
isAccessibleChildSelected(sal_Int32 nChildIndex)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 
clearAccessibleSelection(void)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 
selectAllAccessibleChildren(void)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 
getSelectedAccessibleChildCount(void)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
getSelectedAccessibleChild(sal_Int32 nSelectedChildIndex)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 
deselectAccessibleChild(sal_Int32 nChildIndex)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
getImplementationName(void)683     AccessibleSlideSorterView::getImplementationName (void)
684 {
685     return OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleSlideSorterView"));
686 }
687 
688 
689 
690 
691 sal_Bool SAL_CALL
supportsService(const OUString & sServiceName)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
getSupportedServiceNames(void)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 
ThrowIfDisposed(void)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 
IsDisposed(void)741 sal_Bool AccessibleSlideSorterView::IsDisposed (void)
742 {
743     return (rBHelper.bDisposed || rBHelper.bInDispose);
744 }
745 
746 
747 
748 
749 //===== AccessibleSlideSorterView::Implementation =============================
750 
Implementation(AccessibleSlideSorterView & rAccessibleSlideSorter,::sd::slidesorter::SlideSorter & rSlideSorter,::Window * pWindow)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 
~Implementation(void)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 
RequestUpdateChildren(void)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 
UpdateChildren(void)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 
Clear(void)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 
GetVisibleChildCount(void) const851 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 
GetVisibleChild(sal_Int32 nIndex)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 
GetAccessibleChild(sal_Int32 nIndex)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 
ConnectListeners(void)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 
ReleaseListeners(void)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 
Notify(SfxBroadcaster &,const SfxHint & rHint)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 
SwitchViewActivated(void)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 
Activated()1005 void AccessibleSlideSorterView::Implementation::Activated()
1006 {
1007     mrSlideSorter.GetController().GetFocusManager().ShowFocus();
1008 
1009 }
1010 
1011 
1012 
IMPL_LINK(AccessibleSlideSorterView::Implementation,WindowEventListener,VclWindowEvent *,pEvent)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 
IMPL_LINK(AccessibleSlideSorterView::Implementation,SelectionChangeListener,void *,EMPTYARG)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 
IMPL_LINK(AccessibleSlideSorterView::Implementation,BroadcastSelectionChange,void *,EMPTYARG)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 
IMPL_LINK(AccessibleSlideSorterView::Implementation,FocusChangeListener,void *,EMPTYARG)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 
IMPL_LINK(AccessibleSlideSorterView::Implementation,UpdateChildrenCallback,void *,EMPTYARG)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