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