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 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sd.hxx"
26 
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 "model/SlideSorterModel.hxx"
34 #include "model/SlsPageDescriptor.hxx"
35 #include "view/SlideSorterView.hxx"
36 #include "view/SlsLayouter.hxx"
37 #include "view/SlsPageObjectLayouter.hxx"
38 #include <com/sun/star/accessibility/AccessibleRole.hpp>
39 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
40 #include <comphelper/accessibleeventnotifier.hxx>
41 #include <unotools/accessiblestatesethelper.hxx>
42 
43 #include "sdpage.hxx"
44 #include "sdresid.hxx"
45 #include <vcl/svapp.hxx>
46 
47 #include "glob.hrc"
48 
49 using ::rtl::OUString;
50 using namespace ::com::sun::star;
51 using namespace ::com::sun::star::uno;
52 using namespace ::com::sun::star::accessibility;
53 
54 
55 namespace accessibility {
56 
57 
AccessibleSlideSorterObject(const Reference<XAccessible> & rxParent,::sd::slidesorter::SlideSorter & rSlideSorter,sal_uInt16 nPageNumber)58 AccessibleSlideSorterObject::AccessibleSlideSorterObject(
59     const Reference<XAccessible>& rxParent,
60     ::sd::slidesorter::SlideSorter& rSlideSorter,
61     sal_uInt16 nPageNumber)
62     : AccessibleSlideSorterObjectBase(::sd::MutexOwner::maMutex),
63       mxParent(rxParent),
64       mnPageNumber(nPageNumber),
65       mrSlideSorter(rSlideSorter),
66       mnClientId(0)
67 {
68 }
69 
70 
71 
72 
~AccessibleSlideSorterObject(void)73 AccessibleSlideSorterObject::~AccessibleSlideSorterObject (void)
74 {
75     if ( ! IsDisposed())
76         dispose();
77 }
78 
79 
80 
81 
GetPageNumber(void) const82 sal_uInt16 AccessibleSlideSorterObject::GetPageNumber (void) const
83 {
84     return mnPageNumber;
85 }
86 
87 
88 
89 
FireAccessibleEvent(short nEventId,const uno::Any & rOldValue,const uno::Any & rNewValue)90 void AccessibleSlideSorterObject::FireAccessibleEvent (
91     short nEventId,
92     const uno::Any& rOldValue,
93     const uno::Any& rNewValue)
94 {
95     if (mnClientId != 0)
96     {
97         AccessibleEventObject aEventObject;
98 
99         aEventObject.Source = Reference<XWeak>(this);
100         aEventObject.EventId = nEventId;
101         aEventObject.NewValue = rNewValue;
102         aEventObject.OldValue = rOldValue;
103 
104 		comphelper::AccessibleEventNotifier::addEvent(mnClientId, aEventObject);
105     }
106 }
107 
108 
109 
110 
disposing(void)111 void SAL_CALL AccessibleSlideSorterObject::disposing (void)
112 {
113     const vos::OGuard aSolarGuard (Application::GetSolarMutex());
114 
115     // Send a disposing to all listeners.
116 	if (mnClientId != 0)
117 	{
118         comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing(mnClientId, *this);
119 		mnClientId =  0;
120 	}
121 }
122 
123 
124 
125 //===== XAccessible ===========================================================
126 
127 Reference<XAccessibleContext> SAL_CALL
getAccessibleContext(void)128     AccessibleSlideSorterObject::getAccessibleContext (void)
129     throw (uno::RuntimeException)
130 {
131     ThrowIfDisposed();
132     return this;
133 }
134 
135 
136 
137 //===== XAccessibleContext ====================================================
138 
getAccessibleChildCount(void)139 sal_Int32 SAL_CALL AccessibleSlideSorterObject::getAccessibleChildCount (void)
140     throw (uno::RuntimeException)
141 {
142     ThrowIfDisposed();
143     return 0;
144 }
145 
146 
147 
148 
getAccessibleChild(sal_Int32)149 Reference<XAccessible> SAL_CALL AccessibleSlideSorterObject::getAccessibleChild (sal_Int32 )
150     throw (lang::IndexOutOfBoundsException, RuntimeException)
151 {
152     ThrowIfDisposed();
153     throw lang::IndexOutOfBoundsException();
154 }
155 
156 
157 
158 
getAccessibleParent(void)159 Reference<XAccessible> SAL_CALL AccessibleSlideSorterObject::getAccessibleParent (void)
160     throw (uno::RuntimeException)
161 {
162     ThrowIfDisposed();
163     return mxParent;
164 }
165 
166 
167 
168 
getAccessibleIndexInParent()169 sal_Int32 SAL_CALL AccessibleSlideSorterObject::getAccessibleIndexInParent()
170     throw (uno::RuntimeException)
171 {
172     ThrowIfDisposed();
173     const vos::OGuard aSolarGuard (Application::GetSolarMutex());
174     sal_Int32 nIndexInParent(-1);
175 
176     if (mxParent.is())
177     {
178         Reference<XAccessibleContext> xParentContext (mxParent->getAccessibleContext());
179         if (xParentContext.is())
180         {
181             sal_Int32 nChildCount (xParentContext->getAccessibleChildCount());
182             for (sal_Int32 i=0; i<nChildCount; ++i)
183                 if (xParentContext->getAccessibleChild(i).get()
184                     == static_cast<XAccessible*>(this))
185                 {
186                     nIndexInParent = i;
187                     break;
188                 }
189         }
190     }
191 
192     return nIndexInParent;
193 }
194 
195 
196 
197 
getAccessibleRole(void)198 sal_Int16 SAL_CALL AccessibleSlideSorterObject::getAccessibleRole (void)
199     throw (uno::RuntimeException)
200 {
201     ThrowIfDisposed();
202     //set Role = Shape
203     static sal_Int16 nRole = AccessibleRole::SHAPE;
204     return nRole;
205 }
206 
207 
208 
209 
getAccessibleDescription(void)210 ::rtl::OUString SAL_CALL AccessibleSlideSorterObject::getAccessibleDescription (void)
211     throw (uno::RuntimeException)
212 {
213     ThrowIfDisposed();
214     return String(SdResId(STR_PAGE));
215 }
216 
217 
218 
219 
getAccessibleName(void)220 ::rtl::OUString SAL_CALL AccessibleSlideSorterObject::getAccessibleName (void)
221     throw (uno::RuntimeException)
222 {
223     ThrowIfDisposed();
224     const vos::OGuard aSolarGuard (Application::GetSolarMutex());
225 
226     SdPage* pPage = GetPage();
227     if (pPage != NULL)
228         return pPage->GetName();
229     else
230         return String();
231 }
232 
233 
234 
235 
236 Reference<XAccessibleRelationSet> SAL_CALL
getAccessibleRelationSet(void)237     AccessibleSlideSorterObject::getAccessibleRelationSet (void)
238     throw (uno::RuntimeException)
239 {
240     ThrowIfDisposed();
241     return Reference<XAccessibleRelationSet>();
242 }
243 
244 
245 
246 
247 Reference<XAccessibleStateSet> SAL_CALL
getAccessibleStateSet(void)248     AccessibleSlideSorterObject::getAccessibleStateSet (void)
249     throw (uno::RuntimeException)
250 {
251     ThrowIfDisposed();
252     const vos::OGuard aSolarGuard (Application::GetSolarMutex());
253     ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper();
254 
255     if (mxParent.is())
256     {
257 	    // Unconditional states.
258 	    pStateSet->AddState(AccessibleStateType::SELECTABLE);
259 	    pStateSet->AddState(AccessibleStateType::FOCUSABLE);
260 	    pStateSet->AddState(AccessibleStateType::ENABLED);
261 	    pStateSet->AddState(AccessibleStateType::VISIBLE);
262 	    pStateSet->AddState(AccessibleStateType::SHOWING);
263 	    pStateSet->AddState(AccessibleStateType::ACTIVE);
264 	    pStateSet->AddState(AccessibleStateType::SENSITIVE);
265 
266 	    // Conditional states.
267         if (mrSlideSorter.GetController().GetPageSelector().IsPageSelected(mnPageNumber))
268             pStateSet->AddState(AccessibleStateType::SELECTED);
269         if (mrSlideSorter.GetController().GetFocusManager().GetFocusedPageIndex() == mnPageNumber)
270             if (mrSlideSorter.GetController().GetFocusManager().IsFocusShowing())
271                 pStateSet->AddState(AccessibleStateType::FOCUSED);
272     }
273 
274     return pStateSet;
275 }
276 
277 
278 
279 
getLocale(void)280 lang::Locale SAL_CALL AccessibleSlideSorterObject::getLocale (void)
281     throw (IllegalAccessibleComponentStateException,
282         RuntimeException)
283 {
284     ThrowIfDisposed();
285     // Delegate request to parent.
286 	if (mxParent.is())
287     {
288     	Reference<XAccessibleContext> xParentContext (mxParent->getAccessibleContext());
289         if (xParentContext.is())
290 	    	return xParentContext->getLocale ();
291     }
292 
293     //	No locale and no parent.  Therefore throw exception to indicate this
294     //	cluelessness.
295     throw IllegalAccessibleComponentStateException();
296 }
297 
298 
299 
300 
301 
302 //===== XAccessibleEventBroadcaster ===========================================
303 
addEventListener(const Reference<XAccessibleEventListener> & rxListener)304 void SAL_CALL AccessibleSlideSorterObject::addEventListener(
305     const Reference<XAccessibleEventListener>& rxListener)
306     throw (RuntimeException)
307 {
308 	if (rxListener.is())
309     {
310         const osl::MutexGuard aGuard(maMutex);
311 
312         if (IsDisposed())
313         {
314             uno::Reference<uno::XInterface> x ((lang::XComponent *)this, uno::UNO_QUERY);
315 		    rxListener->disposing (lang::EventObject (x));
316 	    }
317         else
318         {
319             if (mnClientId == 0)
320                 mnClientId = comphelper::AccessibleEventNotifier::registerClient();
321             comphelper::AccessibleEventNotifier::addEventListener(mnClientId, rxListener);
322         }
323     }
324 }
325 
326 
327 
328 
removeEventListener(const Reference<XAccessibleEventListener> & rxListener)329 void SAL_CALL AccessibleSlideSorterObject::removeEventListener(
330     const Reference<XAccessibleEventListener>& rxListener)
331     throw (uno::RuntimeException)
332 {
333     ThrowIfDisposed();
334 	if (rxListener.is())
335 	{
336         const osl::MutexGuard aGuard(maMutex);
337 
338         sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener( mnClientId, rxListener );
339 		if ( !nListenerCount )
340 		{
341 			// no listeners anymore
342 			// -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
343 			// and at least to us not firing any events anymore, in case somebody calls
344 			// NotifyAccessibleEvent, again
345 			comphelper::AccessibleEventNotifier::revokeClient( mnClientId );
346 			mnClientId = 0;
347 		}
348 	}
349 }
350 
351 
352 
353 
354 //===== XAccessibleComponent ==================================================
355 
containsPoint(const awt::Point & aPoint)356 sal_Bool SAL_CALL AccessibleSlideSorterObject::containsPoint(const awt::Point& aPoint)
357     throw (uno::RuntimeException)
358 {
359     ThrowIfDisposed();
360     const awt::Size aSize (getSize());
361     return (aPoint.X >= 0)
362         && (aPoint.X < aSize.Width)
363         && (aPoint.Y >= 0)
364         && (aPoint.Y < aSize.Height);
365 }
366 
367 
368 
369 
370 Reference<XAccessible> SAL_CALL
getAccessibleAtPoint(const awt::Point &)371     AccessibleSlideSorterObject::getAccessibleAtPoint(const awt::Point& )
372     throw (uno::RuntimeException)
373 {
374     return NULL;
375 }
376 
377 
378 
379 
getBounds(void)380 awt::Rectangle SAL_CALL AccessibleSlideSorterObject::getBounds (void)
381     throw (RuntimeException)
382 {
383     ThrowIfDisposed ();
384 
385     const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
386 
387     Rectangle aBBox (
388         mrSlideSorter.GetView().GetLayouter().GetPageObjectLayouter()->GetBoundingBox(
389             mrSlideSorter.GetModel().GetPageDescriptor(mnPageNumber),
390             ::sd::slidesorter::view::PageObjectLayouter::PageObject,
391             ::sd::slidesorter::view::PageObjectLayouter::WindowCoordinateSystem));
392 
393     if (mxParent.is())
394     {
395         Reference<XAccessibleComponent> xParentComponent(mxParent->getAccessibleContext(), UNO_QUERY);
396         if (xParentComponent.is())
397         {
398             awt::Rectangle aParentBBox (xParentComponent->getBounds());
399             aBBox.Intersection(Rectangle(
400                 aParentBBox.X,
401                 aParentBBox.Y,
402                 aParentBBox.Width,
403                 aParentBBox.Height));
404         }
405     }
406 
407     return awt::Rectangle(
408         aBBox.Left(),
409         aBBox.Top(),
410         aBBox.GetWidth(),
411         aBBox.GetHeight());
412 }
413 
414 
415 
416 
getLocation()417 awt::Point SAL_CALL AccessibleSlideSorterObject::getLocation ()
418     throw (RuntimeException)
419 {
420     ThrowIfDisposed ();
421     const awt::Rectangle aBBox (getBounds());
422     return awt::Point(aBBox.X, aBBox.Y);
423 }
424 
425 
426 
427 
getLocationOnScreen(void)428 awt::Point SAL_CALL AccessibleSlideSorterObject::getLocationOnScreen (void)
429     throw (RuntimeException)
430 {
431     ThrowIfDisposed ();
432 
433     const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
434 
435     awt::Point aLocation (getLocation());
436 
437     if (mxParent.is())
438     {
439         Reference<XAccessibleComponent> xParentComponent(mxParent->getAccessibleContext(),UNO_QUERY);
440         if (xParentComponent.is())
441         {
442             const awt::Point aParentLocationOnScreen(xParentComponent->getLocationOnScreen());
443             aLocation.X += aParentLocationOnScreen.X;
444             aLocation.Y += aParentLocationOnScreen.Y;
445         }
446     }
447 
448     return aLocation;
449 }
450 
451 
452 
453 
getSize(void)454 awt::Size SAL_CALL AccessibleSlideSorterObject::getSize (void)
455     throw (RuntimeException)
456 {
457     ThrowIfDisposed ();
458     const awt::Rectangle aBBox (getBounds());
459     return awt::Size(aBBox.Width,aBBox.Height);
460 }
461 
462 
463 
464 
grabFocus(void)465 void SAL_CALL AccessibleSlideSorterObject::grabFocus (void)
466     throw (RuntimeException)
467 {
468     // nothing to do
469 }
470 
471 
472 
473 
getForeground(void)474 sal_Int32 SAL_CALL AccessibleSlideSorterObject::getForeground (void)
475     throw (::com::sun::star::uno::RuntimeException)
476 {
477     ThrowIfDisposed ();
478 	svtools::ColorConfig aColorConfig;
479     sal_uInt32 nColor = aColorConfig.GetColorValue( svtools::FONTCOLOR ).nColor;
480     return static_cast<sal_Int32>(nColor);
481 }
482 
483 
484 
485 
getBackground(void)486 sal_Int32 SAL_CALL AccessibleSlideSorterObject::getBackground (void)
487     throw (::com::sun::star::uno::RuntimeException)
488 {
489     ThrowIfDisposed ();
490     sal_uInt32 nColor = Application::GetSettings().GetStyleSettings().GetWindowColor().GetColor();
491     return static_cast<sal_Int32>(nColor);
492 }
493 
494 
495 
496 
497 
498 //=====  XServiceInfo  ========================================================
499 
500 ::rtl::OUString SAL_CALL
getImplementationName(void)501    	AccessibleSlideSorterObject::getImplementationName (void)
502     throw (::com::sun::star::uno::RuntimeException)
503 {
504 	return OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleSlideSorterObject"));
505 }
506 
507 
508 
509 
510 sal_Bool SAL_CALL
supportsService(const OUString & sServiceName)511  	AccessibleSlideSorterObject::supportsService (const OUString& sServiceName)
512     throw (::com::sun::star::uno::RuntimeException)
513 {
514     ThrowIfDisposed ();
515 
516     //  Iterate over all supported service names and return true if on of them
517     //  matches the given name.
518     uno::Sequence< ::rtl::OUString> aSupportedServices (
519         getSupportedServiceNames ());
520     for (int i=0; i<aSupportedServices.getLength(); i++)
521         if (sServiceName == aSupportedServices[i])
522             return sal_True;
523     return sal_False;
524 }
525 
526 
527 
528 
529 uno::Sequence< ::rtl::OUString> SAL_CALL
getSupportedServiceNames(void)530    	AccessibleSlideSorterObject::getSupportedServiceNames (void)
531     throw (::com::sun::star::uno::RuntimeException)
532 {
533     ThrowIfDisposed ();
534 
535 	static const OUString sServiceNames[2] = {
536         OUString(RTL_CONSTASCII_USTRINGPARAM(
537             "com.sun.star.accessibility.Accessible")),
538         OUString(RTL_CONSTASCII_USTRINGPARAM(
539             "com.sun.star.accessibility.AccessibleContext"))
540     };
541 	return uno::Sequence<OUString> (sServiceNames, 2);
542 }
543 
544 
545 
546 
ThrowIfDisposed(void)547 void AccessibleSlideSorterObject::ThrowIfDisposed (void)
548     throw (lang::DisposedException)
549 {
550 	if (rBHelper.bDisposed || rBHelper.bInDispose)
551 	{
552         OSL_TRACE ("Calling disposed object. Throwing exception:");
553         throw lang::DisposedException (
554             OUString(RTL_CONSTASCII_USTRINGPARAM("object has been already disposed")),
555             static_cast<uno::XWeak*>(this));
556     }
557 }
558 
559 
560 
IsDisposed(void)561 sal_Bool AccessibleSlideSorterObject::IsDisposed (void)
562 {
563 	return (rBHelper.bDisposed || rBHelper.bInDispose);
564 }
565 
566 
567 
568 
GetPage(void) const569 SdPage* AccessibleSlideSorterObject::GetPage (void) const
570 {
571     ::sd::slidesorter::model::SharedPageDescriptor pDescriptor(
572         mrSlideSorter.GetModel().GetPageDescriptor(mnPageNumber));
573     if (pDescriptor.get() != NULL)
574         return pDescriptor->GetPage();
575     else
576         return NULL;
577 }
578 
579 
580 } // end of namespace ::accessibility
581