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 
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 
73 AccessibleSlideSorterObject::~AccessibleSlideSorterObject (void)
74 {
75     if ( ! IsDisposed())
76         dispose();
77 }
78 
79 
80 
81 
82 sal_uInt16 AccessibleSlideSorterObject::GetPageNumber (void) const
83 {
84     return mnPageNumber;
85 }
86 
87 
88 
89 
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 
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
128     AccessibleSlideSorterObject::getAccessibleContext (void)
129     throw (uno::RuntimeException)
130 {
131     ThrowIfDisposed();
132     return this;
133 }
134 
135 
136 
137 //===== XAccessibleContext ====================================================
138 
139 sal_Int32 SAL_CALL AccessibleSlideSorterObject::getAccessibleChildCount (void)
140     throw (uno::RuntimeException)
141 {
142     ThrowIfDisposed();
143     return 0;
144 }
145 
146 
147 
148 
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 
159 Reference<XAccessible> SAL_CALL AccessibleSlideSorterObject::getAccessibleParent (void)
160     throw (uno::RuntimeException)
161 {
162     ThrowIfDisposed();
163     return mxParent;
164 }
165 
166 
167 
168 
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 
198 sal_Int16 SAL_CALL AccessibleSlideSorterObject::getAccessibleRole (void)
199     throw (uno::RuntimeException)
200 {
201     ThrowIfDisposed();
202     static sal_Int16 nRole = AccessibleRole::LIST_ITEM;
203     return nRole;
204 }
205 
206 
207 
208 
209 ::rtl::OUString SAL_CALL AccessibleSlideSorterObject::getAccessibleDescription (void)
210     throw (uno::RuntimeException)
211 {
212     ThrowIfDisposed();
213     return String(SdResId(STR_PAGE));
214 }
215 
216 
217 
218 
219 ::rtl::OUString SAL_CALL AccessibleSlideSorterObject::getAccessibleName (void)
220     throw (uno::RuntimeException)
221 {
222     ThrowIfDisposed();
223     const vos::OGuard aSolarGuard (Application::GetSolarMutex());
224 
225     SdPage* pPage = GetPage();
226     if (pPage != NULL)
227         return pPage->GetName();
228     else
229         return String();
230 }
231 
232 
233 
234 
235 Reference<XAccessibleRelationSet> SAL_CALL
236     AccessibleSlideSorterObject::getAccessibleRelationSet (void)
237     throw (uno::RuntimeException)
238 {
239     ThrowIfDisposed();
240     return Reference<XAccessibleRelationSet>();
241 }
242 
243 
244 
245 
246 Reference<XAccessibleStateSet> SAL_CALL
247     AccessibleSlideSorterObject::getAccessibleStateSet (void)
248     throw (uno::RuntimeException)
249 {
250     ThrowIfDisposed();
251     const vos::OGuard aSolarGuard (Application::GetSolarMutex());
252     ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper();
253 
254     if (mxParent.is())
255     {
256 	    // Unconditional states.
257 	    pStateSet->AddState(AccessibleStateType::SELECTABLE);
258 	    pStateSet->AddState(AccessibleStateType::FOCUSABLE);
259 	    pStateSet->AddState(AccessibleStateType::ENABLED);
260 	    pStateSet->AddState(AccessibleStateType::VISIBLE);
261 	    pStateSet->AddState(AccessibleStateType::SHOWING);
262 	    pStateSet->AddState(AccessibleStateType::ACTIVE);
263 	    pStateSet->AddState(AccessibleStateType::SENSITIVE);
264 
265 	    // Conditional states.
266         if (mrSlideSorter.GetController().GetPageSelector().IsPageSelected(mnPageNumber))
267             pStateSet->AddState(AccessibleStateType::SELECTED);
268         if (mrSlideSorter.GetController().GetFocusManager().GetFocusedPageIndex() == mnPageNumber)
269             if (mrSlideSorter.GetController().GetFocusManager().IsFocusShowing())
270                 pStateSet->AddState(AccessibleStateType::FOCUSED);
271     }
272 
273     return pStateSet;
274 }
275 
276 
277 
278 
279 lang::Locale SAL_CALL AccessibleSlideSorterObject::getLocale (void)
280     throw (IllegalAccessibleComponentStateException,
281         RuntimeException)
282 {
283     ThrowIfDisposed();
284     // Delegate request to parent.
285 	if (mxParent.is())
286     {
287     	Reference<XAccessibleContext> xParentContext (mxParent->getAccessibleContext());
288         if (xParentContext.is())
289 	    	return xParentContext->getLocale ();
290     }
291 
292     //	No locale and no parent.  Therefore throw exception to indicate this
293     //	cluelessness.
294     throw IllegalAccessibleComponentStateException();
295 }
296 
297 
298 
299 
300 
301 //===== XAccessibleEventBroadcaster ===========================================
302 
303 void SAL_CALL AccessibleSlideSorterObject::addEventListener(
304     const Reference<XAccessibleEventListener>& rxListener)
305     throw (RuntimeException)
306 {
307 	if (rxListener.is())
308     {
309         const osl::MutexGuard aGuard(maMutex);
310 
311         if (IsDisposed())
312         {
313             uno::Reference<uno::XInterface> x ((lang::XComponent *)this, uno::UNO_QUERY);
314 		    rxListener->disposing (lang::EventObject (x));
315 	    }
316         else
317         {
318             if (mnClientId == 0)
319                 mnClientId = comphelper::AccessibleEventNotifier::registerClient();
320             comphelper::AccessibleEventNotifier::addEventListener(mnClientId, rxListener);
321         }
322     }
323 }
324 
325 
326 
327 
328 void SAL_CALL AccessibleSlideSorterObject::removeEventListener(
329     const Reference<XAccessibleEventListener>& rxListener)
330     throw (uno::RuntimeException)
331 {
332     ThrowIfDisposed();
333 	if (rxListener.is())
334 	{
335         const osl::MutexGuard aGuard(maMutex);
336 
337         sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener( mnClientId, rxListener );
338 		if ( !nListenerCount )
339 		{
340 			// no listeners anymore
341 			// -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
342 			// and at least to us not firing any events anymore, in case somebody calls
343 			// NotifyAccessibleEvent, again
344 			comphelper::AccessibleEventNotifier::revokeClient( mnClientId );
345 			mnClientId = 0;
346 		}
347 	}
348 }
349 
350 
351 
352 
353 //===== XAccessibleComponent ==================================================
354 
355 sal_Bool SAL_CALL AccessibleSlideSorterObject::containsPoint(const awt::Point& aPoint)
356     throw (uno::RuntimeException)
357 {
358     ThrowIfDisposed();
359     const awt::Size aSize (getSize());
360     return (aPoint.X >= 0)
361         && (aPoint.X < aSize.Width)
362         && (aPoint.Y >= 0)
363         && (aPoint.Y < aSize.Height);
364 }
365 
366 
367 
368 
369 Reference<XAccessible> SAL_CALL
370     AccessibleSlideSorterObject::getAccessibleAtPoint(const awt::Point& )
371     throw (uno::RuntimeException)
372 {
373     return NULL;
374 }
375 
376 
377 
378 
379 awt::Rectangle SAL_CALL AccessibleSlideSorterObject::getBounds (void)
380     throw (RuntimeException)
381 {
382     ThrowIfDisposed ();
383 
384     const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
385 
386     Rectangle aBBox (
387         mrSlideSorter.GetView().GetLayouter().GetPageObjectLayouter()->GetBoundingBox(
388             mrSlideSorter.GetModel().GetPageDescriptor(mnPageNumber),
389             ::sd::slidesorter::view::PageObjectLayouter::PageObject,
390             ::sd::slidesorter::view::PageObjectLayouter::WindowCoordinateSystem));
391 
392     if (mxParent.is())
393     {
394         Reference<XAccessibleComponent> xParentComponent(mxParent->getAccessibleContext(), UNO_QUERY);
395         if (xParentComponent.is())
396         {
397             awt::Rectangle aParentBBox (xParentComponent->getBounds());
398             aBBox.Intersection(Rectangle(
399                 aParentBBox.X,
400                 aParentBBox.Y,
401                 aParentBBox.Width,
402                 aParentBBox.Height));
403         }
404     }
405 
406     return awt::Rectangle(
407         aBBox.Left(),
408         aBBox.Top(),
409         aBBox.GetWidth(),
410         aBBox.GetHeight());
411 }
412 
413 
414 
415 
416 awt::Point SAL_CALL AccessibleSlideSorterObject::getLocation ()
417     throw (RuntimeException)
418 {
419     ThrowIfDisposed ();
420     const awt::Rectangle aBBox (getBounds());
421     return awt::Point(aBBox.X, aBBox.Y);
422 }
423 
424 
425 
426 
427 awt::Point SAL_CALL AccessibleSlideSorterObject::getLocationOnScreen (void)
428     throw (RuntimeException)
429 {
430     ThrowIfDisposed ();
431 
432     const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
433 
434     awt::Point aLocation (getLocation());
435 
436     if (mxParent.is())
437     {
438         Reference<XAccessibleComponent> xParentComponent(mxParent->getAccessibleContext(),UNO_QUERY);
439         if (xParentComponent.is())
440         {
441             const awt::Point aParentLocationOnScreen(xParentComponent->getLocationOnScreen());
442             aLocation.X += aParentLocationOnScreen.X;
443             aLocation.Y += aParentLocationOnScreen.Y;
444         }
445     }
446 
447     return aLocation;
448 }
449 
450 
451 
452 
453 awt::Size SAL_CALL AccessibleSlideSorterObject::getSize (void)
454     throw (RuntimeException)
455 {
456     ThrowIfDisposed ();
457     const awt::Rectangle aBBox (getBounds());
458     return awt::Size(aBBox.Width,aBBox.Height);
459 }
460 
461 
462 
463 
464 void SAL_CALL AccessibleSlideSorterObject::grabFocus (void)
465     throw (RuntimeException)
466 {
467     // nothing to do
468 }
469 
470 
471 
472 
473 sal_Int32 SAL_CALL AccessibleSlideSorterObject::getForeground (void)
474     throw (::com::sun::star::uno::RuntimeException)
475 {
476     ThrowIfDisposed ();
477 	svtools::ColorConfig aColorConfig;
478     sal_uInt32 nColor = aColorConfig.GetColorValue( svtools::FONTCOLOR ).nColor;
479     return static_cast<sal_Int32>(nColor);
480 }
481 
482 
483 
484 
485 sal_Int32 SAL_CALL AccessibleSlideSorterObject::getBackground (void)
486     throw (::com::sun::star::uno::RuntimeException)
487 {
488     ThrowIfDisposed ();
489     sal_uInt32 nColor = Application::GetSettings().GetStyleSettings().GetWindowColor().GetColor();
490     return static_cast<sal_Int32>(nColor);
491 }
492 
493 
494 
495 
496 
497 //=====  XServiceInfo  ========================================================
498 
499 ::rtl::OUString SAL_CALL
500    	AccessibleSlideSorterObject::getImplementationName (void)
501     throw (::com::sun::star::uno::RuntimeException)
502 {
503 	return OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleSlideSorterObject"));
504 }
505 
506 
507 
508 
509 sal_Bool SAL_CALL
510  	AccessibleSlideSorterObject::supportsService (const OUString& sServiceName)
511     throw (::com::sun::star::uno::RuntimeException)
512 {
513     ThrowIfDisposed ();
514 
515     //  Iterate over all supported service names and return true if on of them
516     //  matches the given name.
517     uno::Sequence< ::rtl::OUString> aSupportedServices (
518         getSupportedServiceNames ());
519     for (int i=0; i<aSupportedServices.getLength(); i++)
520         if (sServiceName == aSupportedServices[i])
521             return sal_True;
522     return sal_False;
523 }
524 
525 
526 
527 
528 uno::Sequence< ::rtl::OUString> SAL_CALL
529    	AccessibleSlideSorterObject::getSupportedServiceNames (void)
530     throw (::com::sun::star::uno::RuntimeException)
531 {
532     ThrowIfDisposed ();
533 
534 	static const OUString sServiceNames[2] = {
535         OUString(RTL_CONSTASCII_USTRINGPARAM(
536             "com.sun.star.accessibility.Accessible")),
537         OUString(RTL_CONSTASCII_USTRINGPARAM(
538             "com.sun.star.accessibility.AccessibleContext"))
539     };
540 	return uno::Sequence<OUString> (sServiceNames, 2);
541 }
542 
543 
544 
545 
546 void AccessibleSlideSorterObject::ThrowIfDisposed (void)
547     throw (lang::DisposedException)
548 {
549 	if (rBHelper.bDisposed || rBHelper.bInDispose)
550 	{
551         OSL_TRACE ("Calling disposed object. Throwing exception:");
552         throw lang::DisposedException (
553             OUString(RTL_CONSTASCII_USTRINGPARAM("object has been already disposed")),
554             static_cast<uno::XWeak*>(this));
555     }
556 }
557 
558 
559 
560 sal_Bool AccessibleSlideSorterObject::IsDisposed (void)
561 {
562 	return (rBHelper.bDisposed || rBHelper.bInDispose);
563 }
564 
565 
566 
567 
568 SdPage* AccessibleSlideSorterObject::GetPage (void) const
569 {
570     ::sd::slidesorter::model::SharedPageDescriptor pDescriptor(
571         mrSlideSorter.GetModel().GetPageDescriptor(mnPageNumber));
572     if (pDescriptor.get() != NULL)
573         return pDescriptor->GetPage();
574     else
575         return NULL;
576 }
577 
578 
579 } // end of namespace ::accessibility
580