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