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 #include "AccessibleDrawDocumentView.hxx"
27 #include <com/sun/star/drawing/XDrawPage.hpp>
28 #include <com/sun/star/drawing/XDrawView.hpp>
29 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
30 #include <com/sun/star/drawing/XShapes.hpp>
31 #include <com/sun/star/container/XChild.hpp>
32 #include <com/sun/star/frame/XController.hpp>
33 #include <com/sun/star/frame/XFrame.hpp>
34 #include <com/sun/star/document/XEventBroadcaster.hpp>
35 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
37 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
38 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
39 #include <rtl/ustring.h>
40 #include<sfx2/viewfrm.hxx>
41 
42 #include <svx/AccessibleShape.hxx>
43 
44 #include <svx/svdobj.hxx>
45 #include <svx/svdmodel.hxx>
46 #include <svx/unoapi.hxx>
47 #include <svx/unoshcol.hxx>
48 #include <toolkit/helper/vclunohelper.hxx>
49 #include "Window.hxx"
50 #include <vcl/svapp.hxx>
51 
52 
53 #include "ViewShell.hxx"
54 #include "View.hxx"
55 #include "DrawDocShell.hxx"
56 #include <drawdoc.hxx>
57 #include <algorithm>
58 #include "sdpage.hxx"
59 #include "slideshow.hxx"
60 #include "anminfo.hxx"
61 #include <memory>
62 
63 #include "accessibility.hrc"
64 #include "sdresid.hxx"
65 #include <vos/mutex.hxx>
66 
67 using ::rtl::OUString;
68 using namespace ::com::sun::star;
69 using namespace ::com::sun::star::uno;
70 using namespace	::com::sun::star::accessibility;
71 
72 class SfxViewFrame;
73 
74 #define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString)))
75 
76 namespace accessibility {
77 
78 
79 struct XShapePosCompareHelper
80 {
81 	bool operator() ( const uno::Reference<drawing::XShape>& xshape1,
82 		const uno::Reference<drawing::XShape>& xshape2 ) const
83 	{
84 		// modify the compare method to return the Z-Order, not layout order
85 		SdrObject* pObj1 = GetSdrObjectFromXShape(xshape1);
86 		SdrObject* pObj2 = GetSdrObjectFromXShape(xshape2);
87 		if(pObj1 && pObj2)
88 			return pObj1->GetOrdNum() < pObj2->GetOrdNum();
89 		else
90 			return 0;
91 	}
92 };
93 //=====  internal  ============================================================
94 
95 AccessibleDrawDocumentView::AccessibleDrawDocumentView (
96     ::sd::Window* pSdWindow,
97     ::sd::ViewShell* pViewShell,
98     const uno::Reference<frame::XController>& rxController,
99     const uno::Reference<XAccessible>& rxParent)
100     : AccessibleDocumentViewBase (pSdWindow, pViewShell, rxController, rxParent),
101       mpSdViewSh( pViewShell ),
102       mpChildrenManager (NULL)
103 {
104     OSL_TRACE ("AccessibleDrawDocumentView");
105     UpdateAccessibleName();
106 }
107 
108 
109 
110 
111 AccessibleDrawDocumentView::~AccessibleDrawDocumentView (void)
112 {
113     OSL_TRACE ("~AccessibleDrawDocumentView");
114     DBG_ASSERT (rBHelper.bDisposed || rBHelper.bInDispose,
115         "~AccessibleDrawDocumentView: object has not been disposed");
116 }
117 
118 
119 
120 
121 void AccessibleDrawDocumentView::Init (void)
122 {
123     AccessibleDocumentViewBase::Init ();
124 
125     // Determine the list of shapes on the current page.
126     uno::Reference<drawing::XShapes> xShapeList;
127     uno::Reference<drawing::XDrawView> xView (mxController, uno::UNO_QUERY);
128     if (xView.is())
129         xShapeList = uno::Reference<drawing::XShapes> (
130             xView->getCurrentPage(), uno::UNO_QUERY);
131 
132     // Create the children manager.
133     mpChildrenManager = new ChildrenManager(this, xShapeList, maShapeTreeInfo, *this);
134     if (mpChildrenManager != NULL)
135     {
136         // Create the page shape and initialize it.  The shape is acquired
137         // before initialization and released after transferring ownership
138         // to the children manager to prevent premature disposing of the
139         // shape.
140         AccessiblePageShape* pPage = CreateDrawPageShape();
141         if (pPage != NULL)
142         {
143             pPage->acquire();
144             pPage->Init();
145             mpChildrenManager->AddAccessibleShape (
146                 std::auto_ptr<AccessibleShape>(pPage));
147             pPage->release();
148             mpChildrenManager->Update ();
149         }
150         mpChildrenManager->UpdateSelection ();
151     }
152 }
153 
154 
155 
156 
157 void AccessibleDrawDocumentView::ViewForwarderChanged (ChangeType aChangeType,
158     const IAccessibleViewForwarder* pViewForwarder)
159 {
160     AccessibleDocumentViewBase::ViewForwarderChanged (aChangeType, pViewForwarder);
161     if (mpChildrenManager != NULL)
162         mpChildrenManager->ViewForwarderChanged (aChangeType, pViewForwarder);
163 }
164 
165 
166 
167 
168 /**  The page shape is created on every call at the moment (provided that
169      every thing goes well).
170 */
171 AccessiblePageShape* AccessibleDrawDocumentView::CreateDrawPageShape (void)
172 {
173     AccessiblePageShape* pShape = NULL;
174 
175     // Create a shape that represents the actual draw page.
176     uno::Reference<drawing::XDrawView> xView (mxController, uno::UNO_QUERY);
177     if (xView.is())
178     {
179         uno::Reference<beans::XPropertySet> xSet (
180             uno::Reference<beans::XPropertySet> (xView->getCurrentPage(), uno::UNO_QUERY));
181         if (xSet.is())
182         {
183             // Create a rectangle shape that will represent the draw page.
184             uno::Reference<lang::XMultiServiceFactory> xFactory (mxModel, uno::UNO_QUERY);
185             uno::Reference<drawing::XShape> xRectangle;
186             if (xFactory.is())
187                 xRectangle = uno::Reference<drawing::XShape>(xFactory->createInstance (
188                     OUString (RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.RectangleShape"))),
189                     uno::UNO_QUERY);
190 
191             // Set the shape's size and position.
192             if (xRectangle.is())
193             {
194                 uno::Any aValue;
195                 awt::Point aPosition;
196                 awt::Size aSize;
197 
198                 // Set size and position of the shape to those of the draw
199                 // page.
200                 aValue = xSet->getPropertyValue (
201                     OUString (RTL_CONSTASCII_USTRINGPARAM("BorderLeft")));
202                 aValue >>= aPosition.X;
203                 aValue = xSet->getPropertyValue (
204                     OUString (RTL_CONSTASCII_USTRINGPARAM("BorderTop")));
205                 aValue >>= aPosition.Y;
206                 xRectangle->setPosition (aPosition);
207 
208                 aValue = xSet->getPropertyValue (
209                     OUString (RTL_CONSTASCII_USTRINGPARAM("Width")));
210                 aValue >>= aSize.Width;
211                 aValue = xSet->getPropertyValue (
212                     OUString (RTL_CONSTASCII_USTRINGPARAM("Height")));
213                 aValue >>= aSize.Height;
214                 xRectangle->setSize (aSize);
215 
216                 // Create the accessible object for the shape and
217                 // initialize it.
218                 pShape = new AccessiblePageShape (
219                     xView->getCurrentPage(), this, maShapeTreeInfo);
220             }
221         }
222     }
223     return pShape;
224 }
225 
226 
227 
228 
229 //=====  XAccessibleContext  ==================================================
230 
231 sal_Int32 SAL_CALL
232     AccessibleDrawDocumentView::getAccessibleChildCount (void)
233     throw (uno::RuntimeException)
234 {
235     ThrowIfDisposed ();
236 
237     long mpChildCount = AccessibleDocumentViewBase::getAccessibleChildCount();
238 
239     // Forward request to children manager.
240     if (mpChildrenManager != NULL)
241         mpChildCount += mpChildrenManager->GetChildCount ();
242 
243     return mpChildCount;
244 }
245 
246 
247 
248 
249 uno::Reference<XAccessible> SAL_CALL
250     AccessibleDrawDocumentView::getAccessibleChild (sal_Int32 nIndex)
251     throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
252 {
253     ThrowIfDisposed ();
254 
255     ::osl::ClearableMutexGuard aGuard (maMutex);
256 
257     // Take care of children of the base class.
258     sal_Int32 nCount = AccessibleDocumentViewBase::getAccessibleChildCount();
259     if (nCount > 0)
260     {
261         if (nIndex < nCount)
262             return AccessibleDocumentViewBase::getAccessibleChild(nIndex);
263         else
264             nIndex -= nCount;
265     }
266 
267     // Create a copy of the pointer to the children manager and release the
268     // mutex before calling any of its methods.
269     ChildrenManager* pChildrenManager = mpChildrenManager;
270     aGuard.clear();
271 
272     // Forward request to children manager.
273     if (pChildrenManager != NULL)
274     {
275         return pChildrenManager->GetChild (nIndex);
276     }
277     else
278         throw lang::IndexOutOfBoundsException (
279             ::rtl::OUString::createFromAscii ("no accessible child with index ")
280             + rtl::OUString::valueOf(nIndex),
281             static_cast<uno::XWeak*>(this));
282 }
283 
284 OUString SAL_CALL
285 	AccessibleDrawDocumentView::getAccessibleName(void)
286 	throw (::com::sun::star::uno::RuntimeException)
287 {
288 	OUString sName = String( SdResId(SID_SD_A11Y_D_PRESENTATION) );
289 	::sd::View* pSdView = static_cast< ::sd::View* >( maShapeTreeInfo.GetSdrView() );
290 	if ( pSdView )
291 	{
292 		SdDrawDocument* pDoc = pSdView->GetDoc();
293 		if ( pDoc )
294 		{
295 			rtl::OUString sFileName = pDoc->getDocAccTitle();
296 			if ( !sFileName.getLength() )
297 			{
298 				::sd::DrawDocShell* pDocSh = pSdView->GetDocSh();
299 				if ( pDocSh )
300 				{
301 					sFileName = pDocSh->GetTitle( SFX_TITLE_APINAME );
302 				}
303 			}
304 
305 			OUString sReadOnly;
306 			if(pDoc->getDocReadOnly())
307 			{
308 				sReadOnly = String(SdResId(SID_SD_A11Y_D_PRESENTATION_READONLY));
309 			}
310 
311 			if ( sFileName.getLength() )
312 			{
313 				sName = sFileName + sReadOnly + OUString(RTL_CONSTASCII_USTRINGPARAM(" - ")) + sName;
314 			}
315 		}
316 	}
317 
318 	return sName;
319 }
320 //=====  XEventListener  ======================================================
321 
322 void SAL_CALL
323     AccessibleDrawDocumentView::disposing (const lang::EventObject& rEventObject)
324     throw (::com::sun::star::uno::RuntimeException)
325 {
326     ThrowIfDisposed ();
327 
328     AccessibleDocumentViewBase::disposing (rEventObject);
329     if (rEventObject.Source == mxModel)
330     {
331         ::osl::Guard< ::osl::Mutex> aGuard (::osl::Mutex::getGlobalMutex());
332         // maShapeTreeInfo has been modified in base class.
333         if (mpChildrenManager != NULL)
334             mpChildrenManager->SetInfo (maShapeTreeInfo);
335     }
336 }
337 
338 
339 
340 
341 //=====  XPropertyChangeListener  =============================================
342 
343 void SAL_CALL
344     AccessibleDrawDocumentView::propertyChange (const beans::PropertyChangeEvent& rEventObject)
345     throw (::com::sun::star::uno::RuntimeException)
346 {
347     ThrowIfDisposed ();
348 
349     AccessibleDocumentViewBase::propertyChange (rEventObject);
350 
351     OSL_TRACE ("AccessibleDrawDocumentView::propertyChange");
352     // add page switch event for slide show mode
353     if (rEventObject.PropertyName == OUString (RTL_CONSTASCII_USTRINGPARAM("CurrentPage")) ||
354 		rEventObject.PropertyName == OUString (RTL_CONSTASCII_USTRINGPARAM("PageChange")) )
355     {
356         OSL_TRACE ("    current page changed");
357 
358         // Update the accessible name to reflect the current slide.
359         UpdateAccessibleName();
360 
361         // The current page changed.  Update the children manager accordingly.
362         uno::Reference<drawing::XDrawView> xView (mxController, uno::UNO_QUERY);
363         if (xView.is() && mpChildrenManager!=NULL)
364         {
365             // Inform the children manager to forget all children and give
366             // him the new ones.
367             mpChildrenManager->ClearAccessibleShapeList ();
368             mpChildrenManager->SetShapeList (uno::Reference<drawing::XShapes> (
369                 xView->getCurrentPage(), uno::UNO_QUERY));
370 
371             // Create the page shape and initialize it.  The shape is
372             // acquired before initialization and released after
373             // transferring ownership to the children manager to prevent
374             // premature disposing of the shape.
375             AccessiblePageShape* pPage = CreateDrawPageShape ();
376             if (pPage != NULL)
377             {
378                 pPage->acquire();
379                 pPage->Init();
380                 mpChildrenManager->AddAccessibleShape (
381                     std::auto_ptr<AccessibleShape>(pPage));
382                 mpChildrenManager->Update (false);
383                 pPage->release();
384             }
385         }
386         else
387             OSL_TRACE ("View invalid");
388 		CommitChange(AccessibleEventId::PAGE_CHANGED,rEventObject.NewValue,rEventObject.OldValue);
389     }
390     else if (rEventObject.PropertyName == OUString (RTL_CONSTASCII_USTRINGPARAM("VisibleArea")))
391     {
392         OSL_TRACE ("    visible area changed");
393         if (mpChildrenManager != NULL)
394             mpChildrenManager->ViewForwarderChanged (
395                 IAccessibleViewForwarderListener::VISIBLE_AREA,
396                 &maViewForwarder);
397     }
398 	else if (rEventObject.PropertyName == OUString (RTL_CONSTASCII_USTRINGPARAM("ActiveLayer")))
399 	{
400 		CommitChange(AccessibleEventId::PAGE_CHANGED,rEventObject.NewValue,rEventObject.OldValue);
401 	}
402     else if (rEventObject.PropertyName == OUString (RTL_CONSTASCII_USTRINGPARAM("UpdateAcc")))
403     {
404         OSL_TRACE ("    acc on current page should be updated");
405 
406         // The current page changed.  Update the children manager accordingly.
407         uno::Reference<drawing::XDrawView> xView (mxController, uno::UNO_QUERY);
408         if (xView.is() && mpChildrenManager!=NULL)
409         {
410             // Inform the children manager to forget all children and give
411             // him the new ones.
412             mpChildrenManager->ClearAccessibleShapeList ();
413 			// update the slide show page's accessible info
414             //mpChildrenManager->SetShapeList (uno::Reference<drawing::XShapes> (
415             //    xView->getCurrentPage(), uno::UNO_QUERY));
416 	    rtl::Reference< sd::SlideShow > xSlideshow( sd::SlideShow::GetSlideShow( mpSdViewSh->GetViewShellBase() ) );
417 	    if( xSlideshow.is() && xSlideshow->isRunning() && xSlideshow->isFullScreen() )
418 	    {
419 		    ::com::sun::star::uno::Reference< drawing::XDrawPage > xSlide;
420 			// MT IA2: Not used...
421 			// sal_Int32 currentPageIndex = xSlideshow->getCurrentPageIndex();
422 			::com::sun::star::uno::Reference< ::com::sun::star::presentation::XSlideShowController > mpSlideController = xSlideshow->getController();
423 			if( mpSlideController.is() )
424 			{
425 				xSlide = mpSlideController->getCurrentSlide();
426 				if (xSlide.is())
427 				{
428 					mpChildrenManager->SetShapeList (uno::Reference<drawing::XShapes> (
429 				                xSlide, uno::UNO_QUERY));
430 				}
431 			}
432 	    }
433             // Create the page shape and initialize it.  The shape is
434             // acquired before initialization and released after
435             // transferring ownership to the children manager to prevent
436             // premature disposing of the shape.
437             AccessiblePageShape* pPage = CreateDrawPageShape ();
438             if (pPage != NULL)
439             {
440                 pPage->acquire();
441                 pPage->Init();
442                 mpChildrenManager->AddAccessibleShape (
443                     std::auto_ptr<AccessibleShape>(pPage));
444                 mpChildrenManager->Update (false);
445                 pPage->release();
446             }
447 	}
448     }
449     else
450     {
451         OSL_TRACE ("  unhandled");
452     }
453     OSL_TRACE ("  done");
454 }
455 
456 
457 
458 //=====  XServiceInfo  ========================================================
459 
460 ::rtl::OUString SAL_CALL
461     AccessibleDrawDocumentView::getImplementationName (void)
462     throw (::com::sun::star::uno::RuntimeException)
463 {
464 	return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
465         "AccessibleDrawDocumentView"));
466 }
467 
468 
469 
470 
471 ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL
472     AccessibleDrawDocumentView::getSupportedServiceNames (void)
473     throw (::com::sun::star::uno::RuntimeException)
474 {
475     ThrowIfDisposed();
476     // Get list of supported service names from base class...
477     uno::Sequence<OUString> aServiceNames =
478         AccessibleDocumentViewBase::getSupportedServiceNames();
479     sal_Int32 nCount (aServiceNames.getLength());
480 
481     // ...and add additional names.
482     aServiceNames.realloc (nCount + 1);
483     static const OUString sAdditionalServiceName (RTL_CONSTASCII_USTRINGPARAM(
484         "com.sun.star.drawing.AccessibleDrawDocumentView"));
485     aServiceNames[nCount] = sAdditionalServiceName;
486 
487     return aServiceNames;
488 }
489 
490 //=====  XInterface  ==========================================================
491 
492 uno::Any SAL_CALL
493     AccessibleDrawDocumentView::queryInterface (const uno::Type & rType)
494     throw (uno::RuntimeException)
495 {
496     uno::Any aReturn = AccessibleDocumentViewBase::queryInterface (rType);
497     if ( ! aReturn.hasValue())
498         aReturn = ::cppu::queryInterface (rType,
499             static_cast<XAccessibleGroupPosition*>(this)
500             );
501     return aReturn;
502 }
503 
504 void SAL_CALL
505     AccessibleDrawDocumentView::acquire (void)
506     throw ()
507 {
508     AccessibleDocumentViewBase::acquire ();
509 }
510 void SAL_CALL
511     AccessibleDrawDocumentView::release (void)
512     throw ()
513 {
514     AccessibleDocumentViewBase::release ();
515 }
516 //=====  XAccessibleGroupPosition  =========================================
517 uno::Sequence< sal_Int32 > SAL_CALL
518     AccessibleDrawDocumentView::getGroupPosition( const uno::Any& rAny )
519     throw (uno::RuntimeException)
520 {
521 	// we will return the:
522 	// [0] group level(always be 0 now)
523 	// [1] similar items counts in the group
524 	// [2] the position of the object in the group
525 	uno::Sequence< sal_Int32 > aRet( 3 );
526 	//get the xShape of the current selected drawing object
527 	uno::Reference<XAccessibleContext> xAccContent;
528 	rAny >>= xAccContent;
529 	if ( !xAccContent.is() )
530 	{
531 		return aRet;
532 	}
533 	AccessibleShape* pAcc = AccessibleShape::getImplementation( xAccContent );
534 	if ( !pAcc )
535 	{
536 		return aRet;
537 	}
538 	uno::Reference< drawing::XShape > xCurShape = pAcc->GetXShape();
539 	if ( !xCurShape.is() )
540 	{
541 		return aRet;
542 	}
543 	//find all the child in the page, insert them into a vector and sort
544 	if ( mpChildrenManager == NULL )
545 	{
546 		return aRet;
547 	}
548 	std::vector< uno::Reference<drawing::XShape> > vXShapes;
549 	sal_Int32 nCount = mpChildrenManager->GetChildCount();
550 	//get pointer of SdView & SdrPageView for further use.
551 	SdrPageView* pPV = NULL;
552 	::sd::View* pSdView = NULL;
553 	if ( mpSdViewSh )
554 	{
555 		pSdView = mpSdViewSh->GetView();
556 		pPV = pSdView->GetSdrPageView();
557 	}
558 	for ( sal_Int32 i = 0; i < nCount; i++ )
559 	{
560 		uno::Reference< drawing::XShape > xShape = mpChildrenManager->GetChildShape(i);
561 		if ( xShape.is() )
562 		{
563 			//if the object is visible in the page, we add it into the group list.
564 			SdrObject* pObj = GetSdrObjectFromXShape(xShape);
565 			if ( pObj && pPV && pSdView && pSdView->IsObjMarkable( pObj, pPV ) )
566 			{
567 				vXShapes.push_back( xShape );
568 			}
569 		}
570 	}
571 	std::sort( vXShapes.begin(), vXShapes.end(), XShapePosCompareHelper() );
572 	//get the the index of the selected object in the group
573 	std::vector< uno::Reference<drawing::XShape> >::iterator aIter;
574 	//we start counting position from 1
575 	sal_Int32 nPos = 1;
576 	for ( aIter = vXShapes.begin(); aIter != vXShapes.end(); aIter++, nPos++ )
577 	{
578 		if ( (*aIter).get() == xCurShape.get() )
579 		{
580 			sal_Int32* pArray = aRet.getArray();
581 			pArray[0] = 1; //it should be 1 based, not 0 based.
582 			pArray[1] = vXShapes.size();
583 			pArray[2] = nPos;
584 			break;
585 		}
586 	}
587 	return aRet;
588 }
589 ::rtl::OUString AccessibleDrawDocumentView::getObjectLink( const uno::Any& rAny )
590 	throw (uno::RuntimeException)
591 {
592 	::rtl::OUString aRet;
593 	//get the xShape of the current selected drawing object
594 	uno::Reference<XAccessibleContext> xAccContent;
595 	rAny >>= xAccContent;
596 	if ( !xAccContent.is() )
597 	{
598 		return aRet;
599 	}
600 	AccessibleShape* pAcc = AccessibleShape::getImplementation( xAccContent );
601 	if ( !pAcc )
602 	{
603 		return aRet;
604 	}
605 	uno::Reference< drawing::XShape > xCurShape = pAcc->GetXShape();
606 	if ( !xCurShape.is() )
607 	{
608 		return aRet;
609 	}
610 	SdrObject* pObj = GetSdrObjectFromXShape(xCurShape);
611 	if (pObj)
612 	{
613 		SdAnimationInfo* pInfo = SdDrawDocument::GetShapeUserData(*pObj);
614 		if( pInfo && (pInfo->meClickAction == presentation::ClickAction_DOCUMENT) )
615 			aRet = (::rtl::OUString)pInfo->GetBookmark();
616 	}
617 	return aRet;
618 }
619 ///	Create a name for this view.
620 ::rtl::OUString
621     AccessibleDrawDocumentView::CreateAccessibleName (void)
622     throw (::com::sun::star::uno::RuntimeException)
623 {
624 	rtl::OUString sName;
625 
626     uno::Reference<lang::XServiceInfo> xInfo (mxController, uno::UNO_QUERY);
627     if (xInfo.is())
628     {
629         uno::Sequence< ::rtl::OUString > aServices( xInfo->getSupportedServiceNames() );
630         OUString sFirstService = aServices[0];
631         if (sFirstService == OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.DrawingDocumentDrawView")))
632         {
633             if( aServices.getLength() >= 2 &&
634                 aServices[1] == OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.presentation.PresentationView")))
635             {
636                 ::vos::OGuard aGuard( Application::GetSolarMutex() );
637 
638                 sName = String( SdResId(SID_SD_A11Y_I_DRAWVIEW_N) );
639             }
640             else
641             {
642                 ::vos::OGuard aGuard( Application::GetSolarMutex() );
643 
644                 sName = String( SdResId(SID_SD_A11Y_D_DRAWVIEW_N) );
645             }
646         }
647         else if (sFirstService == OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.presentation.NotesView")))
648         {
649             ::vos::OGuard aGuard( Application::GetSolarMutex() );
650 
651             sName = String( SdResId(SID_SD_A11Y_I_NOTESVIEW_N) );
652         }
653         else if (sFirstService == OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.presentation.HandoutView")))
654         {
655             ::vos::OGuard aGuard( Application::GetSolarMutex() );
656 
657             sName = String( SdResId(SID_SD_A11Y_I_HANDOUTVIEW_N) );
658         }
659         else
660         {
661             sName = sFirstService;
662         }
663     }
664     else
665     {
666         sName = OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleDrawDocumentView"));
667     }
668 	return sName;
669 }
670 
671 
672 
673 
674 /** Create a description for this view.  Use the model's description or URL
675     if a description is not available.
676 */
677 ::rtl::OUString
678     AccessibleDrawDocumentView::CreateAccessibleDescription (void)
679     throw (::com::sun::star::uno::RuntimeException)
680 {
681 	rtl::OUString sDescription;
682 
683     uno::Reference<lang::XServiceInfo> xInfo (mxController, uno::UNO_QUERY);
684     if (xInfo.is())
685     {
686         uno::Sequence< ::rtl::OUString > aServices( xInfo->getSupportedServiceNames() );
687         OUString sFirstService = aServices[0];
688         if (sFirstService == OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.DrawingDocumentDrawView")))
689         {
690             if( aServices.getLength() >= 2 &&
691                 aServices[1] == OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.presentation.PresentationView")))
692             {
693                 ::vos::OGuard aGuard( Application::GetSolarMutex() );
694 
695                 sDescription = String( SdResId(SID_SD_A11Y_I_DRAWVIEW_D) );
696             }
697             else
698             {
699                 ::vos::OGuard aGuard( Application::GetSolarMutex() );
700 
701                 sDescription = String( SdResId(SID_SD_A11Y_D_DRAWVIEW_D) );
702             }
703         }
704         else if (sFirstService == OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.presentation.NotesView")))
705         {
706             ::vos::OGuard aGuard( Application::GetSolarMutex() );
707 
708             sDescription = String( SdResId(SID_SD_A11Y_I_NOTESVIEW_D) );
709         }
710         else if (sFirstService == OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.presentation.HandoutView")))
711         {
712             ::vos::OGuard aGuard( Application::GetSolarMutex() );
713 
714             sDescription = String( SdResId(SID_SD_A11Y_I_HANDOUTVIEW_D) );
715         }
716         else
717         {
718             sDescription = sFirstService;
719         }
720     }
721     else
722     {
723         sDescription = OUString(RTL_CONSTASCII_USTRINGPARAM("Accessible Draw Document"));
724     }
725 	return sDescription;
726 }
727 
728 
729 
730 
731 /** Return selection state of specified child
732 */
733 sal_Bool
734     AccessibleDrawDocumentView::implIsSelected( sal_Int32 nAccessibleChildIndex )
735     throw (uno::RuntimeException)
736 {
737     const vos::OGuard                           aSolarGuard( Application::GetSolarMutex() );
738     uno::Reference< view::XSelectionSupplier >  xSel( mxController, uno::UNO_QUERY );
739     sal_Bool                                    bRet = sal_False;
740 
741 	OSL_ENSURE( 0 <= nAccessibleChildIndex, "AccessibleDrawDocumentView::implIsSelected: invalid index!" );
742 
743     if( xSel.is() && ( 0 <= nAccessibleChildIndex ) )
744     {
745         uno::Any                            aAny( xSel->getSelection() );
746         uno::Reference< drawing::XShapes >  xShapes;
747 
748         aAny >>= xShapes;
749 
750         if( xShapes.is() )
751         {
752             AccessibleShape* pAcc = AccessibleShape::getImplementation( getAccessibleChild( nAccessibleChildIndex ) );
753 
754             if( pAcc )
755             {
756                 uno::Reference< drawing::XShape > xShape( pAcc->GetXShape() );
757 
758                 if( xShape.is() )
759                 {
760                     for( sal_Int32 i = 0, nCount = xShapes->getCount(); ( i < nCount ) && !bRet; ++i )
761                         if( xShapes->getByIndex( i ) == xShape )
762                             bRet = sal_True;
763                 }
764             }
765         }
766     }
767 
768     return( bRet );
769 }
770 
771 
772 
773 
774 /** Select or delselect the specified shapes.  The corresponding accessible
775     shapes are notified over the selection change listeners registered with
776     the XSelectionSupplier of the controller.
777 */
778 void
779     AccessibleDrawDocumentView::implSelect( sal_Int32 nAccessibleChildIndex, sal_Bool bSelect )
780     throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
781 {
782     const vos::OGuard                           aSolarGuard( Application::GetSolarMutex() );
783     uno::Reference< view::XSelectionSupplier >  xSel( mxController, uno::UNO_QUERY );
784     AccessibleShape* pAccessibleChild;
785 
786     if( xSel.is() )
787     {
788         uno::Any aAny;
789 
790         if( ACCESSIBLE_SELECTION_CHILD_ALL == nAccessibleChildIndex )
791         {
792             // Select or deselect all children.
793 
794             if( !bSelect )
795                 xSel->select( aAny );
796             else
797             {
798                 uno::Reference< drawing::XShapes > xShapes( new SvxShapeCollection() );
799 
800                 for(sal_Int32 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i )
801                 {
802                     AccessibleShape* pAcc = AccessibleShape::getImplementation( getAccessibleChild( i ) );
803 
804                     if( pAcc && pAcc->GetXShape().is() )
805                     {
806                         xShapes->add( pAcc->GetXShape() );
807                         pAccessibleChild = pAcc;
808                     }
809                 }
810 
811                 if( xShapes->getCount() )
812                 {
813                     aAny <<= xShapes;
814                     xSel->select( aAny );
815                 }
816             }
817         }
818         else if( nAccessibleChildIndex >= 0 )
819         {
820             // Select or deselect only the child with index
821             // nAccessibleChildIndex.
822 
823             AccessibleShape* pAcc = AccessibleShape::getImplementation(
824                 getAccessibleChild( nAccessibleChildIndex ));
825             pAccessibleChild = pAcc;
826 
827             // Add or remove the shape that is made accessible from the
828             // selection of the controller.
829             if( pAcc )
830             {
831                 uno::Reference< drawing::XShape > xShape( pAcc->GetXShape() );
832 
833                 if( xShape.is() )
834                 {
835                     uno::Reference< drawing::XShapes >  xShapes;
836                     sal_Bool                            bFound = sal_False;
837 
838                     aAny = xSel->getSelection();
839                     aAny >>= xShapes;
840 
841                     // Search shape to be selected in current selection.
842                     if (xShapes.is())
843                     {
844                         sal_Int32 nCount = xShapes->getCount();
845                         for (sal_Int32 i=0; ( i < nCount ) && !bFound; ++i )
846                             if( xShapes->getByIndex( i ) == xShape )
847                                 bFound = sal_True;
848                     }
849                     else
850                         // Create an empty selection to add the shape to.
851                         xShapes = new SvxShapeCollection();
852 
853                     // Update the selection.
854                     if( !bFound && bSelect )
855                         xShapes->add( xShape );
856                     else if( bFound && !bSelect )
857                         xShapes->remove( xShape );
858 
859                     aAny <<= xShapes;
860                     xSel->select( aAny );
861                 }
862             }
863         }
864     }
865 }
866 
867 
868 
869 
870 void AccessibleDrawDocumentView::Activated (void)
871 {
872     if (mpChildrenManager != NULL)
873     {
874 	sal_Bool bChange = sal_False;
875         // When none of the children has the focus then claim it for the
876         // view.
877         if ( ! mpChildrenManager->HasFocus())
878 	{
879             SetState (AccessibleStateType::FOCUSED);
880 	    bChange = sal_True;
881 	}
882         else
883             ResetState (AccessibleStateType::FOCUSED);
884 	mpChildrenManager->UpdateSelection();
885 	// if the child gets focus in UpdateSelection(), needs to reset the focus on document.
886 	if (mpChildrenManager->HasFocus() && bChange)
887 		ResetState (AccessibleStateType::FOCUSED);
888     }
889 }
890 
891 
892 
893 
894 void AccessibleDrawDocumentView::Deactivated (void)
895 {
896     if (mpChildrenManager != NULL)
897         mpChildrenManager->RemoveFocus();
898     ResetState (AccessibleStateType::FOCUSED);
899 }
900 
901 
902 
903 
904 void AccessibleDrawDocumentView::impl_dispose (void)
905 {
906     if (mpChildrenManager != NULL)
907     {
908         delete mpChildrenManager;
909         mpChildrenManager = NULL;
910     }
911 
912     AccessibleDocumentViewBase::impl_dispose();
913 }
914 
915 
916 
917 /** This method is called from the component helper base class while
918     disposing.
919 */
920 void SAL_CALL AccessibleDrawDocumentView::disposing (void)
921 {
922 
923     // Release resources.
924     if (mpChildrenManager != NULL)
925     {
926         delete mpChildrenManager;
927         mpChildrenManager = NULL;
928     }
929 
930     // Forward call to base classes.
931     AccessibleDocumentViewBase::disposing ();
932 }
933 
934 ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >
935 		SAL_CALL AccessibleDrawDocumentView::get_AccFlowTo(const ::com::sun::star::uno::Any& rAny, sal_Int32 nType)
936 		throw ( ::com::sun::star::uno::RuntimeException )
937 {
938 	const sal_Int32 SPELLCHECKFLOWTO = 1;
939 	const sal_Int32 FINDREPLACEFLOWTO = 2;
940 	if ( nType == SPELLCHECKFLOWTO )
941 	{
942 		uno::Reference< ::com::sun::star::drawing::XShape > xShape;
943 		rAny >>= xShape;
944 		if ( mpChildrenManager && xShape.is() )
945 		{
946 			uno::Reference < XAccessible > xAcc = mpChildrenManager->GetChild(xShape);
947 			uno::Reference < XAccessibleSelection > xAccSelection( xAcc, uno::UNO_QUERY );
948 			if ( xAccSelection.is() )
949 			{
950 				if ( xAccSelection->getSelectedAccessibleChildCount() )
951 				{
952 					uno::Reference < XAccessible > xSel = xAccSelection->getSelectedAccessibleChild( 0 );
953 					if ( xSel.is() )
954 					{
955 						uno::Reference < XAccessibleContext > xSelContext( xSel->getAccessibleContext() );
956 						if ( xSelContext.is() )
957 						{
958 							//if in sw we find the selected paragraph here
959 							if ( xSelContext->getAccessibleRole() == AccessibleRole::PARAGRAPH )
960 							{
961 								uno::Sequence<uno::Any> aRet( 1 );
962 								aRet[0] = uno::makeAny( xSel );
963 								return aRet;
964 							}
965 						}
966 					}
967 				}
968 			}
969 			uno::Reference<XAccessible> xPara = GetSelAccContextInTable();
970 			if ( xPara.is() )
971 			{
972 				uno::Sequence<uno::Any> aRet( 1 );
973 				aRet[0] = uno::makeAny( xPara );
974 				return aRet;
975 			}
976 		}
977 		else
978 		{
979 			goto Rt;
980 		}
981 	}
982 	else if ( nType == FINDREPLACEFLOWTO )
983 	{
984 		sal_Int32 nChildCount = getSelectedAccessibleChildCount();
985 		if ( nChildCount )
986 		{
987 			uno::Reference < XAccessible > xSel = getSelectedAccessibleChild( 0 );
988 			if ( xSel.is() )
989 			{
990 				uno::Reference < XAccessibleSelection > xAccChildSelection( xSel, uno::UNO_QUERY );
991 				if ( xAccChildSelection.is() )
992 				{
993 					if ( xAccChildSelection->getSelectedAccessibleChildCount() )
994 					{
995 						uno::Reference < XAccessible > xChildSel = xAccChildSelection->getSelectedAccessibleChild( 0 );
996 						if ( xChildSel.is() )
997 						{
998 							uno::Reference < XAccessibleContext > xChildSelContext( xChildSel->getAccessibleContext() );
999 							if ( xChildSelContext.is() &&
1000 								xChildSelContext->getAccessibleRole() == AccessibleRole::PARAGRAPH )
1001 							{
1002 								uno::Sequence<uno::Any> aRet( 1 );
1003 								aRet[0] = uno::makeAny( xChildSel );
1004 								return aRet;
1005 							}
1006 						}
1007 					}
1008 				}
1009 			}
1010 		}
1011 		else
1012 		{
1013 			uno::Reference<XAccessible> xPara = GetSelAccContextInTable();
1014 			if ( xPara.is() )
1015 			{
1016 				uno::Sequence<uno::Any> aRet( 1 );
1017 				aRet[0] = uno::makeAny( xPara );
1018 				return aRet;
1019 			}
1020 		}
1021 	}
1022 
1023 Rt:
1024 	::com::sun::star::uno::Sequence< uno::Any> aRet;
1025 	return aRet;
1026 }
1027 uno::Reference<XAccessible> AccessibleDrawDocumentView::GetSelAccContextInTable()
1028 {
1029 	uno::Reference<XAccessible> xRet;
1030 	sal_Int32 nCount = mpChildrenManager ? mpChildrenManager->GetChildCount() : 0;
1031 	if ( nCount )
1032 	{
1033 		for ( sal_Int32 i = 0; i < nCount; i++ )
1034 		{
1035 			try
1036 			{
1037 				uno::Reference<XAccessible> xObj = mpChildrenManager->GetChild(i);
1038 				if ( xObj.is() )
1039 				{
1040 					uno::Reference<XAccessibleContext> xObjContext( xObj, uno::UNO_QUERY );
1041 					if ( xObjContext.is() && xObjContext->getAccessibleRole() == AccessibleRole::TABLE )
1042 					{
1043 						uno::Reference<XAccessibleSelection> xObjSelection( xObj, uno::UNO_QUERY );
1044 						if ( xObjSelection.is() && xObjSelection->getSelectedAccessibleChildCount() )
1045 						{
1046 							uno::Reference<XAccessible> xCell = xObjSelection->getSelectedAccessibleChild(0);
1047 							if ( xCell.is() )
1048 							{
1049 								uno::Reference<XAccessibleSelection> xCellSel( xCell, uno::UNO_QUERY );
1050 								if ( xCellSel.is() && xCellSel->getSelectedAccessibleChildCount() )
1051 								{
1052 									uno::Reference<XAccessible> xPara = xCellSel->getSelectedAccessibleChild( 0 );
1053 									if ( xPara.is() )
1054 									{
1055 										uno::Reference<XAccessibleContext> xParaContext( xPara, uno::UNO_QUERY );
1056 										if ( xParaContext.is() &&
1057 											xParaContext->getAccessibleRole() == AccessibleRole::PARAGRAPH )
1058 										{
1059 											xRet = xPara;
1060 											return xRet;
1061 										}
1062 									}
1063 								}
1064 							}
1065 						}
1066 					}
1067 				}
1068 			}
1069 			catch ( lang::IndexOutOfBoundsException )
1070 			{
1071 				uno::Reference<XAccessible> xEmpty;
1072 				return xEmpty;
1073 			}
1074 			catch ( uno::RuntimeException )
1075 			{
1076 				uno::Reference<XAccessible> xEmpty;
1077 				return xEmpty;
1078 			}
1079 		}
1080 	}
1081 
1082 	return xRet;
1083 }
1084 
1085 void AccessibleDrawDocumentView::UpdateAccessibleName (void)
1086 {
1087 	OUString sNewName (CreateAccessibleName());
1088     sNewName += A2S(": ");
1089 
1090     // Add the number of the current slide.
1091     uno::Reference<drawing::XDrawView> xView (mxController, uno::UNO_QUERY);
1092     if (xView.is())
1093     {
1094         uno::Reference<beans::XPropertySet> xProperties (xView->getCurrentPage(), UNO_QUERY);
1095         if (xProperties.is())
1096             try
1097             {
1098                 sal_Int16 nPageNumber (0);
1099                 if (xProperties->getPropertyValue(A2S("Number")) >>= nPageNumber)
1100                 {
1101                     sNewName += OUString::valueOf(sal_Int32(nPageNumber));
1102                 }
1103             }
1104             catch (beans::UnknownPropertyException&)
1105             {
1106             }
1107     }
1108 
1109     // Add the number of pages/slides.
1110     Reference<drawing::XDrawPagesSupplier> xPagesSupplier (mxModel, UNO_QUERY);
1111     if (xPagesSupplier.is())
1112     {
1113         Reference<container::XIndexAccess> xPages (xPagesSupplier->getDrawPages(), UNO_QUERY);
1114         if (xPages.is())
1115         {
1116             sNewName += A2S(" / ");
1117             sNewName += OUString::valueOf(xPages->getCount());
1118         }
1119     }
1120 
1121     SetAccessibleName (sNewName, AutomaticallyCreated);
1122 }
1123 
1124 
1125 
1126 
1127 } // end of namespace accessibility
1128