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 throw (uno::RuntimeException)
204 {
205 ThrowIfDisposed ();
206 return this;
207 }
208
209 //===== XAccessibleContext ==================================================
210
getAccessibleChildCount(void)211 sal_Int32 SAL_CALL AccessibleSlideSorterView::getAccessibleChildCount (void)
212 throw (RuntimeException)
213 {
214 ThrowIfDisposed();
215 ::osl::MutexGuard aGuard (maMutex);
216 return mpImpl->GetVisibleChildCount();
217 }
218
219 Reference<XAccessible > SAL_CALL
getAccessibleChild(sal_Int32 nIndex)220 AccessibleSlideSorterView::getAccessibleChild (sal_Int32 nIndex)
221 throw (lang::IndexOutOfBoundsException, RuntimeException)
222 {
223 ThrowIfDisposed();
224 ::osl::MutexGuard aGuard (maMutex);
225
226 if (nIndex<0 || nIndex>=mpImpl->GetVisibleChildCount())
227 throw lang::IndexOutOfBoundsException();
228
229 return mpImpl->GetVisibleChild(nIndex);
230 }
231
getAccessibleParent(void)232 Reference<XAccessible > SAL_CALL AccessibleSlideSorterView::getAccessibleParent (void)
233 throw (uno::RuntimeException)
234 {
235 ThrowIfDisposed();
236 const vos::OGuard aSolarGuard (Application::GetSolarMutex());
237 Reference<XAccessible> xParent;
238
239 if (mpContentWindow != NULL)
240 {
241 ::Window* pParent = mpContentWindow->GetAccessibleParentWindow();
242 if (pParent != NULL)
243 xParent = pParent->GetAccessible();
244 }
245
246 return xParent;
247 }
248
getAccessibleIndexInParent(void)249 sal_Int32 SAL_CALL AccessibleSlideSorterView::getAccessibleIndexInParent (void)
250 throw (uno::RuntimeException)
251 {
252 OSL_ASSERT(getAccessibleParent().is());
253 ThrowIfDisposed();
254 const vos::OGuard aSolarGuard (Application::GetSolarMutex());
255 sal_Int32 nIndexInParent(-1);
256
257
258 Reference<XAccessibleContext> xParentContext (getAccessibleParent()->getAccessibleContext());
259 if (xParentContext.is())
260 {
261 sal_Int32 nChildCount (xParentContext->getAccessibleChildCount());
262 for (sal_Int32 i=0; i<nChildCount; ++i)
263 if (xParentContext->getAccessibleChild(i).get()
264 == static_cast<XAccessible*>(this))
265 {
266 nIndexInParent = i;
267 break;
268 }
269 }
270
271 return nIndexInParent;
272 }
273
274
275
276
getAccessibleRole(void)277 sal_Int16 SAL_CALL AccessibleSlideSorterView::getAccessibleRole (void)
278 throw (uno::RuntimeException)
279 {
280 ThrowIfDisposed();
281 static sal_Int16 nRole = AccessibleRole::DOCUMENT;
282 return nRole;
283 }
284
285
286
287
getAccessibleDescription(void)288 ::rtl::OUString SAL_CALL AccessibleSlideSorterView::getAccessibleDescription (void)
289 throw (uno::RuntimeException)
290 {
291 ThrowIfDisposed();
292 ::vos::OGuard aGuard (Application::GetSolarMutex());
293
294 return String(SdResId(SID_SD_A11Y_I_SLIDEVIEW_D));
295 }
296
297
298
299
getAccessibleName(void)300 ::rtl::OUString SAL_CALL AccessibleSlideSorterView::getAccessibleName (void)
301 throw (uno::RuntimeException)
302 {
303 ThrowIfDisposed();
304 ::vos::OGuard aGuard (Application::GetSolarMutex());
305
306 return String(SdResId(SID_SD_A11Y_I_SLIDEVIEW_N));
307 }
308
309
310
311
312 Reference<XAccessibleRelationSet> SAL_CALL
getAccessibleRelationSet(void)313 AccessibleSlideSorterView::getAccessibleRelationSet (void)
314 throw (uno::RuntimeException)
315 {
316 return Reference<XAccessibleRelationSet>();
317 }
318
319
320
321
322 Reference<XAccessibleStateSet > SAL_CALL
getAccessibleStateSet(void)323 AccessibleSlideSorterView::getAccessibleStateSet (void)
324 throw (uno::RuntimeException)
325 {
326 ThrowIfDisposed();
327 const vos::OGuard aSolarGuard (Application::GetSolarMutex());
328 ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper();
329
330 pStateSet->AddState(AccessibleStateType::FOCUSABLE);
331 pStateSet->AddState(AccessibleStateType::SELECTABLE);
332 pStateSet->AddState(AccessibleStateType::ENABLED);
333 pStateSet->AddState(AccessibleStateType::ACTIVE);
334 pStateSet->AddState(AccessibleStateType::MULTI_SELECTABLE);
335 pStateSet->AddState(AccessibleStateType::OPAQUE);
336 if (mpContentWindow!=NULL)
337 {
338 if (mpContentWindow->IsVisible())
339 pStateSet->AddState(AccessibleStateType::VISIBLE);
340 if (mpContentWindow->IsReallyVisible())
341 pStateSet->AddState(AccessibleStateType::SHOWING);
342 }
343
344 return pStateSet;
345 }
346
347
348
349
getLocale(void)350 lang::Locale SAL_CALL AccessibleSlideSorterView::getLocale (void)
351 throw (IllegalAccessibleComponentStateException,
352 RuntimeException)
353 {
354 ThrowIfDisposed ();
355 Reference<XAccessibleContext> xParentContext;
356 Reference<XAccessible> xParent (getAccessibleParent());
357 if (xParent.is())
358 xParentContext = xParent->getAccessibleContext();
359
360 if (xParentContext.is())
361 return xParentContext->getLocale();
362 else
363 // Strange, no parent! Anyway, return the default locale.
364 return Application::GetSettings().GetLocale();
365 }
366
367
368
369
addEventListener(const Reference<XAccessibleEventListener> & rxListener)370 void SAL_CALL AccessibleSlideSorterView::addEventListener(
371 const Reference<XAccessibleEventListener >& rxListener)
372 throw (RuntimeException)
373 {
374 if (rxListener.is())
375 {
376 const osl::MutexGuard aGuard(maMutex);
377
378 if (IsDisposed())
379 {
380 uno::Reference<uno::XInterface> x ((lang::XComponent *)this, uno::UNO_QUERY);
381 rxListener->disposing (lang::EventObject (x));
382 }
383 else
384 {
385 if ( ! mnClientId)
386 mnClientId = comphelper::AccessibleEventNotifier::registerClient();
387 comphelper::AccessibleEventNotifier::addEventListener(mnClientId, rxListener);
388 }
389 }
390 }
391
392
393
394
removeEventListener(const Reference<XAccessibleEventListener> & rxListener)395 void SAL_CALL AccessibleSlideSorterView::removeEventListener(
396 const Reference<XAccessibleEventListener >& rxListener)
397 throw (RuntimeException)
398 {
399 ThrowIfDisposed();
400 if (rxListener.is())
401 {
402 const osl::MutexGuard aGuard(maMutex);
403
404 if (mnClientId != 0)
405 {
406 sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener(
407 mnClientId, rxListener );
408 if ( !nListenerCount )
409 {
410 // no listeners anymore -> revoke ourself. This may lead to
411 // the notifier thread dying (if we were the last client),
412 // and at least to us not firing any events anymore, in case
413 // somebody calls NotifyAccessibleEvent, again
414 comphelper::AccessibleEventNotifier::revokeClient( mnClientId );
415 mnClientId = 0;
416 }
417 }
418 }
419 }
420
421
422
423
424 //===== XAccessibleComponent ==================================================
425
containsPoint(const awt::Point & aPoint)426 sal_Bool SAL_CALL AccessibleSlideSorterView::containsPoint (const awt::Point& aPoint)
427 throw (RuntimeException)
428 {
429 ThrowIfDisposed();
430 const awt::Rectangle aBBox (getBounds());
431 return (aPoint.X >= 0)
432 && (aPoint.X < aBBox.Width)
433 && (aPoint.Y >= 0)
434 && (aPoint.Y < aBBox.Height);
435 }
436
437
438
439
440 Reference<XAccessible> SAL_CALL
getAccessibleAtPoint(const awt::Point & aPoint)441 AccessibleSlideSorterView::getAccessibleAtPoint (const awt::Point& aPoint)
442 throw (RuntimeException)
443 {
444 ThrowIfDisposed();
445 Reference<XAccessible> xAccessible;
446 const vos::OGuard aSolarGuard (Application::GetSolarMutex());
447
448 const Point aTestPoint (aPoint.X, aPoint.Y);
449 ::sd::slidesorter::model::SharedPageDescriptor pHitDescriptor (
450 mrSlideSorter.GetController().GetPageAt(aTestPoint));
451 if (pHitDescriptor.get() != NULL)
452 xAccessible = mpImpl->GetAccessibleChild(
453 (pHitDescriptor->GetPage()->GetPageNum()-1)/2);
454
455 return xAccessible;
456 }
457
458
459
460
getBounds(void)461 awt::Rectangle SAL_CALL AccessibleSlideSorterView::getBounds (void)
462 throw (uno::RuntimeException)
463 {
464 ThrowIfDisposed();
465 const vos::OGuard aSolarGuard (Application::GetSolarMutex());
466 awt::Rectangle aBBox;
467
468 if (mpContentWindow != NULL)
469 {
470 const Point aPosition (mpContentWindow->GetPosPixel());
471 const Size aSize (mpContentWindow->GetOutputSizePixel());
472
473 aBBox.X = aPosition.X();
474 aBBox.Y = aPosition.Y();
475 aBBox.Width = aSize.Width();
476 aBBox.Height = aSize.Height();
477 }
478
479 return aBBox;
480 }
481
482
483
484
getLocation(void)485 awt::Point SAL_CALL AccessibleSlideSorterView::getLocation (void)
486 throw (uno::RuntimeException)
487 {
488 ThrowIfDisposed();
489 awt::Point aLocation;
490
491 if (mpContentWindow != NULL)
492 {
493 const Point aPosition (mpContentWindow->GetPosPixel());
494 aLocation.X = aPosition.X();
495 aLocation.Y = aPosition.Y();
496 }
497
498 return aLocation;
499 }
500
501
502
503
504 /** Calculate the location on screen from the parent's location on screen
505 and our own relative location.
506 */
getLocationOnScreen()507 awt::Point SAL_CALL AccessibleSlideSorterView::getLocationOnScreen()
508 throw (uno::RuntimeException)
509 {
510 ThrowIfDisposed();
511 const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
512 awt::Point aParentLocationOnScreen;
513
514 Reference<XAccessible> xParent (getAccessibleParent());
515 if (xParent.is())
516 {
517 Reference<XAccessibleComponent> xParentComponent (
518 xParent->getAccessibleContext(), uno::UNO_QUERY);
519 if (xParentComponent.is())
520 aParentLocationOnScreen = xParentComponent->getLocationOnScreen();
521 }
522
523 awt::Point aLocationOnScreen (getLocation());
524 aLocationOnScreen.X += aParentLocationOnScreen.X;
525 aLocationOnScreen.Y += aParentLocationOnScreen.Y;
526
527 return aLocationOnScreen;
528 }
529
530
531
532
getSize(void)533 awt::Size SAL_CALL AccessibleSlideSorterView::getSize (void)
534 throw (uno::RuntimeException)
535 {
536 ThrowIfDisposed();
537 awt::Size aSize;
538
539 if (mpContentWindow != NULL)
540 {
541 const Size aOutputSize (mpContentWindow->GetOutputSizePixel());
542 aSize.Width = aOutputSize.Width();
543 aSize.Height = aOutputSize.Height();
544 }
545
546 return aSize;
547 }
548
549
550
551
grabFocus(void)552 void SAL_CALL AccessibleSlideSorterView::grabFocus (void)
553 throw (uno::RuntimeException)
554 {
555 ThrowIfDisposed();
556 const vos::OGuard aSolarGuard (Application::GetSolarMutex());
557
558 if (mpContentWindow)
559 mpContentWindow->GrabFocus();
560 }
561
562
563
564
getForeground(void)565 sal_Int32 SAL_CALL AccessibleSlideSorterView::getForeground (void)
566 throw (RuntimeException)
567 {
568 ThrowIfDisposed();
569 svtools::ColorConfig aColorConfig;
570 sal_uInt32 nColor = aColorConfig.GetColorValue( svtools::FONTCOLOR ).nColor;
571 return static_cast<sal_Int32>(nColor);
572 }
573
574
575
576
getBackground(void)577 sal_Int32 SAL_CALL AccessibleSlideSorterView::getBackground (void)
578 throw (RuntimeException)
579 {
580 ThrowIfDisposed();
581 sal_uInt32 nColor = Application::GetSettings().GetStyleSettings().GetWindowColor().GetColor();
582 return static_cast<sal_Int32>(nColor);
583 }
584
585
586
587
588 //===== XAccessibleSelection ==================================================
589
selectAccessibleChild(sal_Int32 nChildIndex)590 void SAL_CALL AccessibleSlideSorterView::selectAccessibleChild (sal_Int32 nChildIndex)
591 throw (lang::IndexOutOfBoundsException,
592 RuntimeException)
593 {
594 ThrowIfDisposed();
595 const vos::OGuard aSolarGuard (Application::GetSolarMutex());
596
597 AccessibleSlideSorterObject* pChild = mpImpl->GetAccessibleChild(nChildIndex);
598 if (pChild != NULL)
599 mrSlideSorter.GetController().GetPageSelector().SelectPage(pChild->GetPageNumber());
600 else
601 throw lang::IndexOutOfBoundsException();
602 }
603
604
605
606
isAccessibleChildSelected(sal_Int32 nChildIndex)607 sal_Bool SAL_CALL AccessibleSlideSorterView::isAccessibleChildSelected (sal_Int32 nChildIndex)
608 throw (lang::IndexOutOfBoundsException,
609 RuntimeException)
610 {
611 ThrowIfDisposed();
612 sal_Bool bIsSelected = sal_False;
613 const vos::OGuard aSolarGuard (Application::GetSolarMutex());
614
615 AccessibleSlideSorterObject* pChild = mpImpl->GetAccessibleChild(nChildIndex);
616 if (pChild != NULL)
617 bIsSelected = mrSlideSorter.GetController().GetPageSelector().IsPageSelected(
618 pChild->GetPageNumber());
619 else
620 throw lang::IndexOutOfBoundsException();
621
622 return bIsSelected;
623 }
624
625
626
627
clearAccessibleSelection(void)628 void SAL_CALL AccessibleSlideSorterView::clearAccessibleSelection (void)
629 throw (uno::RuntimeException)
630 {
631 ThrowIfDisposed();
632 const vos::OGuard aSolarGuard (Application::GetSolarMutex());
633
634 mrSlideSorter.GetController().GetPageSelector().DeselectAllPages();
635 }
636
637
638
639
selectAllAccessibleChildren(void)640 void SAL_CALL AccessibleSlideSorterView::selectAllAccessibleChildren (void)
641 throw (uno::RuntimeException)
642 {
643 ThrowIfDisposed();
644 const vos::OGuard aSolarGuard (Application::GetSolarMutex());
645
646 mrSlideSorter.GetController().GetPageSelector().SelectAllPages();
647 }
648
649
650
651
getSelectedAccessibleChildCount(void)652 sal_Int32 SAL_CALL AccessibleSlideSorterView::getSelectedAccessibleChildCount (void)
653 throw (uno::RuntimeException)
654 {
655 ThrowIfDisposed ();
656 const vos::OGuard aSolarGuard (Application::GetSolarMutex());
657 return mrSlideSorter.GetController().GetPageSelector().GetSelectedPageCount();
658 }
659
660
661
662
663 Reference<XAccessible > SAL_CALL
getSelectedAccessibleChild(sal_Int32 nSelectedChildIndex)664 AccessibleSlideSorterView::getSelectedAccessibleChild (sal_Int32 nSelectedChildIndex )
665 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
666 {
667 ThrowIfDisposed ();
668 const vos::OGuard aSolarGuard (Application::GetSolarMutex());
669 Reference<XAccessible> xChild;
670
671 ::sd::slidesorter::controller::PageSelector& rSelector (
672 mrSlideSorter.GetController().GetPageSelector());
673 sal_Int32 nPageCount(rSelector.GetPageCount());
674 sal_Int32 nSelectedCount = 0;
675 for (sal_Int32 i=0; i<nPageCount; i++)
676 if (rSelector.IsPageSelected(i))
677 {
678 if (nSelectedCount == nSelectedChildIndex)
679 {
680 xChild = mpImpl->GetAccessibleChild(i);
681 break;
682 }
683 ++nSelectedCount;
684 }
685
686
687 if ( ! xChild.is() )
688 throw lang::IndexOutOfBoundsException();
689
690 return xChild;
691 }
692
693
694
695
deselectAccessibleChild(sal_Int32 nChildIndex)696 void SAL_CALL AccessibleSlideSorterView::deselectAccessibleChild (sal_Int32 nChildIndex)
697 throw (lang::IndexOutOfBoundsException,
698 RuntimeException)
699 {
700 ThrowIfDisposed();
701 const vos::OGuard aSolarGuard (Application::GetSolarMutex());
702
703 AccessibleSlideSorterObject* pChild = mpImpl->GetAccessibleChild(nChildIndex);
704 if (pChild != NULL)
705 mrSlideSorter.GetController().GetPageSelector().DeselectPage(pChild->GetPageNumber());
706 else
707 throw lang::IndexOutOfBoundsException();
708 }
709
710
711
712
713 //===== XServiceInfo ========================================================
714
715 ::rtl::OUString SAL_CALL
getImplementationName(void)716 AccessibleSlideSorterView::getImplementationName (void)
717 throw (::com::sun::star::uno::RuntimeException)
718 {
719 return OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleSlideSorterView"));
720 }
721
722
723
724
725 sal_Bool SAL_CALL
supportsService(const OUString & sServiceName)726 AccessibleSlideSorterView::supportsService (const OUString& sServiceName)
727 throw (::com::sun::star::uno::RuntimeException)
728 {
729 ThrowIfDisposed ();
730
731 // Iterate over all supported service names and return true if on of them
732 // matches the given name.
733 uno::Sequence< ::rtl::OUString> aSupportedServices (
734 getSupportedServiceNames ());
735 for (int i=0; i<aSupportedServices.getLength(); i++)
736 if (sServiceName == aSupportedServices[i])
737 return sal_True;
738 return sal_False;
739 }
740
741
742
743
744 uno::Sequence< ::rtl::OUString> SAL_CALL
getSupportedServiceNames(void)745 AccessibleSlideSorterView::getSupportedServiceNames (void)
746 throw (::com::sun::star::uno::RuntimeException)
747 {
748 ThrowIfDisposed ();
749
750 static const OUString sServiceNames[3] = {
751 OUString(RTL_CONSTASCII_USTRINGPARAM(
752 "com.sun.star.accessibility.Accessible")),
753 OUString(RTL_CONSTASCII_USTRINGPARAM(
754 "com.sun.star.accessibility.AccessibleContext")),
755 OUString(RTL_CONSTASCII_USTRINGPARAM(
756 "com.sun.star.drawing.AccessibleSlideSorterView"))
757 };
758 return uno::Sequence<OUString> (sServiceNames, 3);
759 }
760
761
762
763
ThrowIfDisposed(void)764 void AccessibleSlideSorterView::ThrowIfDisposed (void)
765 throw (lang::DisposedException)
766 {
767 if (rBHelper.bDisposed || rBHelper.bInDispose)
768 {
769 OSL_TRACE ("Calling disposed object. Throwing exception:");
770 throw lang::DisposedException (
771 OUString(RTL_CONSTASCII_USTRINGPARAM("object has been already disposed")),
772 static_cast<uno::XWeak*>(this));
773 }
774 }
775
776
777
IsDisposed(void)778 sal_Bool AccessibleSlideSorterView::IsDisposed (void)
779 {
780 return (rBHelper.bDisposed || rBHelper.bInDispose);
781 }
782
783
784
785
786 //===== AccessibleSlideSorterView::Implementation =============================
787
Implementation(AccessibleSlideSorterView & rAccessibleSlideSorter,::sd::slidesorter::SlideSorter & rSlideSorter,::Window * pWindow)788 AccessibleSlideSorterView::Implementation::Implementation (
789 AccessibleSlideSorterView& rAccessibleSlideSorter,
790 ::sd::slidesorter::SlideSorter& rSlideSorter,
791 ::Window* pWindow)
792 : mrAccessibleSlideSorter(rAccessibleSlideSorter),
793 mrSlideSorter(rSlideSorter),
794 maPageObjects(),
795 mnFirstVisibleChild(0),
796 mnLastVisibleChild(-1),
797 mbListeningToDocument(false),
798 mpWindow(pWindow),
799 mnFocusedIndex(-1),
800 mbModelChangeLocked(false),
801 mnUpdateChildrenUserEventId(0),
802 mnSelectionChangeUserEventId(0)
803 {
804 ConnectListeners();
805 UpdateChildren();
806 }
807
808
809
810
~Implementation(void)811 AccessibleSlideSorterView::Implementation::~Implementation (void)
812 {
813 if (mnUpdateChildrenUserEventId != 0)
814 Application::RemoveUserEvent(mnUpdateChildrenUserEventId);
815 if (mnSelectionChangeUserEventId != 0)
816 Application::RemoveUserEvent(mnSelectionChangeUserEventId);
817 ReleaseListeners();
818 Clear();
819 }
820
821
822
823
RequestUpdateChildren(void)824 void AccessibleSlideSorterView::Implementation::RequestUpdateChildren (void)
825 {
826 if (mnUpdateChildrenUserEventId == 0)
827 mnUpdateChildrenUserEventId = Application::PostUserEvent(
828 LINK(this, AccessibleSlideSorterView::Implementation,
829 UpdateChildrenCallback));
830 }
831
832
833
834
UpdateChildren(void)835 void AccessibleSlideSorterView::Implementation::UpdateChildren (void)
836 {
837 //By default, all children should be accessible. So here workaround is to make all children visible.
838 // MT: THis was in UpdateVisibility, which has some similarity, and hg merge automatically has put it here. Correct?!
839 // In the IA2 CWS, also setting mnFirst/LastVisibleChild was commented out!
840 mnLastVisibleChild = maPageObjects.size();
841
842 if (mbModelChangeLocked)
843 {
844 // Do nothing right now. When the flag is reset, this method is
845 // called again.
846 return;
847 }
848
849 const Pair aRange (mrSlideSorter.GetView().GetVisiblePageRange());
850 mnFirstVisibleChild = aRange.A();
851 mnLastVisibleChild = aRange.B();
852
853 // Release all children.
854 Clear();
855
856 // Create new children for the modified visible range.
857 maPageObjects.resize(mrSlideSorter.GetModel().GetPageCount());
858 for (sal_Int32 nIndex(mnFirstVisibleChild); nIndex<=mnLastVisibleChild; ++nIndex)
859 GetAccessibleChild(nIndex);
860 }
861
862
863
864
Clear(void)865 void AccessibleSlideSorterView::Implementation::Clear (void)
866 {
867 PageObjectList::iterator iPageObject;
868 PageObjectList::iterator iEnd = maPageObjects.end();
869 for (iPageObject=maPageObjects.begin(); iPageObject!=iEnd; ++iPageObject)
870 if (*iPageObject != NULL)
871 {
872 mrAccessibleSlideSorter.FireAccessibleEvent(
873 AccessibleEventId::CHILD,
874 Any(Reference<XAccessible>(iPageObject->get())),
875 Any());
876
877 Reference<XComponent> xComponent (Reference<XWeak>(iPageObject->get()), UNO_QUERY);
878 if (xComponent.is())
879 xComponent->dispose();
880 *iPageObject = NULL;
881 }
882 maPageObjects.clear();
883 }
884
885
886
887
GetVisibleChildCount(void) const888 sal_Int32 AccessibleSlideSorterView::Implementation::GetVisibleChildCount (void) const
889 {
890 if (mnFirstVisibleChild<=mnLastVisibleChild && mnFirstVisibleChild>=0)
891 return mnLastVisibleChild - mnFirstVisibleChild + 1;
892 else
893 return 0;
894 }
895
896
897
898
GetVisibleChild(sal_Int32 nIndex)899 AccessibleSlideSorterObject* AccessibleSlideSorterView::Implementation::GetVisibleChild (
900 sal_Int32 nIndex)
901 {
902 assert(nIndex>=0 && nIndex<GetVisibleChildCount());
903
904 return GetAccessibleChild(nIndex+mnFirstVisibleChild);
905 }
906
907
908
909
GetAccessibleChild(sal_Int32 nIndex)910 AccessibleSlideSorterObject* AccessibleSlideSorterView::Implementation::GetAccessibleChild (
911 sal_Int32 nIndex)
912 {
913 AccessibleSlideSorterObject* pChild = NULL;
914
915 if (nIndex>=0 && (sal_uInt32)nIndex<maPageObjects.size())
916 {
917 if (maPageObjects[nIndex] == NULL)
918 {
919 ::sd::slidesorter::model::SharedPageDescriptor pDescriptor(
920 mrSlideSorter.GetModel().GetPageDescriptor(nIndex));
921 if (pDescriptor.get() != NULL)
922 {
923 maPageObjects[nIndex] = new AccessibleSlideSorterObject(
924 &mrAccessibleSlideSorter,
925 mrSlideSorter,
926 (pDescriptor->GetPage()->GetPageNum()-1)/2);
927
928 mrAccessibleSlideSorter.FireAccessibleEvent(
929 AccessibleEventId::CHILD,
930 Any(),
931 Any(Reference<XAccessible>(maPageObjects[nIndex].get())));
932 }
933
934 }
935
936 pChild = maPageObjects[nIndex].get();
937 }
938 else
939 {
940 OSL_ASSERT(nIndex>=0 && (sal_uInt32)nIndex<maPageObjects.size());
941 }
942
943 return pChild;
944 }
945
946
947
948
ConnectListeners(void)949 void AccessibleSlideSorterView::Implementation::ConnectListeners (void)
950 {
951 StartListening (*mrSlideSorter.GetModel().GetDocument());
952 if (mrSlideSorter.GetViewShell() != NULL)
953 StartListening (*mrSlideSorter.GetViewShell());
954 mbListeningToDocument = true;
955
956 if (mpWindow != NULL)
957 mpWindow->AddEventListener(
958 LINK(this,AccessibleSlideSorterView::Implementation,WindowEventListener));
959
960 mrSlideSorter.GetController().GetSelectionManager()->AddSelectionChangeListener(
961 LINK(this,AccessibleSlideSorterView::Implementation,SelectionChangeListener));
962 mrSlideSorter.GetController().GetFocusManager().AddFocusChangeListener(
963 LINK(this,AccessibleSlideSorterView::Implementation,FocusChangeListener));
964 mrSlideSorter.GetView().AddVisibilityChangeListener(
965 LINK(this,AccessibleSlideSorterView::Implementation,UpdateChildrenCallback));
966 }
967
968
969
970
ReleaseListeners(void)971 void AccessibleSlideSorterView::Implementation::ReleaseListeners (void)
972 {
973 mrSlideSorter.GetController().GetFocusManager().RemoveFocusChangeListener(
974 LINK(this,AccessibleSlideSorterView::Implementation,FocusChangeListener));
975 mrSlideSorter.GetController().GetSelectionManager()->RemoveSelectionChangeListener(
976 LINK(this,AccessibleSlideSorterView::Implementation,SelectionChangeListener));
977 mrSlideSorter.GetView().RemoveVisibilityChangeListener(
978 LINK(this,AccessibleSlideSorterView::Implementation,UpdateChildrenCallback));
979
980 if (mpWindow != NULL)
981 mpWindow->RemoveEventListener(
982 LINK(this,AccessibleSlideSorterView::Implementation,WindowEventListener));
983
984 if (mbListeningToDocument)
985 {
986 if (mrSlideSorter.GetViewShell() != NULL)
987 StartListening(*mrSlideSorter.GetViewShell());
988 EndListening (*mrSlideSorter.GetModel().GetDocument());
989 mbListeningToDocument = false;
990 }
991 }
992
993
994
995
Notify(SfxBroadcaster &,const SfxHint & rHint)996 void AccessibleSlideSorterView::Implementation::Notify (
997 SfxBroadcaster&,
998 const SfxHint& rHint)
999 {
1000 if (rHint.ISA(SdrHint))
1001 {
1002 SdrHint& rSdrHint (*PTR_CAST(SdrHint,&rHint));
1003 switch (rSdrHint.GetKind())
1004 {
1005 case HINT_PAGEORDERCHG:
1006 RequestUpdateChildren();
1007 break;
1008 default:
1009 break;
1010 }
1011 }
1012 else if (rHint.ISA(sd::ViewShellHint))
1013 {
1014 sd::ViewShellHint& rViewShellHint (*PTR_CAST(sd::ViewShellHint, &rHint));
1015 switch (rViewShellHint.GetHintId())
1016 {
1017 case sd::ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_START:
1018 mbModelChangeLocked = true;
1019 break;
1020
1021 case sd::ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_END:
1022 mbModelChangeLocked = false;
1023 RequestUpdateChildren();
1024 break;
1025 default:
1026 break;
1027 }
1028 }
1029 }
1030
1031
SwitchViewActivated(void)1032 void AccessibleSlideSorterView::SwitchViewActivated (void)
1033 {
1034 // Firstly, set focus to view
1035 this->FireAccessibleEvent(AccessibleEventId::STATE_CHANGED,
1036 Any(),
1037 Any(AccessibleStateType::FOCUSED));
1038
1039 mpImpl->Activated();
1040 }
1041
Activated()1042 void AccessibleSlideSorterView::Implementation::Activated()
1043 {
1044 mrSlideSorter.GetController().GetFocusManager().ShowFocus();
1045
1046 }
1047
1048
1049
IMPL_LINK(AccessibleSlideSorterView::Implementation,WindowEventListener,VclWindowEvent *,pEvent)1050 IMPL_LINK(AccessibleSlideSorterView::Implementation, WindowEventListener, VclWindowEvent*, pEvent)
1051 {
1052 switch (pEvent->GetId())
1053 {
1054 case VCLEVENT_WINDOW_MOVE:
1055 case VCLEVENT_WINDOW_RESIZE:
1056 RequestUpdateChildren();
1057 break;
1058
1059 case VCLEVENT_WINDOW_GETFOCUS:
1060 case VCLEVENT_WINDOW_LOSEFOCUS:
1061 mrAccessibleSlideSorter.FireAccessibleEvent(
1062 AccessibleEventId::SELECTION_CHANGED,
1063 Any(),
1064 Any());
1065 break;
1066 default:
1067 break;
1068 }
1069 return 1;
1070 }
1071
1072
1073
1074
IMPL_LINK(AccessibleSlideSorterView::Implementation,SelectionChangeListener,void *,EMPTYARG)1075 IMPL_LINK(AccessibleSlideSorterView::Implementation, SelectionChangeListener, void*, EMPTYARG )
1076 {
1077 if (mnSelectionChangeUserEventId == 0)
1078 mnSelectionChangeUserEventId = Application::PostUserEvent(
1079 LINK(this, AccessibleSlideSorterView::Implementation, BroadcastSelectionChange));
1080 return 1;
1081 }
1082
1083
1084
1085
IMPL_LINK(AccessibleSlideSorterView::Implementation,BroadcastSelectionChange,void *,EMPTYARG)1086 IMPL_LINK(AccessibleSlideSorterView::Implementation, BroadcastSelectionChange, void*, EMPTYARG )
1087 {
1088 mnSelectionChangeUserEventId = 0;
1089 mrAccessibleSlideSorter.FireAccessibleEvent(
1090 AccessibleEventId::SELECTION_CHANGED,
1091 Any(),
1092 Any());
1093 return 1;
1094 }
1095
1096
1097
1098
IMPL_LINK(AccessibleSlideSorterView::Implementation,FocusChangeListener,void *,EMPTYARG)1099 IMPL_LINK(AccessibleSlideSorterView::Implementation, FocusChangeListener, void*, EMPTYARG )
1100 {
1101 sal_Int32 nNewFocusedIndex (
1102 mrSlideSorter.GetController().GetFocusManager().GetFocusedPageIndex());
1103
1104 sal_Bool bHasFocus = mrSlideSorter.GetController().GetFocusManager().IsFocusShowing();
1105 if (!bHasFocus)
1106 nNewFocusedIndex = -1;
1107
1108 // add a checker whether the focus event is sent out. Only after sent, the mnFocusedIndex should be updated.
1109 sal_Bool bSentFocus = sal_False;
1110 if (nNewFocusedIndex != mnFocusedIndex)
1111 {
1112 if (mnFocusedIndex >= 0)
1113 {
1114 AccessibleSlideSorterObject* pObject = GetAccessibleChild(mnFocusedIndex);
1115 if (pObject != NULL)
1116 {
1117 pObject->FireAccessibleEvent(
1118 AccessibleEventId::STATE_CHANGED,
1119 Any(AccessibleStateType::FOCUSED),
1120 Any());
1121 bSentFocus = sal_True;
1122 }
1123 }
1124 if (nNewFocusedIndex >= 0)
1125 {
1126 AccessibleSlideSorterObject* pObject = GetAccessibleChild(nNewFocusedIndex);
1127 if (pObject != NULL)
1128 {
1129 pObject->FireAccessibleEvent(
1130 AccessibleEventId::STATE_CHANGED,
1131 Any(),
1132 Any(AccessibleStateType::FOCUSED));
1133 bSentFocus = sal_True;
1134 }
1135 }
1136 if (bSentFocus == sal_True)
1137 mnFocusedIndex = nNewFocusedIndex;
1138 }
1139 return 1;
1140 }
1141
1142
1143
1144
IMPL_LINK(AccessibleSlideSorterView::Implementation,UpdateChildrenCallback,void *,EMPTYARG)1145 IMPL_LINK(AccessibleSlideSorterView::Implementation, UpdateChildrenCallback, void*, EMPTYARG )
1146 {
1147 mnUpdateChildrenUserEventId = 0;
1148 UpdateChildren();
1149
1150 return 1;
1151 }
1152
1153
1154
1155
1156 } // end of namespace ::accessibility
1157