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: AccessibleShape.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_svx.hxx"
33 #include <svx/AccessibleShape.hxx>
34 #include "DescriptionGenerator.hxx"
35 #include <svx/AccessibleShapeInfo.hxx>
36 #include <com/sun/star/view/XSelectionSupplier.hpp>
38 #ifndef _COM_SUN_STAR_ACCESSIBILITY_ACCESSIBLE_ROLE_HPP_
39 #include <com/sun/star/accessibility/AccessibleRole.hpp>
41 #ifndef _COM_SUN_STAR_ACCESSIBILITY_ACCESSIBLE_STATE_TYPE_HPP_
42 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
44 #include <com/sun/star/beans/XPropertySet.hpp>
45 #include <com/sun/star/container/XChild.hpp>
46 #include <com/sun/star/drawing/XShapes.hpp>
47 #include <com/sun/star/drawing/XShapeDescriptor.hpp>
48 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
49 #include <com/sun/star/drawing/FillStyle.hpp>
50 #include <com/sun/star/text/XText.hpp>
51 #include <svx/outlobj.hxx>
52 #include <rtl/ref.hxx>
53 #include <svx/unoedsrc.hxx>
54 #include <svx/unoshtxt.hxx>
55 #include <svx/svdobj.hxx>
56 #include <svx/svdmodel.hxx>
58 #include <com/sun/star/uno/Exception.hpp>
59 #include <svx/ShapeTypeHandler.hxx>
60 #include <svx/SvxShapeTypes.hxx>
62 #ifndef _SVX_ACCESSIBILITY_HRC
63 #include "accessibility.hrc"
66 #include <svx/dialmgr.hxx>
67 #include <vcl/svapp.hxx>
68 #include <unotools/accessiblestatesethelper.hxx>
69 #include <svx/svdview.hxx>
70 #include "AccessibleEmptyEditSource.hxx"
72 using namespace ::com::sun::star
;
73 using namespace ::com::sun::star::accessibility
;
74 using ::com::sun::star::uno::Reference
;
75 using ::rtl::OUString
;
77 namespace accessibility
{
81 OUString
GetOptionalProperty (
82 const Reference
<beans::XPropertySet
>& rxSet
,
83 const OUString
& rsPropertyName
)
89 const Reference
<beans::XPropertySetInfo
> xInfo (rxSet
->getPropertySetInfo());
90 if ( ! xInfo
.is() || xInfo
->hasPropertyByName(rsPropertyName
))
94 rxSet
->getPropertyValue(rsPropertyName
) >>= sValue
;
96 catch (beans::UnknownPropertyException
&)
98 // This exception should only be thrown when the property
99 // does not exits (of course) and the XPropertySetInfo is
107 } // end of anonymous namespace
112 //===== internal ============================================================
114 AccessibleShape::AccessibleShape (
115 const AccessibleShapeInfo
& rShapeInfo
,
116 const AccessibleShapeTreeInfo
& rShapeTreeInfo
)
117 : AccessibleContextBase (rShapeInfo
.mxParent
,AccessibleRole::LIST_ITEM
),
118 mpChildrenManager(NULL
),
119 mxShape (rShapeInfo
.mxShape
),
120 maShapeTreeInfo (rShapeTreeInfo
),
121 mnIndex (rShapeInfo
.mnIndex
),
122 m_nIndexInParent(-1),
124 mpParent (rShapeInfo
.mpChildrenManager
)
126 m_pShape
= GetSdrObjectFromXShape(mxShape
);
127 UpdateNameAndDescription();
133 AccessibleShape::~AccessibleShape (void)
135 if (mpChildrenManager
!= NULL
)
136 delete mpChildrenManager
;
139 OSL_TRACE ("~AccessibleShape");
141 // Unregistering from the various broadcasters should be unnecessary
142 // since this destructor would not have been called if one of the
143 // broadcasters would still hold a strong reference to this object.
149 void AccessibleShape::Init (void)
151 // Update the OPAQUE and SELECTED shape.
154 // Create a children manager when this shape has children of its own.
155 Reference
<drawing::XShapes
> xShapes (mxShape
, uno::UNO_QUERY
);
156 if (xShapes
.is() && xShapes
->getCount() > 0)
157 mpChildrenManager
= new ChildrenManager (
158 this, xShapes
, maShapeTreeInfo
, *this);
159 if (mpChildrenManager
!= NULL
)
160 mpChildrenManager
->Update();
162 // Register at model as document::XEventListener.
163 if (maShapeTreeInfo
.GetModelBroadcaster().is())
164 maShapeTreeInfo
.GetModelBroadcaster()->addEventListener (
165 static_cast<document::XEventListener
*>(this));
167 // Beware! Here we leave the paths of the UNO API and descend into the
168 // depths of the core. Necessary for makeing the edit engine
170 Reference
<text::XText
> xText (mxShape
, uno::UNO_QUERY
);
173 SdrView
* pView
= maShapeTreeInfo
.GetSdrView ();
174 const Window
* pWindow
= maShapeTreeInfo
.GetWindow ();
175 if (pView
!= NULL
&& pWindow
!= NULL
&& mxShape
.is())
177 // #107948# Determine whether shape text is empty
178 SdrObject
* pSdrObject
= GetSdrObjectFromXShape(mxShape
);
181 SdrTextObj
* pTextObj
= PTR_CAST( SdrTextObj
, pSdrObject
);
182 OutlinerParaObject
* pOutlinerParaObject
= NULL
;
185 pOutlinerParaObject
= pTextObj
->GetEditOutlinerParaObject(); // Get the OutlinerParaObject if text edit is active
187 bool bOwnParaObj
= pOutlinerParaObject
!= NULL
;
189 if( !pOutlinerParaObject
&& pSdrObject
)
190 pOutlinerParaObject
= pSdrObject
->GetOutlinerParaObject();
192 // create AccessibleTextHelper to handle this shape's text
193 if( !pOutlinerParaObject
)
195 // empty text -> use proxy edit source to delay creation of EditEngine
196 ::std::auto_ptr
<SvxEditSource
> pEditSource( new AccessibleEmptyEditSource ( *pSdrObject
, *pView
, *pWindow
) );
197 mpText
= new AccessibleTextHelper( pEditSource
);
201 // non-empty text -> use full-fledged edit source right away
202 ::std::auto_ptr
<SvxEditSource
> pEditSource( new SvxTextEditSource ( *pSdrObject
, 0, *pView
, *pWindow
) );
203 mpText
= new AccessibleTextHelper( pEditSource
);
207 delete pOutlinerParaObject
;
209 mpText
->SetEventSource(this);
218 void AccessibleShape::UpdateStates (void)
220 ::utl::AccessibleStateSetHelper
* pStateSet
=
221 static_cast< ::utl::AccessibleStateSetHelper
*>(mxStateSet
.get());
222 if (pStateSet
== NULL
)
225 // Set the opaque state for certain shape types when their fill style is
227 bool bShapeIsOpaque
= false;
228 switch (ShapeTypeHandler::Instance().GetTypeId (mxShape
))
231 case DRAWING_RECTANGLE
:
234 uno::Reference
<beans::XPropertySet
> xSet (mxShape
, uno::UNO_QUERY
);
239 drawing::FillStyle aFillStyle
;
240 bShapeIsOpaque
= ( xSet
->getPropertyValue (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FillStyle"))) >>= aFillStyle
)
241 && aFillStyle
== drawing::FillStyle_SOLID
;
243 catch (::com::sun::star::beans::UnknownPropertyException
&)
251 pStateSet
->AddState (AccessibleStateType::OPAQUE
);
253 pStateSet
->RemoveState (AccessibleStateType::OPAQUE
);
255 // Set the selected state.
256 bool bShapeIsSelected
= false;
257 // XXX fix_me this has to be done with an extra interface later on
258 if ( m_pShape
&& maShapeTreeInfo
.GetSdrView() )
260 bShapeIsSelected
= maShapeTreeInfo
.GetSdrView()->IsObjMarked(m_pShape
) == TRUE
;
263 if (bShapeIsSelected
)
264 pStateSet
->AddState (AccessibleStateType::SELECTED
);
266 pStateSet
->RemoveState (AccessibleStateType::SELECTED
);
272 bool AccessibleShape::operator== (const AccessibleShape
& rShape
)
274 return this==&rShape
;
280 sal_Bool
AccessibleShape::SetState (sal_Int16 aState
)
282 sal_Bool bStateHasChanged
= sal_False
;
284 if (aState
== AccessibleStateType::FOCUSED
&& mpText
!= NULL
)
286 // Offer FOCUSED state to edit engine and detect whether the state
288 sal_Bool bIsFocused
= mpText
->HaveFocus ();
289 mpText
->SetFocus (sal_True
);
290 bStateHasChanged
= (bIsFocused
!= mpText
->HaveFocus ());
293 bStateHasChanged
= AccessibleContextBase::SetState (aState
);
295 return bStateHasChanged
;
301 sal_Bool
AccessibleShape::ResetState (sal_Int16 aState
)
303 sal_Bool bStateHasChanged
= sal_False
;
305 if (aState
== AccessibleStateType::FOCUSED
&& mpText
!= NULL
)
307 // Try to remove FOCUSED state from the edit engine and detect
308 // whether the state changes.
309 sal_Bool bIsFocused
= mpText
->HaveFocus ();
310 mpText
->SetFocus (sal_False
);
311 bStateHasChanged
= (bIsFocused
!= mpText
->HaveFocus ());
314 bStateHasChanged
= AccessibleContextBase::ResetState (aState
);
316 return bStateHasChanged
;
322 sal_Bool
AccessibleShape::GetState (sal_Int16 aState
)
324 if (aState
== AccessibleStateType::FOCUSED
&& mpText
!= NULL
)
326 // Just delegate the call to the edit engine. The state is not
327 // merged into the state set.
328 return mpText
->HaveFocus();
331 return AccessibleContextBase::GetState (aState
);
337 //===== XAccessibleContext ==================================================
339 /** The children of this shape come from two sources: The children from
340 group or scene shapes and the paragraphs of text.
343 AccessibleShape::getAccessibleChildCount ()
344 throw (::com::sun::star::uno::RuntimeException
)
347 sal_Int32 nChildCount
= 0;
349 // Add the number of shapes that are children of this shape.
350 if (mpChildrenManager
!= NULL
)
351 nChildCount
+= mpChildrenManager
->GetChildCount ();
352 // Add the number text paragraphs.
354 nChildCount
+= mpText
->GetChildCount ();
362 /** Forward the request to the shape. Return the requested shape or throw
363 an exception for a wrong index.
365 uno::Reference
<XAccessible
> SAL_CALL
366 AccessibleShape::getAccessibleChild (sal_Int32 nIndex
)
367 throw (::com::sun::star::lang::IndexOutOfBoundsException
, ::com::sun::star::uno::RuntimeException
)
371 uno::Reference
<XAccessible
> xChild
;
373 // Depending on the index decide whether to delegate this call to the
374 // children manager or the edit engine.
375 if ((mpChildrenManager
!= NULL
)
376 && (nIndex
< mpChildrenManager
->GetChildCount()))
378 xChild
= mpChildrenManager
->GetChild (nIndex
);
380 else if (mpText
!= NULL
)
382 sal_Int32 nI
= nIndex
;
383 if (mpChildrenManager
!= NULL
)
384 nI
-= mpChildrenManager
->GetChildCount();
385 xChild
= mpText
->GetChild (nI
);
388 throw lang::IndexOutOfBoundsException (
389 ::rtl::OUString::createFromAscii ("shape has no child with index ")
390 + rtl::OUString::valueOf(nIndex
),
391 static_cast<uno::XWeak
*>(this));
399 /** Return a copy of the state set.
405 uno::Reference
<XAccessibleStateSet
> SAL_CALL
406 AccessibleShape::getAccessibleStateSet (void)
407 throw (::com::sun::star::uno::RuntimeException
)
409 ::osl::MutexGuard
aGuard (maMutex
);
410 Reference
<XAccessibleStateSet
> xStateSet
;
412 if (rBHelper
.bDisposed
|| mpText
== NULL
)
413 // Return a minimal state set that only contains the DEFUNC state.
414 xStateSet
= AccessibleContextBase::getAccessibleStateSet ();
417 ::utl::AccessibleStateSetHelper
* pStateSet
=
418 static_cast< ::utl::AccessibleStateSetHelper
*>(mxStateSet
.get());
420 if (pStateSet
!= NULL
)
422 // Merge current FOCUSED state from edit engine.
425 if (mpText
->HaveFocus())
426 pStateSet
->AddState (AccessibleStateType::FOCUSED
);
428 pStateSet
->RemoveState (AccessibleStateType::FOCUSED
);
431 // Create a copy of the state set that may be modified by the
432 // caller without affecting the current state set.
433 xStateSet
= Reference
<XAccessibleStateSet
>(
434 new ::utl::AccessibleStateSetHelper (*pStateSet
));
444 //===== XAccessibleComponent ================================================
446 /** The implementation below is at the moment straightforward. It iterates
447 over all children (and thereby instances all children which have not
448 been already instatiated) until a child covering the specifed point is
450 This leaves room for improvement. For instance, first iterate only over
451 the already instantiated children and only if no match is found
452 instantiate the remaining ones.
454 uno::Reference
<XAccessible
> SAL_CALL
455 AccessibleShape::getAccessibleAtPoint (
456 const awt::Point
& aPoint
)
457 throw (uno::RuntimeException
)
459 ::osl::MutexGuard
aGuard (maMutex
);
461 sal_Int32 nChildCount
= getAccessibleChildCount ();
462 for (sal_Int32 i
=0; i
<nChildCount
; ++i
)
464 Reference
<XAccessible
> xChild (getAccessibleChild (i
));
467 Reference
<XAccessibleComponent
> xChildComponent (
468 xChild
->getAccessibleContext(), uno::UNO_QUERY
);
469 if (xChildComponent
.is())
471 awt::Rectangle
aBBox (xChildComponent
->getBounds());
472 if ( (aPoint
.X
>= aBBox
.X
)
473 && (aPoint
.Y
>= aBBox
.Y
)
474 && (aPoint
.X
< aBBox
.X
+aBBox
.Width
)
475 && (aPoint
.Y
< aBBox
.Y
+aBBox
.Height
) )
481 // Have not found a child under the given point. Returning empty
482 // reference to indicate this.
483 return uno::Reference
<XAccessible
>();
489 awt::Rectangle SAL_CALL
AccessibleShape::getBounds (void)
490 throw (::com::sun::star::uno::RuntimeException
)
492 ::vos::OGuard
aSolarGuard (::Application::GetSolarMutex());
493 ::osl::MutexGuard
aGuard (maMutex
);
496 awt::Rectangle aBoundingBox
;
500 static const OUString
sBoundRectName (
501 RTL_CONSTASCII_USTRINGPARAM("BoundRect"));
502 static const OUString
sAnchorPositionName (
503 RTL_CONSTASCII_USTRINGPARAM("AnchorPosition"));
505 // Get the shape's bounding box in internal coordinates (in 100th of
506 // mm). Use the property BoundRect. Only if that is not supported ask
507 // the shape for its position and size directly.
508 Reference
<beans::XPropertySet
> xSet (mxShape
, uno::UNO_QUERY
);
509 Reference
<beans::XPropertySetInfo
> xSetInfo
;
510 bool bFoundBoundRect
= false;
513 xSetInfo
= xSet
->getPropertySetInfo ();
516 if (xSetInfo
->hasPropertyByName (sBoundRectName
))
520 uno::Any aValue
= xSet
->getPropertyValue (sBoundRectName
);
521 aValue
>>= aBoundingBox
;
522 bFoundBoundRect
= true;
524 catch (beans::UnknownPropertyException e
)
526 // Handled below (bFoundBoundRect stays false).
530 OSL_TRACE (" no property BoundRect");
534 // Fallback when there is no BoundRect Property.
535 if ( ! bFoundBoundRect
)
537 awt::Point
aPosition (mxShape
->getPosition());
538 awt::Size
aSize (mxShape
->getSize());
539 aBoundingBox
= awt::Rectangle (
540 aPosition
.X
, aPosition
.Y
,
541 aSize
.Width
, aSize
.Height
);
543 // While BoundRects have absolute positions, the position returned
544 // by XPosition::getPosition is relative. Get the anchor position
545 // (usually not (0,0) for Writer shapes).
548 if (xSetInfo
->hasPropertyByName (sAnchorPositionName
))
550 uno::Any aPos
= xSet
->getPropertyValue (sAnchorPositionName
);
551 awt::Point aAnchorPosition
;
552 aPos
>>= aAnchorPosition
;
553 aBoundingBox
.X
+= aAnchorPosition
.X
;
554 aBoundingBox
.Y
+= aAnchorPosition
.Y
;
559 // Transform coordinates from internal to pixel.
560 if (maShapeTreeInfo
.GetViewForwarder() == NULL
)
561 throw uno::RuntimeException (::rtl::OUString (
562 RTL_CONSTASCII_USTRINGPARAM(
563 "AccessibleShape has no valid view forwarder")),
564 static_cast<uno::XWeak
*>(this));
565 ::Size aPixelSize
= maShapeTreeInfo
.GetViewForwarder()->LogicToPixel (
566 ::Size (aBoundingBox
.Width
, aBoundingBox
.Height
));
567 ::Point aPixelPosition
= maShapeTreeInfo
.GetViewForwarder()->LogicToPixel (
568 ::Point (aBoundingBox
.X
, aBoundingBox
.Y
));
570 // Clip the shape's bounding box with the bounding box of its parent.
571 Reference
<XAccessibleComponent
> xParentComponent (
572 getAccessibleParent(), uno::UNO_QUERY
);
573 if (xParentComponent
.is())
575 // Make the coordinates relative to the parent.
576 awt::Point
aParentLocation (xParentComponent
->getLocationOnScreen());
577 int x
= aPixelPosition
.getX() - aParentLocation
.X
;
578 int y
= aPixelPosition
.getY() - aParentLocation
.Y
;
580 /* // The following block is a workarround for bug #99889# (property
581 // BoundRect returnes coordinates relative to document window
582 // instead of absolute coordinates for shapes in Writer). Has to
583 // be removed as soon as bug is fixed.
585 // Use a non-null anchor position as flag that the shape is in a
588 if (xSetInfo->hasPropertyByName (sAnchorPositionName))
590 uno::Any aPos = xSet->getPropertyValue (sAnchorPositionName);
591 awt::Point aAnchorPosition;
592 aPos >>= aAnchorPosition;
593 if (aAnchorPosition.X > 0)
595 x = aPixelPosition.getX();
596 y = aPixelPosition.getY();
599 // End of workarround.
601 // Clip with parent (with coordinates relative to itself).
603 x
, y
, x
+ aPixelSize
.getWidth(), y
+ aPixelSize
.getHeight());
604 awt::Size
aParentSize (xParentComponent
->getSize());
605 ::Rectangle
aParentBBox (0,0, aParentSize
.Width
, aParentSize
.Height
);
606 aBBox
= aBBox
.GetIntersection (aParentBBox
);
607 aBoundingBox
= awt::Rectangle (
615 OSL_TRACE ("parent does not support component");
616 aBoundingBox
= awt::Rectangle (
617 aPixelPosition
.getX(), aPixelPosition
.getY(),
618 aPixelSize
.getWidth(), aPixelSize
.getHeight());
628 awt::Point SAL_CALL
AccessibleShape::getLocation (void)
629 throw (::com::sun::star::uno::RuntimeException
)
632 awt::Rectangle
aBoundingBox (getBounds());
633 return awt::Point (aBoundingBox
.X
, aBoundingBox
.Y
);
639 awt::Point SAL_CALL
AccessibleShape::getLocationOnScreen (void)
640 throw (::com::sun::star::uno::RuntimeException
)
644 // Get relative position...
645 awt::Point
aLocation (getLocation ());
647 // ... and add absolute position of the parent.
648 uno::Reference
<XAccessibleComponent
> xParentComponent (
649 getAccessibleParent(), uno::UNO_QUERY
);
650 if (xParentComponent
.is())
652 awt::Point
aParentLocation (xParentComponent
->getLocationOnScreen());
653 aLocation
.X
+= aParentLocation
.X
;
654 aLocation
.Y
+= aParentLocation
.Y
;
657 OSL_TRACE ("getLocation: parent does not support XAccessibleComponent");
664 awt::Size SAL_CALL
AccessibleShape::getSize (void)
665 throw (uno::RuntimeException
)
668 awt::Rectangle
aBoundingBox (getBounds());
669 return awt::Size (aBoundingBox
.Width
, aBoundingBox
.Height
);
675 sal_Int32 SAL_CALL
AccessibleShape::getForeground (void)
676 throw (::com::sun::star::uno::RuntimeException
)
679 sal_Int32
nColor (0x0ffffffL
);
683 uno::Reference
<beans::XPropertySet
> aSet (mxShape
, uno::UNO_QUERY
);
687 aColor
= aSet
->getPropertyValue (OUString::createFromAscii ("LineColor"));
691 catch (::com::sun::star::beans::UnknownPropertyException
)
693 // Ignore exception and return default color.
701 sal_Int32 SAL_CALL
AccessibleShape::getBackground (void)
702 throw (::com::sun::star::uno::RuntimeException
)
705 sal_Int32
nColor (0L);
709 uno::Reference
<beans::XPropertySet
> aSet (mxShape
, uno::UNO_QUERY
);
713 aColor
= aSet
->getPropertyValue (OUString::createFromAscii ("FillColor"));
717 catch (::com::sun::star::beans::UnknownPropertyException
)
719 // Ignore exception and return default color.
727 //===== XAccessibleEventBroadcaster =========================================
729 void SAL_CALL
AccessibleShape::addEventListener (
730 const Reference
<XAccessibleEventListener
>& rxListener
)
731 throw (uno::RuntimeException
)
733 if (rBHelper
.bDisposed
|| rBHelper
.bInDispose
)
735 uno::Reference
<uno::XInterface
> xThis (
736 (lang::XComponent
*)this, uno::UNO_QUERY
);
737 rxListener
->disposing (lang::EventObject (xThis
));
741 AccessibleContextBase::addEventListener (rxListener
);
743 mpText
->AddEventListener (rxListener
);
750 void SAL_CALL
AccessibleShape::removeEventListener (
751 const Reference
<XAccessibleEventListener
>& rxListener
)
752 throw (uno::RuntimeException
)
754 AccessibleContextBase::removeEventListener (rxListener
);
756 mpText
->RemoveEventListener (rxListener
);
762 //===== XInterface ==========================================================
764 com::sun::star::uno::Any SAL_CALL
765 AccessibleShape::queryInterface (const com::sun::star::uno::Type
& rType
)
766 throw (::com::sun::star::uno::RuntimeException
)
768 ::com::sun::star::uno::Any aReturn
= AccessibleContextBase::queryInterface (rType
);
769 if ( ! aReturn
.hasValue())
770 aReturn
= ::cppu::queryInterface (rType
,
771 static_cast<XAccessibleComponent
*>(this),
772 static_cast<XAccessibleExtendedComponent
*>(this),
773 static_cast<lang::XEventListener
*>(this),
774 static_cast<document::XEventListener
*>(this),
775 static_cast<lang::XUnoTunnel
*>(this)
784 AccessibleShape::acquire (void)
787 AccessibleContextBase::acquire ();
794 AccessibleShape::release (void)
797 AccessibleContextBase::release ();
803 //===== XServiceInfo ========================================================
805 ::rtl::OUString SAL_CALL
806 AccessibleShape::getImplementationName (void)
807 throw (::com::sun::star::uno::RuntimeException
)
809 return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleShape"));
815 uno::Sequence
<OUString
> SAL_CALL
816 AccessibleShape::getSupportedServiceNames (void)
817 throw (::com::sun::star::uno::RuntimeException
)
820 // Get list of supported service names from base class...
821 uno::Sequence
<OUString
> aServiceNames
=
822 AccessibleContextBase::getSupportedServiceNames();
823 sal_Int32
nCount (aServiceNames
.getLength());
825 // ...and add additional names.
826 aServiceNames
.realloc (nCount
+ 1);
827 static const OUString
sAdditionalServiceName (RTL_CONSTASCII_USTRINGPARAM(
828 "com.sun.star.drawing.AccessibleShape"));
829 aServiceNames
[nCount
] = sAdditionalServiceName
;
831 return aServiceNames
;
838 //===== XTypeProvider ===================================================
840 uno::Sequence
<uno::Type
> SAL_CALL
841 AccessibleShape::getTypes (void)
842 throw (uno::RuntimeException
)
845 // Get list of types from the context base implementation, ...
846 uno::Sequence
<uno::Type
> aTypeList (AccessibleContextBase::getTypes());
847 // ... get list of types from component base implementation, ...
848 uno::Sequence
<uno::Type
> aComponentTypeList (AccessibleComponentBase::getTypes());
849 // ... define local types, ...
850 const uno::Type aLangEventListenerType
=
851 ::getCppuType((const uno::Reference
<lang::XEventListener
>*)0);
852 const uno::Type aDocumentEventListenerType
=
853 ::getCppuType((const uno::Reference
<document::XEventListener
>*)0);
854 const uno::Type aUnoTunnelType
=
855 ::getCppuType((const uno::Reference
<lang::XUnoTunnel
>*)0);
856 // const uno::Type aStateSetType =
857 // ::getCppuType((const uno::Reference<XAccessibleStateSet>*)0);
859 // ... and merge them all into one list.
860 sal_Int32
nTypeCount (aTypeList
.getLength()),
861 nComponentTypeCount (aComponentTypeList
.getLength());
864 aTypeList
.realloc (nTypeCount
+ nComponentTypeCount
+ 3);
866 for (i
=0; i
<nComponentTypeCount
; i
++)
867 aTypeList
[nTypeCount
+ i
] = aComponentTypeList
[i
];
869 aTypeList
[nTypeCount
+ i
++ ] = aLangEventListenerType
;
870 aTypeList
[nTypeCount
+ i
++ ] = aDocumentEventListenerType
;
871 aTypeList
[nTypeCount
+ i
] = aUnoTunnelType
;
879 //===== lang::XEventListener ================================================
881 /** Disposing calls are accepted only from the model: Just reset the
882 reference to the model in the shape tree info. Otherwise this object
886 AccessibleShape::disposing (const lang::EventObject
& aEvent
)
887 throw (uno::RuntimeException
)
889 ::vos::OGuard
aSolarGuard (::Application::GetSolarMutex());
890 ::osl::MutexGuard
aGuard (maMutex
);
894 if (aEvent
.Source
== maShapeTreeInfo
.GetModelBroadcaster())
896 // Remove reference to model broadcaster to allow it to pass
898 maShapeTreeInfo
.SetModelBroadcaster(NULL
);
902 catch (uno::RuntimeException e
)
904 OSL_TRACE ("caught exception while disposing");
911 //===== document::XEventListener ============================================
914 AccessibleShape::notifyEvent (const document::EventObject
& rEventObject
)
915 throw (uno::RuntimeException
)
917 static const OUString
sShapeModified (
918 RTL_CONSTASCII_USTRINGPARAM("ShapeModified"));
920 // First check if the event is for us.
921 uno::Reference
<drawing::XShape
> xShape (
922 rEventObject
.Source
, uno::UNO_QUERY
);
923 if ( xShape
.get() == mxShape
.get() )
925 if (rEventObject
.EventName
.equals (sShapeModified
))
927 // Some property of a shape has been modified. Send an event
928 // that indicates a change of the visible data to all listeners.
930 AccessibleEventId::VISIBLE_DATA_CHANGED
,
934 // Name and Description may have changed. Update the local
935 // values accordingly.
936 UpdateNameAndDescription();
944 //===== lang::XUnoTunnel ================================================
946 const uno::Sequence
< sal_Int8
>&
947 AccessibleShape::getUnoTunnelImplementationId()
950 static uno::Sequence
< sal_Int8
>* pSeq
= 0;
954 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
958 static uno::Sequence
< sal_Int8
> aSeq( 16 );
959 rtl_createUuid( (sal_uInt8
*) aSeq
.getArray(), 0, sal_True
);
967 //------------------------------------------------------------------------------
969 AccessibleShape::getImplementation( const uno::Reference
< uno::XInterface
>& rxIFace
)
972 uno::Reference
< lang::XUnoTunnel
> xTunnel( rxIFace
, uno::UNO_QUERY
);
973 AccessibleShape
* pReturn
= NULL
;
976 pReturn
= reinterpret_cast< AccessibleShape
* >( xTunnel
->getSomething( getUnoTunnelImplementationId() ) );
981 //------------------------------------------------------------------------------
983 AccessibleShape::getSomething( const uno::Sequence
< sal_Int8
>& rIdentifier
)
984 throw(uno::RuntimeException
)
986 sal_Int64
nReturn( 0 );
988 if( ( rIdentifier
.getLength() == 16 ) && ( 0 == rtl_compareMemory( getUnoTunnelImplementationId().getConstArray(), rIdentifier
.getConstArray(), 16 ) ) )
989 nReturn
= reinterpret_cast< sal_Int64
>( this );
994 //===== IAccessibleViewForwarderListener ====================================
996 void AccessibleShape::ViewForwarderChanged (ChangeType aChangeType
,
997 const IAccessibleViewForwarder
* pViewForwarder
)
999 // Inform all listeners that the graphical representation (i.e. size
1000 // and/or position) of the shape has changed.
1001 CommitChange (AccessibleEventId::VISIBLE_DATA_CHANGED
,
1005 // Tell children manager of the modified view forwarder.
1006 if (mpChildrenManager
!= NULL
)
1007 mpChildrenManager
->ViewForwarderChanged (aChangeType
, pViewForwarder
);
1009 // update our children that our screen position might have changed
1011 mpText
->UpdateChildren();
1017 //===== protected internal ==================================================
1018 /// Set this object's name if is different to the current name.
1020 AccessibleShape::CreateAccessibleBaseName (void)
1021 throw (::com::sun::star::uno::RuntimeException
)
1023 return ShapeTypeHandler::CreateAccessibleBaseName( mxShape
);
1028 AccessibleShape::CreateAccessibleName (void)
1029 throw (::com::sun::star::uno::RuntimeException
)
1031 OUString
sName (CreateAccessibleBaseName());
1033 // Append the shape's index to the name to disambiguate between shapes
1034 // of the same type. If such an index where not given to the
1035 // constructor then use the z-order instead. If even that does not exist
1036 // we throw an exception.
1037 long nIndex
= mnIndex
;
1042 uno::Reference
<beans::XPropertySet
> xSet (mxShape
, uno::UNO_QUERY
);
1045 uno::Any
aZOrder (xSet
->getPropertyValue (::rtl::OUString::createFromAscii ("ZOrder")));
1048 // Add one to be not zero based.
1052 catch (beans::UnknownPropertyException
)
1054 // We throw our own exception that is a bit more informative.
1055 throw uno::RuntimeException (::rtl::OUString (
1056 RTL_CONSTASCII_USTRINGPARAM("AccessibleShape has invalid index and no ZOrder property")),
1057 static_cast<uno::XWeak
*>(this));
1062 // Put a space between name and index because of Gnopernicus othewise
1064 sName
+= OUString (RTL_CONSTASCII_USTRINGPARAM(" ")) + OUString::valueOf (nIndex
);
1073 AccessibleShape::CreateAccessibleDescription (void)
1074 throw (::com::sun::star::uno::RuntimeException
)
1076 DescriptionGenerator
aDG (mxShape
);
1077 aDG
.Initialize (CreateAccessibleBaseName());
1078 switch (ShapeTypeHandler::Instance().GetTypeId (mxShape
))
1080 case DRAWING_3D_CUBE
:
1081 case DRAWING_3D_EXTRUDE
:
1082 case DRAWING_3D_LATHE
:
1083 case DRAWING_3D_SPHERE
:
1084 aDG
.Add3DProperties ();
1087 case DRAWING_3D_SCENE
:
1090 // No further information is appended.
1093 case DRAWING_CAPTION
:
1094 case DRAWING_CLOSED_BEZIER
:
1095 case DRAWING_CLOSED_FREEHAND
:
1096 case DRAWING_ELLIPSE
:
1097 case DRAWING_POLY_POLYGON
:
1098 case DRAWING_POLY_POLYGON_PATH
:
1099 case DRAWING_RECTANGLE
:
1100 aDG
.AddLineProperties ();
1101 aDG
.AddFillProperties ();
1104 case DRAWING_CONNECTOR
:
1106 case DRAWING_MEASURE
:
1107 case DRAWING_OPEN_BEZIER
:
1108 case DRAWING_OPEN_FREEHAND
:
1109 case DRAWING_POLY_LINE
:
1110 case DRAWING_POLY_LINE_PATH
:
1111 aDG
.AddLineProperties ();
1114 case DRAWING_CONTROL
:
1115 aDG
.AddProperty (OUString::createFromAscii ("ControlBackground"),
1116 DescriptionGenerator::COLOR
,
1118 aDG
.AddProperty (OUString::createFromAscii ("ControlBorder"),
1119 DescriptionGenerator::INTEGER
,
1124 aDG
.AddTextProperties ();
1128 aDG
.Initialize (::rtl::OUString (
1129 RTL_CONSTASCII_USTRINGPARAM("Unknown accessible shape")));
1130 uno::Reference
<drawing::XShapeDescriptor
> xDescriptor (mxShape
, uno::UNO_QUERY
);
1131 if (xDescriptor
.is())
1133 aDG
.AppendString (::rtl::OUString (RTL_CONSTASCII_USTRINGPARAM("service name=")));
1134 aDG
.AppendString (xDescriptor
->getShapeType());
1144 uno::Reference
< drawing::XShape
> AccessibleShape::GetXShape()
1152 void AccessibleShape::disposing (void)
1154 ::vos::OGuard
aSolarGuard (::Application::GetSolarMutex());
1155 ::osl::MutexGuard
aGuard (maMutex
);
1157 // Make sure to send an event that this object looses the focus in the
1158 // case that it has the focus.
1159 ::utl::AccessibleStateSetHelper
* pStateSet
=
1160 static_cast< ::utl::AccessibleStateSetHelper
*>(mxStateSet
.get());
1161 if (pStateSet
!= NULL
)
1162 pStateSet
->RemoveState (AccessibleStateType::FOCUSED
);
1164 // Unregister from broadcasters.
1165 Reference
<lang::XComponent
> xComponent (mxShape
, uno::UNO_QUERY
);
1166 if (xComponent
.is())
1167 xComponent
->removeEventListener (this);
1169 // Unregister from model.
1170 if (maShapeTreeInfo
.GetModelBroadcaster().is())
1171 maShapeTreeInfo
.GetModelBroadcaster()->removeEventListener (
1172 static_cast<document::XEventListener
*>(this));
1174 // Release the child containers.
1175 if (mpChildrenManager
!= NULL
)
1177 delete mpChildrenManager
;
1178 mpChildrenManager
= NULL
;
1187 // Cleanup. Remove references to objects to allow them to be
1190 maShapeTreeInfo
= AccessibleShapeTreeInfo();
1192 // Call base classes.
1193 AccessibleContextBase::dispose ();
1197 AccessibleShape::getAccessibleIndexInParent (void)
1198 throw (::com::sun::star::uno::RuntimeException
)
1201 // Use a simple but slow solution for now. Optimize later.
1203 sal_Int32 nIndex
= m_nIndexInParent
;
1205 nIndex
= AccessibleContextBase::getAccessibleIndexInParent();
1212 void AccessibleShape::UpdateNameAndDescription (void)
1214 // Ignore missing title, name, or description. There are fallbacks for
1218 Reference
<beans::XPropertySet
> xSet (mxShape
, uno::UNO_QUERY_THROW
);
1221 // Get the accessible name.
1222 sString
= GetOptionalProperty(xSet
, OUString(RTL_CONSTASCII_USTRINGPARAM("Title")));
1223 if (sString
.getLength() > 0)
1225 SetAccessibleName(sString
, AccessibleContextBase::FromShape
);
1229 sString
= GetOptionalProperty(xSet
, OUString(RTL_CONSTASCII_USTRINGPARAM("Name")));
1230 if (sString
.getLength() > 0)
1231 SetAccessibleName(sString
, AccessibleContextBase::FromShape
);
1234 // Get the accessible description.
1235 sString
= GetOptionalProperty(xSet
, OUString(RTL_CONSTASCII_USTRINGPARAM("Description")));
1236 if (sString
.getLength() > 0)
1237 SetAccessibleDescription(sString
, AccessibleContextBase::FromShape
);
1239 catch (uno::RuntimeException
&)
1247 } // end of namespace accessibility