xref: /AOO41X/main/sd/source/ui/accessibility/AccessibleSlideSorterView.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include "precompiled_sd.hxx"
29 
30 #include "AccessibleSlideSorterView.hxx"
31 #include "AccessibleSlideSorterObject.hxx"
32 
33 #include "SlideSorter.hxx"
34 #include "controller/SlideSorterController.hxx"
35 #include "controller/SlsPageSelector.hxx"
36 #include "controller/SlsFocusManager.hxx"
37 #include "controller/SlsSelectionManager.hxx"
38 #include "view/SlideSorterView.hxx"
39 #include "model/SlideSorterModel.hxx"
40 #include "model/SlsPageDescriptor.hxx"
41 #include "SlideSorterViewShell.hxx"
42 
43 #include "ViewShellHint.hxx"
44 #include "sdpage.hxx"
45 #include "drawdoc.hxx"
46 
47 #include "sdresid.hxx"
48 #include "accessibility.hrc"
49 #include <com/sun/star/accessibility/AccessibleRole.hpp>
50 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
51 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
52 #include <comphelper/accessibleeventnotifier.hxx>
53 #include <unotools/accessiblestatesethelper.hxx>
54 #include <rtl/ref.hxx>
55 #include <vcl/svapp.hxx>
56 
57 using ::rtl::OUString;
58 using namespace ::com::sun::star;
59 using namespace ::com::sun::star::uno;
60 using namespace ::com::sun::star::accessibility;
61 
62 namespace accessibility {
63 
64 
65 /** Inner implementation class of the AccessibleSlideSorterView.
66 
67     Note that some event broadcasting is done asynchronously because
68     otherwise it could lead to deadlocks on (at least) some Solaris
69     machines.  Probably (but unverified) this can happen on all GTK based
70     systems.  The asynchronous broadcasting is just a workaround for a
71     poorly understood problem.
72 */
73 class AccessibleSlideSorterView::Implementation
74     : public SfxListener
75 {
76 public:
77     Implementation (
78         AccessibleSlideSorterView& rAccessibleSlideSorter,
79         ::sd::slidesorter::SlideSorter& rSlideSorter,
80         ::Window* pWindow);
81     ~Implementation (void);
82 
83     void RequestUpdateChildren (void);
84     void Clear (void);
85     sal_Int32 GetVisibleChildCount (void) const;
86     AccessibleSlideSorterObject* GetAccessibleChild (sal_Int32 nIndex);
87     AccessibleSlideSorterObject* GetVisibleChild (sal_Int32 nIndex);
88 
89     void ConnectListeners (void);
90     void ReleaseListeners (void);
91     void Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint);
92     DECL_LINK(WindowEventListener, VclWindowEvent*);
93     DECL_LINK(SelectionChangeListener, void*);
94     DECL_LINK(BroadcastSelectionChange, void*);
95     DECL_LINK(FocusChangeListener, void*);
96     DECL_LINK(UpdateChildrenCallback, void*);
97 
98 private:
99     AccessibleSlideSorterView& mrAccessibleSlideSorter;
100     ::sd::slidesorter::SlideSorter& mrSlideSorter;
101     typedef ::std::vector<rtl::Reference<AccessibleSlideSorterObject> > PageObjectList;
102     PageObjectList maPageObjects;
103     sal_Int32 mnFirstVisibleChild;
104     sal_Int32 mnLastVisibleChild;
105     bool mbListeningToDocument;
106     ::Window* mpWindow;
107     sal_Int32 mnFocusedIndex;
108     bool mbModelChangeLocked;
109     sal_uLong mnUpdateChildrenUserEventId;
110     sal_uLong mnSelectionChangeUserEventId;
111 
112     void UpdateChildren (void);
113 };
114 
115 
116 
117 
118 //===== AccessibleSlideSorterView =============================================
119 
120 AccessibleSlideSorterView::AccessibleSlideSorterView(
121     ::sd::slidesorter::SlideSorter& rSlideSorter,
122     const Reference<XAccessible>& rxParent,
123     ::Window* pContentWindow)
124     : AccessibleSlideSorterViewBase(MutexOwner::maMutex),
125       mpImpl(new Implementation(*this,rSlideSorter,pContentWindow)),
126       mrSlideSorter(rSlideSorter),
127       mxParent(rxParent),
128       mnClientId(0),
129       mpContentWindow(pContentWindow)
130 {
131 }
132 
133 
134 
135 
136 AccessibleSlideSorterView::~AccessibleSlideSorterView (void)
137 {
138     Destroyed ();
139 }
140 
141 
142 
143 
144 void AccessibleSlideSorterView::FireAccessibleEvent (
145     short nEventId,
146     const uno::Any& rOldValue,
147     const uno::Any& rNewValue )
148 {
149     if (mnClientId != 0)
150     {
151         AccessibleEventObject aEventObject;
152 
153         aEventObject.Source = Reference<XWeak>(this);
154         aEventObject.EventId = nEventId;
155         aEventObject.NewValue = rNewValue;
156 	    aEventObject.OldValue = rOldValue;
157 
158 		comphelper::AccessibleEventNotifier::addEvent (mnClientId, aEventObject);
159     }
160 }
161 
162 
163 
164 
165 void SAL_CALL AccessibleSlideSorterView::disposing (void)
166 {
167     if (mnClientId != 0)
168     {
169         comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( mnClientId, *this );
170         mnClientId = 0;
171     }
172     mpImpl.reset(NULL);
173 }
174 
175 
176 
177 
178 AccessibleSlideSorterObject* AccessibleSlideSorterView::GetAccessibleChildImplementation (
179     sal_Int32 nIndex)
180 {
181     AccessibleSlideSorterObject* pResult = NULL;
182     ::osl::MutexGuard aGuard (maMutex);
183 
184     if (nIndex>=0 && nIndex<mpImpl->GetVisibleChildCount())
185         pResult = mpImpl->GetVisibleChild(nIndex);
186 
187     return pResult;
188 }
189 
190 void AccessibleSlideSorterView::Destroyed (void)
191 {
192     ::osl::MutexGuard aGuard (maMutex);
193 
194     // Send a disposing to all listeners.
195 	if (mnClientId != 0)
196 	{
197         comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( mnClientId, *this );
198 		mnClientId = 0;
199 	}
200 }
201 
202 //=====  XAccessible  =========================================================
203 
204 Reference<XAccessibleContext > SAL_CALL
205     AccessibleSlideSorterView::getAccessibleContext (void)
206     throw (uno::RuntimeException)
207 {
208     ThrowIfDisposed ();
209     return this;
210 }
211 
212 //=====  XAccessibleContext  ==================================================
213 
214 sal_Int32 SAL_CALL AccessibleSlideSorterView::getAccessibleChildCount (void)
215     throw (RuntimeException)
216 {
217     ThrowIfDisposed();
218     ::osl::MutexGuard aGuard (maMutex);
219     return mpImpl->GetVisibleChildCount();
220 }
221 
222 Reference<XAccessible > SAL_CALL
223     AccessibleSlideSorterView::getAccessibleChild (sal_Int32 nIndex)
224     throw (lang::IndexOutOfBoundsException, RuntimeException)
225 {
226     ThrowIfDisposed();
227     ::osl::MutexGuard aGuard (maMutex);
228 
229     if (nIndex<0 || nIndex>=mpImpl->GetVisibleChildCount())
230         throw lang::IndexOutOfBoundsException();
231 
232     return  mpImpl->GetVisibleChild(nIndex);
233 }
234 
235 Reference<XAccessible > SAL_CALL AccessibleSlideSorterView::getAccessibleParent (void)
236     throw (uno::RuntimeException)
237 {
238     ThrowIfDisposed();
239     const vos::OGuard aSolarGuard (Application::GetSolarMutex());
240     Reference<XAccessible> xParent;
241 
242     if (mpContentWindow != NULL)
243     {
244         ::Window* pParent = mpContentWindow->GetAccessibleParentWindow();
245         if (pParent != NULL)
246             xParent = pParent->GetAccessible();
247     }
248 
249     return xParent;
250 }
251 
252 sal_Int32 SAL_CALL AccessibleSlideSorterView::getAccessibleIndexInParent (void)
253     throw (uno::RuntimeException)
254 {
255     OSL_ASSERT(getAccessibleParent().is());
256     ThrowIfDisposed();
257     const vos::OGuard aSolarGuard (Application::GetSolarMutex());
258     sal_Int32 nIndexInParent(-1);
259 
260 
261     Reference<XAccessibleContext> xParentContext (getAccessibleParent()->getAccessibleContext());
262     if (xParentContext.is())
263     {
264         sal_Int32 nChildCount (xParentContext->getAccessibleChildCount());
265         for (sal_Int32 i=0; i<nChildCount; ++i)
266             if (xParentContext->getAccessibleChild(i).get()
267                     == static_cast<XAccessible*>(this))
268             {
269                 nIndexInParent = i;
270                 break;
271             }
272     }
273 
274     return nIndexInParent;
275 }
276 
277 
278 
279 
280 sal_Int16 SAL_CALL AccessibleSlideSorterView::getAccessibleRole (void)
281     throw (uno::RuntimeException)
282 {
283     ThrowIfDisposed();
284     static sal_Int16 nRole = AccessibleRole::DOCUMENT;
285     return nRole;
286 }
287 
288 
289 
290 
291 ::rtl::OUString SAL_CALL AccessibleSlideSorterView::getAccessibleDescription (void)
292     throw (uno::RuntimeException)
293 {
294     ThrowIfDisposed();
295     ::vos::OGuard aGuard (Application::GetSolarMutex());
296 
297     return String(SdResId(SID_SD_A11Y_I_SLIDEVIEW_D));
298 }
299 
300 
301 
302 
303 ::rtl::OUString SAL_CALL AccessibleSlideSorterView::getAccessibleName (void)
304     throw (uno::RuntimeException)
305 {
306     ThrowIfDisposed();
307     ::vos::OGuard aGuard (Application::GetSolarMutex());
308 
309     return String(SdResId(SID_SD_A11Y_I_SLIDEVIEW_N));
310 }
311 
312 
313 
314 
315 Reference<XAccessibleRelationSet> SAL_CALL
316     AccessibleSlideSorterView::getAccessibleRelationSet (void)
317     throw (uno::RuntimeException)
318 {
319     return Reference<XAccessibleRelationSet>();
320 }
321 
322 
323 
324 
325 Reference<XAccessibleStateSet > SAL_CALL
326     AccessibleSlideSorterView::getAccessibleStateSet (void)
327     throw (uno::RuntimeException)
328 {
329     ThrowIfDisposed();
330     const vos::OGuard aSolarGuard (Application::GetSolarMutex());
331     ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper();
332 
333     pStateSet->AddState(AccessibleStateType::FOCUSABLE);
334     pStateSet->AddState(AccessibleStateType::SELECTABLE);
335     pStateSet->AddState(AccessibleStateType::ENABLED);
336     pStateSet->AddState(AccessibleStateType::ACTIVE);
337     pStateSet->AddState(AccessibleStateType::MULTI_SELECTABLE);
338     pStateSet->AddState(AccessibleStateType::OPAQUE);
339     if (mpContentWindow!=NULL)
340     {
341         if (mpContentWindow->IsVisible())
342             pStateSet->AddState(AccessibleStateType::VISIBLE);
343         if (mpContentWindow->IsReallyVisible())
344             pStateSet->AddState(AccessibleStateType::SHOWING);
345     }
346 
347     return pStateSet;
348 }
349 
350 
351 
352 
353 lang::Locale SAL_CALL AccessibleSlideSorterView::getLocale (void)
354     throw (IllegalAccessibleComponentStateException,
355         RuntimeException)
356 {
357     ThrowIfDisposed ();
358     Reference<XAccessibleContext> xParentContext;
359     Reference<XAccessible> xParent (getAccessibleParent());
360     if (xParent.is())
361         xParentContext = xParent->getAccessibleContext();
362 
363     if (xParentContext.is())
364         return xParentContext->getLocale();
365     else
366         // Strange, no parent!  Anyway, return the default locale.
367         return Application::GetSettings().GetLocale();
368 }
369 
370 
371 
372 
373 void SAL_CALL AccessibleSlideSorterView::addEventListener(
374     const Reference<XAccessibleEventListener >& rxListener)
375     throw (RuntimeException)
376 {
377 	if (rxListener.is())
378     {
379         const osl::MutexGuard aGuard(maMutex);
380 
381         if (IsDisposed())
382         {
383             uno::Reference<uno::XInterface> x ((lang::XComponent *)this, uno::UNO_QUERY);
384 		    rxListener->disposing (lang::EventObject (x));
385 	    }
386         else
387         {
388             if ( ! mnClientId)
389                 mnClientId = comphelper::AccessibleEventNotifier::registerClient();
390             comphelper::AccessibleEventNotifier::addEventListener(mnClientId, rxListener);
391         }
392     }
393 }
394 
395 
396 
397 
398 void SAL_CALL AccessibleSlideSorterView::removeEventListener(
399     const Reference<XAccessibleEventListener >& rxListener)
400     throw (RuntimeException)
401 {
402     ThrowIfDisposed();
403 	if (rxListener.is())
404 	{
405         const osl::MutexGuard aGuard(maMutex);
406 
407         if (mnClientId != 0)
408         {
409             sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener(
410                 mnClientId, rxListener );
411             if ( !nListenerCount )
412             {
413                 // no listeners anymore -> revoke ourself. This may lead to
414                 // the notifier thread dying (if we were the last client),
415                 // and at least to us not firing any events anymore, in case
416                 // somebody calls NotifyAccessibleEvent, again
417                 comphelper::AccessibleEventNotifier::revokeClient( mnClientId );
418                 mnClientId = 0;
419             }
420         }
421 	}
422 }
423 
424 
425 
426 
427 //===== XAccessibleComponent ==================================================
428 
429 sal_Bool SAL_CALL AccessibleSlideSorterView::containsPoint (const awt::Point& aPoint)
430     throw (RuntimeException)
431 {
432     ThrowIfDisposed();
433     const awt::Rectangle aBBox (getBounds());
434     return (aPoint.X >= 0)
435         && (aPoint.X < aBBox.Width)
436         && (aPoint.Y >= 0)
437         && (aPoint.Y < aBBox.Height);
438 }
439 
440 
441 
442 
443 Reference<XAccessible> SAL_CALL
444     AccessibleSlideSorterView::getAccessibleAtPoint (const awt::Point& aPoint)
445     throw (RuntimeException)
446 {
447     ThrowIfDisposed();
448     Reference<XAccessible> xAccessible;
449     const vos::OGuard aSolarGuard (Application::GetSolarMutex());
450 
451     const Point aTestPoint (aPoint.X, aPoint.Y);
452     ::sd::slidesorter::model::SharedPageDescriptor pHitDescriptor (
453         mrSlideSorter.GetController().GetPageAt(aTestPoint));
454     if (pHitDescriptor.get() != NULL)
455         xAccessible = mpImpl->GetAccessibleChild(
456             (pHitDescriptor->GetPage()->GetPageNum()-1)/2);
457 
458     return xAccessible;
459 }
460 
461 
462 
463 
464 awt::Rectangle SAL_CALL AccessibleSlideSorterView::getBounds (void)
465     throw (uno::RuntimeException)
466 {
467     ThrowIfDisposed();
468     const vos::OGuard aSolarGuard (Application::GetSolarMutex());
469     awt::Rectangle aBBox;
470 
471     if (mpContentWindow != NULL)
472     {
473         const Point aPosition (mpContentWindow->GetPosPixel());
474         const Size aSize (mpContentWindow->GetOutputSizePixel());
475 
476         aBBox.X = aPosition.X();
477         aBBox.Y = aPosition.Y();
478         aBBox.Width = aSize.Width();
479         aBBox.Height = aSize.Height();
480     }
481 
482     return aBBox;
483 }
484 
485 
486 
487 
488 awt::Point SAL_CALL AccessibleSlideSorterView::getLocation (void)
489     throw (uno::RuntimeException)
490 {
491     ThrowIfDisposed();
492     awt::Point aLocation;
493 
494     if (mpContentWindow != NULL)
495     {
496         const Point aPosition (mpContentWindow->GetPosPixel());
497         aLocation.X = aPosition.X();
498         aLocation.Y = aPosition.Y();
499     }
500 
501     return aLocation;
502 }
503 
504 
505 
506 
507 /** Calculate the location on screen from the parent's location on screen
508     and our own relative location.
509 */
510 awt::Point SAL_CALL AccessibleSlideSorterView::getLocationOnScreen()
511     throw (uno::RuntimeException)
512 {
513     ThrowIfDisposed();
514     const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
515     awt::Point aParentLocationOnScreen;
516 
517     Reference<XAccessible> xParent (getAccessibleParent());
518     if (xParent.is())
519     {
520         Reference<XAccessibleComponent> xParentComponent (
521             xParent->getAccessibleContext(), uno::UNO_QUERY);
522         if (xParentComponent.is())
523             aParentLocationOnScreen = xParentComponent->getLocationOnScreen();
524     }
525 
526     awt::Point aLocationOnScreen (getLocation());
527     aLocationOnScreen.X += aParentLocationOnScreen.X;
528     aLocationOnScreen.Y += aParentLocationOnScreen.Y;
529 
530     return aLocationOnScreen;
531 }
532 
533 
534 
535 
536 awt::Size SAL_CALL AccessibleSlideSorterView::getSize (void)
537     throw (uno::RuntimeException)
538 {
539     ThrowIfDisposed();
540     awt::Size aSize;
541 
542     if (mpContentWindow != NULL)
543     {
544         const Size aOutputSize (mpContentWindow->GetOutputSizePixel());
545         aSize.Width = aOutputSize.Width();
546         aSize.Height = aOutputSize.Height();
547     }
548 
549     return aSize;
550 }
551 
552 
553 
554 
555 void SAL_CALL AccessibleSlideSorterView::grabFocus (void)
556     throw (uno::RuntimeException)
557 {
558     ThrowIfDisposed();
559     const vos::OGuard aSolarGuard (Application::GetSolarMutex());
560 
561     if (mpContentWindow)
562         mpContentWindow->GrabFocus();
563 }
564 
565 
566 
567 
568 sal_Int32 SAL_CALL AccessibleSlideSorterView::getForeground (void)
569     throw (RuntimeException)
570 {
571     ThrowIfDisposed();
572 	svtools::ColorConfig aColorConfig;
573     sal_uInt32 nColor = aColorConfig.GetColorValue( svtools::FONTCOLOR ).nColor;
574     return static_cast<sal_Int32>(nColor);
575 }
576 
577 
578 
579 
580 sal_Int32 SAL_CALL AccessibleSlideSorterView::getBackground (void)
581     throw (RuntimeException)
582 {
583     ThrowIfDisposed();
584     sal_uInt32 nColor = Application::GetSettings().GetStyleSettings().GetWindowColor().GetColor();
585     return static_cast<sal_Int32>(nColor);
586 }
587 
588 
589 
590 
591 //===== XAccessibleSelection ==================================================
592 
593 void SAL_CALL AccessibleSlideSorterView::selectAccessibleChild (sal_Int32 nChildIndex)
594     throw (lang::IndexOutOfBoundsException,
595         RuntimeException)
596 {
597     ThrowIfDisposed();
598     const vos::OGuard aSolarGuard (Application::GetSolarMutex());
599 
600     AccessibleSlideSorterObject* pChild = mpImpl->GetAccessibleChild(nChildIndex);
601     if (pChild != NULL)
602         mrSlideSorter.GetController().GetPageSelector().SelectPage(pChild->GetPageNumber());
603     else
604         throw lang::IndexOutOfBoundsException();
605 }
606 
607 
608 
609 
610 sal_Bool SAL_CALL AccessibleSlideSorterView::isAccessibleChildSelected (sal_Int32 nChildIndex)
611     throw (lang::IndexOutOfBoundsException,
612         RuntimeException)
613 {
614     ThrowIfDisposed();
615     sal_Bool bIsSelected = sal_False;
616     const vos::OGuard aSolarGuard (Application::GetSolarMutex());
617 
618     AccessibleSlideSorterObject* pChild = mpImpl->GetAccessibleChild(nChildIndex);
619     if (pChild != NULL)
620         bIsSelected = mrSlideSorter.GetController().GetPageSelector().IsPageSelected(
621             pChild->GetPageNumber());
622     else
623         throw lang::IndexOutOfBoundsException();
624 
625     return bIsSelected;
626 }
627 
628 
629 
630 
631 void SAL_CALL AccessibleSlideSorterView::clearAccessibleSelection (void)
632     throw (uno::RuntimeException)
633 {
634     ThrowIfDisposed();
635     const vos::OGuard aSolarGuard (Application::GetSolarMutex());
636 
637     mrSlideSorter.GetController().GetPageSelector().DeselectAllPages();
638 }
639 
640 
641 
642 
643 void SAL_CALL AccessibleSlideSorterView::selectAllAccessibleChildren (void)
644     throw (uno::RuntimeException)
645 {
646     ThrowIfDisposed();
647     const vos::OGuard aSolarGuard (Application::GetSolarMutex());
648 
649     mrSlideSorter.GetController().GetPageSelector().SelectAllPages();
650 }
651 
652 
653 
654 
655 sal_Int32 SAL_CALL AccessibleSlideSorterView::getSelectedAccessibleChildCount (void)
656     throw (uno::RuntimeException)
657 {
658     ThrowIfDisposed ();
659     const vos::OGuard aSolarGuard (Application::GetSolarMutex());
660     return mrSlideSorter.GetController().GetPageSelector().GetSelectedPageCount();
661 }
662 
663 
664 
665 
666 Reference<XAccessible > SAL_CALL
667     AccessibleSlideSorterView::getSelectedAccessibleChild (sal_Int32 nSelectedChildIndex )
668     throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
669 {
670     ThrowIfDisposed ();
671     const vos::OGuard aSolarGuard (Application::GetSolarMutex());
672     Reference<XAccessible> xChild;
673 
674     ::sd::slidesorter::controller::PageSelector& rSelector (
675         mrSlideSorter.GetController().GetPageSelector());
676     sal_Int32 nPageCount(rSelector.GetPageCount());
677     sal_Int32 nSelectedCount = 0;
678     for (sal_Int32 i=0; i<nPageCount; i++)
679         if (rSelector.IsPageSelected(i))
680         {
681             if (nSelectedCount == nSelectedChildIndex)
682             {
683                 xChild = mpImpl->GetAccessibleChild(i);
684                 break;
685             }
686             ++nSelectedCount;
687         }
688 
689 
690     if ( ! xChild.is() )
691         throw lang::IndexOutOfBoundsException();
692 
693     return xChild;
694 }
695 
696 
697 
698 
699 void SAL_CALL AccessibleSlideSorterView::deselectAccessibleChild (sal_Int32 nChildIndex)
700     throw (lang::IndexOutOfBoundsException,
701         RuntimeException)
702 {
703     ThrowIfDisposed();
704     const vos::OGuard aSolarGuard (Application::GetSolarMutex());
705 
706     AccessibleSlideSorterObject* pChild = mpImpl->GetAccessibleChild(nChildIndex);
707     if (pChild != NULL)
708         mrSlideSorter.GetController().GetPageSelector().DeselectPage(pChild->GetPageNumber());
709     else
710         throw lang::IndexOutOfBoundsException();
711 }
712 
713 
714 
715 
716 //=====  XServiceInfo  ========================================================
717 
718 ::rtl::OUString SAL_CALL
719    	AccessibleSlideSorterView::getImplementationName (void)
720     throw (::com::sun::star::uno::RuntimeException)
721 {
722 	return OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleSlideSorterView"));
723 }
724 
725 
726 
727 
728 sal_Bool SAL_CALL
729  	AccessibleSlideSorterView::supportsService (const OUString& sServiceName)
730     throw (::com::sun::star::uno::RuntimeException)
731 {
732     ThrowIfDisposed ();
733 
734     //  Iterate over all supported service names and return true if on of them
735     //  matches the given name.
736     uno::Sequence< ::rtl::OUString> aSupportedServices (
737         getSupportedServiceNames ());
738     for (int i=0; i<aSupportedServices.getLength(); i++)
739         if (sServiceName == aSupportedServices[i])
740             return sal_True;
741     return sal_False;
742 }
743 
744 
745 
746 
747 uno::Sequence< ::rtl::OUString> SAL_CALL
748    	AccessibleSlideSorterView::getSupportedServiceNames (void)
749     throw (::com::sun::star::uno::RuntimeException)
750 {
751     ThrowIfDisposed ();
752 
753 	static const OUString sServiceNames[3] = {
754         OUString(RTL_CONSTASCII_USTRINGPARAM(
755             "com.sun.star.accessibility.Accessible")),
756         OUString(RTL_CONSTASCII_USTRINGPARAM(
757             "com.sun.star.accessibility.AccessibleContext")),
758         OUString(RTL_CONSTASCII_USTRINGPARAM(
759             "com.sun.star.drawing.AccessibleSlideSorterView"))
760     };
761 	return uno::Sequence<OUString> (sServiceNames, 3);
762 }
763 
764 
765 
766 
767 void AccessibleSlideSorterView::ThrowIfDisposed (void)
768     throw (lang::DisposedException)
769 {
770 	if (rBHelper.bDisposed || rBHelper.bInDispose)
771 	{
772         OSL_TRACE ("Calling disposed object. Throwing exception:");
773         throw lang::DisposedException (
774             OUString(RTL_CONSTASCII_USTRINGPARAM("object has been already disposed")),
775             static_cast<uno::XWeak*>(this));
776     }
777 }
778 
779 
780 
781 sal_Bool AccessibleSlideSorterView::IsDisposed (void)
782 {
783 	return (rBHelper.bDisposed || rBHelper.bInDispose);
784 }
785 
786 
787 
788 
789 //===== AccessibleSlideSorterView::Implementation =============================
790 
791 AccessibleSlideSorterView::Implementation::Implementation (
792     AccessibleSlideSorterView& rAccessibleSlideSorter,
793     ::sd::slidesorter::SlideSorter& rSlideSorter,
794     ::Window* pWindow)
795     : mrAccessibleSlideSorter(rAccessibleSlideSorter),
796       mrSlideSorter(rSlideSorter),
797       maPageObjects(),
798       mnFirstVisibleChild(0),
799       mnLastVisibleChild(-1),
800       mbListeningToDocument(false),
801       mpWindow(pWindow),
802       mnFocusedIndex(-1),
803       mbModelChangeLocked(false),
804       mnUpdateChildrenUserEventId(0),
805       mnSelectionChangeUserEventId(0)
806 {
807     ConnectListeners();
808     UpdateChildren();
809 }
810 
811 
812 
813 
814 AccessibleSlideSorterView::Implementation::~Implementation (void)
815 {
816     if (mnUpdateChildrenUserEventId != 0)
817         Application::RemoveUserEvent(mnUpdateChildrenUserEventId);
818     if (mnSelectionChangeUserEventId != 0)
819         Application::RemoveUserEvent(mnSelectionChangeUserEventId);
820     ReleaseListeners();
821     Clear();
822 }
823 
824 
825 
826 
827 void AccessibleSlideSorterView::Implementation::RequestUpdateChildren (void)
828 {
829     if (mnUpdateChildrenUserEventId == 0)
830         mnUpdateChildrenUserEventId = Application::PostUserEvent(
831             LINK(this, AccessibleSlideSorterView::Implementation,
832             UpdateChildrenCallback));
833 }
834 
835 
836 
837 
838 void AccessibleSlideSorterView::Implementation::UpdateChildren (void)
839 {
840     if (mbModelChangeLocked)
841     {
842         // Do nothing right now.  When the flag is reset, this method is
843         // called again.
844         return;
845     }
846 
847     const Pair aRange (mrSlideSorter.GetView().GetVisiblePageRange());
848     mnFirstVisibleChild = aRange.A();
849     mnLastVisibleChild = aRange.B();
850 
851     // Release all children.
852     Clear();
853 
854     // Create new children for the modified visible range.
855     maPageObjects.resize(mrSlideSorter.GetModel().GetPageCount());
856     for (sal_Int32 nIndex(mnFirstVisibleChild); nIndex<=mnLastVisibleChild; ++nIndex)
857         GetAccessibleChild(nIndex);
858 }
859 
860 
861 
862 
863 void AccessibleSlideSorterView::Implementation::Clear (void)
864 {
865     PageObjectList::iterator iPageObject;
866     PageObjectList::iterator iEnd = maPageObjects.end();
867     for (iPageObject=maPageObjects.begin(); iPageObject!=iEnd; ++iPageObject)
868         if (*iPageObject != NULL)
869         {
870             mrAccessibleSlideSorter.FireAccessibleEvent(
871                 AccessibleEventId::CHILD,
872                 Any(Reference<XAccessible>(iPageObject->get())),
873                 Any());
874 
875             Reference<XComponent> xComponent (Reference<XWeak>(iPageObject->get()), UNO_QUERY);
876             if (xComponent.is())
877                 xComponent->dispose();
878             *iPageObject = NULL;
879         }
880     maPageObjects.clear();
881 }
882 
883 
884 
885 
886 sal_Int32 AccessibleSlideSorterView::Implementation::GetVisibleChildCount (void) const
887 {
888     if (mnFirstVisibleChild<=mnLastVisibleChild && mnFirstVisibleChild>=0)
889         return mnLastVisibleChild - mnFirstVisibleChild + 1;
890     else
891         return 0;
892 }
893 
894 
895 
896 
897 AccessibleSlideSorterObject* AccessibleSlideSorterView::Implementation::GetVisibleChild (
898     sal_Int32 nIndex)
899 {
900     assert(nIndex>=0 && nIndex<GetVisibleChildCount());
901 
902     return GetAccessibleChild(nIndex+mnFirstVisibleChild);
903 }
904 
905 
906 
907 
908 AccessibleSlideSorterObject* AccessibleSlideSorterView::Implementation::GetAccessibleChild (
909     sal_Int32 nIndex)
910 {
911     AccessibleSlideSorterObject* pChild = NULL;
912 
913     if (nIndex>=0 && (sal_uInt32)nIndex<maPageObjects.size())
914     {
915         if (maPageObjects[nIndex] == NULL)
916         {
917             ::sd::slidesorter::model::SharedPageDescriptor pDescriptor(
918                 mrSlideSorter.GetModel().GetPageDescriptor(nIndex));
919             if (pDescriptor.get() != NULL)
920             {
921                 maPageObjects[nIndex] = new AccessibleSlideSorterObject(
922                     &mrAccessibleSlideSorter,
923                     mrSlideSorter,
924                     (pDescriptor->GetPage()->GetPageNum()-1)/2);
925 
926                 mrAccessibleSlideSorter.FireAccessibleEvent(
927                     AccessibleEventId::CHILD,
928                     Any(),
929                     Any(Reference<XAccessible>(maPageObjects[nIndex].get())));
930             }
931 
932         }
933 
934         pChild = maPageObjects[nIndex].get();
935     }
936     else
937     {
938         OSL_ASSERT(nIndex>=0 && (sal_uInt32)nIndex<maPageObjects.size());
939     }
940 
941     return pChild;
942 }
943 
944 
945 
946 
947 void AccessibleSlideSorterView::Implementation::ConnectListeners (void)
948 {
949     StartListening (*mrSlideSorter.GetModel().GetDocument());
950     if (mrSlideSorter.GetViewShell() != NULL)
951         StartListening (*mrSlideSorter.GetViewShell());
952     mbListeningToDocument = true;
953 
954     if (mpWindow != NULL)
955         mpWindow->AddEventListener(
956             LINK(this,AccessibleSlideSorterView::Implementation,WindowEventListener));
957 
958     mrSlideSorter.GetController().GetSelectionManager()->AddSelectionChangeListener(
959         LINK(this,AccessibleSlideSorterView::Implementation,SelectionChangeListener));
960     mrSlideSorter.GetController().GetFocusManager().AddFocusChangeListener(
961         LINK(this,AccessibleSlideSorterView::Implementation,FocusChangeListener));
962     mrSlideSorter.GetView().AddVisibilityChangeListener(
963         LINK(this,AccessibleSlideSorterView::Implementation,UpdateChildrenCallback));
964 }
965 
966 
967 
968 
969 void AccessibleSlideSorterView::Implementation::ReleaseListeners (void)
970 {
971     mrSlideSorter.GetController().GetFocusManager().RemoveFocusChangeListener(
972         LINK(this,AccessibleSlideSorterView::Implementation,FocusChangeListener));
973     mrSlideSorter.GetController().GetSelectionManager()->RemoveSelectionChangeListener(
974         LINK(this,AccessibleSlideSorterView::Implementation,SelectionChangeListener));
975     mrSlideSorter.GetView().RemoveVisibilityChangeListener(
976         LINK(this,AccessibleSlideSorterView::Implementation,UpdateChildrenCallback));
977 
978     if (mpWindow != NULL)
979         mpWindow->RemoveEventListener(
980             LINK(this,AccessibleSlideSorterView::Implementation,WindowEventListener));
981 
982     if (mbListeningToDocument)
983     {
984         if (mrSlideSorter.GetViewShell() != NULL)
985             StartListening(*mrSlideSorter.GetViewShell());
986         EndListening (*mrSlideSorter.GetModel().GetDocument());
987         mbListeningToDocument = false;
988     }
989 }
990 
991 
992 
993 
994 void AccessibleSlideSorterView::Implementation::Notify (
995     SfxBroadcaster&,
996     const SfxHint& rHint)
997 {
998     if (rHint.ISA(SdrHint))
999     {
1000         SdrHint& rSdrHint (*PTR_CAST(SdrHint,&rHint));
1001         switch (rSdrHint.GetKind())
1002         {
1003             case HINT_PAGEORDERCHG:
1004                 RequestUpdateChildren();
1005                 break;
1006             default:
1007                 break;
1008         }
1009     }
1010     else if (rHint.ISA(sd::ViewShellHint))
1011     {
1012         sd::ViewShellHint& rViewShellHint (*PTR_CAST(sd::ViewShellHint, &rHint));
1013         switch (rViewShellHint.GetHintId())
1014         {
1015             case sd::ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_START:
1016                 mbModelChangeLocked = true;
1017                 break;
1018 
1019             case sd::ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_END:
1020                 mbModelChangeLocked = false;
1021                 RequestUpdateChildren();
1022                 break;
1023             default:
1024                 break;
1025         }
1026     }
1027 }
1028 
1029 
1030 
1031 
1032 IMPL_LINK(AccessibleSlideSorterView::Implementation, WindowEventListener, VclWindowEvent*, pEvent)
1033 {
1034 	switch (pEvent->GetId())
1035     {
1036         case VCLEVENT_WINDOW_MOVE:
1037         case VCLEVENT_WINDOW_RESIZE:
1038             RequestUpdateChildren();
1039             break;
1040 
1041         case VCLEVENT_WINDOW_GETFOCUS:
1042         case VCLEVENT_WINDOW_LOSEFOCUS:
1043             mrAccessibleSlideSorter.FireAccessibleEvent(
1044                 AccessibleEventId::SELECTION_CHANGED,
1045                 Any(),
1046                 Any());
1047             break;
1048         default:
1049             break;
1050     }
1051     return 1;
1052 }
1053 
1054 
1055 
1056 
1057 IMPL_LINK(AccessibleSlideSorterView::Implementation, SelectionChangeListener, void*, EMPTYARG )
1058 {
1059     if (mnSelectionChangeUserEventId == 0)
1060         mnSelectionChangeUserEventId = Application::PostUserEvent(
1061             LINK(this, AccessibleSlideSorterView::Implementation, BroadcastSelectionChange));
1062     return 1;
1063 }
1064 
1065 
1066 
1067 
1068 IMPL_LINK(AccessibleSlideSorterView::Implementation, BroadcastSelectionChange, void*, EMPTYARG )
1069 {
1070     mnSelectionChangeUserEventId = 0;
1071     mrAccessibleSlideSorter.FireAccessibleEvent(
1072         AccessibleEventId::SELECTION_CHANGED,
1073         Any(),
1074         Any());
1075     return 1;
1076 }
1077 
1078 
1079 
1080 
1081 IMPL_LINK(AccessibleSlideSorterView::Implementation, FocusChangeListener, void*, EMPTYARG )
1082 {
1083     sal_Int32 nNewFocusedIndex (
1084         mrSlideSorter.GetController().GetFocusManager().GetFocusedPageIndex());
1085 
1086     if (nNewFocusedIndex != mnFocusedIndex)
1087     {
1088         if (mnFocusedIndex >= 0)
1089         {
1090             AccessibleSlideSorterObject* pObject = GetAccessibleChild(mnFocusedIndex);
1091             if (pObject != NULL)
1092                 pObject->FireAccessibleEvent(
1093                     AccessibleEventId::STATE_CHANGED,
1094                     Any(AccessibleStateType::FOCUSED),
1095                     Any());
1096         }
1097         if (nNewFocusedIndex >= 0)
1098         {
1099             AccessibleSlideSorterObject* pObject = GetAccessibleChild(nNewFocusedIndex);
1100             if (pObject != NULL)
1101                 pObject->FireAccessibleEvent(
1102                     AccessibleEventId::STATE_CHANGED,
1103                     Any(),
1104                     Any(AccessibleStateType::FOCUSED));
1105         }
1106         mnFocusedIndex = nNewFocusedIndex;
1107     }
1108     return 1;
1109 }
1110 
1111 
1112 
1113 
1114 IMPL_LINK(AccessibleSlideSorterView::Implementation, UpdateChildrenCallback, void*, EMPTYARG )
1115 {
1116     mnUpdateChildrenUserEventId = 0;
1117     UpdateChildren();
1118 
1119     return 1;
1120 }
1121 
1122 
1123 
1124 
1125 } // end of namespace ::accessibility
1126