summaryrefslogtreecommitdiff
path: root/svx/source/accessibility/AccessibleShape.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'svx/source/accessibility/AccessibleShape.cxx')
-rwxr-xr-xsvx/source/accessibility/AccessibleShape.cxx1244
1 files changed, 1244 insertions, 0 deletions
diff --git a/svx/source/accessibility/AccessibleShape.cxx b/svx/source/accessibility/AccessibleShape.cxx
new file mode 100755
index 000000000000..28cdb8b0882b
--- /dev/null
+++ b/svx/source/accessibility/AccessibleShape.cxx
@@ -0,0 +1,1244 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+#include <svx/AccessibleShape.hxx>
+#include "DescriptionGenerator.hxx"
+#include <svx/AccessibleShapeInfo.hxx>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <rtl/uuid.h>
+#ifndef _COM_SUN_STAR_ACCESSIBILITY_ACCESSIBLE_ROLE_HPP_
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#endif
+#ifndef _COM_SUN_STAR_ACCESSIBILITY_ACCESSIBLE_STATE_TYPE_HPP_
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#endif
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
+#include <com/sun/star/drawing/XShapeDescriptor.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/text/XText.hpp>
+#include <editeng/outlobj.hxx>
+#include <rtl/ref.hxx>
+#include <editeng/unoedsrc.hxx>
+#include <svx/unoshtxt.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/svdmodel.hxx>
+#include "unoapi.hxx"
+#include <com/sun/star/uno/Exception.hpp>
+#include <svx/ShapeTypeHandler.hxx>
+#include <svx/SvxShapeTypes.hxx>
+
+#ifndef _SVX_ACCESSIBILITY_HRC
+#include "accessibility.hrc"
+#endif
+#include "svdstr.hrc"
+#include <svx/dialmgr.hxx>
+#include <vcl/svapp.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <svx/svdview.hxx>
+#include "AccessibleEmptyEditSource.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+using ::com::sun::star::uno::Reference;
+using ::rtl::OUString;
+
+namespace accessibility {
+
+namespace {
+
+OUString GetOptionalProperty (
+ const Reference<beans::XPropertySet>& rxSet,
+ const OUString& rsPropertyName)
+{
+ OUString sValue;
+
+ if (rxSet.is())
+ {
+ const Reference<beans::XPropertySetInfo> xInfo (rxSet->getPropertySetInfo());
+ if ( ! xInfo.is() || xInfo->hasPropertyByName(rsPropertyName))
+ {
+ try
+ {
+ rxSet->getPropertyValue(rsPropertyName) >>= sValue;
+ }
+ catch (beans::UnknownPropertyException&)
+ {
+ // This exception should only be thrown when the property
+ // does not exits (of course) and the XPropertySetInfo is
+ // not available.
+ }
+ }
+ }
+ return sValue;
+}
+
+} // end of anonymous namespace
+
+
+
+
+//===== internal ============================================================
+
+AccessibleShape::AccessibleShape (
+ const AccessibleShapeInfo& rShapeInfo,
+ const AccessibleShapeTreeInfo& rShapeTreeInfo)
+ : AccessibleContextBase (rShapeInfo.mxParent,AccessibleRole::LIST_ITEM),
+ mpChildrenManager(NULL),
+ mxShape (rShapeInfo.mxShape),
+ maShapeTreeInfo (rShapeTreeInfo),
+ mnIndex (rShapeInfo.mnIndex),
+ m_nIndexInParent(-1),
+ mpText (NULL),
+ mpParent (rShapeInfo.mpChildrenManager)
+{
+ m_pShape = GetSdrObjectFromXShape(mxShape);
+ UpdateNameAndDescription();
+}
+
+
+
+
+AccessibleShape::~AccessibleShape (void)
+{
+ if (mpChildrenManager != NULL)
+ delete mpChildrenManager;
+ if (mpText != NULL)
+ delete mpText;
+ OSL_TRACE ("~AccessibleShape");
+
+ // Unregistering from the various broadcasters should be unnecessary
+ // since this destructor would not have been called if one of the
+ // broadcasters would still hold a strong reference to this object.
+}
+
+
+
+
+void AccessibleShape::Init (void)
+{
+ // Update the OPAQUE and SELECTED shape.
+ UpdateStates ();
+
+ // Create a children manager when this shape has children of its own.
+ Reference<drawing::XShapes> xShapes (mxShape, uno::UNO_QUERY);
+ if (xShapes.is() && xShapes->getCount() > 0)
+ mpChildrenManager = new ChildrenManager (
+ this, xShapes, maShapeTreeInfo, *this);
+ if (mpChildrenManager != NULL)
+ mpChildrenManager->Update();
+
+ // Register at model as document::XEventListener.
+ if (maShapeTreeInfo.GetModelBroadcaster().is())
+ maShapeTreeInfo.GetModelBroadcaster()->addEventListener (
+ static_cast<document::XEventListener*>(this));
+
+ // Beware! Here we leave the paths of the UNO API and descend into the
+ // depths of the core. Necessary for makeing the edit engine
+ // accessible.
+ Reference<text::XText> xText (mxShape, uno::UNO_QUERY);
+ if (xText.is())
+ {
+ SdrView* pView = maShapeTreeInfo.GetSdrView ();
+ const Window* pWindow = maShapeTreeInfo.GetWindow ();
+ if (pView != NULL && pWindow != NULL && mxShape.is())
+ {
+ // #107948# Determine whether shape text is empty
+ SdrObject* pSdrObject = GetSdrObjectFromXShape(mxShape);
+ if( pSdrObject )
+ {
+ SdrTextObj* pTextObj = PTR_CAST( SdrTextObj, pSdrObject );
+ OutlinerParaObject* pOutlinerParaObject = NULL;
+
+ if( pTextObj )
+ pOutlinerParaObject = pTextObj->GetEditOutlinerParaObject(); // Get the OutlinerParaObject if text edit is active
+
+ bool bOwnParaObj = pOutlinerParaObject != NULL;
+
+ if( !pOutlinerParaObject && pSdrObject )
+ pOutlinerParaObject = pSdrObject->GetOutlinerParaObject();
+
+ // create AccessibleTextHelper to handle this shape's text
+ if( !pOutlinerParaObject )
+ {
+ // empty text -> use proxy edit source to delay creation of EditEngine
+ ::std::auto_ptr<SvxEditSource> pEditSource( new AccessibleEmptyEditSource ( *pSdrObject, *pView, *pWindow) );
+ mpText = new AccessibleTextHelper( pEditSource );
+ }
+ else
+ {
+ // non-empty text -> use full-fledged edit source right away
+ ::std::auto_ptr<SvxEditSource> pEditSource( new SvxTextEditSource ( *pSdrObject, 0, *pView, *pWindow) );
+ mpText = new AccessibleTextHelper( pEditSource );
+ }
+
+ if( bOwnParaObj )
+ delete pOutlinerParaObject;
+
+ mpText->SetEventSource(this);
+ }
+ }
+ }
+}
+
+
+
+
+void AccessibleShape::UpdateStates (void)
+{
+ ::utl::AccessibleStateSetHelper* pStateSet =
+ static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get());
+ if (pStateSet == NULL)
+ return;
+
+ // Set the opaque state for certain shape types when their fill style is
+ // solid.
+ bool bShapeIsOpaque = false;
+ switch (ShapeTypeHandler::Instance().GetTypeId (mxShape))
+ {
+ case DRAWING_PAGE:
+ case DRAWING_RECTANGLE:
+ case DRAWING_TEXT:
+ {
+ uno::Reference<beans::XPropertySet> xSet (mxShape, uno::UNO_QUERY);
+ if (xSet.is())
+ {
+ try
+ {
+ drawing::FillStyle aFillStyle;
+ bShapeIsOpaque = ( xSet->getPropertyValue (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FillStyle"))) >>= aFillStyle)
+ && aFillStyle == drawing::FillStyle_SOLID;
+ }
+ catch (::com::sun::star::beans::UnknownPropertyException&)
+ {
+ // Ignore.
+ }
+ }
+ }
+ }
+ if (bShapeIsOpaque)
+ pStateSet->AddState (AccessibleStateType::OPAQUE);
+ else
+ pStateSet->RemoveState (AccessibleStateType::OPAQUE);
+
+ // Set the selected state.
+ bool bShapeIsSelected = false;
+ // XXX fix_me this has to be done with an extra interface later on
+ if ( m_pShape && maShapeTreeInfo.GetSdrView() )
+ {
+ bShapeIsSelected = maShapeTreeInfo.GetSdrView()->IsObjMarked(m_pShape) == TRUE;
+ }
+
+ if (bShapeIsSelected)
+ pStateSet->AddState (AccessibleStateType::SELECTED);
+ else
+ pStateSet->RemoveState (AccessibleStateType::SELECTED);
+}
+
+
+
+
+bool AccessibleShape::operator== (const AccessibleShape& rShape)
+{
+ return this==&rShape;
+}
+
+
+
+
+sal_Bool AccessibleShape::SetState (sal_Int16 aState)
+{
+ sal_Bool bStateHasChanged = sal_False;
+
+ if (aState == AccessibleStateType::FOCUSED && mpText != NULL)
+ {
+ // Offer FOCUSED state to edit engine and detect whether the state
+ // changes.
+ sal_Bool bIsFocused = mpText->HaveFocus ();
+ mpText->SetFocus (sal_True);
+ bStateHasChanged = (bIsFocused != mpText->HaveFocus ());
+ }
+ else
+ bStateHasChanged = AccessibleContextBase::SetState (aState);
+
+ return bStateHasChanged;
+}
+
+
+
+
+sal_Bool AccessibleShape::ResetState (sal_Int16 aState)
+{
+ sal_Bool bStateHasChanged = sal_False;
+
+ if (aState == AccessibleStateType::FOCUSED && mpText != NULL)
+ {
+ // Try to remove FOCUSED state from the edit engine and detect
+ // whether the state changes.
+ sal_Bool bIsFocused = mpText->HaveFocus ();
+ mpText->SetFocus (sal_False);
+ bStateHasChanged = (bIsFocused != mpText->HaveFocus ());
+ }
+ else
+ bStateHasChanged = AccessibleContextBase::ResetState (aState);
+
+ return bStateHasChanged;
+}
+
+
+
+
+sal_Bool AccessibleShape::GetState (sal_Int16 aState)
+{
+ if (aState == AccessibleStateType::FOCUSED && mpText != NULL)
+ {
+ // Just delegate the call to the edit engine. The state is not
+ // merged into the state set.
+ return mpText->HaveFocus();
+ }
+ else
+ return AccessibleContextBase::GetState (aState);
+}
+
+
+
+
+//===== XAccessibleContext ==================================================
+
+/** The children of this shape come from two sources: The children from
+ group or scene shapes and the paragraphs of text.
+*/
+sal_Int32 SAL_CALL
+ AccessibleShape::getAccessibleChildCount ()
+ throw (::com::sun::star::uno::RuntimeException)
+{
+ ThrowIfDisposed ();
+ sal_Int32 nChildCount = 0;
+
+ // Add the number of shapes that are children of this shape.
+ if (mpChildrenManager != NULL)
+ nChildCount += mpChildrenManager->GetChildCount ();
+ // Add the number text paragraphs.
+ if (mpText != NULL)
+ nChildCount += mpText->GetChildCount ();
+
+ return nChildCount;
+}
+
+
+
+
+/** Forward the request to the shape. Return the requested shape or throw
+ an exception for a wrong index.
+*/
+uno::Reference<XAccessible> SAL_CALL
+ AccessibleShape::getAccessibleChild (sal_Int32 nIndex)
+ throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
+{
+ ThrowIfDisposed ();
+
+ uno::Reference<XAccessible> xChild;
+
+ // Depending on the index decide whether to delegate this call to the
+ // children manager or the edit engine.
+ if ((mpChildrenManager != NULL)
+ && (nIndex < mpChildrenManager->GetChildCount()))
+ {
+ xChild = mpChildrenManager->GetChild (nIndex);
+ }
+ else if (mpText != NULL)
+ {
+ sal_Int32 nI = nIndex;
+ if (mpChildrenManager != NULL)
+ nI -= mpChildrenManager->GetChildCount();
+ xChild = mpText->GetChild (nI);
+ }
+ else
+ throw lang::IndexOutOfBoundsException (
+ ::rtl::OUString::createFromAscii ("shape has no child with index ")
+ + rtl::OUString::valueOf(nIndex),
+ static_cast<uno::XWeak*>(this));
+
+ return xChild;
+}
+
+
+
+
+/** Return a copy of the state set.
+ Possible states are:
+ ENABLED
+ SHOWING
+ VISIBLE
+*/
+uno::Reference<XAccessibleStateSet> SAL_CALL
+ AccessibleShape::getAccessibleStateSet (void)
+ throw (::com::sun::star::uno::RuntimeException)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+ Reference<XAccessibleStateSet> xStateSet;
+
+ if (rBHelper.bDisposed || mpText == NULL)
+ // Return a minimal state set that only contains the DEFUNC state.
+ xStateSet = AccessibleContextBase::getAccessibleStateSet ();
+ else
+ {
+ ::utl::AccessibleStateSetHelper* pStateSet =
+ static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get());
+
+ if (pStateSet != NULL)
+ {
+ // Merge current FOCUSED state from edit engine.
+ if (mpText != NULL)
+ {
+ if (mpText->HaveFocus())
+ pStateSet->AddState (AccessibleStateType::FOCUSED);
+ else
+ pStateSet->RemoveState (AccessibleStateType::FOCUSED);
+ }
+
+ // Create a copy of the state set that may be modified by the
+ // caller without affecting the current state set.
+ xStateSet = Reference<XAccessibleStateSet>(
+ new ::utl::AccessibleStateSetHelper (*pStateSet));
+ }
+ }
+
+ return xStateSet;
+}
+
+
+
+
+//===== XAccessibleComponent ================================================
+
+/** The implementation below is at the moment straightforward. It iterates
+ over all children (and thereby instances all children which have not
+ been already instatiated) until a child covering the specifed point is
+ found.
+ This leaves room for improvement. For instance, first iterate only over
+ the already instantiated children and only if no match is found
+ instantiate the remaining ones.
+*/
+uno::Reference<XAccessible > SAL_CALL
+ AccessibleShape::getAccessibleAtPoint (
+ const awt::Point& aPoint)
+ throw (uno::RuntimeException)
+{
+ ::osl::MutexGuard aGuard (maMutex);
+
+ sal_Int32 nChildCount = getAccessibleChildCount ();
+ for (sal_Int32 i=0; i<nChildCount; ++i)
+ {
+ Reference<XAccessible> xChild (getAccessibleChild (i));
+ if (xChild.is())
+ {
+ Reference<XAccessibleComponent> xChildComponent (
+ xChild->getAccessibleContext(), uno::UNO_QUERY);
+ if (xChildComponent.is())
+ {
+ awt::Rectangle aBBox (xChildComponent->getBounds());
+ if ( (aPoint.X >= aBBox.X)
+ && (aPoint.Y >= aBBox.Y)
+ && (aPoint.X < aBBox.X+aBBox.Width)
+ && (aPoint.Y < aBBox.Y+aBBox.Height) )
+ return xChild;
+ }
+ }
+ }
+
+ // Have not found a child under the given point. Returning empty
+ // reference to indicate this.
+ return uno::Reference<XAccessible>();
+}
+
+
+
+
+awt::Rectangle SAL_CALL AccessibleShape::getBounds (void)
+ throw (::com::sun::star::uno::RuntimeException)
+{
+ ::vos::OGuard aSolarGuard (::Application::GetSolarMutex());
+ ::osl::MutexGuard aGuard (maMutex);
+
+ ThrowIfDisposed ();
+ awt::Rectangle aBoundingBox;
+ if ( mxShape.is() )
+ {
+
+ static const OUString sBoundRectName (
+ RTL_CONSTASCII_USTRINGPARAM("BoundRect"));
+ static const OUString sAnchorPositionName (
+ RTL_CONSTASCII_USTRINGPARAM("AnchorPosition"));
+
+ // Get the shape's bounding box in internal coordinates (in 100th of
+ // mm). Use the property BoundRect. Only if that is not supported ask
+ // the shape for its position and size directly.
+ Reference<beans::XPropertySet> xSet (mxShape, uno::UNO_QUERY);
+ Reference<beans::XPropertySetInfo> xSetInfo;
+ bool bFoundBoundRect = false;
+ if (xSet.is())
+ {
+ xSetInfo = xSet->getPropertySetInfo ();
+ if (xSetInfo.is())
+ {
+ if (xSetInfo->hasPropertyByName (sBoundRectName))
+ {
+ try
+ {
+ uno::Any aValue = xSet->getPropertyValue (sBoundRectName);
+ aValue >>= aBoundingBox;
+ bFoundBoundRect = true;
+ }
+ catch (beans::UnknownPropertyException e)
+ {
+ // Handled below (bFoundBoundRect stays false).
+ }
+ }
+ else
+ OSL_TRACE (" no property BoundRect");
+ }
+ }
+
+ // Fallback when there is no BoundRect Property.
+ if ( ! bFoundBoundRect )
+ {
+ awt::Point aPosition (mxShape->getPosition());
+ awt::Size aSize (mxShape->getSize());
+ aBoundingBox = awt::Rectangle (
+ aPosition.X, aPosition.Y,
+ aSize.Width, aSize.Height);
+
+ // While BoundRects have absolute positions, the position returned
+ // by XPosition::getPosition is relative. Get the anchor position
+ // (usually not (0,0) for Writer shapes).
+ if (xSetInfo.is())
+ {
+ if (xSetInfo->hasPropertyByName (sAnchorPositionName))
+ {
+ uno::Any aPos = xSet->getPropertyValue (sAnchorPositionName);
+ awt::Point aAnchorPosition;
+ aPos >>= aAnchorPosition;
+ aBoundingBox.X += aAnchorPosition.X;
+ aBoundingBox.Y += aAnchorPosition.Y;
+ }
+ }
+ }
+
+ // Transform coordinates from internal to pixel.
+ if (maShapeTreeInfo.GetViewForwarder() == NULL)
+ throw uno::RuntimeException (::rtl::OUString (
+ RTL_CONSTASCII_USTRINGPARAM(
+ "AccessibleShape has no valid view forwarder")),
+ static_cast<uno::XWeak*>(this));
+ ::Size aPixelSize = maShapeTreeInfo.GetViewForwarder()->LogicToPixel (
+ ::Size (aBoundingBox.Width, aBoundingBox.Height));
+ ::Point aPixelPosition = maShapeTreeInfo.GetViewForwarder()->LogicToPixel (
+ ::Point (aBoundingBox.X, aBoundingBox.Y));
+
+ // Clip the shape's bounding box with the bounding box of its parent.
+ Reference<XAccessibleComponent> xParentComponent (
+ getAccessibleParent(), uno::UNO_QUERY);
+ if (xParentComponent.is())
+ {
+ // Make the coordinates relative to the parent.
+ awt::Point aParentLocation (xParentComponent->getLocationOnScreen());
+ int x = aPixelPosition.getX() - aParentLocation.X;
+ int y = aPixelPosition.getY() - aParentLocation.Y;
+
+ /* // The following block is a workarround for bug #99889# (property
+ // BoundRect returnes coordinates relative to document window
+ // instead of absolute coordinates for shapes in Writer). Has to
+ // be removed as soon as bug is fixed.
+
+ // Use a non-null anchor position as flag that the shape is in a
+ // Writer document.
+ if (xSetInfo.is())
+ if (xSetInfo->hasPropertyByName (sAnchorPositionName))
+ {
+ uno::Any aPos = xSet->getPropertyValue (sAnchorPositionName);
+ awt::Point aAnchorPosition;
+ aPos >>= aAnchorPosition;
+ if (aAnchorPosition.X > 0)
+ {
+ x = aPixelPosition.getX();
+ y = aPixelPosition.getY();
+ }
+ }
+ // End of workarround.
+ */
+ // Clip with parent (with coordinates relative to itself).
+ ::Rectangle aBBox (
+ x, y, x + aPixelSize.getWidth(), y + aPixelSize.getHeight());
+ awt::Size aParentSize (xParentComponent->getSize());
+ ::Rectangle aParentBBox (0,0, aParentSize.Width, aParentSize.Height);
+ aBBox = aBBox.GetIntersection (aParentBBox);
+ aBoundingBox = awt::Rectangle (
+ aBBox.getX(),
+ aBBox.getY(),
+ aBBox.getWidth(),
+ aBBox.getHeight());
+ }
+ else
+ {
+ OSL_TRACE ("parent does not support component");
+ aBoundingBox = awt::Rectangle (
+ aPixelPosition.getX(), aPixelPosition.getY(),
+ aPixelSize.getWidth(), aPixelSize.getHeight());
+ }
+ }
+
+ return aBoundingBox;
+}
+
+
+
+
+awt::Point SAL_CALL AccessibleShape::getLocation (void)
+ throw (::com::sun::star::uno::RuntimeException)
+{
+ ThrowIfDisposed ();
+ awt::Rectangle aBoundingBox (getBounds());
+ return awt::Point (aBoundingBox.X, aBoundingBox.Y);
+}
+
+
+
+
+awt::Point SAL_CALL AccessibleShape::getLocationOnScreen (void)
+ throw (::com::sun::star::uno::RuntimeException)
+{
+ ThrowIfDisposed ();
+
+ // Get relative position...
+ awt::Point aLocation (getLocation ());
+
+ // ... and add absolute position of the parent.
+ uno::Reference<XAccessibleComponent> xParentComponent (
+ getAccessibleParent(), uno::UNO_QUERY);
+ if (xParentComponent.is())
+ {
+ awt::Point aParentLocation (xParentComponent->getLocationOnScreen());
+ aLocation.X += aParentLocation.X;
+ aLocation.Y += aParentLocation.Y;
+ }
+ else
+ OSL_TRACE ("getLocation: parent does not support XAccessibleComponent");
+ return aLocation;
+}
+
+
+
+
+awt::Size SAL_CALL AccessibleShape::getSize (void)
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed ();
+ awt::Rectangle aBoundingBox (getBounds());
+ return awt::Size (aBoundingBox.Width, aBoundingBox.Height);
+}
+
+
+
+
+sal_Int32 SAL_CALL AccessibleShape::getForeground (void)
+ throw (::com::sun::star::uno::RuntimeException)
+{
+ ThrowIfDisposed ();
+ sal_Int32 nColor (0x0ffffffL);
+
+ try
+ {
+ uno::Reference<beans::XPropertySet> aSet (mxShape, uno::UNO_QUERY);
+ if (aSet.is())
+ {
+ uno::Any aColor;
+ aColor = aSet->getPropertyValue (OUString::createFromAscii ("LineColor"));
+ aColor >>= nColor;
+ }
+ }
+ catch (::com::sun::star::beans::UnknownPropertyException)
+ {
+ // Ignore exception and return default color.
+ }
+ return nColor;
+}
+
+
+
+
+sal_Int32 SAL_CALL AccessibleShape::getBackground (void)
+ throw (::com::sun::star::uno::RuntimeException)
+{
+ ThrowIfDisposed ();
+ sal_Int32 nColor (0L);
+
+ try
+ {
+ uno::Reference<beans::XPropertySet> aSet (mxShape, uno::UNO_QUERY);
+ if (aSet.is())
+ {
+ uno::Any aColor;
+ aColor = aSet->getPropertyValue (OUString::createFromAscii ("FillColor"));
+ aColor >>= nColor;
+ }
+ }
+ catch (::com::sun::star::beans::UnknownPropertyException)
+ {
+ // Ignore exception and return default color.
+ }
+ return nColor;
+}
+
+
+
+
+//===== XAccessibleEventBroadcaster =========================================
+
+void SAL_CALL AccessibleShape::addEventListener (
+ const Reference<XAccessibleEventListener >& rxListener)
+ throw (uno::RuntimeException)
+{
+ if (rBHelper.bDisposed || rBHelper.bInDispose)
+ {
+ uno::Reference<uno::XInterface> xThis (
+ (lang::XComponent *)this, uno::UNO_QUERY);
+ rxListener->disposing (lang::EventObject (xThis));
+ }
+ else
+ {
+ AccessibleContextBase::addEventListener (rxListener);
+ if (mpText != NULL)
+ mpText->AddEventListener (rxListener);
+ }
+}
+
+
+
+
+void SAL_CALL AccessibleShape::removeEventListener (
+ const Reference<XAccessibleEventListener >& rxListener)
+ throw (uno::RuntimeException)
+{
+ AccessibleContextBase::removeEventListener (rxListener);
+ if (mpText != NULL)
+ mpText->RemoveEventListener (rxListener);
+}
+
+
+
+
+//===== XInterface ==========================================================
+
+com::sun::star::uno::Any SAL_CALL
+ AccessibleShape::queryInterface (const com::sun::star::uno::Type & rType)
+ throw (::com::sun::star::uno::RuntimeException)
+{
+ ::com::sun::star::uno::Any aReturn = AccessibleContextBase::queryInterface (rType);
+ if ( ! aReturn.hasValue())
+ aReturn = ::cppu::queryInterface (rType,
+ static_cast<XAccessibleComponent*>(this),
+ static_cast<XAccessibleExtendedComponent*>(this),
+ static_cast<lang::XEventListener*>(this),
+ static_cast<document::XEventListener*>(this),
+ static_cast<lang::XUnoTunnel*>(this)
+ );
+ return aReturn;
+}
+
+
+
+
+void SAL_CALL
+ AccessibleShape::acquire (void)
+ throw ()
+{
+ AccessibleContextBase::acquire ();
+}
+
+
+
+
+void SAL_CALL
+ AccessibleShape::release (void)
+ throw ()
+{
+ AccessibleContextBase::release ();
+}
+
+
+
+
+//===== XServiceInfo ========================================================
+
+::rtl::OUString SAL_CALL
+ AccessibleShape::getImplementationName (void)
+ throw (::com::sun::star::uno::RuntimeException)
+{
+ return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleShape"));
+}
+
+
+
+
+uno::Sequence<OUString> SAL_CALL
+ AccessibleShape::getSupportedServiceNames (void)
+ throw (::com::sun::star::uno::RuntimeException)
+{
+ ThrowIfDisposed ();
+ // Get list of supported service names from base class...
+ uno::Sequence<OUString> aServiceNames =
+ AccessibleContextBase::getSupportedServiceNames();
+ sal_Int32 nCount (aServiceNames.getLength());
+
+ // ...and add additional names.
+ aServiceNames.realloc (nCount + 1);
+ static const OUString sAdditionalServiceName (RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.drawing.AccessibleShape"));
+ aServiceNames[nCount] = sAdditionalServiceName;
+
+ return aServiceNames;
+}
+
+
+
+
+
+//===== XTypeProvider ===================================================
+
+uno::Sequence<uno::Type> SAL_CALL
+ AccessibleShape::getTypes (void)
+ throw (uno::RuntimeException)
+{
+ ThrowIfDisposed ();
+ // Get list of types from the context base implementation, ...
+ uno::Sequence<uno::Type> aTypeList (AccessibleContextBase::getTypes());
+ // ... get list of types from component base implementation, ...
+ uno::Sequence<uno::Type> aComponentTypeList (AccessibleComponentBase::getTypes());
+ // ... define local types, ...
+ const uno::Type aLangEventListenerType =
+ ::getCppuType((const uno::Reference<lang::XEventListener>*)0);
+ const uno::Type aDocumentEventListenerType =
+ ::getCppuType((const uno::Reference<document::XEventListener>*)0);
+ const uno::Type aUnoTunnelType =
+ ::getCppuType((const uno::Reference<lang::XUnoTunnel>*)0);
+ // const uno::Type aStateSetType =
+ // ::getCppuType((const uno::Reference<XAccessibleStateSet>*)0);
+
+ // ... and merge them all into one list.
+ sal_Int32 nTypeCount (aTypeList.getLength()),
+ nComponentTypeCount (aComponentTypeList.getLength());
+ int i;
+
+ aTypeList.realloc (nTypeCount + nComponentTypeCount + 3);
+
+ for (i=0; i<nComponentTypeCount; i++)
+ aTypeList[nTypeCount + i] = aComponentTypeList[i];
+
+ aTypeList[nTypeCount + i++ ] = aLangEventListenerType;
+ aTypeList[nTypeCount + i++ ] = aDocumentEventListenerType;
+ aTypeList[nTypeCount + i ] = aUnoTunnelType;
+
+ return aTypeList;
+}
+
+
+
+
+//===== lang::XEventListener ================================================
+
+/** Disposing calls are accepted only from the model: Just reset the
+ reference to the model in the shape tree info. Otherwise this object
+ remains functional.
+*/
+void SAL_CALL
+ AccessibleShape::disposing (const lang::EventObject& aEvent)
+ throw (uno::RuntimeException)
+{
+ ::vos::OGuard aSolarGuard (::Application::GetSolarMutex());
+ ::osl::MutexGuard aGuard (maMutex);
+
+ try
+ {
+ if (aEvent.Source == maShapeTreeInfo.GetModelBroadcaster())
+ {
+ // Remove reference to model broadcaster to allow it to pass
+ // away.
+ maShapeTreeInfo.SetModelBroadcaster(NULL);
+ }
+
+ }
+ catch (uno::RuntimeException e)
+ {
+ OSL_TRACE ("caught exception while disposing");
+ }
+}
+
+
+
+
+//===== document::XEventListener ============================================
+
+void SAL_CALL
+ AccessibleShape::notifyEvent (const document::EventObject& rEventObject)
+ throw (uno::RuntimeException)
+{
+ static const OUString sShapeModified (
+ RTL_CONSTASCII_USTRINGPARAM("ShapeModified"));
+
+ // First check if the event is for us.
+ uno::Reference<drawing::XShape> xShape (
+ rEventObject.Source, uno::UNO_QUERY);
+ if ( xShape.get() == mxShape.get() )
+ {
+ if (rEventObject.EventName.equals (sShapeModified))
+ {
+ // Some property of a shape has been modified. Send an event
+ // that indicates a change of the visible data to all listeners.
+ CommitChange (
+ AccessibleEventId::VISIBLE_DATA_CHANGED,
+ uno::Any(),
+ uno::Any());
+
+ // Name and Description may have changed. Update the local
+ // values accordingly.
+ UpdateNameAndDescription();
+ }
+ }
+}
+
+
+
+
+//===== lang::XUnoTunnel ================================================
+
+const uno::Sequence< sal_Int8 >&
+ AccessibleShape::getUnoTunnelImplementationId()
+ throw()
+{
+ static uno::Sequence< sal_Int8 >* pSeq = 0;
+
+ if( !pSeq )
+ {
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
+
+ if( !pSeq )
+ {
+ static uno::Sequence< sal_Int8 > aSeq( 16 );
+ rtl_createUuid( (sal_uInt8*) aSeq.getArray(), 0, sal_True );
+ pSeq = &aSeq;
+ }
+ }
+
+ return( *pSeq );
+}
+
+//------------------------------------------------------------------------------
+AccessibleShape*
+ AccessibleShape::getImplementation( const uno::Reference< uno::XInterface >& rxIFace )
+ throw()
+{
+ uno::Reference< lang::XUnoTunnel > xTunnel( rxIFace, uno::UNO_QUERY );
+ AccessibleShape* pReturn = NULL;
+
+ if( xTunnel.is() )
+ pReturn = reinterpret_cast< AccessibleShape* >( xTunnel->getSomething( getUnoTunnelImplementationId() ) );
+
+ return( pReturn );
+}
+
+//------------------------------------------------------------------------------
+sal_Int64 SAL_CALL
+ AccessibleShape::getSomething( const uno::Sequence< sal_Int8 >& rIdentifier )
+ throw(uno::RuntimeException)
+{
+ sal_Int64 nReturn( 0 );
+
+ if( ( rIdentifier.getLength() == 16 ) && ( 0 == rtl_compareMemory( getUnoTunnelImplementationId().getConstArray(), rIdentifier.getConstArray(), 16 ) ) )
+ nReturn = reinterpret_cast< sal_Int64 >( this );
+
+ return( nReturn );
+}
+
+//===== IAccessibleViewForwarderListener ====================================
+
+void AccessibleShape::ViewForwarderChanged (ChangeType aChangeType,
+ const IAccessibleViewForwarder* pViewForwarder)
+{
+ // Inform all listeners that the graphical representation (i.e. size
+ // and/or position) of the shape has changed.
+ CommitChange (AccessibleEventId::VISIBLE_DATA_CHANGED,
+ uno::Any(),
+ uno::Any());
+
+ // Tell children manager of the modified view forwarder.
+ if (mpChildrenManager != NULL)
+ mpChildrenManager->ViewForwarderChanged (aChangeType, pViewForwarder);
+
+ // update our children that our screen position might have changed
+ if( mpText )
+ mpText->UpdateChildren();
+}
+
+
+
+
+//===== protected internal ==================================================
+/// Set this object's name if is different to the current name.
+::rtl::OUString
+ AccessibleShape::CreateAccessibleBaseName (void)
+ throw (::com::sun::star::uno::RuntimeException)
+{
+ return ShapeTypeHandler::CreateAccessibleBaseName( mxShape );
+}
+
+
+::rtl::OUString
+ AccessibleShape::CreateAccessibleName (void)
+ throw (::com::sun::star::uno::RuntimeException)
+{
+ OUString sName (CreateAccessibleBaseName());
+
+ // Append the shape's index to the name to disambiguate between shapes
+ // of the same type. If such an index where not given to the
+ // constructor then use the z-order instead. If even that does not exist
+ // we throw an exception.
+ long nIndex = mnIndex;
+ if (nIndex == -1)
+ {
+ try
+ {
+ uno::Reference<beans::XPropertySet> xSet (mxShape, uno::UNO_QUERY);
+ if (xSet.is())
+ {
+ uno::Any aZOrder (xSet->getPropertyValue (::rtl::OUString::createFromAscii ("ZOrder")));
+ aZOrder >>= nIndex;
+
+ // Add one to be not zero based.
+ nIndex += 1;
+ }
+ }
+ catch (beans::UnknownPropertyException)
+ {
+ // We throw our own exception that is a bit more informative.
+ throw uno::RuntimeException (::rtl::OUString (
+ RTL_CONSTASCII_USTRINGPARAM("AccessibleShape has invalid index and no ZOrder property")),
+ static_cast<uno::XWeak*>(this));
+ }
+
+ }
+
+ // Put a space between name and index because of Gnopernicus othewise
+ // spells the name.
+ sName += OUString (RTL_CONSTASCII_USTRINGPARAM(" ")) + OUString::valueOf (nIndex);
+
+ return sName;
+}
+
+
+
+
+::rtl::OUString
+ AccessibleShape::CreateAccessibleDescription (void)
+ throw (::com::sun::star::uno::RuntimeException)
+{
+ DescriptionGenerator aDG (mxShape);
+ aDG.Initialize (CreateAccessibleBaseName());
+ switch (ShapeTypeHandler::Instance().GetTypeId (mxShape))
+ {
+ case DRAWING_3D_CUBE:
+ case DRAWING_3D_EXTRUDE:
+ case DRAWING_3D_LATHE:
+ case DRAWING_3D_SPHERE:
+ aDG.Add3DProperties ();
+ break;
+
+ case DRAWING_3D_SCENE:
+ case DRAWING_GROUP:
+ case DRAWING_PAGE:
+ // No further information is appended.
+ break;
+
+ case DRAWING_CAPTION:
+ case DRAWING_CLOSED_BEZIER:
+ case DRAWING_CLOSED_FREEHAND:
+ case DRAWING_ELLIPSE:
+ case DRAWING_POLY_POLYGON:
+ case DRAWING_POLY_POLYGON_PATH:
+ case DRAWING_RECTANGLE:
+ aDG.AddLineProperties ();
+ aDG.AddFillProperties ();
+ break;
+
+ case DRAWING_CONNECTOR:
+ case DRAWING_LINE:
+ case DRAWING_MEASURE:
+ case DRAWING_OPEN_BEZIER:
+ case DRAWING_OPEN_FREEHAND:
+ case DRAWING_POLY_LINE:
+ case DRAWING_POLY_LINE_PATH:
+ aDG.AddLineProperties ();
+ break;
+
+ case DRAWING_CONTROL:
+ aDG.AddProperty (OUString::createFromAscii ("ControlBackground"),
+ DescriptionGenerator::COLOR,
+ OUString());
+ aDG.AddProperty (OUString::createFromAscii ("ControlBorder"),
+ DescriptionGenerator::INTEGER,
+ OUString());
+ break;
+
+ case DRAWING_TEXT:
+ aDG.AddTextProperties ();
+ break;
+
+ default:
+ aDG.Initialize (::rtl::OUString (
+ RTL_CONSTASCII_USTRINGPARAM("Unknown accessible shape")));
+ uno::Reference<drawing::XShapeDescriptor> xDescriptor (mxShape, uno::UNO_QUERY);
+ if (xDescriptor.is())
+ {
+ aDG.AppendString (::rtl::OUString (RTL_CONSTASCII_USTRINGPARAM("service name=")));
+ aDG.AppendString (xDescriptor->getShapeType());
+ }
+ }
+
+ return aDG();
+}
+
+
+
+
+uno::Reference< drawing::XShape > AccessibleShape::GetXShape()
+{
+ return( mxShape );
+}
+
+
+
+// protected
+void AccessibleShape::disposing (void)
+{
+ ::vos::OGuard aSolarGuard (::Application::GetSolarMutex());
+ ::osl::MutexGuard aGuard (maMutex);
+
+ // Make sure to send an event that this object looses the focus in the
+ // case that it has the focus.
+ ::utl::AccessibleStateSetHelper* pStateSet =
+ static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get());
+ if (pStateSet != NULL)
+ pStateSet->RemoveState (AccessibleStateType::FOCUSED);
+
+ // Unregister from broadcasters.
+ Reference<lang::XComponent> xComponent (mxShape, uno::UNO_QUERY);
+ if (xComponent.is())
+ xComponent->removeEventListener (this);
+
+ // Unregister from model.
+ if (maShapeTreeInfo.GetModelBroadcaster().is())
+ maShapeTreeInfo.GetModelBroadcaster()->removeEventListener (
+ static_cast<document::XEventListener*>(this));
+
+ // Release the child containers.
+ if (mpChildrenManager != NULL)
+ {
+ delete mpChildrenManager;
+ mpChildrenManager = NULL;
+ }
+ if (mpText != NULL)
+ {
+ mpText->Dispose();
+ delete mpText;
+ mpText = NULL;
+ }
+
+ // Cleanup. Remove references to objects to allow them to be
+ // destroyed.
+ mxShape = NULL;
+ maShapeTreeInfo = AccessibleShapeTreeInfo();
+
+ // Call base classes.
+ AccessibleContextBase::dispose ();
+}
+
+sal_Int32 SAL_CALL
+ AccessibleShape::getAccessibleIndexInParent (void)
+ throw (::com::sun::star::uno::RuntimeException)
+{
+ ThrowIfDisposed ();
+ // Use a simple but slow solution for now. Optimize later.
+
+ sal_Int32 nIndex = m_nIndexInParent;
+ if ( -1 == nIndex )
+ nIndex = AccessibleContextBase::getAccessibleIndexInParent();
+ return nIndex;
+}
+
+
+
+
+void AccessibleShape::UpdateNameAndDescription (void)
+{
+ // Ignore missing title, name, or description. There are fallbacks for
+ // them.
+ try
+ {
+ Reference<beans::XPropertySet> xSet (mxShape, uno::UNO_QUERY_THROW);
+ OUString sString;
+
+ // Get the accessible name.
+ sString = GetOptionalProperty(xSet, OUString(RTL_CONSTASCII_USTRINGPARAM("Title")));
+ if (sString.getLength() > 0)
+ {
+ SetAccessibleName(sString, AccessibleContextBase::FromShape);
+ }
+ else
+ {
+ sString = GetOptionalProperty(xSet, OUString(RTL_CONSTASCII_USTRINGPARAM("Name")));
+ if (sString.getLength() > 0)
+ SetAccessibleName(sString, AccessibleContextBase::FromShape);
+ }
+
+ // Get the accessible description.
+ sString = GetOptionalProperty(xSet, OUString(RTL_CONSTASCII_USTRINGPARAM("Description")));
+ if (sString.getLength() > 0)
+ SetAccessibleDescription(sString, AccessibleContextBase::FromShape);
+ }
+ catch (uno::RuntimeException&)
+ {
+ }
+}
+
+
+
+
+} // end of namespace accessibility