1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: AccessibleDrawDocumentView.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sd.hxx"
33 #include "AccessibleDrawDocumentView.hxx"
34 #include <com/sun/star/drawing/XDrawPage.hpp>
35 #include <com/sun/star/drawing/XDrawView.hpp>
36 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
37 #include <com/sun/star/drawing/XShapes.hpp>
38 #include <com/sun/star/container/XChild.hpp>
39 #include <com/sun/star/frame/XController.hpp>
40 #include <com/sun/star/frame/XFrame.hpp>
41 #include <com/sun/star/document/XEventBroadcaster.hpp>
42 #include <com/sun/star/beans/XPropertySet.hpp>
43 #ifndef _COM_SUN_STAR_ACCESSIBLE_ACCESSIBLEEVENTID_HPP_
44 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
46 #ifndef _COM_SUN_STAR_ACCESSIBLE_ACCESSIBLESTATETYPE_HPP_
47 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
49 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
50 #ifndef _COM_SUN_STAR_LANG_XMULSTISERVICEFACTORY_HPP_
51 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
53 #include <rtl/ustring.h>
55 #include<sfx2/viewfrm.hxx>
58 #include <svx/AccessibleShape.hxx>
60 #include <svx/svdobj.hxx>
61 #include <svx/svdmodel.hxx>
62 #include <svx/unoapi.hxx>
63 #include <svx/unoshcol.hxx>
64 #include <toolkit/helper/vclunohelper.hxx>
66 #include <vcl/svapp.hxx>
69 #include "ViewShell.hxx"
73 #include "accessibility.hrc"
74 #include "sdresid.hxx"
75 #include <vos/mutex.hxx>
77 using ::rtl::OUString
;
78 using namespace ::com::sun::star
;
79 using namespace ::com::sun::star::uno
;
80 using namespace ::com::sun::star::accessibility
;
84 #define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString)))
86 namespace accessibility
{
89 //===== internal ============================================================
91 AccessibleDrawDocumentView::AccessibleDrawDocumentView (
92 ::sd::Window
* pSdWindow
,
93 ::sd::ViewShell
* pViewShell
,
94 const uno::Reference
<frame::XController
>& rxController
,
95 const uno::Reference
<XAccessible
>& rxParent
)
96 : AccessibleDocumentViewBase (pSdWindow
, pViewShell
, rxController
, rxParent
),
97 mpChildrenManager (NULL
)
99 OSL_TRACE ("AccessibleDrawDocumentView");
100 UpdateAccessibleName();
106 AccessibleDrawDocumentView::~AccessibleDrawDocumentView (void)
108 OSL_TRACE ("~AccessibleDrawDocumentView");
109 DBG_ASSERT (rBHelper
.bDisposed
|| rBHelper
.bInDispose
,
110 "~AccessibleDrawDocumentView: object has not been disposed");
116 void AccessibleDrawDocumentView::Init (void)
118 AccessibleDocumentViewBase::Init ();
120 // Determine the list of shapes on the current page.
121 uno::Reference
<drawing::XShapes
> xShapeList
;
122 uno::Reference
<drawing::XDrawView
> xView (mxController
, uno::UNO_QUERY
);
124 xShapeList
= uno::Reference
<drawing::XShapes
> (
125 xView
->getCurrentPage(), uno::UNO_QUERY
);
127 // Create the children manager.
128 mpChildrenManager
= new ChildrenManager(this, xShapeList
, maShapeTreeInfo
, *this);
129 if (mpChildrenManager
!= NULL
)
131 // Create the page shape and initialize it. The shape is acquired
132 // before initialization and released after transferring ownership
133 // to the children manager to prevent premature disposing of the
135 AccessiblePageShape
* pPage
= CreateDrawPageShape();
140 mpChildrenManager
->AddAccessibleShape (
141 std::auto_ptr
<AccessibleShape
>(pPage
));
143 mpChildrenManager
->Update ();
145 mpChildrenManager
->UpdateSelection ();
152 void AccessibleDrawDocumentView::ViewForwarderChanged (ChangeType aChangeType
,
153 const IAccessibleViewForwarder
* pViewForwarder
)
155 AccessibleDocumentViewBase::ViewForwarderChanged (aChangeType
, pViewForwarder
);
156 if (mpChildrenManager
!= NULL
)
157 mpChildrenManager
->ViewForwarderChanged (aChangeType
, pViewForwarder
);
163 /** The page shape is created on every call at the moment (provided that
164 every thing goes well).
166 AccessiblePageShape
* AccessibleDrawDocumentView::CreateDrawPageShape (void)
168 AccessiblePageShape
* pShape
= NULL
;
170 // Create a shape that represents the actual draw page.
171 uno::Reference
<drawing::XDrawView
> xView (mxController
, uno::UNO_QUERY
);
174 uno::Reference
<beans::XPropertySet
> xSet (
175 uno::Reference
<beans::XPropertySet
> (xView
->getCurrentPage(), uno::UNO_QUERY
));
178 // Create a rectangle shape that will represent the draw page.
179 uno::Reference
<lang::XMultiServiceFactory
> xFactory (mxModel
, uno::UNO_QUERY
);
180 uno::Reference
<drawing::XShape
> xRectangle
;
182 xRectangle
= uno::Reference
<drawing::XShape
>(xFactory
->createInstance (
183 OUString (RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.RectangleShape"))),
186 // Set the shape's size and position.
190 awt::Point aPosition
;
193 // Set size and position of the shape to those of the draw
195 aValue
= xSet
->getPropertyValue (
196 OUString (RTL_CONSTASCII_USTRINGPARAM("BorderLeft")));
197 aValue
>>= aPosition
.X
;
198 aValue
= xSet
->getPropertyValue (
199 OUString (RTL_CONSTASCII_USTRINGPARAM("BorderTop")));
200 aValue
>>= aPosition
.Y
;
201 xRectangle
->setPosition (aPosition
);
203 aValue
= xSet
->getPropertyValue (
204 OUString (RTL_CONSTASCII_USTRINGPARAM("Width")));
205 aValue
>>= aSize
.Width
;
206 aValue
= xSet
->getPropertyValue (
207 OUString (RTL_CONSTASCII_USTRINGPARAM("Height")));
208 aValue
>>= aSize
.Height
;
209 xRectangle
->setSize (aSize
);
211 // Create the accessible object for the shape and
213 pShape
= new AccessiblePageShape (
214 xView
->getCurrentPage(), this, maShapeTreeInfo
);
224 //===== XAccessibleContext ==================================================
227 AccessibleDrawDocumentView::getAccessibleChildCount (void)
228 throw (uno::RuntimeException
)
232 long mpChildCount
= AccessibleDocumentViewBase::getAccessibleChildCount();
234 // Forward request to children manager.
235 if (mpChildrenManager
!= NULL
)
236 mpChildCount
+= mpChildrenManager
->GetChildCount ();
244 uno::Reference
<XAccessible
> SAL_CALL
245 AccessibleDrawDocumentView::getAccessibleChild (sal_Int32 nIndex
)
246 throw (::com::sun::star::uno::RuntimeException
)
250 ::osl::ClearableMutexGuard
aGuard (maMutex
);
252 // Take care of children of the base class.
253 sal_Int32 nCount
= AccessibleDocumentViewBase::getAccessibleChildCount();
257 return AccessibleDocumentViewBase::getAccessibleChild(nIndex
);
262 // Create a copy of the pointer to the children manager and release the
263 // mutex before calling any of its methods.
264 ChildrenManager
* pChildrenManager
= mpChildrenManager
;
267 // Forward request to children manager.
268 if (pChildrenManager
!= NULL
)
270 return pChildrenManager
->GetChild (nIndex
);
273 throw lang::IndexOutOfBoundsException (
274 ::rtl::OUString::createFromAscii ("no accessible child with index ")
275 + rtl::OUString::valueOf(nIndex
),
276 static_cast<uno::XWeak
*>(this));
282 //===== XEventListener ======================================================
285 AccessibleDrawDocumentView::disposing (const lang::EventObject
& rEventObject
)
286 throw (::com::sun::star::uno::RuntimeException
)
290 AccessibleDocumentViewBase::disposing (rEventObject
);
291 if (rEventObject
.Source
== mxModel
)
293 ::osl::Guard
< ::osl::Mutex
> aGuard (::osl::Mutex::getGlobalMutex());
294 // maShapeTreeInfo has been modified in base class.
295 if (mpChildrenManager
!= NULL
)
296 mpChildrenManager
->SetInfo (maShapeTreeInfo
);
303 //===== XPropertyChangeListener =============================================
306 AccessibleDrawDocumentView::propertyChange (const beans::PropertyChangeEvent
& rEventObject
)
307 throw (::com::sun::star::uno::RuntimeException
)
311 AccessibleDocumentViewBase::propertyChange (rEventObject
);
313 OSL_TRACE ("AccessibleDrawDocumentView::propertyChange");
314 if (rEventObject
.PropertyName
== OUString (RTL_CONSTASCII_USTRINGPARAM("CurrentPage")))
316 OSL_TRACE (" current page changed");
318 // Update the accessible name to reflect the current slide.
319 UpdateAccessibleName();
321 // The current page changed. Update the children manager accordingly.
322 uno::Reference
<drawing::XDrawView
> xView (mxController
, uno::UNO_QUERY
);
323 if (xView
.is() && mpChildrenManager
!=NULL
)
325 // Inform the children manager to forget all children and give
327 mpChildrenManager
->ClearAccessibleShapeList ();
328 mpChildrenManager
->SetShapeList (uno::Reference
<drawing::XShapes
> (
329 xView
->getCurrentPage(), uno::UNO_QUERY
));
331 // Create the page shape and initialize it. The shape is
332 // acquired before initialization and released after
333 // transferring ownership to the children manager to prevent
334 // premature disposing of the shape.
335 AccessiblePageShape
* pPage
= CreateDrawPageShape ();
340 mpChildrenManager
->AddAccessibleShape (
341 std::auto_ptr
<AccessibleShape
>(pPage
));
342 mpChildrenManager
->Update (false);
347 OSL_TRACE ("View invalid");
349 else if (rEventObject
.PropertyName
== OUString (RTL_CONSTASCII_USTRINGPARAM("VisibleArea")))
351 OSL_TRACE (" visible area changed");
352 if (mpChildrenManager
!= NULL
)
353 mpChildrenManager
->ViewForwarderChanged (
354 IAccessibleViewForwarderListener::VISIBLE_AREA
,
359 OSL_TRACE (" unhandled");
366 //===== XServiceInfo ========================================================
368 ::rtl::OUString SAL_CALL
369 AccessibleDrawDocumentView::getImplementationName (void)
370 throw (::com::sun::star::uno::RuntimeException
)
372 return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
373 "AccessibleDrawDocumentView"));
379 ::com::sun::star::uno::Sequence
< ::rtl::OUString
> SAL_CALL
380 AccessibleDrawDocumentView::getSupportedServiceNames (void)
381 throw (::com::sun::star::uno::RuntimeException
)
384 // Get list of supported service names from base class...
385 uno::Sequence
<OUString
> aServiceNames
=
386 AccessibleDocumentViewBase::getSupportedServiceNames();
387 sal_Int32
nCount (aServiceNames
.getLength());
389 // ...and add additional names.
390 aServiceNames
.realloc (nCount
+ 1);
391 static const OUString
sAdditionalServiceName (RTL_CONSTASCII_USTRINGPARAM(
392 "com.sun.star.drawing.AccessibleDrawDocumentView"));
393 aServiceNames
[nCount
] = sAdditionalServiceName
;
395 return aServiceNames
;
401 /// Create a name for this view.
403 AccessibleDrawDocumentView::CreateAccessibleName (void)
404 throw (::com::sun::star::uno::RuntimeException
)
408 uno::Reference
<lang::XServiceInfo
> xInfo (mxController
, uno::UNO_QUERY
);
411 uno::Sequence
< ::rtl::OUString
> aServices( xInfo
->getSupportedServiceNames() );
412 OUString sFirstService
= aServices
[0];
413 if (sFirstService
== OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.DrawingDocumentDrawView")))
415 if( aServices
.getLength() >= 2 &&
416 aServices
[1] == OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.presentation.PresentationView")))
418 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
420 sName
= String( SdResId(SID_SD_A11Y_I_DRAWVIEW_N
) );
424 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
426 sName
= String( SdResId(SID_SD_A11Y_D_DRAWVIEW_N
) );
429 else if (sFirstService
== OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.presentation.NotesView")))
431 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
433 sName
= String( SdResId(SID_SD_A11Y_I_NOTESVIEW_N
) );
435 else if (sFirstService
== OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.presentation.HandoutView")))
437 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
439 sName
= String( SdResId(SID_SD_A11Y_I_HANDOUTVIEW_N
) );
443 sName
= sFirstService
;
448 sName
= OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleDrawDocumentView"));
456 /** Create a description for this view. Use the model's description or URL
457 if a description is not available.
460 AccessibleDrawDocumentView::CreateAccessibleDescription (void)
461 throw (::com::sun::star::uno::RuntimeException
)
463 rtl::OUString sDescription
;
465 uno::Reference
<lang::XServiceInfo
> xInfo (mxController
, uno::UNO_QUERY
);
468 uno::Sequence
< ::rtl::OUString
> aServices( xInfo
->getSupportedServiceNames() );
469 OUString sFirstService
= aServices
[0];
470 if (sFirstService
== OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.DrawingDocumentDrawView")))
472 if( aServices
.getLength() >= 2 &&
473 aServices
[1] == OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.presentation.PresentationView")))
475 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
477 sDescription
= String( SdResId(SID_SD_A11Y_I_DRAWVIEW_D
) );
481 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
483 sDescription
= String( SdResId(SID_SD_A11Y_D_DRAWVIEW_D
) );
486 else if (sFirstService
== OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.presentation.NotesView")))
488 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
490 sDescription
= String( SdResId(SID_SD_A11Y_I_NOTESVIEW_D
) );
492 else if (sFirstService
== OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.presentation.HandoutView")))
494 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
496 sDescription
= String( SdResId(SID_SD_A11Y_I_HANDOUTVIEW_D
) );
500 sDescription
= sFirstService
;
505 sDescription
= OUString(RTL_CONSTASCII_USTRINGPARAM("Accessible Draw Document"));
513 /** Return selection state of specified child
516 AccessibleDrawDocumentView::implIsSelected( sal_Int32 nAccessibleChildIndex
)
517 throw (uno::RuntimeException
)
519 const vos::OGuard
aSolarGuard( Application::GetSolarMutex() );
520 uno::Reference
< view::XSelectionSupplier
> xSel( mxController
, uno::UNO_QUERY
);
521 sal_Bool bRet
= sal_False
;
523 OSL_ENSURE( 0 <= nAccessibleChildIndex
, "AccessibleDrawDocumentView::implIsSelected: invalid index!" );
525 if( xSel
.is() && ( 0 <= nAccessibleChildIndex
) )
527 uno::Any
aAny( xSel
->getSelection() );
528 uno::Reference
< drawing::XShapes
> xShapes
;
534 AccessibleShape
* pAcc
= AccessibleShape::getImplementation( getAccessibleChild( nAccessibleChildIndex
) );
538 uno::Reference
< drawing::XShape
> xShape( pAcc
->GetXShape() );
542 for( sal_Int32 i
= 0, nCount
= xShapes
->getCount(); ( i
< nCount
) && !bRet
; ++i
)
543 if( xShapes
->getByIndex( i
) == xShape
)
556 /** Select or delselect the specified shapes. The corresponding accessible
557 shapes are notified over the selection change listeners registered with
558 the XSelectionSupplier of the controller.
561 AccessibleDrawDocumentView::implSelect( sal_Int32 nAccessibleChildIndex
, sal_Bool bSelect
)
562 throw (lang::IndexOutOfBoundsException
, uno::RuntimeException
)
564 const vos::OGuard
aSolarGuard( Application::GetSolarMutex() );
565 uno::Reference
< view::XSelectionSupplier
> xSel( mxController
, uno::UNO_QUERY
);
566 AccessibleShape
* pAccessibleChild
;
572 if( ACCESSIBLE_SELECTION_CHILD_ALL
== nAccessibleChildIndex
)
574 // Select or deselect all children.
577 xSel
->select( aAny
);
580 uno::Reference
< drawing::XShapes
> xShapes( new SvxShapeCollection() );
582 for(sal_Int32 i
= 0, nCount
= getAccessibleChildCount(); i
< nCount
; ++i
)
584 AccessibleShape
* pAcc
= AccessibleShape::getImplementation( getAccessibleChild( i
) );
586 if( pAcc
&& pAcc
->GetXShape().is() )
588 xShapes
->add( pAcc
->GetXShape() );
589 pAccessibleChild
= pAcc
;
593 if( xShapes
->getCount() )
596 xSel
->select( aAny
);
600 else if( nAccessibleChildIndex
>= 0 )
602 // Select or deselect only the child with index
603 // nAccessibleChildIndex.
605 AccessibleShape
* pAcc
= AccessibleShape::getImplementation(
606 getAccessibleChild( nAccessibleChildIndex
));
607 pAccessibleChild
= pAcc
;
609 // Add or remove the shape that is made accessible from the
610 // selection of the controller.
613 uno::Reference
< drawing::XShape
> xShape( pAcc
->GetXShape() );
617 uno::Reference
< drawing::XShapes
> xShapes
;
618 sal_Bool bFound
= sal_False
;
620 aAny
= xSel
->getSelection();
623 // Search shape to be selected in current selection.
626 sal_Int32 nCount
= xShapes
->getCount();
627 for (sal_Int32 i
=0; ( i
< nCount
) && !bFound
; ++i
)
628 if( xShapes
->getByIndex( i
) == xShape
)
632 // Create an empty selection to add the shape to.
633 xShapes
= new SvxShapeCollection();
635 // Update the selection.
636 if( !bFound
&& bSelect
)
637 xShapes
->add( xShape
);
638 else if( bFound
&& !bSelect
)
639 xShapes
->remove( xShape
);
642 xSel
->select( aAny
);
652 void AccessibleDrawDocumentView::Activated (void)
654 if (mpChildrenManager
!= NULL
)
656 mpChildrenManager
->UpdateSelection();
657 // When none of the children has the focus then claim it for the
659 if ( ! mpChildrenManager
->HasFocus())
660 SetState (AccessibleStateType::FOCUSED
);
662 ResetState (AccessibleStateType::FOCUSED
);
669 void AccessibleDrawDocumentView::Deactivated (void)
671 if (mpChildrenManager
!= NULL
)
672 mpChildrenManager
->RemoveFocus();
673 ResetState (AccessibleStateType::FOCUSED
);
679 void AccessibleDrawDocumentView::impl_dispose (void)
681 if (mpChildrenManager
!= NULL
)
683 delete mpChildrenManager
;
684 mpChildrenManager
= NULL
;
687 AccessibleDocumentViewBase::impl_dispose();
692 /** This method is called from the component helper base class while
695 void SAL_CALL
AccessibleDrawDocumentView::disposing (void)
698 // Release resources.
699 if (mpChildrenManager
!= NULL
)
701 delete mpChildrenManager
;
702 mpChildrenManager
= NULL
;
705 // Forward call to base classes.
706 AccessibleDocumentViewBase::disposing ();
712 void AccessibleDrawDocumentView::UpdateAccessibleName (void)
714 OUString
sNewName (CreateAccessibleName());
715 sNewName
+= A2S(": ");
717 // Add the number of the current slide.
718 uno::Reference
<drawing::XDrawView
> xView (mxController
, uno::UNO_QUERY
);
721 uno::Reference
<beans::XPropertySet
> xProperties (xView
->getCurrentPage(), UNO_QUERY
);
722 if (xProperties
.is())
725 sal_Int16
nPageNumber (0);
726 if (xProperties
->getPropertyValue(A2S("Number")) >>= nPageNumber
)
728 sNewName
+= OUString::valueOf(sal_Int32(nPageNumber
));
731 catch (beans::UnknownPropertyException
&)
736 // Add the number of pages/slides.
737 Reference
<drawing::XDrawPagesSupplier
> xPagesSupplier (mxModel
, UNO_QUERY
);
738 if (xPagesSupplier
.is())
740 Reference
<container::XIndexAccess
> xPages (xPagesSupplier
->getDrawPages(), UNO_QUERY
);
743 sNewName
+= A2S(" / ");
744 sNewName
+= OUString::valueOf(xPages
->getCount());
748 SetAccessibleName (sNewName
, AutomaticallyCreated
);
754 } // end of namespace accessibility