usingnamespace ::com::sun::star; usingnamespace ::com::sun::star::accessibility; using ::com::sun::star::uno::Reference; using ::com::sun::star::lang::IndexOutOfBoundsException; using ::com::sun::star::uno::RuntimeException;
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;
}
// 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()
{ // 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.reset( new ChildrenManager ( this, xShapes, maShapeTreeInfo, *this) ); if (mpChildrenManager != nullptr)
mpChildrenManager->Update();
// Register at model as document::XEventListener. if (mxShape.is() && maShapeTreeInfo.GetModelBroadcaster().is())
maShapeTreeInfo.GetModelBroadcaster()->addShapeEventListener(mxShape, static_cast<document::XShapeEventListener*>(this));
// Beware! Here we leave the paths of the UNO API and descend into the // depths of the core. Necessary for making the edit engine // accessible.
Reference<text::XText> xText (mxShape, uno::UNO_QUERY); if (!xText.is()) return;
// create AccessibleTextHelper to handle this shape's text if( !hasOutlinerParaObject )
{ // empty text -> use proxy edit source to delay creation of EditEngine
mpText.reset( new AccessibleTextHelper( std::make_unique<AccessibleEmptyEditSource >(*pSdrObject, *pView, *pWindow->GetOutDev()) ) );
} else
{ // non-empty text -> use full-fledged edit source right away
mpText.reset( new AccessibleTextHelper( std::make_unique<SvxTextEditSource >(*pSdrObject, nullptr, *pView, *pWindow->GetOutDev()) ) );
} if( pWindow->HasFocus() )
mpText->SetFocus();
mpText->SetEventSource(this);
}
void AccessibleShape::UpdateStates()
{ // 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 (u"FillStyle"_ustr) >>= aFillStyle)
&& aFillStyle == drawing::FillStyle_SOLID;
} catch (css::beans::UnknownPropertyException&)
{ // Ignore.
}
}
}
} if (bShapeIsOpaque)
mnStateSet |= AccessibleStateType::OPAQUE; else
mnStateSet &= ~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);
}
if (bShapeIsSelected)
mnStateSet |= AccessibleStateType::SELECTED; else
mnStateSet &= ~AccessibleStateType::SELECTED;
}
if (aState == AccessibleStateType::FOCUSED && mpText != nullptr)
{ // Try to remove FOCUSED state from the edit engine and detect // whether the state changes. bool bIsFocused = mpText->HaveFocus ();
mpText->SetFocus (false);
bStateHasChanged = (bIsFocused != mpText->HaveFocus ());
} else
bStateHasChanged = AccessibleContextBase::ResetState (aState);
return bStateHasChanged;
}
bool AccessibleShape::GetState (sal_Int64 aState)
{ if (aState == AccessibleStateType::FOCUSED && mpText != nullptr)
{ // 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 grouporsceneshapesandtheparagraphsoftext.
*/
sal_Int64 SAL_CALL
AccessibleShape::getAccessibleChildCount ()
{ if (!isAlive())
{ return0;
}
sal_Int64 nChildCount = 0;
// Add the number of shapes that are children of this shape. if (mpChildrenManager != nullptr)
nChildCount += mpChildrenManager->GetChildCount (); // Add the number text paragraphs. if (mpText != nullptr)
nChildCount += mpText->GetChildCount ();
return nChildCount;
}
/** Forward the request to the shape. Return the requested shape or throw anexceptionforawrongindex.
*/
uno::Reference<XAccessible> SAL_CALL
AccessibleShape::getAccessibleChild (sal_Int64 nIndex)
{
ensureAlive();
uno::Reference<XAccessible> xChild;
// Depending on the index decide whether to delegate this call to the // children manager or the edit engine. if ((mpChildrenManager != nullptr)
&& (nIndex < mpChildrenManager->GetChildCount()))
{
xChild = mpChildrenManager->GetChild (nIndex);
} elseif (mpText != nullptr)
{
sal_Int64 nI = nIndex; if (mpChildrenManager != nullptr)
nI -= mpChildrenManager->GetChildCount();
xChild = mpText->GetChild (nI);
} else throw lang::IndexOutOfBoundsException ( "shape has no child with index " + OUString::number(nIndex),
getXWeak());
rtl::Reference<::utl::AccessibleRelationSetHelper> pRelationSet = new utl::AccessibleRelationSetHelper;
//this mxshape is the captioned shape
uno::Sequence<uno::Reference<css::accessibility::XAccessible>> aSequence { mpParent->GetAccessibleCaption(mxShape) }; if(aSequence[0])
{
pRelationSet->AddRelation(
AccessibleRelation(AccessibleRelationType_DESCRIBED_BY, aSequence));
} return pRelationSet;
}
/** Return a copy of the state set. Possiblestatesare: ENABLED SHOWING VISIBLE
*/
sal_Int64 SAL_CALL
AccessibleShape::getAccessibleStateSet()
{
::osl::MutexGuard aGuard (m_aMutex);
if (!isAlive())
{ // Return a minimal state set that only contains the DEFUNC state. return AccessibleContextBase::getAccessibleStateSet ();
}
// Merge current FOCUSED state from edit engine. if (mpText)
{ if (mpText->HaveFocus())
mnStateSet |= AccessibleStateType::FOCUSED; else
mnStateSet &= ~AccessibleStateType::FOCUSED;
} //Just when the document is not read-only,set states EDITABLE,RESIZABLE,MOVEABLE
css::uno::Reference<XAccessible> xTempAcc = getAccessibleParent(); if( xTempAcc.is() )
{
css::uno::Reference<XAccessibleContext>
xTempAccContext = xTempAcc->getAccessibleContext(); if( xTempAccContext.is() )
{
sal_Int64 nState = xTempAccContext->getAccessibleStateSet(); if (nState & AccessibleStateType::EDITABLE)
{
mnStateSet |= AccessibleStateType::EDITABLE;
mnStateSet |= AccessibleStateType::RESIZABLE;
mnStateSet |= AccessibleStateType::MOVEABLE;
}
}
}
sal_Int64 nRetStateSet = mnStateSet;
if (mpParent && mpParent->IsDocumentSelAll())
{
nRetStateSet |= AccessibleStateType::SELECTED;
}
return nRetStateSet;
}
// XAccessibleComponent /** The implementation below is at the moment straightforward. It iterates overallchildren(andtherebyinstancesallchildrenwhichhavenot beenalreadyinstantiated)untilachildcoveringthespecifiedpointis found. Thisleavesroomforimprovement.Forinstance,firstiterateonlyover thealreadyinstantiatedchildrenandonlyifnomatchisfound instantiatetheremainingones.
*/
uno::Reference<XAccessible > SAL_CALL
AccessibleShape::getAccessibleAtPoint ( const awt::Point& aPoint)
{
::osl::MutexGuard aGuard (m_aMutex);
sal_Int64 nChildCount = getAccessibleChildCount (); for (sal_Int64 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 AccessibleShape::implGetBounds()
{
awt::Rectangle aBoundingBox; if ( mxShape.is() )
{
// 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 const&)
{ // Handled below (bFoundBoundRect stays false).
}
} else
SAL_WARN("svx", "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() == nullptr) throw uno::RuntimeException (
u"AccessibleShape has no valid view forwarder"_ustr,
getXWeak());
::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;
// Clip with parent (with coordinates relative to itself).
::tools::Rectangle aBBox (
x, y, x + aPixelSize.getWidth(), y + aPixelSize.getHeight());
awt::Size aParentSize (xParentComponent->getSize());
::tools::Rectangle aParentBBox (0,0, aParentSize.Width, aParentSize.Height);
aBBox = aBBox.GetIntersection (aParentBBox);
aBoundingBox = awt::Rectangle (
aBBox.Left(),
aBBox.Top(),
aBBox.getOpenWidth(),
aBBox.getOpenHeight());
} else
{
SAL_INFO("svx", "parent does not support component");
aBoundingBox = awt::Rectangle (
aPixelPosition.getX(), aPixelPosition.getY(),
aPixelSize.getWidth(), aPixelSize.getHeight());
}
}
// XTypeProvider
uno::Sequence<uno::Type> SAL_CALL
AccessibleShape::getTypes()
{
ensureAlive(); // Get list of types from the context base implementation, ...
uno::Sequence<uno::Type> aTypeList (AccessibleContextBase::getTypes()); // ... define local types
uno::Sequence<uno::Type> localTypesList = {
cppu::UnoType<lang::XEventListener>::get(),
cppu::UnoType<document::XEventListener>::get(),
cppu::UnoType<lang::XUnoTunnel>::get()
};
// lang::XEventListener /** Disposing calls are accepted only from the model: Just reset the referencetothemodelintheshapetreeinfo.Otherwisethisobject remainsfunctional.
*/ void AccessibleShape::disposing (const lang::EventObject& aEvent)
{
SolarMutexGuard aSolarGuard;
::osl::MutexGuard aGuard (m_aMutex);
try
{ if (aEvent.Source == maShapeTreeInfo.GetModelBroadcaster())
{ // Remove reference to model broadcaster to allow it to pass // away.
maShapeTreeInfo.SetModelBroadcaster(nullptr);
}
//Need to update text children when receiving ShapeModified hint when exiting edit mode for text box if (mpText)
mpText->UpdateChildren();
// 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(), -1);
// Name and Description may have changed. Update the local // values accordingly.
UpdateNameAndDescription();
}
// IAccessibleViewForwarderListener void AccessibleShape::ViewForwarderChanged()
{ // 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(), -1);
// Tell children manager of the modified view forwarder. if (mpChildrenManager != nullptr)
mpChildrenManager->ViewForwarderChanged();
// 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.
OUString AccessibleShape::CreateAccessibleBaseName()
{ return ShapeTypeHandler::CreateAccessibleBaseName( mxShape );
}
OUString AccessibleShape::GetFullAccessibleName (AccessibleShape *shape)
{
OUString sName (shape->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.
OUString nameStr; if (shape->m_pShape)
nameStr = shape->m_pShape->GetName(); if (nameStr.isEmpty())
{
sName += " ";
} else
{
sName = nameStr;
}
//If the new produced name if not the same with last,notify name changed //Event if (aAccName != sName && !aAccName.isEmpty())
{
uno::Any aOldValue, aNewValue;
aOldValue <<= aAccName;
aNewValue <<= sName;
CommitChange(
AccessibleEventId::NAME_CHANGED,
aNewValue,
aOldValue, -1);
}
aAccName = sName; return sName;
}
// Make sure to send an event that this object loses the focus in the // case that it has the focus.
mnStateSet &= ~AccessibleStateType::FOCUSED;
// Unregister from model. if (mxShape.is() && maShapeTreeInfo.GetModelBroadcaster().is())
maShapeTreeInfo.GetModelBroadcaster()->removeShapeEventListener(mxShape, static_cast<document::XShapeEventListener*>(this));
// Release the child containers. if (mpChildrenManager != nullptr)
{
mpChildrenManager.reset();
} if (mpText != nullptr)
{
mpText->Dispose();
mpText.reset();
}
// Cleanup. Remove references to objects to allow them to be // destroyed.
mxShape = nullptr;
maShapeTreeInfo.dispose();
// Call base classes.
AccessibleContextBase::disposing();
}
//sort the drawing objects from up to down, from left to right struct XShapePosCompareHelper
{ booloperator() ( const uno::Reference<drawing::XShape>& xshape1, const uno::Reference<drawing::XShape>& xshape2 ) const
{
SdrObject* pObj1 = SdrObject::getSdrObjectFromXShape(xshape1);
SdrObject* pObj2 = SdrObject::getSdrObjectFromXShape(xshape2); if(pObj1 && pObj2) return pObj1->GetOrdNum() < pObj2->GetOrdNum(); else returnfalse;
}
};
} //end of group position
// XAccessibleGroupPosition
uno::Sequence< sal_Int32 > SAL_CALL
AccessibleShape::getGroupPosition( const uno::Any& )
{ // we will return the: // [0] group level // [1] similar items counts in the group // [2] the position of the object in the group
uno::Sequence< sal_Int32 > aRet{ 0, 0, 0 };
//get the index of the selected object in the group //we start counting position from 1
sal_Int32 nPos = 1; for ( constauto& rpShape : vXShapes )
{ if ( rpShape.get() == mxShape.get() )
{
sal_Int32* pArray = aRet.getArray();
pArray[0] = nGroupLevel;
pArray[1] = vXShapes.size();
pArray[2] = nPos; break;
}
nPos++;
}
// XAccessibleHypertext
sal_Int32 SAL_CALL AccessibleShape::getHyperLinkCount()
{ // MT: Introduced with IA2 CWS, but SvxAccessibleHyperlink was redundant to svx::AccessibleHyperlink which we introduced meanwhile. // Code need to be adapted... return0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.