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