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