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 <svx/AccessibleShape.hxx>
21 #include "svx/DescriptionGenerator.hxx"
22 #include <svx/AccessibleShapeInfo.hxx>
23 #include <com/sun/star/view/XSelectionSupplier.hpp>
24 #include <com/sun/star/accessibility/AccessibleRole.hpp>
25 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
26 #include <com/sun/star/beans/XPropertySet.hpp>
27 #include <com/sun/star/container/XChild.hpp>
28 #include <com/sun/star/drawing/XShapes.hpp>
29 #include <com/sun/star/drawing/XShapeDescriptor.hpp>
30 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
31 #include <com/sun/star/drawing/FillStyle.hpp>
32 #include <com/sun/star/text/XText.hpp>
33 #include <editeng/outlobj.hxx>
34 #include <rtl/ref.hxx>
35 #include <editeng/unoedsrc.hxx>
36 #include <svx/unoshtxt.hxx>
37 #include <svx/svdobj.hxx>
38 #include <svx/svdmodel.hxx>
39 #include "svx/unoapi.hxx"
40 #include <com/sun/star/uno/Exception.hpp>
41 #include <svx/ShapeTypeHandler.hxx>
42 #include <svx/SvxShapeTypes.hxx>
44 #include "accessibility.hrc"
45 #include "svx/svdstr.hrc"
46 #include <svx/dialmgr.hxx>
47 #include <vcl/svapp.hxx>
48 #include <unotools/accessiblestatesethelper.hxx>
49 #include <svx/svdview.hxx>
50 #include <comphelper/servicehelper.hxx>
51 #include "AccessibleEmptyEditSource.hxx"
53 using namespace ::com::sun::star
;
54 using namespace ::com::sun::star::accessibility
;
55 using ::com::sun::star::uno::Reference
;
57 namespace accessibility
{
61 OUString
GetOptionalProperty (
62 const Reference
<beans::XPropertySet
>& rxSet
,
63 const OUString
& rsPropertyName
)
69 const Reference
<beans::XPropertySetInfo
> xInfo (rxSet
->getPropertySetInfo());
70 if ( ! xInfo
.is() || xInfo
->hasPropertyByName(rsPropertyName
))
74 rxSet
->getPropertyValue(rsPropertyName
) >>= sValue
;
76 catch (beans::UnknownPropertyException
&)
78 // This exception should only be thrown when the property
79 // does not exits (of course) and the XPropertySetInfo is
87 } // end of anonymous namespace
92 //===== internal ============================================================
94 AccessibleShape::AccessibleShape (
95 const AccessibleShapeInfo
& rShapeInfo
,
96 const AccessibleShapeTreeInfo
& rShapeTreeInfo
)
97 : AccessibleContextBase (rShapeInfo
.mxParent
,AccessibleRole::LIST_ITEM
),
98 mpChildrenManager(NULL
),
99 mxShape (rShapeInfo
.mxShape
),
100 maShapeTreeInfo (rShapeTreeInfo
),
101 mnIndex (rShapeInfo
.mnIndex
),
102 m_nIndexInParent(-1),
104 mpParent (rShapeInfo
.mpChildrenManager
)
106 m_pShape
= GetSdrObjectFromXShape(mxShape
);
107 UpdateNameAndDescription();
113 AccessibleShape::~AccessibleShape (void)
115 delete mpChildrenManager
;
117 OSL_TRACE ("~AccessibleShape");
119 // Unregistering from the various broadcasters should be unnecessary
120 // since this destructor would not have been called if one of the
121 // broadcasters would still hold a strong reference to this object.
127 void AccessibleShape::Init (void)
129 // Update the OPAQUE and SELECTED shape.
132 // Create a children manager when this shape has children of its own.
133 Reference
<drawing::XShapes
> xShapes (mxShape
, uno::UNO_QUERY
);
134 if (xShapes
.is() && xShapes
->getCount() > 0)
135 mpChildrenManager
= new ChildrenManager (
136 this, xShapes
, maShapeTreeInfo
, *this);
137 if (mpChildrenManager
!= NULL
)
138 mpChildrenManager
->Update();
140 // Register at model as document::XEventListener.
141 if (maShapeTreeInfo
.GetModelBroadcaster().is())
142 maShapeTreeInfo
.GetModelBroadcaster()->addEventListener (
143 static_cast<document::XEventListener
*>(this));
145 // Beware! Here we leave the paths of the UNO API and descend into the
146 // depths of the core. Necessary for making the edit engine
148 Reference
<text::XText
> xText (mxShape
, uno::UNO_QUERY
);
151 SdrView
* pView
= maShapeTreeInfo
.GetSdrView ();
152 const Window
* pWindow
= maShapeTreeInfo
.GetWindow ();
153 if (pView
!= NULL
&& pWindow
!= NULL
&& mxShape
.is())
155 // #107948# Determine whether shape text is empty
156 SdrObject
* pSdrObject
= GetSdrObjectFromXShape(mxShape
);
159 SdrTextObj
* pTextObj
= PTR_CAST( SdrTextObj
, pSdrObject
);
160 OutlinerParaObject
* pOutlinerParaObject
= NULL
;
163 pOutlinerParaObject
= pTextObj
->GetEditOutlinerParaObject(); // Get the OutlinerParaObject if text edit is active
165 bool bOwnParaObj
= pOutlinerParaObject
!= NULL
;
167 if( !pOutlinerParaObject
&& pSdrObject
)
168 pOutlinerParaObject
= pSdrObject
->GetOutlinerParaObject();
170 // create AccessibleTextHelper to handle this shape's text
171 if( !pOutlinerParaObject
)
173 // empty text -> use proxy edit source to delay creation of EditEngine
174 SAL_WNODEPRECATED_DECLARATIONS_PUSH
175 ::std::auto_ptr
<SvxEditSource
> pEditSource( new AccessibleEmptyEditSource ( *pSdrObject
, *pView
, *pWindow
) );
176 SAL_WNODEPRECATED_DECLARATIONS_POP
177 mpText
= new AccessibleTextHelper( pEditSource
);
181 // non-empty text -> use full-fledged edit source right away
182 SAL_WNODEPRECATED_DECLARATIONS_PUSH
183 ::std::auto_ptr
<SvxEditSource
> pEditSource( new SvxTextEditSource ( *pSdrObject
, 0, *pView
, *pWindow
) );
184 SAL_WNODEPRECATED_DECLARATIONS_POP
185 mpText
= new AccessibleTextHelper( pEditSource
);
189 delete pOutlinerParaObject
;
191 mpText
->SetEventSource(this);
200 void AccessibleShape::UpdateStates (void)
202 ::utl::AccessibleStateSetHelper
* pStateSet
=
203 static_cast< ::utl::AccessibleStateSetHelper
*>(mxStateSet
.get());
204 if (pStateSet
== NULL
)
207 // Set the opaque state for certain shape types when their fill style is
209 bool bShapeIsOpaque
= false;
210 switch (ShapeTypeHandler::Instance().GetTypeId (mxShape
))
213 case DRAWING_RECTANGLE
:
216 uno::Reference
<beans::XPropertySet
> xSet (mxShape
, uno::UNO_QUERY
);
221 drawing::FillStyle aFillStyle
;
222 bShapeIsOpaque
= ( xSet
->getPropertyValue (OUString("FillStyle")) >>= aFillStyle
)
223 && aFillStyle
== drawing::FillStyle_SOLID
;
225 catch (::com::sun::star::beans::UnknownPropertyException
&)
233 pStateSet
->AddState (AccessibleStateType::OPAQUE
);
235 pStateSet
->RemoveState (AccessibleStateType::OPAQUE
);
237 // Set the selected state.
238 bool bShapeIsSelected
= false;
239 // XXX fix_me this has to be done with an extra interface later on
240 if ( m_pShape
&& maShapeTreeInfo
.GetSdrView() )
242 bShapeIsSelected
= maShapeTreeInfo
.GetSdrView()->IsObjMarked(m_pShape
) == sal_True
;
245 if (bShapeIsSelected
)
246 pStateSet
->AddState (AccessibleStateType::SELECTED
);
248 pStateSet
->RemoveState (AccessibleStateType::SELECTED
);
254 bool AccessibleShape::operator== (const AccessibleShape
& rShape
)
256 return this==&rShape
;
262 sal_Bool
AccessibleShape::SetState (sal_Int16 aState
)
264 sal_Bool bStateHasChanged
= sal_False
;
266 if (aState
== AccessibleStateType::FOCUSED
&& mpText
!= NULL
)
268 // Offer FOCUSED state to edit engine and detect whether the state
270 sal_Bool bIsFocused
= mpText
->HaveFocus ();
271 mpText
->SetFocus (sal_True
);
272 bStateHasChanged
= (bIsFocused
!= mpText
->HaveFocus ());
275 bStateHasChanged
= AccessibleContextBase::SetState (aState
);
277 return bStateHasChanged
;
283 sal_Bool
AccessibleShape::ResetState (sal_Int16 aState
)
285 sal_Bool bStateHasChanged
= sal_False
;
287 if (aState
== AccessibleStateType::FOCUSED
&& mpText
!= NULL
)
289 // Try to remove FOCUSED state from the edit engine and detect
290 // whether the state changes.
291 sal_Bool bIsFocused
= mpText
->HaveFocus ();
292 mpText
->SetFocus (sal_False
);
293 bStateHasChanged
= (bIsFocused
!= mpText
->HaveFocus ());
296 bStateHasChanged
= AccessibleContextBase::ResetState (aState
);
298 return bStateHasChanged
;
304 sal_Bool
AccessibleShape::GetState (sal_Int16 aState
)
306 if (aState
== AccessibleStateType::FOCUSED
&& mpText
!= NULL
)
308 // Just delegate the call to the edit engine. The state is not
309 // merged into the state set.
310 return mpText
->HaveFocus();
313 return AccessibleContextBase::GetState (aState
);
319 //===== XAccessibleContext ==================================================
321 /** The children of this shape come from two sources: The children from
322 group or scene shapes and the paragraphs of text.
325 AccessibleShape::getAccessibleChildCount ()
326 throw (::com::sun::star::uno::RuntimeException
)
329 sal_Int32 nChildCount
= 0;
331 // Add the number of shapes that are children of this shape.
332 if (mpChildrenManager
!= NULL
)
333 nChildCount
+= mpChildrenManager
->GetChildCount ();
334 // Add the number text paragraphs.
336 nChildCount
+= mpText
->GetChildCount ();
344 /** Forward the request to the shape. Return the requested shape or throw
345 an exception for a wrong index.
347 uno::Reference
<XAccessible
> SAL_CALL
348 AccessibleShape::getAccessibleChild (sal_Int32 nIndex
)
349 throw (::com::sun::star::lang::IndexOutOfBoundsException
, ::com::sun::star::uno::RuntimeException
)
353 uno::Reference
<XAccessible
> xChild
;
355 // Depending on the index decide whether to delegate this call to the
356 // children manager or the edit engine.
357 if ((mpChildrenManager
!= NULL
)
358 && (nIndex
< mpChildrenManager
->GetChildCount()))
360 xChild
= mpChildrenManager
->GetChild (nIndex
);
362 else if (mpText
!= NULL
)
364 sal_Int32 nI
= nIndex
;
365 if (mpChildrenManager
!= NULL
)
366 nI
-= mpChildrenManager
->GetChildCount();
367 xChild
= mpText
->GetChild (nI
);
370 throw lang::IndexOutOfBoundsException (
371 OUString("shape has no child with index ")
372 + OUString::valueOf(nIndex
),
373 static_cast<uno::XWeak
*>(this));
381 /** Return a copy of the state set.
387 uno::Reference
<XAccessibleStateSet
> SAL_CALL
388 AccessibleShape::getAccessibleStateSet (void)
389 throw (::com::sun::star::uno::RuntimeException
)
391 ::osl::MutexGuard
aGuard (maMutex
);
392 Reference
<XAccessibleStateSet
> xStateSet
;
394 if (rBHelper
.bDisposed
|| mpText
== NULL
)
395 // Return a minimal state set that only contains the DEFUNC state.
396 xStateSet
= AccessibleContextBase::getAccessibleStateSet ();
399 ::utl::AccessibleStateSetHelper
* pStateSet
=
400 static_cast< ::utl::AccessibleStateSetHelper
*>(mxStateSet
.get());
402 if (pStateSet
!= NULL
)
404 // Merge current FOCUSED state from edit engine.
407 if (mpText
->HaveFocus())
408 pStateSet
->AddState (AccessibleStateType::FOCUSED
);
410 pStateSet
->RemoveState (AccessibleStateType::FOCUSED
);
413 // Create a copy of the state set that may be modified by the
414 // caller without affecting the current state set.
415 xStateSet
= Reference
<XAccessibleStateSet
>(
416 new ::utl::AccessibleStateSetHelper (*pStateSet
));
426 //===== XAccessibleComponent ================================================
428 /** The implementation below is at the moment straightforward. It iterates
429 over all children (and thereby instances all children which have not
430 been already instatiated) until a child covering the specifed point is
432 This leaves room for improvement. For instance, first iterate only over
433 the already instantiated children and only if no match is found
434 instantiate the remaining ones.
436 uno::Reference
<XAccessible
> SAL_CALL
437 AccessibleShape::getAccessibleAtPoint (
438 const awt::Point
& aPoint
)
439 throw (uno::RuntimeException
)
441 ::osl::MutexGuard
aGuard (maMutex
);
443 sal_Int32 nChildCount
= getAccessibleChildCount ();
444 for (sal_Int32 i
=0; i
<nChildCount
; ++i
)
446 Reference
<XAccessible
> xChild (getAccessibleChild (i
));
449 Reference
<XAccessibleComponent
> xChildComponent (
450 xChild
->getAccessibleContext(), uno::UNO_QUERY
);
451 if (xChildComponent
.is())
453 awt::Rectangle
aBBox (xChildComponent
->getBounds());
454 if ( (aPoint
.X
>= aBBox
.X
)
455 && (aPoint
.Y
>= aBBox
.Y
)
456 && (aPoint
.X
< aBBox
.X
+aBBox
.Width
)
457 && (aPoint
.Y
< aBBox
.Y
+aBBox
.Height
) )
463 // Have not found a child under the given point. Returning empty
464 // reference to indicate this.
465 return uno::Reference
<XAccessible
>();
471 awt::Rectangle SAL_CALL
AccessibleShape::getBounds (void)
472 throw (::com::sun::star::uno::RuntimeException
)
474 SolarMutexGuard aSolarGuard
;
475 ::osl::MutexGuard
aGuard (maMutex
);
478 awt::Rectangle aBoundingBox
;
482 static const OUString
sBoundRectName ("BoundRect");
483 static const OUString
sAnchorPositionName ("AnchorPosition");
485 // Get the shape's bounding box in internal coordinates (in 100th of
486 // mm). Use the property BoundRect. Only if that is not supported ask
487 // the shape for its position and size directly.
488 Reference
<beans::XPropertySet
> xSet (mxShape
, uno::UNO_QUERY
);
489 Reference
<beans::XPropertySetInfo
> xSetInfo
;
490 bool bFoundBoundRect
= false;
493 xSetInfo
= xSet
->getPropertySetInfo ();
496 if (xSetInfo
->hasPropertyByName (sBoundRectName
))
500 uno::Any aValue
= xSet
->getPropertyValue (sBoundRectName
);
501 aValue
>>= aBoundingBox
;
502 bFoundBoundRect
= true;
504 catch (beans::UnknownPropertyException
const&)
506 // Handled below (bFoundBoundRect stays false).
510 OSL_TRACE (" no property BoundRect");
514 // Fallback when there is no BoundRect Property.
515 if ( ! bFoundBoundRect
)
517 awt::Point
aPosition (mxShape
->getPosition());
518 awt::Size
aSize (mxShape
->getSize());
519 aBoundingBox
= awt::Rectangle (
520 aPosition
.X
, aPosition
.Y
,
521 aSize
.Width
, aSize
.Height
);
523 // While BoundRects have absolute positions, the position returned
524 // by XPosition::getPosition is relative. Get the anchor position
525 // (usually not (0,0) for Writer shapes).
528 if (xSetInfo
->hasPropertyByName (sAnchorPositionName
))
530 uno::Any aPos
= xSet
->getPropertyValue (sAnchorPositionName
);
531 awt::Point aAnchorPosition
;
532 aPos
>>= aAnchorPosition
;
533 aBoundingBox
.X
+= aAnchorPosition
.X
;
534 aBoundingBox
.Y
+= aAnchorPosition
.Y
;
539 // Transform coordinates from internal to pixel.
540 if (maShapeTreeInfo
.GetViewForwarder() == NULL
)
541 throw uno::RuntimeException (OUString (
542 "AccessibleShape has no valid view forwarder"),
543 static_cast<uno::XWeak
*>(this));
544 ::Size aPixelSize
= maShapeTreeInfo
.GetViewForwarder()->LogicToPixel (
545 ::Size (aBoundingBox
.Width
, aBoundingBox
.Height
));
546 ::Point aPixelPosition
= maShapeTreeInfo
.GetViewForwarder()->LogicToPixel (
547 ::Point (aBoundingBox
.X
, aBoundingBox
.Y
));
549 // Clip the shape's bounding box with the bounding box of its parent.
550 Reference
<XAccessibleComponent
> xParentComponent (
551 getAccessibleParent(), uno::UNO_QUERY
);
552 if (xParentComponent
.is())
554 // Make the coordinates relative to the parent.
555 awt::Point
aParentLocation (xParentComponent
->getLocationOnScreen());
556 int x
= aPixelPosition
.getX() - aParentLocation
.X
;
557 int y
= aPixelPosition
.getY() - aParentLocation
.Y
;
559 // Clip with parent (with coordinates relative to itself).
561 x
, y
, x
+ aPixelSize
.getWidth(), y
+ aPixelSize
.getHeight());
562 awt::Size
aParentSize (xParentComponent
->getSize());
563 ::Rectangle
aParentBBox (0,0, aParentSize
.Width
, aParentSize
.Height
);
564 aBBox
= aBBox
.GetIntersection (aParentBBox
);
565 aBoundingBox
= awt::Rectangle (
573 OSL_TRACE ("parent does not support component");
574 aBoundingBox
= awt::Rectangle (
575 aPixelPosition
.getX(), aPixelPosition
.getY(),
576 aPixelSize
.getWidth(), aPixelSize
.getHeight());
586 awt::Point SAL_CALL
AccessibleShape::getLocation (void)
587 throw (::com::sun::star::uno::RuntimeException
)
590 awt::Rectangle
aBoundingBox (getBounds());
591 return awt::Point (aBoundingBox
.X
, aBoundingBox
.Y
);
597 awt::Point SAL_CALL
AccessibleShape::getLocationOnScreen (void)
598 throw (::com::sun::star::uno::RuntimeException
)
602 // Get relative position...
603 awt::Point
aLocation (getLocation ());
605 // ... and add absolute position of the parent.
606 uno::Reference
<XAccessibleComponent
> xParentComponent (
607 getAccessibleParent(), uno::UNO_QUERY
);
608 if (xParentComponent
.is())
610 awt::Point
aParentLocation (xParentComponent
->getLocationOnScreen());
611 aLocation
.X
+= aParentLocation
.X
;
612 aLocation
.Y
+= aParentLocation
.Y
;
615 OSL_TRACE ("getLocation: parent does not support XAccessibleComponent");
622 awt::Size SAL_CALL
AccessibleShape::getSize (void)
623 throw (uno::RuntimeException
)
626 awt::Rectangle
aBoundingBox (getBounds());
627 return awt::Size (aBoundingBox
.Width
, aBoundingBox
.Height
);
633 sal_Int32 SAL_CALL
AccessibleShape::getForeground (void)
634 throw (::com::sun::star::uno::RuntimeException
)
637 sal_Int32
nColor (0x0ffffffL
);
641 uno::Reference
<beans::XPropertySet
> aSet (mxShape
, uno::UNO_QUERY
);
645 aColor
= aSet
->getPropertyValue (OUString("LineColor"));
649 catch (const ::com::sun::star::beans::UnknownPropertyException
&)
651 // Ignore exception and return default color.
659 sal_Int32 SAL_CALL
AccessibleShape::getBackground (void)
660 throw (::com::sun::star::uno::RuntimeException
)
663 sal_Int32
nColor (0L);
667 uno::Reference
<beans::XPropertySet
> aSet (mxShape
, uno::UNO_QUERY
);
671 aColor
= aSet
->getPropertyValue (OUString("FillColor"));
675 catch (const ::com::sun::star::beans::UnknownPropertyException
&)
677 // Ignore exception and return default color.
685 //===== XAccessibleEventBroadcaster =========================================
687 void SAL_CALL
AccessibleShape::addAccessibleEventListener (
688 const Reference
<XAccessibleEventListener
>& rxListener
)
689 throw (uno::RuntimeException
)
691 if (rBHelper
.bDisposed
|| rBHelper
.bInDispose
)
693 uno::Reference
<uno::XInterface
> xThis (
694 (lang::XComponent
*)this, uno::UNO_QUERY
);
695 rxListener
->disposing (lang::EventObject (xThis
));
699 AccessibleContextBase::addAccessibleEventListener (rxListener
);
701 mpText
->AddEventListener (rxListener
);
708 void SAL_CALL
AccessibleShape::removeAccessibleEventListener (
709 const Reference
<XAccessibleEventListener
>& rxListener
)
710 throw (uno::RuntimeException
)
712 AccessibleContextBase::removeAccessibleEventListener (rxListener
);
714 mpText
->RemoveEventListener (rxListener
);
720 //===== XInterface ==========================================================
722 com::sun::star::uno::Any SAL_CALL
723 AccessibleShape::queryInterface (const com::sun::star::uno::Type
& rType
)
724 throw (::com::sun::star::uno::RuntimeException
)
726 ::com::sun::star::uno::Any aReturn
= AccessibleContextBase::queryInterface (rType
);
727 if ( ! aReturn
.hasValue())
728 aReturn
= ::cppu::queryInterface (rType
,
729 static_cast<XAccessibleComponent
*>(this),
730 static_cast<XAccessibleExtendedComponent
*>(this),
731 static_cast<lang::XEventListener
*>(this),
732 static_cast<document::XEventListener
*>(this),
733 static_cast<lang::XUnoTunnel
*>(this)
742 AccessibleShape::acquire (void)
745 AccessibleContextBase::acquire ();
752 AccessibleShape::release (void)
755 AccessibleContextBase::release ();
761 //===== XServiceInfo ========================================================
764 AccessibleShape::getImplementationName (void)
765 throw (::com::sun::star::uno::RuntimeException
)
767 return OUString("AccessibleShape");
773 uno::Sequence
<OUString
> SAL_CALL
774 AccessibleShape::getSupportedServiceNames (void)
775 throw (::com::sun::star::uno::RuntimeException
)
778 // Get list of supported service names from base class...
779 uno::Sequence
<OUString
> aServiceNames
=
780 AccessibleContextBase::getSupportedServiceNames();
781 sal_Int32
nCount (aServiceNames
.getLength());
783 // ...and add additional names.
784 aServiceNames
.realloc (nCount
+ 1);
785 static const OUString
sAdditionalServiceName ("com.sun.star.drawing.AccessibleShape");
786 aServiceNames
[nCount
] = sAdditionalServiceName
;
788 return aServiceNames
;
795 //===== XTypeProvider ===================================================
797 uno::Sequence
<uno::Type
> SAL_CALL
798 AccessibleShape::getTypes (void)
799 throw (uno::RuntimeException
)
802 // Get list of types from the context base implementation, ...
803 uno::Sequence
<uno::Type
> aTypeList (AccessibleContextBase::getTypes());
804 // ... get list of types from component base implementation, ...
805 uno::Sequence
<uno::Type
> aComponentTypeList (AccessibleComponentBase::getTypes());
806 // ... define local types, ...
807 const uno::Type aLangEventListenerType
=
808 ::getCppuType((const uno::Reference
<lang::XEventListener
>*)0);
809 const uno::Type aDocumentEventListenerType
=
810 ::getCppuType((const uno::Reference
<document::XEventListener
>*)0);
811 const uno::Type aUnoTunnelType
=
812 ::getCppuType((const uno::Reference
<lang::XUnoTunnel
>*)0);
814 // ... and merge them all into one list.
815 sal_Int32
nTypeCount (aTypeList
.getLength()),
816 nComponentTypeCount (aComponentTypeList
.getLength());
819 aTypeList
.realloc (nTypeCount
+ nComponentTypeCount
+ 3);
821 for (i
=0; i
<nComponentTypeCount
; i
++)
822 aTypeList
[nTypeCount
+ i
] = aComponentTypeList
[i
];
824 aTypeList
[nTypeCount
+ i
++ ] = aLangEventListenerType
;
825 aTypeList
[nTypeCount
+ i
++ ] = aDocumentEventListenerType
;
826 aTypeList
[nTypeCount
+ i
] = aUnoTunnelType
;
834 //===== lang::XEventListener ================================================
836 /** Disposing calls are accepted only from the model: Just reset the
837 reference to the model in the shape tree info. Otherwise this object
841 AccessibleShape::disposing (const lang::EventObject
& aEvent
)
842 throw (uno::RuntimeException
)
844 SolarMutexGuard aSolarGuard
;
845 ::osl::MutexGuard
aGuard (maMutex
);
849 if (aEvent
.Source
== maShapeTreeInfo
.GetModelBroadcaster())
851 // Remove reference to model broadcaster to allow it to pass
853 maShapeTreeInfo
.SetModelBroadcaster(NULL
);
857 catch (uno::RuntimeException
const&)
859 OSL_TRACE ("caught exception while disposing");
866 //===== document::XEventListener ============================================
869 AccessibleShape::notifyEvent (const document::EventObject
& rEventObject
)
870 throw (uno::RuntimeException
)
872 static const OUString
sShapeModified ("ShapeModified");
874 // First check if the event is for us.
875 uno::Reference
<drawing::XShape
> xShape (
876 rEventObject
.Source
, uno::UNO_QUERY
);
877 if ( xShape
.get() == mxShape
.get() )
879 if (rEventObject
.EventName
.equals (sShapeModified
))
881 // Some property of a shape has been modified. Send an event
882 // that indicates a change of the visible data to all listeners.
884 AccessibleEventId::VISIBLE_DATA_CHANGED
,
888 // Name and Description may have changed. Update the local
889 // values accordingly.
890 UpdateNameAndDescription();
895 //===== lang::XUnoTunnel ================================================
899 class theAccessibleShapeImplementationId
: public rtl::Static
< UnoTunnelIdInit
, theAccessibleShapeImplementationId
> {};
902 const uno::Sequence
< sal_Int8
>&
903 AccessibleShape::getUnoTunnelImplementationId()
906 return theAccessibleShapeImplementationId::get().getSeq();
909 //------------------------------------------------------------------------------
911 AccessibleShape::getImplementation( const uno::Reference
< uno::XInterface
>& rxIFace
)
914 uno::Reference
< lang::XUnoTunnel
> xTunnel( rxIFace
, uno::UNO_QUERY
);
915 AccessibleShape
* pReturn
= NULL
;
918 pReturn
= reinterpret_cast< AccessibleShape
* >( xTunnel
->getSomething( getUnoTunnelImplementationId() ) );
923 //------------------------------------------------------------------------------
925 AccessibleShape::getSomething( const uno::Sequence
< sal_Int8
>& rIdentifier
)
926 throw(uno::RuntimeException
)
928 sal_Int64
nReturn( 0 );
930 if( ( rIdentifier
.getLength() == 16 ) && ( 0 == memcmp( getUnoTunnelImplementationId().getConstArray(), rIdentifier
.getConstArray(), 16 ) ) )
931 nReturn
= reinterpret_cast< sal_Int64
>( this );
936 //===== IAccessibleViewForwarderListener ====================================
938 void AccessibleShape::ViewForwarderChanged (ChangeType aChangeType
,
939 const IAccessibleViewForwarder
* pViewForwarder
)
941 // Inform all listeners that the graphical representation (i.e. size
942 // and/or position) of the shape has changed.
943 CommitChange (AccessibleEventId::VISIBLE_DATA_CHANGED
,
947 // Tell children manager of the modified view forwarder.
948 if (mpChildrenManager
!= NULL
)
949 mpChildrenManager
->ViewForwarderChanged (aChangeType
, pViewForwarder
);
951 // update our children that our screen position might have changed
953 mpText
->UpdateChildren();
959 //===== protected internal ==================================================
960 /// Set this object's name if is different to the current name.
962 AccessibleShape::CreateAccessibleBaseName (void)
963 throw (::com::sun::star::uno::RuntimeException
)
965 return ShapeTypeHandler::CreateAccessibleBaseName( mxShape
);
970 AccessibleShape::CreateAccessibleName (void)
971 throw (::com::sun::star::uno::RuntimeException
)
973 OUString
sName (CreateAccessibleBaseName());
975 // Append the shape's index to the name to disambiguate between shapes
976 // of the same type. If such an index where not given to the
977 // constructor then use the z-order instead. If even that does not exist
978 // we throw an exception.
979 long nIndex
= mnIndex
;
984 uno::Reference
<beans::XPropertySet
> xSet (mxShape
, uno::UNO_QUERY
);
987 uno::Any
aZOrder (xSet
->getPropertyValue (OUString("ZOrder")));
990 // Add one to be not zero based.
994 catch (const beans::UnknownPropertyException
&)
996 // We throw our own exception that is a bit more informative.
997 throw uno::RuntimeException (OUString (
998 "AccessibleShape has invalid index and no ZOrder property"),
999 static_cast<uno::XWeak
*>(this));
1004 // Put a space between name and index because of Gnopernicus othewise
1006 sName
+= " " + OUString::valueOf (nIndex
);
1015 AccessibleShape::CreateAccessibleDescription (void)
1016 throw (::com::sun::star::uno::RuntimeException
)
1018 DescriptionGenerator
aDG (mxShape
);
1019 aDG
.Initialize (CreateAccessibleBaseName());
1020 switch (ShapeTypeHandler::Instance().GetTypeId (mxShape
))
1022 case DRAWING_3D_CUBE
:
1023 case DRAWING_3D_EXTRUDE
:
1024 case DRAWING_3D_LATHE
:
1025 case DRAWING_3D_SPHERE
:
1026 aDG
.Add3DProperties ();
1029 case DRAWING_3D_SCENE
:
1032 // No further information is appended.
1035 case DRAWING_CAPTION
:
1036 case DRAWING_CLOSED_BEZIER
:
1037 case DRAWING_CLOSED_FREEHAND
:
1038 case DRAWING_ELLIPSE
:
1039 case DRAWING_POLY_POLYGON
:
1040 case DRAWING_POLY_POLYGON_PATH
:
1041 case DRAWING_RECTANGLE
:
1042 aDG
.AddLineProperties ();
1043 aDG
.AddFillProperties ();
1046 case DRAWING_CONNECTOR
:
1048 case DRAWING_MEASURE
:
1049 case DRAWING_OPEN_BEZIER
:
1050 case DRAWING_OPEN_FREEHAND
:
1051 case DRAWING_POLY_LINE
:
1052 case DRAWING_POLY_LINE_PATH
:
1053 aDG
.AddLineProperties ();
1056 case DRAWING_CONTROL
:
1057 aDG
.AddProperty ("ControlBackground", DescriptionGenerator::COLOR
, "");
1058 aDG
.AddProperty ("ControlBorder", DescriptionGenerator::INTEGER
, "");
1062 aDG
.AddTextProperties ();
1066 aDG
.Initialize ("Unknown accessible shape");
1067 uno::Reference
<drawing::XShapeDescriptor
> xDescriptor (mxShape
, uno::UNO_QUERY
);
1068 if (xDescriptor
.is())
1070 aDG
.AppendString ("service name=");
1071 aDG
.AppendString (xDescriptor
->getShapeType());
1081 uno::Reference
< drawing::XShape
> AccessibleShape::GetXShape()
1089 void AccessibleShape::disposing (void)
1091 SolarMutexGuard aSolarGuard
;
1092 ::osl::MutexGuard
aGuard (maMutex
);
1094 // Make sure to send an event that this object looses the focus in the
1095 // case that it has the focus.
1096 ::utl::AccessibleStateSetHelper
* pStateSet
=
1097 static_cast< ::utl::AccessibleStateSetHelper
*>(mxStateSet
.get());
1098 if (pStateSet
!= NULL
)
1099 pStateSet
->RemoveState (AccessibleStateType::FOCUSED
);
1101 // Unregister from broadcasters.
1102 Reference
<lang::XComponent
> xComponent (mxShape
, uno::UNO_QUERY
);
1103 if (xComponent
.is())
1104 xComponent
->removeEventListener (this);
1106 // Unregister from model.
1107 if (maShapeTreeInfo
.GetModelBroadcaster().is())
1108 maShapeTreeInfo
.GetModelBroadcaster()->removeEventListener (
1109 static_cast<document::XEventListener
*>(this));
1111 // Release the child containers.
1112 if (mpChildrenManager
!= NULL
)
1114 delete mpChildrenManager
;
1115 mpChildrenManager
= NULL
;
1124 // Cleanup. Remove references to objects to allow them to be
1127 maShapeTreeInfo
= AccessibleShapeTreeInfo();
1129 // Call base classes.
1130 AccessibleContextBase::dispose ();
1134 AccessibleShape::getAccessibleIndexInParent (void)
1135 throw (::com::sun::star::uno::RuntimeException
)
1138 // Use a simple but slow solution for now. Optimize later.
1140 sal_Int32 nIndex
= m_nIndexInParent
;
1142 nIndex
= AccessibleContextBase::getAccessibleIndexInParent();
1149 void AccessibleShape::UpdateNameAndDescription (void)
1151 // Ignore missing title, name, or description. There are fallbacks for
1155 Reference
<beans::XPropertySet
> xSet (mxShape
, uno::UNO_QUERY_THROW
);
1158 // Get the accessible name.
1159 sString
= GetOptionalProperty(xSet
, "Title");
1160 if (!sString
.isEmpty())
1162 SetAccessibleName(sString
, AccessibleContextBase::FromShape
);
1166 sString
= GetOptionalProperty(xSet
, "Name");
1167 if (!sString
.isEmpty())
1168 SetAccessibleName(sString
, AccessibleContextBase::FromShape
);
1171 // Get the accessible description.
1172 sString
= GetOptionalProperty(xSet
, "Description");
1173 if (!sString
.isEmpty())
1174 SetAccessibleDescription(sString
, AccessibleContextBase::FromShape
);
1176 catch (uno::RuntimeException
&)
1181 } // end of namespace accessibility
1183 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */