1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "AccessibleDrawDocumentView.hxx"
21 #include <com/sun/star/drawing/XDrawPage.hpp>
22 #include <com/sun/star/drawing/XDrawView.hpp>
23 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
24 #include <com/sun/star/drawing/XShapes.hpp>
25 #include <com/sun/star/container/XChild.hpp>
26 #include <com/sun/star/frame/XController.hpp>
27 #include <com/sun/star/frame/XFrame.hpp>
28 #include <com/sun/star/document/XEventBroadcaster.hpp>
29 #include <com/sun/star/beans/XPropertySet.hpp>
30 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
31 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
32 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
33 #include <rtl/ustring.h>
34 #include<sfx2/viewfrm.hxx>
36 #include <svx/AccessibleShape.hxx>
38 #include <svx/svdobj.hxx>
39 #include <svx/svdmodel.hxx>
40 #include <svx/unoapi.hxx>
41 #include <svx/unoshcol.hxx>
42 #include <toolkit/helper/vclunohelper.hxx>
44 #include <vcl/svapp.hxx>
47 #include "ViewShell.hxx"
51 #include "accessibility.hrc"
52 #include "sdresid.hxx"
53 #include <osl/mutex.hxx>
55 using namespace ::com::sun::star
;
56 using namespace ::com::sun::star::uno
;
57 using namespace ::com::sun::star::accessibility
;
59 namespace accessibility
{
62 //===== internal ============================================================
64 AccessibleDrawDocumentView::AccessibleDrawDocumentView (
65 ::sd::Window
* pSdWindow
,
66 ::sd::ViewShell
* pViewShell
,
67 const uno::Reference
<frame::XController
>& rxController
,
68 const uno::Reference
<XAccessible
>& rxParent
)
69 : AccessibleDocumentViewBase (pSdWindow
, pViewShell
, rxController
, rxParent
),
70 mpChildrenManager (NULL
)
72 OSL_TRACE ("AccessibleDrawDocumentView");
73 UpdateAccessibleName();
79 AccessibleDrawDocumentView::~AccessibleDrawDocumentView (void)
81 OSL_TRACE ("~AccessibleDrawDocumentView");
82 DBG_ASSERT (rBHelper
.bDisposed
|| rBHelper
.bInDispose
,
83 "~AccessibleDrawDocumentView: object has not been disposed");
89 void AccessibleDrawDocumentView::Init (void)
91 AccessibleDocumentViewBase::Init ();
93 // Determine the list of shapes on the current page.
94 uno::Reference
<drawing::XShapes
> xShapeList
;
95 uno::Reference
<drawing::XDrawView
> xView (mxController
, uno::UNO_QUERY
);
97 xShapeList
= uno::Reference
<drawing::XShapes
> (
98 xView
->getCurrentPage(), uno::UNO_QUERY
);
100 // Create the children manager.
101 mpChildrenManager
= new ChildrenManager(this, xShapeList
, maShapeTreeInfo
, *this);
102 if (mpChildrenManager
!= NULL
)
104 // Create the page shape and initialize it. The shape is acquired
105 // before initialization and released after transferring ownership
106 // to the children manager to prevent premature disposing of the
108 AccessiblePageShape
* pPage
= CreateDrawPageShape();
113 mpChildrenManager
->AddAccessibleShape (
114 std::auto_ptr
<AccessibleShape
>(pPage
));
116 mpChildrenManager
->Update ();
118 mpChildrenManager
->UpdateSelection ();
125 void AccessibleDrawDocumentView::ViewForwarderChanged (ChangeType aChangeType
,
126 const IAccessibleViewForwarder
* pViewForwarder
)
128 AccessibleDocumentViewBase::ViewForwarderChanged (aChangeType
, pViewForwarder
);
129 if (mpChildrenManager
!= NULL
)
130 mpChildrenManager
->ViewForwarderChanged (aChangeType
, pViewForwarder
);
136 /** The page shape is created on every call at the moment (provided that
137 every thing goes well).
139 AccessiblePageShape
* AccessibleDrawDocumentView::CreateDrawPageShape (void)
141 AccessiblePageShape
* pShape
= NULL
;
143 // Create a shape that represents the actual draw page.
144 uno::Reference
<drawing::XDrawView
> xView (mxController
, uno::UNO_QUERY
);
147 uno::Reference
<beans::XPropertySet
> xSet (
148 uno::Reference
<beans::XPropertySet
> (xView
->getCurrentPage(), uno::UNO_QUERY
));
151 // Create a rectangle shape that will represent the draw page.
152 uno::Reference
<lang::XMultiServiceFactory
> xFactory (mxModel
, uno::UNO_QUERY
);
153 uno::Reference
<drawing::XShape
> xRectangle
;
155 xRectangle
= uno::Reference
<drawing::XShape
>(xFactory
->createInstance ("com.sun.star.drawing.RectangleShape"),
158 // Set the shape's size and position.
162 awt::Point aPosition
;
165 // Set size and position of the shape to those of the draw
167 aValue
= xSet
->getPropertyValue ("BorderLeft");
168 aValue
>>= aPosition
.X
;
169 aValue
= xSet
->getPropertyValue ("BorderTop");
170 aValue
>>= aPosition
.Y
;
171 xRectangle
->setPosition (aPosition
);
173 aValue
= xSet
->getPropertyValue ("Width");
174 aValue
>>= aSize
.Width
;
175 aValue
= xSet
->getPropertyValue ("Height");
176 aValue
>>= aSize
.Height
;
177 xRectangle
->setSize (aSize
);
179 // Create the accessible object for the shape and
181 pShape
= new AccessiblePageShape (
182 xView
->getCurrentPage(), this, maShapeTreeInfo
);
192 //===== XAccessibleContext ==================================================
195 AccessibleDrawDocumentView::getAccessibleChildCount (void)
196 throw (uno::RuntimeException
)
200 long mpChildCount
= AccessibleDocumentViewBase::getAccessibleChildCount();
202 // Forward request to children manager.
203 if (mpChildrenManager
!= NULL
)
204 mpChildCount
+= mpChildrenManager
->GetChildCount ();
212 uno::Reference
<XAccessible
> SAL_CALL
213 AccessibleDrawDocumentView::getAccessibleChild (sal_Int32 nIndex
)
214 throw (uno::RuntimeException
, lang::IndexOutOfBoundsException
)
218 ::osl::ClearableMutexGuard
aGuard (maMutex
);
220 // Take care of children of the base class.
221 sal_Int32 nCount
= AccessibleDocumentViewBase::getAccessibleChildCount();
225 return AccessibleDocumentViewBase::getAccessibleChild(nIndex
);
230 // Create a copy of the pointer to the children manager and release the
231 // mutex before calling any of its methods.
232 ChildrenManager
* pChildrenManager
= mpChildrenManager
;
235 // Forward request to children manager.
236 if (pChildrenManager
!= NULL
)
238 return pChildrenManager
->GetChild (nIndex
);
241 throw lang::IndexOutOfBoundsException (
242 "no accessible child with index " + OUString::valueOf(nIndex
),
243 static_cast<uno::XWeak
*>(this));
249 //===== XEventListener ======================================================
252 AccessibleDrawDocumentView::disposing (const lang::EventObject
& rEventObject
)
253 throw (::com::sun::star::uno::RuntimeException
)
257 AccessibleDocumentViewBase::disposing (rEventObject
);
258 if (rEventObject
.Source
== mxModel
)
260 ::osl::Guard
< ::osl::Mutex
> aGuard (::osl::Mutex::getGlobalMutex());
261 // maShapeTreeInfo has been modified in base class.
262 if (mpChildrenManager
!= NULL
)
263 mpChildrenManager
->SetInfo (maShapeTreeInfo
);
270 //===== XPropertyChangeListener =============================================
273 AccessibleDrawDocumentView::propertyChange (const beans::PropertyChangeEvent
& rEventObject
)
274 throw (::com::sun::star::uno::RuntimeException
)
278 AccessibleDocumentViewBase::propertyChange (rEventObject
);
280 OSL_TRACE ("AccessibleDrawDocumentView::propertyChange");
281 if ( rEventObject
.PropertyName
== "CurrentPage" )
283 OSL_TRACE (" current page changed");
285 // Update the accessible name to reflect the current slide.
286 UpdateAccessibleName();
288 // The current page changed. Update the children manager accordingly.
289 uno::Reference
<drawing::XDrawView
> xView (mxController
, uno::UNO_QUERY
);
290 if (xView
.is() && mpChildrenManager
!=NULL
)
292 // Inform the children manager to forget all children and give
294 mpChildrenManager
->ClearAccessibleShapeList ();
295 mpChildrenManager
->SetShapeList (uno::Reference
<drawing::XShapes
> (
296 xView
->getCurrentPage(), uno::UNO_QUERY
));
298 // Create the page shape and initialize it. The shape is
299 // acquired before initialization and released after
300 // transferring ownership to the children manager to prevent
301 // premature disposing of the shape.
302 AccessiblePageShape
* pPage
= CreateDrawPageShape ();
307 mpChildrenManager
->AddAccessibleShape (
308 std::auto_ptr
<AccessibleShape
>(pPage
));
309 mpChildrenManager
->Update (false);
314 OSL_TRACE ("View invalid");
316 else if ( rEventObject
.PropertyName
== "VisibleArea" )
318 OSL_TRACE (" visible area changed");
319 if (mpChildrenManager
!= NULL
)
320 mpChildrenManager
->ViewForwarderChanged (
321 IAccessibleViewForwarderListener::VISIBLE_AREA
,
326 OSL_TRACE (" unhandled");
333 //===== XServiceInfo ========================================================
336 AccessibleDrawDocumentView::getImplementationName (void)
337 throw (::com::sun::star::uno::RuntimeException
)
339 return OUString("AccessibleDrawDocumentView");
345 ::com::sun::star::uno::Sequence
< OUString
> SAL_CALL
346 AccessibleDrawDocumentView::getSupportedServiceNames (void)
347 throw (::com::sun::star::uno::RuntimeException
)
350 // Get list of supported service names from base class...
351 uno::Sequence
<OUString
> aServiceNames
=
352 AccessibleDocumentViewBase::getSupportedServiceNames();
353 sal_Int32
nCount (aServiceNames
.getLength());
355 // ...and add additional names.
356 aServiceNames
.realloc (nCount
+ 1);
357 static const OUString
sAdditionalServiceName ("com.sun.star.drawing.AccessibleDrawDocumentView");
358 aServiceNames
[nCount
] = sAdditionalServiceName
;
360 return aServiceNames
;
366 /// Create a name for this view.
368 AccessibleDrawDocumentView::CreateAccessibleName (void)
369 throw (::com::sun::star::uno::RuntimeException
)
373 uno::Reference
<lang::XServiceInfo
> xInfo (mxController
, uno::UNO_QUERY
);
376 uno::Sequence
< OUString
> aServices( xInfo
->getSupportedServiceNames() );
377 OUString sFirstService
= aServices
[0];
378 if ( sFirstService
== "com.sun.star.drawing.DrawingDocumentDrawView" )
380 if( aServices
.getLength() >= 2 && aServices
[1] == "com.sun.star.presentation.PresentationView")
382 SolarMutexGuard aGuard
;
384 sName
= SD_RESSTR(SID_SD_A11Y_I_DRAWVIEW_N
);
388 SolarMutexGuard aGuard
;
390 sName
= SD_RESSTR(SID_SD_A11Y_D_DRAWVIEW_N
);
393 else if ( sFirstService
== "com.sun.star.presentation.NotesView" )
395 SolarMutexGuard aGuard
;
397 sName
= SD_RESSTR(SID_SD_A11Y_I_NOTESVIEW_N
);
399 else if ( sFirstService
== "com.sun.star.presentation.HandoutView" )
401 SolarMutexGuard aGuard
;
403 sName
= SD_RESSTR(SID_SD_A11Y_I_HANDOUTVIEW_N
);
407 sName
= sFirstService
;
412 sName
= "AccessibleDrawDocumentView";
420 /** Create a description for this view. Use the model's description or URL
421 if a description is not available.
424 AccessibleDrawDocumentView::CreateAccessibleDescription (void)
425 throw (::com::sun::star::uno::RuntimeException
)
427 OUString sDescription
;
429 uno::Reference
<lang::XServiceInfo
> xInfo (mxController
, uno::UNO_QUERY
);
432 uno::Sequence
< OUString
> aServices( xInfo
->getSupportedServiceNames() );
433 OUString sFirstService
= aServices
[0];
434 if ( sFirstService
== "com.sun.star.drawing.DrawingDocumentDrawView" )
436 if( aServices
.getLength() >= 2 && aServices
[1] == "com.sun.star.presentation.PresentationView")
438 SolarMutexGuard aGuard
;
440 sDescription
= SD_RESSTR(SID_SD_A11Y_I_DRAWVIEW_D
);
444 SolarMutexGuard aGuard
;
446 sDescription
= SD_RESSTR(SID_SD_A11Y_D_DRAWVIEW_D
);
449 else if ( sFirstService
== "com.sun.star.presentation.NotesView" )
451 SolarMutexGuard aGuard
;
453 sDescription
= SD_RESSTR(SID_SD_A11Y_I_NOTESVIEW_D
);
455 else if ( sFirstService
== "com.sun.star.presentation.HandoutView" )
457 SolarMutexGuard aGuard
;
459 sDescription
= SD_RESSTR(SID_SD_A11Y_I_HANDOUTVIEW_D
);
463 sDescription
= sFirstService
;
468 sDescription
= "Accessible Draw Document";
476 /** Return selection state of specified child
479 AccessibleDrawDocumentView::implIsSelected( sal_Int32 nAccessibleChildIndex
)
480 throw (uno::RuntimeException
)
482 const SolarMutexGuard aSolarGuard
;
483 uno::Reference
< view::XSelectionSupplier
> xSel( mxController
, uno::UNO_QUERY
);
484 sal_Bool bRet
= sal_False
;
486 OSL_ENSURE( 0 <= nAccessibleChildIndex
, "AccessibleDrawDocumentView::implIsSelected: invalid index!" );
488 if( xSel
.is() && ( 0 <= nAccessibleChildIndex
) )
490 uno::Any
aAny( xSel
->getSelection() );
491 uno::Reference
< drawing::XShapes
> xShapes
;
497 AccessibleShape
* pAcc
= AccessibleShape::getImplementation( getAccessibleChild( nAccessibleChildIndex
) );
501 uno::Reference
< drawing::XShape
> xShape( pAcc
->GetXShape() );
505 for( sal_Int32 i
= 0, nCount
= xShapes
->getCount(); ( i
< nCount
) && !bRet
; ++i
)
506 if( xShapes
->getByIndex( i
) == xShape
)
519 /** Select or delselect the specified shapes. The corresponding accessible
520 shapes are notified over the selection change listeners registered with
521 the XSelectionSupplier of the controller.
524 AccessibleDrawDocumentView::implSelect( sal_Int32 nAccessibleChildIndex
, sal_Bool bSelect
)
525 throw (lang::IndexOutOfBoundsException
, uno::RuntimeException
)
527 const SolarMutexGuard aSolarGuard
;
528 uno::Reference
< view::XSelectionSupplier
> xSel( mxController
, uno::UNO_QUERY
);
534 if( ACCESSIBLE_SELECTION_CHILD_ALL
== nAccessibleChildIndex
)
536 // Select or deselect all children.
539 xSel
->select( aAny
);
542 uno::Reference
< drawing::XShapes
> xShapes( new SvxShapeCollection() );
544 for(sal_Int32 i
= 0, nCount
= getAccessibleChildCount(); i
< nCount
; ++i
)
546 AccessibleShape
* pAcc
= AccessibleShape::getImplementation( getAccessibleChild( i
) );
548 if( pAcc
&& pAcc
->GetXShape().is() )
549 xShapes
->add( pAcc
->GetXShape() );
552 if( xShapes
->getCount() )
555 xSel
->select( aAny
);
559 else if( nAccessibleChildIndex
>= 0 )
561 // Select or deselect only the child with index
562 // nAccessibleChildIndex.
564 AccessibleShape
* pAcc
= AccessibleShape::getImplementation(
565 getAccessibleChild( nAccessibleChildIndex
));
567 // Add or remove the shape that is made accessible from the
568 // selection of the controller.
571 uno::Reference
< drawing::XShape
> xShape( pAcc
->GetXShape() );
575 uno::Reference
< drawing::XShapes
> xShapes
;
576 sal_Bool bFound
= sal_False
;
578 aAny
= xSel
->getSelection();
581 // Search shape to be selected in current selection.
584 sal_Int32 nCount
= xShapes
->getCount();
585 for (sal_Int32 i
=0; ( i
< nCount
) && !bFound
; ++i
)
586 if( xShapes
->getByIndex( i
) == xShape
)
590 // Create an empty selection to add the shape to.
591 xShapes
= new SvxShapeCollection();
593 // Update the selection.
594 if( !bFound
&& bSelect
)
595 xShapes
->add( xShape
);
596 else if( bFound
&& !bSelect
)
597 xShapes
->remove( xShape
);
600 xSel
->select( aAny
);
610 void AccessibleDrawDocumentView::Activated (void)
612 if (mpChildrenManager
!= NULL
)
614 mpChildrenManager
->UpdateSelection();
615 // When none of the children has the focus then claim it for the
617 if ( ! mpChildrenManager
->HasFocus())
618 SetState (AccessibleStateType::FOCUSED
);
620 ResetState (AccessibleStateType::FOCUSED
);
627 void AccessibleDrawDocumentView::Deactivated (void)
629 if (mpChildrenManager
!= NULL
)
630 mpChildrenManager
->RemoveFocus();
631 ResetState (AccessibleStateType::FOCUSED
);
637 void AccessibleDrawDocumentView::impl_dispose (void)
639 if (mpChildrenManager
!= NULL
)
641 delete mpChildrenManager
;
642 mpChildrenManager
= NULL
;
645 AccessibleDocumentViewBase::impl_dispose();
650 /** This method is called from the component helper base class while
653 void SAL_CALL
AccessibleDrawDocumentView::disposing (void)
656 // Release resources.
657 if (mpChildrenManager
!= NULL
)
659 delete mpChildrenManager
;
660 mpChildrenManager
= NULL
;
663 // Forward call to base classes.
664 AccessibleDocumentViewBase::disposing ();
670 void AccessibleDrawDocumentView::UpdateAccessibleName (void)
672 OUString
sNewName (CreateAccessibleName());
675 // Add the number of the current slide.
676 uno::Reference
<drawing::XDrawView
> xView (mxController
, uno::UNO_QUERY
);
679 uno::Reference
<beans::XPropertySet
> xProperties (xView
->getCurrentPage(), UNO_QUERY
);
680 if (xProperties
.is())
683 sal_Int16
nPageNumber (0);
684 if (xProperties
->getPropertyValue("Number") >>= nPageNumber
)
686 sNewName
+= OUString::valueOf(sal_Int32(nPageNumber
));
689 catch (beans::UnknownPropertyException
&)
694 // Add the number of pages/slides.
695 Reference
<drawing::XDrawPagesSupplier
> xPagesSupplier (mxModel
, UNO_QUERY
);
696 if (xPagesSupplier
.is())
698 Reference
<container::XIndexAccess
> xPages (xPagesSupplier
->getDrawPages(), UNO_QUERY
);
702 sNewName
+= OUString::valueOf(xPages
->getCount());
706 SetAccessibleName (sNewName
, AutomaticallyCreated
);
709 } // end of namespace accessibility
711 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */