1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include <svx/AccessibleShape.hxx>
30 #include "svx/DescriptionGenerator.hxx"
31 #include <svx/AccessibleShapeInfo.hxx>
32 #include <com/sun/star/view/XSelectionSupplier.hpp>
33 #include <com/sun/star/accessibility/AccessibleRole.hpp>
34 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
35 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/container/XChild.hpp>
37 #include <com/sun/star/drawing/XShapes.hpp>
38 #include <com/sun/star/drawing/XShapeDescriptor.hpp>
39 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
40 #include <com/sun/star/drawing/FillStyle.hpp>
41 #include <com/sun/star/text/XText.hpp>
42 #include <editeng/outlobj.hxx>
43 #include <rtl/ref.hxx>
44 #include <editeng/unoedsrc.hxx>
45 #include <svx/unoshtxt.hxx>
46 #include <svx/svdobj.hxx>
47 #include <svx/svdmodel.hxx>
48 #include "svx/unoapi.hxx"
49 #include <com/sun/star/uno/Exception.hpp>
50 #include <svx/ShapeTypeHandler.hxx>
51 #include <svx/SvxShapeTypes.hxx>
53 #include "accessibility.hrc"
54 #include "svx/svdstr.hrc"
55 #include <svx/dialmgr.hxx>
56 #include <vcl/svapp.hxx>
57 #include <unotools/accessiblestatesethelper.hxx>
58 #include <svx/svdview.hxx>
59 #include <comphelper/servicehelper.hxx>
60 #include "AccessibleEmptyEditSource.hxx"
62 using namespace ::com::sun::star
;
63 using namespace ::com::sun::star::accessibility
;
64 using ::com::sun::star::uno::Reference
;
65 using ::rtl::OUString
;
67 namespace accessibility
{
71 OUString
GetOptionalProperty (
72 const Reference
<beans::XPropertySet
>& rxSet
,
73 const OUString
& rsPropertyName
)
79 const Reference
<beans::XPropertySetInfo
> xInfo (rxSet
->getPropertySetInfo());
80 if ( ! xInfo
.is() || xInfo
->hasPropertyByName(rsPropertyName
))
84 rxSet
->getPropertyValue(rsPropertyName
) >>= sValue
;
86 catch (beans::UnknownPropertyException
&)
88 // This exception should only be thrown when the property
89 // does not exits (of course) and the XPropertySetInfo is
97 } // end of anonymous namespace
102 //===== internal ============================================================
104 AccessibleShape::AccessibleShape (
105 const AccessibleShapeInfo
& rShapeInfo
,
106 const AccessibleShapeTreeInfo
& rShapeTreeInfo
)
107 : AccessibleContextBase (rShapeInfo
.mxParent
,AccessibleRole::LIST_ITEM
),
108 mpChildrenManager(NULL
),
109 mxShape (rShapeInfo
.mxShape
),
110 maShapeTreeInfo (rShapeTreeInfo
),
111 mnIndex (rShapeInfo
.mnIndex
),
112 m_nIndexInParent(-1),
114 mpParent (rShapeInfo
.mpChildrenManager
)
116 m_pShape
= GetSdrObjectFromXShape(mxShape
);
117 UpdateNameAndDescription();
123 AccessibleShape::~AccessibleShape (void)
125 if (mpChildrenManager
!= NULL
)
126 delete mpChildrenManager
;
129 OSL_TRACE ("~AccessibleShape");
131 // Unregistering from the various broadcasters should be unnecessary
132 // since this destructor would not have been called if one of the
133 // broadcasters would still hold a strong reference to this object.
139 void AccessibleShape::Init (void)
141 // Update the OPAQUE and SELECTED shape.
144 // Create a children manager when this shape has children of its own.
145 Reference
<drawing::XShapes
> xShapes (mxShape
, uno::UNO_QUERY
);
146 if (xShapes
.is() && xShapes
->getCount() > 0)
147 mpChildrenManager
= new ChildrenManager (
148 this, xShapes
, maShapeTreeInfo
, *this);
149 if (mpChildrenManager
!= NULL
)
150 mpChildrenManager
->Update();
152 // Register at model as document::XEventListener.
153 if (maShapeTreeInfo
.GetModelBroadcaster().is())
154 maShapeTreeInfo
.GetModelBroadcaster()->addEventListener (
155 static_cast<document::XEventListener
*>(this));
157 // Beware! Here we leave the paths of the UNO API and descend into the
158 // depths of the core. Necessary for makeing the edit engine
160 Reference
<text::XText
> xText (mxShape
, uno::UNO_QUERY
);
163 SdrView
* pView
= maShapeTreeInfo
.GetSdrView ();
164 const Window
* pWindow
= maShapeTreeInfo
.GetWindow ();
165 if (pView
!= NULL
&& pWindow
!= NULL
&& mxShape
.is())
167 // #107948# Determine whether shape text is empty
168 SdrObject
* pSdrObject
= GetSdrObjectFromXShape(mxShape
);
171 SdrTextObj
* pTextObj
= PTR_CAST( SdrTextObj
, pSdrObject
);
172 OutlinerParaObject
* pOutlinerParaObject
= NULL
;
175 pOutlinerParaObject
= pTextObj
->GetEditOutlinerParaObject(); // Get the OutlinerParaObject if text edit is active
177 bool bOwnParaObj
= pOutlinerParaObject
!= NULL
;
179 if( !pOutlinerParaObject
&& pSdrObject
)
180 pOutlinerParaObject
= pSdrObject
->GetOutlinerParaObject();
182 // create AccessibleTextHelper to handle this shape's text
183 if( !pOutlinerParaObject
)
185 // empty text -> use proxy edit source to delay creation of EditEngine
186 SAL_WNODEPRECATED_DECLARATIONS_PUSH
187 ::std::auto_ptr
<SvxEditSource
> pEditSource( new AccessibleEmptyEditSource ( *pSdrObject
, *pView
, *pWindow
) );
188 SAL_WNODEPRECATED_DECLARATIONS_POP
189 mpText
= new AccessibleTextHelper( pEditSource
);
193 // non-empty text -> use full-fledged edit source right away
194 SAL_WNODEPRECATED_DECLARATIONS_PUSH
195 ::std::auto_ptr
<SvxEditSource
> pEditSource( new SvxTextEditSource ( *pSdrObject
, 0, *pView
, *pWindow
) );
196 SAL_WNODEPRECATED_DECLARATIONS_POP
197 mpText
= new AccessibleTextHelper( pEditSource
);
201 delete pOutlinerParaObject
;
203 mpText
->SetEventSource(this);
212 void AccessibleShape::UpdateStates (void)
214 ::utl::AccessibleStateSetHelper
* pStateSet
=
215 static_cast< ::utl::AccessibleStateSetHelper
*>(mxStateSet
.get());
216 if (pStateSet
== NULL
)
219 // Set the opaque state for certain shape types when their fill style is
221 bool bShapeIsOpaque
= false;
222 switch (ShapeTypeHandler::Instance().GetTypeId (mxShape
))
225 case DRAWING_RECTANGLE
:
228 uno::Reference
<beans::XPropertySet
> xSet (mxShape
, uno::UNO_QUERY
);
233 drawing::FillStyle aFillStyle
;
234 bShapeIsOpaque
= ( xSet
->getPropertyValue (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FillStyle"))) >>= aFillStyle
)
235 && aFillStyle
== drawing::FillStyle_SOLID
;
237 catch (::com::sun::star::beans::UnknownPropertyException
&)
245 pStateSet
->AddState (AccessibleStateType::OPAQUE
);
247 pStateSet
->RemoveState (AccessibleStateType::OPAQUE
);
249 // Set the selected state.
250 bool bShapeIsSelected
= false;
251 // XXX fix_me this has to be done with an extra interface later on
252 if ( m_pShape
&& maShapeTreeInfo
.GetSdrView() )
254 bShapeIsSelected
= maShapeTreeInfo
.GetSdrView()->IsObjMarked(m_pShape
) == sal_True
;
257 if (bShapeIsSelected
)
258 pStateSet
->AddState (AccessibleStateType::SELECTED
);
260 pStateSet
->RemoveState (AccessibleStateType::SELECTED
);
266 bool AccessibleShape::operator== (const AccessibleShape
& rShape
)
268 return this==&rShape
;
274 sal_Bool
AccessibleShape::SetState (sal_Int16 aState
)
276 sal_Bool bStateHasChanged
= sal_False
;
278 if (aState
== AccessibleStateType::FOCUSED
&& mpText
!= NULL
)
280 // Offer FOCUSED state to edit engine and detect whether the state
282 sal_Bool bIsFocused
= mpText
->HaveFocus ();
283 mpText
->SetFocus (sal_True
);
284 bStateHasChanged
= (bIsFocused
!= mpText
->HaveFocus ());
287 bStateHasChanged
= AccessibleContextBase::SetState (aState
);
289 return bStateHasChanged
;
295 sal_Bool
AccessibleShape::ResetState (sal_Int16 aState
)
297 sal_Bool bStateHasChanged
= sal_False
;
299 if (aState
== AccessibleStateType::FOCUSED
&& mpText
!= NULL
)
301 // Try to remove FOCUSED state from the edit engine and detect
302 // whether the state changes.
303 sal_Bool bIsFocused
= mpText
->HaveFocus ();
304 mpText
->SetFocus (sal_False
);
305 bStateHasChanged
= (bIsFocused
!= mpText
->HaveFocus ());
308 bStateHasChanged
= AccessibleContextBase::ResetState (aState
);
310 return bStateHasChanged
;
316 sal_Bool
AccessibleShape::GetState (sal_Int16 aState
)
318 if (aState
== AccessibleStateType::FOCUSED
&& mpText
!= NULL
)
320 // Just delegate the call to the edit engine. The state is not
321 // merged into the state set.
322 return mpText
->HaveFocus();
325 return AccessibleContextBase::GetState (aState
);
331 //===== XAccessibleContext ==================================================
333 /** The children of this shape come from two sources: The children from
334 group or scene shapes and the paragraphs of text.
337 AccessibleShape::getAccessibleChildCount ()
338 throw (::com::sun::star::uno::RuntimeException
)
341 sal_Int32 nChildCount
= 0;
343 // Add the number of shapes that are children of this shape.
344 if (mpChildrenManager
!= NULL
)
345 nChildCount
+= mpChildrenManager
->GetChildCount ();
346 // Add the number text paragraphs.
348 nChildCount
+= mpText
->GetChildCount ();
356 /** Forward the request to the shape. Return the requested shape or throw
357 an exception for a wrong index.
359 uno::Reference
<XAccessible
> SAL_CALL
360 AccessibleShape::getAccessibleChild (sal_Int32 nIndex
)
361 throw (::com::sun::star::lang::IndexOutOfBoundsException
, ::com::sun::star::uno::RuntimeException
)
365 uno::Reference
<XAccessible
> xChild
;
367 // Depending on the index decide whether to delegate this call to the
368 // children manager or the edit engine.
369 if ((mpChildrenManager
!= NULL
)
370 && (nIndex
< mpChildrenManager
->GetChildCount()))
372 xChild
= mpChildrenManager
->GetChild (nIndex
);
374 else if (mpText
!= NULL
)
376 sal_Int32 nI
= nIndex
;
377 if (mpChildrenManager
!= NULL
)
378 nI
-= mpChildrenManager
->GetChildCount();
379 xChild
= mpText
->GetChild (nI
);
382 throw lang::IndexOutOfBoundsException (
383 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("shape has no child with index "))
384 + rtl::OUString::valueOf(nIndex
),
385 static_cast<uno::XWeak
*>(this));
393 /** Return a copy of the state set.
399 uno::Reference
<XAccessibleStateSet
> SAL_CALL
400 AccessibleShape::getAccessibleStateSet (void)
401 throw (::com::sun::star::uno::RuntimeException
)
403 ::osl::MutexGuard
aGuard (maMutex
);
404 Reference
<XAccessibleStateSet
> xStateSet
;
406 if (rBHelper
.bDisposed
|| mpText
== NULL
)
407 // Return a minimal state set that only contains the DEFUNC state.
408 xStateSet
= AccessibleContextBase::getAccessibleStateSet ();
411 ::utl::AccessibleStateSetHelper
* pStateSet
=
412 static_cast< ::utl::AccessibleStateSetHelper
*>(mxStateSet
.get());
414 if (pStateSet
!= NULL
)
416 // Merge current FOCUSED state from edit engine.
419 if (mpText
->HaveFocus())
420 pStateSet
->AddState (AccessibleStateType::FOCUSED
);
422 pStateSet
->RemoveState (AccessibleStateType::FOCUSED
);
425 // Create a copy of the state set that may be modified by the
426 // caller without affecting the current state set.
427 xStateSet
= Reference
<XAccessibleStateSet
>(
428 new ::utl::AccessibleStateSetHelper (*pStateSet
));
438 //===== XAccessibleComponent ================================================
440 /** The implementation below is at the moment straightforward. It iterates
441 over all children (and thereby instances all children which have not
442 been already instatiated) until a child covering the specifed point is
444 This leaves room for improvement. For instance, first iterate only over
445 the already instantiated children and only if no match is found
446 instantiate the remaining ones.
448 uno::Reference
<XAccessible
> SAL_CALL
449 AccessibleShape::getAccessibleAtPoint (
450 const awt::Point
& aPoint
)
451 throw (uno::RuntimeException
)
453 ::osl::MutexGuard
aGuard (maMutex
);
455 sal_Int32 nChildCount
= getAccessibleChildCount ();
456 for (sal_Int32 i
=0; i
<nChildCount
; ++i
)
458 Reference
<XAccessible
> xChild (getAccessibleChild (i
));
461 Reference
<XAccessibleComponent
> xChildComponent (
462 xChild
->getAccessibleContext(), uno::UNO_QUERY
);
463 if (xChildComponent
.is())
465 awt::Rectangle
aBBox (xChildComponent
->getBounds());
466 if ( (aPoint
.X
>= aBBox
.X
)
467 && (aPoint
.Y
>= aBBox
.Y
)
468 && (aPoint
.X
< aBBox
.X
+aBBox
.Width
)
469 && (aPoint
.Y
< aBBox
.Y
+aBBox
.Height
) )
475 // Have not found a child under the given point. Returning empty
476 // reference to indicate this.
477 return uno::Reference
<XAccessible
>();
483 awt::Rectangle SAL_CALL
AccessibleShape::getBounds (void)
484 throw (::com::sun::star::uno::RuntimeException
)
486 SolarMutexGuard aSolarGuard
;
487 ::osl::MutexGuard
aGuard (maMutex
);
490 awt::Rectangle aBoundingBox
;
494 static const OUString
sBoundRectName (
495 RTL_CONSTASCII_USTRINGPARAM("BoundRect"));
496 static const OUString
sAnchorPositionName (
497 RTL_CONSTASCII_USTRINGPARAM("AnchorPosition"));
499 // Get the shape's bounding box in internal coordinates (in 100th of
500 // mm). Use the property BoundRect. Only if that is not supported ask
501 // the shape for its position and size directly.
502 Reference
<beans::XPropertySet
> xSet (mxShape
, uno::UNO_QUERY
);
503 Reference
<beans::XPropertySetInfo
> xSetInfo
;
504 bool bFoundBoundRect
= false;
507 xSetInfo
= xSet
->getPropertySetInfo ();
510 if (xSetInfo
->hasPropertyByName (sBoundRectName
))
514 uno::Any aValue
= xSet
->getPropertyValue (sBoundRectName
);
515 aValue
>>= aBoundingBox
;
516 bFoundBoundRect
= true;
518 catch (beans::UnknownPropertyException
const&)
520 // Handled below (bFoundBoundRect stays false).
524 OSL_TRACE (" no property BoundRect");
528 // Fallback when there is no BoundRect Property.
529 if ( ! bFoundBoundRect
)
531 awt::Point
aPosition (mxShape
->getPosition());
532 awt::Size
aSize (mxShape
->getSize());
533 aBoundingBox
= awt::Rectangle (
534 aPosition
.X
, aPosition
.Y
,
535 aSize
.Width
, aSize
.Height
);
537 // While BoundRects have absolute positions, the position returned
538 // by XPosition::getPosition is relative. Get the anchor position
539 // (usually not (0,0) for Writer shapes).
542 if (xSetInfo
->hasPropertyByName (sAnchorPositionName
))
544 uno::Any aPos
= xSet
->getPropertyValue (sAnchorPositionName
);
545 awt::Point aAnchorPosition
;
546 aPos
>>= aAnchorPosition
;
547 aBoundingBox
.X
+= aAnchorPosition
.X
;
548 aBoundingBox
.Y
+= aAnchorPosition
.Y
;
553 // Transform coordinates from internal to pixel.
554 if (maShapeTreeInfo
.GetViewForwarder() == NULL
)
555 throw uno::RuntimeException (::rtl::OUString (
556 RTL_CONSTASCII_USTRINGPARAM(
557 "AccessibleShape has no valid view forwarder")),
558 static_cast<uno::XWeak
*>(this));
559 ::Size aPixelSize
= maShapeTreeInfo
.GetViewForwarder()->LogicToPixel (
560 ::Size (aBoundingBox
.Width
, aBoundingBox
.Height
));
561 ::Point aPixelPosition
= maShapeTreeInfo
.GetViewForwarder()->LogicToPixel (
562 ::Point (aBoundingBox
.X
, aBoundingBox
.Y
));
564 // Clip the shape's bounding box with the bounding box of its parent.
565 Reference
<XAccessibleComponent
> xParentComponent (
566 getAccessibleParent(), uno::UNO_QUERY
);
567 if (xParentComponent
.is())
569 // Make the coordinates relative to the parent.
570 awt::Point
aParentLocation (xParentComponent
->getLocationOnScreen());
571 int x
= aPixelPosition
.getX() - aParentLocation
.X
;
572 int y
= aPixelPosition
.getY() - aParentLocation
.Y
;
574 // Clip with parent (with coordinates relative to itself).
576 x
, y
, x
+ aPixelSize
.getWidth(), y
+ aPixelSize
.getHeight());
577 awt::Size
aParentSize (xParentComponent
->getSize());
578 ::Rectangle
aParentBBox (0,0, aParentSize
.Width
, aParentSize
.Height
);
579 aBBox
= aBBox
.GetIntersection (aParentBBox
);
580 aBoundingBox
= awt::Rectangle (
588 OSL_TRACE ("parent does not support component");
589 aBoundingBox
= awt::Rectangle (
590 aPixelPosition
.getX(), aPixelPosition
.getY(),
591 aPixelSize
.getWidth(), aPixelSize
.getHeight());
601 awt::Point SAL_CALL
AccessibleShape::getLocation (void)
602 throw (::com::sun::star::uno::RuntimeException
)
605 awt::Rectangle
aBoundingBox (getBounds());
606 return awt::Point (aBoundingBox
.X
, aBoundingBox
.Y
);
612 awt::Point SAL_CALL
AccessibleShape::getLocationOnScreen (void)
613 throw (::com::sun::star::uno::RuntimeException
)
617 // Get relative position...
618 awt::Point
aLocation (getLocation ());
620 // ... and add absolute position of the parent.
621 uno::Reference
<XAccessibleComponent
> xParentComponent (
622 getAccessibleParent(), uno::UNO_QUERY
);
623 if (xParentComponent
.is())
625 awt::Point
aParentLocation (xParentComponent
->getLocationOnScreen());
626 aLocation
.X
+= aParentLocation
.X
;
627 aLocation
.Y
+= aParentLocation
.Y
;
630 OSL_TRACE ("getLocation: parent does not support XAccessibleComponent");
637 awt::Size SAL_CALL
AccessibleShape::getSize (void)
638 throw (uno::RuntimeException
)
641 awt::Rectangle
aBoundingBox (getBounds());
642 return awt::Size (aBoundingBox
.Width
, aBoundingBox
.Height
);
648 sal_Int32 SAL_CALL
AccessibleShape::getForeground (void)
649 throw (::com::sun::star::uno::RuntimeException
)
652 sal_Int32
nColor (0x0ffffffL
);
656 uno::Reference
<beans::XPropertySet
> aSet (mxShape
, uno::UNO_QUERY
);
660 aColor
= aSet
->getPropertyValue (OUString(RTL_CONSTASCII_USTRINGPARAM("LineColor")) );
664 catch (const ::com::sun::star::beans::UnknownPropertyException
&)
666 // Ignore exception and return default color.
674 sal_Int32 SAL_CALL
AccessibleShape::getBackground (void)
675 throw (::com::sun::star::uno::RuntimeException
)
678 sal_Int32
nColor (0L);
682 uno::Reference
<beans::XPropertySet
> aSet (mxShape
, uno::UNO_QUERY
);
686 aColor
= aSet
->getPropertyValue (OUString(RTL_CONSTASCII_USTRINGPARAM("FillColor")) );
690 catch (const ::com::sun::star::beans::UnknownPropertyException
&)
692 // Ignore exception and return default color.
700 //===== XAccessibleEventBroadcaster =========================================
702 void SAL_CALL
AccessibleShape::addEventListener (
703 const Reference
<XAccessibleEventListener
>& rxListener
)
704 throw (uno::RuntimeException
)
706 if (rBHelper
.bDisposed
|| rBHelper
.bInDispose
)
708 uno::Reference
<uno::XInterface
> xThis (
709 (lang::XComponent
*)this, uno::UNO_QUERY
);
710 rxListener
->disposing (lang::EventObject (xThis
));
714 AccessibleContextBase::addEventListener (rxListener
);
716 mpText
->AddEventListener (rxListener
);
723 void SAL_CALL
AccessibleShape::removeEventListener (
724 const Reference
<XAccessibleEventListener
>& rxListener
)
725 throw (uno::RuntimeException
)
727 AccessibleContextBase::removeEventListener (rxListener
);
729 mpText
->RemoveEventListener (rxListener
);
735 //===== XInterface ==========================================================
737 com::sun::star::uno::Any SAL_CALL
738 AccessibleShape::queryInterface (const com::sun::star::uno::Type
& rType
)
739 throw (::com::sun::star::uno::RuntimeException
)
741 ::com::sun::star::uno::Any aReturn
= AccessibleContextBase::queryInterface (rType
);
742 if ( ! aReturn
.hasValue())
743 aReturn
= ::cppu::queryInterface (rType
,
744 static_cast<XAccessibleComponent
*>(this),
745 static_cast<XAccessibleExtendedComponent
*>(this),
746 static_cast<lang::XEventListener
*>(this),
747 static_cast<document::XEventListener
*>(this),
748 static_cast<lang::XUnoTunnel
*>(this)
757 AccessibleShape::acquire (void)
760 AccessibleContextBase::acquire ();
767 AccessibleShape::release (void)
770 AccessibleContextBase::release ();
776 //===== XServiceInfo ========================================================
778 ::rtl::OUString SAL_CALL
779 AccessibleShape::getImplementationName (void)
780 throw (::com::sun::star::uno::RuntimeException
)
782 return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleShape"));
788 uno::Sequence
<OUString
> SAL_CALL
789 AccessibleShape::getSupportedServiceNames (void)
790 throw (::com::sun::star::uno::RuntimeException
)
793 // Get list of supported service names from base class...
794 uno::Sequence
<OUString
> aServiceNames
=
795 AccessibleContextBase::getSupportedServiceNames();
796 sal_Int32
nCount (aServiceNames
.getLength());
798 // ...and add additional names.
799 aServiceNames
.realloc (nCount
+ 1);
800 static const OUString
sAdditionalServiceName (RTL_CONSTASCII_USTRINGPARAM(
801 "com.sun.star.drawing.AccessibleShape"));
802 aServiceNames
[nCount
] = sAdditionalServiceName
;
804 return aServiceNames
;
811 //===== XTypeProvider ===================================================
813 uno::Sequence
<uno::Type
> SAL_CALL
814 AccessibleShape::getTypes (void)
815 throw (uno::RuntimeException
)
818 // Get list of types from the context base implementation, ...
819 uno::Sequence
<uno::Type
> aTypeList (AccessibleContextBase::getTypes());
820 // ... get list of types from component base implementation, ...
821 uno::Sequence
<uno::Type
> aComponentTypeList (AccessibleComponentBase::getTypes());
822 // ... define local types, ...
823 const uno::Type aLangEventListenerType
=
824 ::getCppuType((const uno::Reference
<lang::XEventListener
>*)0);
825 const uno::Type aDocumentEventListenerType
=
826 ::getCppuType((const uno::Reference
<document::XEventListener
>*)0);
827 const uno::Type aUnoTunnelType
=
828 ::getCppuType((const uno::Reference
<lang::XUnoTunnel
>*)0);
830 // ... and merge them all into one list.
831 sal_Int32
nTypeCount (aTypeList
.getLength()),
832 nComponentTypeCount (aComponentTypeList
.getLength());
835 aTypeList
.realloc (nTypeCount
+ nComponentTypeCount
+ 3);
837 for (i
=0; i
<nComponentTypeCount
; i
++)
838 aTypeList
[nTypeCount
+ i
] = aComponentTypeList
[i
];
840 aTypeList
[nTypeCount
+ i
++ ] = aLangEventListenerType
;
841 aTypeList
[nTypeCount
+ i
++ ] = aDocumentEventListenerType
;
842 aTypeList
[nTypeCount
+ i
] = aUnoTunnelType
;
850 //===== lang::XEventListener ================================================
852 /** Disposing calls are accepted only from the model: Just reset the
853 reference to the model in the shape tree info. Otherwise this object
857 AccessibleShape::disposing (const lang::EventObject
& aEvent
)
858 throw (uno::RuntimeException
)
860 SolarMutexGuard aSolarGuard
;
861 ::osl::MutexGuard
aGuard (maMutex
);
865 if (aEvent
.Source
== maShapeTreeInfo
.GetModelBroadcaster())
867 // Remove reference to model broadcaster to allow it to pass
869 maShapeTreeInfo
.SetModelBroadcaster(NULL
);
873 catch (uno::RuntimeException
const&)
875 OSL_TRACE ("caught exception while disposing");
882 //===== document::XEventListener ============================================
885 AccessibleShape::notifyEvent (const document::EventObject
& rEventObject
)
886 throw (uno::RuntimeException
)
888 static const OUString
sShapeModified (
889 RTL_CONSTASCII_USTRINGPARAM("ShapeModified"));
891 // First check if the event is for us.
892 uno::Reference
<drawing::XShape
> xShape (
893 rEventObject
.Source
, uno::UNO_QUERY
);
894 if ( xShape
.get() == mxShape
.get() )
896 if (rEventObject
.EventName
.equals (sShapeModified
))
898 // Some property of a shape has been modified. Send an event
899 // that indicates a change of the visible data to all listeners.
901 AccessibleEventId::VISIBLE_DATA_CHANGED
,
905 // Name and Description may have changed. Update the local
906 // values accordingly.
907 UpdateNameAndDescription();
912 //===== lang::XUnoTunnel ================================================
916 class theAccessibleShapeImplementationId
: public rtl::Static
< UnoTunnelIdInit
, theAccessibleShapeImplementationId
> {};
919 const uno::Sequence
< sal_Int8
>&
920 AccessibleShape::getUnoTunnelImplementationId()
923 return theAccessibleShapeImplementationId::get().getSeq();
926 //------------------------------------------------------------------------------
928 AccessibleShape::getImplementation( const uno::Reference
< uno::XInterface
>& rxIFace
)
931 uno::Reference
< lang::XUnoTunnel
> xTunnel( rxIFace
, uno::UNO_QUERY
);
932 AccessibleShape
* pReturn
= NULL
;
935 pReturn
= reinterpret_cast< AccessibleShape
* >( xTunnel
->getSomething( getUnoTunnelImplementationId() ) );
940 //------------------------------------------------------------------------------
942 AccessibleShape::getSomething( const uno::Sequence
< sal_Int8
>& rIdentifier
)
943 throw(uno::RuntimeException
)
945 sal_Int64
nReturn( 0 );
947 if( ( rIdentifier
.getLength() == 16 ) && ( 0 == rtl_compareMemory( getUnoTunnelImplementationId().getConstArray(), rIdentifier
.getConstArray(), 16 ) ) )
948 nReturn
= reinterpret_cast< sal_Int64
>( this );
953 //===== IAccessibleViewForwarderListener ====================================
955 void AccessibleShape::ViewForwarderChanged (ChangeType aChangeType
,
956 const IAccessibleViewForwarder
* pViewForwarder
)
958 // Inform all listeners that the graphical representation (i.e. size
959 // and/or position) of the shape has changed.
960 CommitChange (AccessibleEventId::VISIBLE_DATA_CHANGED
,
964 // Tell children manager of the modified view forwarder.
965 if (mpChildrenManager
!= NULL
)
966 mpChildrenManager
->ViewForwarderChanged (aChangeType
, pViewForwarder
);
968 // update our children that our screen position might have changed
970 mpText
->UpdateChildren();
976 //===== protected internal ==================================================
977 /// Set this object's name if is different to the current name.
979 AccessibleShape::CreateAccessibleBaseName (void)
980 throw (::com::sun::star::uno::RuntimeException
)
982 return ShapeTypeHandler::CreateAccessibleBaseName( mxShape
);
987 AccessibleShape::CreateAccessibleName (void)
988 throw (::com::sun::star::uno::RuntimeException
)
990 OUString
sName (CreateAccessibleBaseName());
992 // Append the shape's index to the name to disambiguate between shapes
993 // of the same type. If such an index where not given to the
994 // constructor then use the z-order instead. If even that does not exist
995 // we throw an exception.
996 long nIndex
= mnIndex
;
1001 uno::Reference
<beans::XPropertySet
> xSet (mxShape
, uno::UNO_QUERY
);
1004 uno::Any
aZOrder (xSet
->getPropertyValue (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ZOrder")) ));
1007 // Add one to be not zero based.
1011 catch (const beans::UnknownPropertyException
&)
1013 // We throw our own exception that is a bit more informative.
1014 throw uno::RuntimeException (::rtl::OUString (
1015 RTL_CONSTASCII_USTRINGPARAM("AccessibleShape has invalid index and no ZOrder property")),
1016 static_cast<uno::XWeak
*>(this));
1021 // Put a space between name and index because of Gnopernicus othewise
1023 sName
+= OUString (RTL_CONSTASCII_USTRINGPARAM(" ")) + OUString::valueOf (nIndex
);
1032 AccessibleShape::CreateAccessibleDescription (void)
1033 throw (::com::sun::star::uno::RuntimeException
)
1035 DescriptionGenerator
aDG (mxShape
);
1036 aDG
.Initialize (CreateAccessibleBaseName());
1037 switch (ShapeTypeHandler::Instance().GetTypeId (mxShape
))
1039 case DRAWING_3D_CUBE
:
1040 case DRAWING_3D_EXTRUDE
:
1041 case DRAWING_3D_LATHE
:
1042 case DRAWING_3D_SPHERE
:
1043 aDG
.Add3DProperties ();
1046 case DRAWING_3D_SCENE
:
1049 // No further information is appended.
1052 case DRAWING_CAPTION
:
1053 case DRAWING_CLOSED_BEZIER
:
1054 case DRAWING_CLOSED_FREEHAND
:
1055 case DRAWING_ELLIPSE
:
1056 case DRAWING_POLY_POLYGON
:
1057 case DRAWING_POLY_POLYGON_PATH
:
1058 case DRAWING_RECTANGLE
:
1059 aDG
.AddLineProperties ();
1060 aDG
.AddFillProperties ();
1063 case DRAWING_CONNECTOR
:
1065 case DRAWING_MEASURE
:
1066 case DRAWING_OPEN_BEZIER
:
1067 case DRAWING_OPEN_FREEHAND
:
1068 case DRAWING_POLY_LINE
:
1069 case DRAWING_POLY_LINE_PATH
:
1070 aDG
.AddLineProperties ();
1073 case DRAWING_CONTROL
:
1074 aDG
.AddProperty (OUString(RTL_CONSTASCII_USTRINGPARAM("ControlBackground")),
1075 DescriptionGenerator::COLOR
,
1077 aDG
.AddProperty (OUString(RTL_CONSTASCII_USTRINGPARAM("ControlBorder")),
1078 DescriptionGenerator::INTEGER
,
1083 aDG
.AddTextProperties ();
1087 aDG
.Initialize (::rtl::OUString (
1088 RTL_CONSTASCII_USTRINGPARAM("Unknown accessible shape")));
1089 uno::Reference
<drawing::XShapeDescriptor
> xDescriptor (mxShape
, uno::UNO_QUERY
);
1090 if (xDescriptor
.is())
1092 aDG
.AppendString (::rtl::OUString (RTL_CONSTASCII_USTRINGPARAM("service name=")));
1093 aDG
.AppendString (xDescriptor
->getShapeType());
1103 uno::Reference
< drawing::XShape
> AccessibleShape::GetXShape()
1111 void AccessibleShape::disposing (void)
1113 SolarMutexGuard aSolarGuard
;
1114 ::osl::MutexGuard
aGuard (maMutex
);
1116 // Make sure to send an event that this object looses the focus in the
1117 // case that it has the focus.
1118 ::utl::AccessibleStateSetHelper
* pStateSet
=
1119 static_cast< ::utl::AccessibleStateSetHelper
*>(mxStateSet
.get());
1120 if (pStateSet
!= NULL
)
1121 pStateSet
->RemoveState (AccessibleStateType::FOCUSED
);
1123 // Unregister from broadcasters.
1124 Reference
<lang::XComponent
> xComponent (mxShape
, uno::UNO_QUERY
);
1125 if (xComponent
.is())
1126 xComponent
->removeEventListener (this);
1128 // Unregister from model.
1129 if (maShapeTreeInfo
.GetModelBroadcaster().is())
1130 maShapeTreeInfo
.GetModelBroadcaster()->removeEventListener (
1131 static_cast<document::XEventListener
*>(this));
1133 // Release the child containers.
1134 if (mpChildrenManager
!= NULL
)
1136 delete mpChildrenManager
;
1137 mpChildrenManager
= NULL
;
1146 // Cleanup. Remove references to objects to allow them to be
1149 maShapeTreeInfo
= AccessibleShapeTreeInfo();
1151 // Call base classes.
1152 AccessibleContextBase::dispose ();
1156 AccessibleShape::getAccessibleIndexInParent (void)
1157 throw (::com::sun::star::uno::RuntimeException
)
1160 // Use a simple but slow solution for now. Optimize later.
1162 sal_Int32 nIndex
= m_nIndexInParent
;
1164 nIndex
= AccessibleContextBase::getAccessibleIndexInParent();
1171 void AccessibleShape::UpdateNameAndDescription (void)
1173 // Ignore missing title, name, or description. There are fallbacks for
1177 Reference
<beans::XPropertySet
> xSet (mxShape
, uno::UNO_QUERY_THROW
);
1180 // Get the accessible name.
1181 sString
= GetOptionalProperty(xSet
, OUString(RTL_CONSTASCII_USTRINGPARAM("Title")));
1182 if (!sString
.isEmpty())
1184 SetAccessibleName(sString
, AccessibleContextBase::FromShape
);
1188 sString
= GetOptionalProperty(xSet
, OUString(RTL_CONSTASCII_USTRINGPARAM("Name")));
1189 if (!sString
.isEmpty())
1190 SetAccessibleName(sString
, AccessibleContextBase::FromShape
);
1193 // Get the accessible description.
1194 sString
= GetOptionalProperty(xSet
, OUString(RTL_CONSTASCII_USTRINGPARAM("Description")));
1195 if (!sString
.isEmpty())
1196 SetAccessibleDescription(sString
, AccessibleContextBase::FromShape
);
1198 catch (uno::RuntimeException
&)
1206 } // end of namespace accessibility
1208 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */