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/AccessibleShapeInfo.hxx>
22 #include <com/sun/star/accessibility/AccessibleRole.hpp>
23 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
24 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
25 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
26 #include <com/sun/star/beans/XPropertySet.hpp>
27 #include <com/sun/star/drawing/XShapes.hpp>
28 #include <com/sun/star/document/XShapeEventBroadcaster.hpp>
29 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
30 #include <com/sun/star/drawing/FillStyle.hpp>
31 #include <com/sun/star/text/XText.hpp>
32 #include <sal/log.hxx>
33 #include <editeng/unoedsrc.hxx>
34 #include <svx/AccessibleTextHelper.hxx>
35 #include <svx/ChildrenManager.hxx>
36 #include <svx/IAccessibleParent.hxx>
37 #include <svx/IAccessibleViewForwarder.hxx>
38 #include <svx/unoshtxt.hxx>
39 #include <svx/svdobj.hxx>
40 #include <svx/unoapi.hxx>
41 #include <svx/svdpage.hxx>
42 #include <svx/ShapeTypeHandler.hxx>
43 #include <svx/SvxShapeTypes.hxx>
45 #include <vcl/svapp.hxx>
46 #include <vcl/window.hxx>
47 #include <unotools/accessiblerelationsethelper.hxx>
48 #include <svx/svdview.hxx>
49 #include <comphelper/diagnose_ex.hxx>
50 #include <cppuhelper/queryinterface.hxx>
51 #include <comphelper/sequence.hxx>
52 #include "AccessibleEmptyEditSource.hxx"
57 using namespace ::com::sun::star
;
58 using namespace ::com::sun::star::accessibility
;
59 using ::com::sun::star::uno::Reference
;
60 using ::com::sun::star::lang::IndexOutOfBoundsException
;
61 using ::com::sun::star::uno::RuntimeException
;
63 namespace accessibility
{
67 OUString
GetOptionalProperty (
68 const Reference
<beans::XPropertySet
>& rxSet
,
69 const OUString
& rsPropertyName
)
75 const Reference
<beans::XPropertySetInfo
> xInfo (rxSet
->getPropertySetInfo());
76 if ( ! xInfo
.is() || xInfo
->hasPropertyByName(rsPropertyName
))
80 rxSet
->getPropertyValue(rsPropertyName
) >>= sValue
;
82 catch (beans::UnknownPropertyException
&)
84 // This exception should only be thrown when the property
85 // does not exits (of course) and the XPropertySetInfo is
93 } // end of anonymous namespace
96 AccessibleShape::AccessibleShape (
97 const AccessibleShapeInfo
& rShapeInfo
,
98 const AccessibleShapeTreeInfo
& rShapeTreeInfo
)
99 : AccessibleContextBase (rShapeInfo
.mxParent
,AccessibleRole::SHAPE
),
100 mxShape (rShapeInfo
.mxShape
),
101 maShapeTreeInfo (rShapeTreeInfo
),
102 m_nIndexInParent(-1),
103 mpParent (rShapeInfo
.mpChildrenManager
)
105 m_pShape
= SdrObject::getSdrObjectFromXShape(mxShape
);
106 UpdateNameAndDescription();
109 AccessibleShape::~AccessibleShape()
111 mpChildrenManager
.reset();
113 SAL_INFO("svx", "~AccessibleShape");
115 // Unregistering from the various broadcasters should be unnecessary
116 // since this destructor would not have been called if one of the
117 // broadcasters would still hold a strong reference to this object.
120 void AccessibleShape::Init()
122 // Update the OPAQUE and SELECTED shape.
125 // Create a children manager when this shape has children of its own.
126 Reference
<drawing::XShapes
> xShapes (mxShape
, uno::UNO_QUERY
);
127 if (xShapes
.is() && xShapes
->getCount() > 0)
128 mpChildrenManager
.reset( new ChildrenManager (
129 this, xShapes
, maShapeTreeInfo
, *this) );
130 if (mpChildrenManager
!= nullptr)
131 mpChildrenManager
->Update();
133 // Register at model as document::XEventListener.
134 if (mxShape
.is() && maShapeTreeInfo
.GetModelBroadcaster().is())
135 maShapeTreeInfo
.GetModelBroadcaster()->addShapeEventListener(mxShape
,
136 static_cast<document::XShapeEventListener
*>(this));
138 // Beware! Here we leave the paths of the UNO API and descend into the
139 // depths of the core. Necessary for making the edit engine
141 Reference
<text::XText
> xText (mxShape
, uno::UNO_QUERY
);
145 SdrView
* pView
= maShapeTreeInfo
.GetSdrView ();
146 const vcl::Window
* pWindow
= maShapeTreeInfo
.GetWindow ();
147 if (!(pView
!= nullptr && pWindow
!= nullptr && mxShape
.is()))
150 // #107948# Determine whether shape text is empty
151 SdrObject
* pSdrObject
= SdrObject::getSdrObjectFromXShape(mxShape
);
155 SdrTextObj
* pTextObj
= DynCastSdrTextObj( pSdrObject
);
156 const bool hasOutlinerParaObject
= (pTextObj
&& pTextObj
->CanCreateEditOutlinerParaObject()) || (pSdrObject
->GetOutlinerParaObject() != nullptr);
158 // create AccessibleTextHelper to handle this shape's text
159 if( !hasOutlinerParaObject
)
161 // empty text -> use proxy edit source to delay creation of EditEngine
162 mpText
.reset( new AccessibleTextHelper( std::make_unique
<AccessibleEmptyEditSource
>(*pSdrObject
, *pView
, *pWindow
->GetOutDev()) ) );
166 // non-empty text -> use full-fledged edit source right away
167 mpText
.reset( new AccessibleTextHelper( std::make_unique
<SvxTextEditSource
>(*pSdrObject
, nullptr, *pView
, *pWindow
->GetOutDev()) ) );
169 if( pWindow
->HasFocus() )
172 mpText
->SetEventSource(this);
176 void AccessibleShape::UpdateStates()
178 // Set the opaque state for certain shape types when their fill style is
180 bool bShapeIsOpaque
= false;
181 switch (ShapeTypeHandler::Instance().GetTypeId (mxShape
))
184 case DRAWING_RECTANGLE
:
187 uno::Reference
<beans::XPropertySet
> xSet (mxShape
, uno::UNO_QUERY
);
192 drawing::FillStyle aFillStyle
;
193 bShapeIsOpaque
= ( xSet
->getPropertyValue (u
"FillStyle"_ustr
) >>= aFillStyle
)
194 && aFillStyle
== drawing::FillStyle_SOLID
;
196 catch (css::beans::UnknownPropertyException
&)
204 mnStateSet
|= AccessibleStateType::OPAQUE
;
206 mnStateSet
&= ~AccessibleStateType::OPAQUE
;
208 // Set the selected state.
209 bool bShapeIsSelected
= false;
210 // XXX fix_me this has to be done with an extra interface later on
211 if ( m_pShape
&& maShapeTreeInfo
.GetSdrView() )
213 bShapeIsSelected
= maShapeTreeInfo
.GetSdrView()->IsObjMarked(m_pShape
);
216 if (bShapeIsSelected
)
217 mnStateSet
|= AccessibleStateType::SELECTED
;
219 mnStateSet
&= ~AccessibleStateType::SELECTED
;
222 OUString
AccessibleShape::GetStyle() const
224 return ShapeTypeHandler::CreateAccessibleBaseName( mxShape
);
227 bool AccessibleShape::SetState (sal_Int64 aState
)
229 bool bStateHasChanged
= false;
231 if (aState
== AccessibleStateType::FOCUSED
&& mpText
!= nullptr)
233 // Offer FOCUSED state to edit engine and detect whether the state
235 bool bIsFocused
= mpText
->HaveFocus ();
237 bStateHasChanged
= (bIsFocused
!= mpText
->HaveFocus ());
240 bStateHasChanged
= AccessibleContextBase::SetState (aState
);
242 return bStateHasChanged
;
246 bool AccessibleShape::ResetState (sal_Int64 aState
)
248 bool bStateHasChanged
= false;
250 if (aState
== AccessibleStateType::FOCUSED
&& mpText
!= nullptr)
252 // Try to remove FOCUSED state from the edit engine and detect
253 // whether the state changes.
254 bool bIsFocused
= mpText
->HaveFocus ();
255 mpText
->SetFocus (false);
256 bStateHasChanged
= (bIsFocused
!= mpText
->HaveFocus ());
259 bStateHasChanged
= AccessibleContextBase::ResetState (aState
);
261 return bStateHasChanged
;
265 bool AccessibleShape::GetState (sal_Int64 aState
)
267 if (aState
== AccessibleStateType::FOCUSED
&& mpText
!= nullptr)
269 // Just delegate the call to the edit engine. The state is not
270 // merged into the state set.
271 return mpText
->HaveFocus();
274 return AccessibleContextBase::GetState (aState
);
277 // OverWrite the parent's getAccessibleName method
278 OUString SAL_CALL
AccessibleShape::getAccessibleName()
281 if (m_pShape
&& !m_pShape
->GetTitle().isEmpty())
282 return CreateAccessibleName() + " " + m_pShape
->GetTitle();
284 return CreateAccessibleName();
287 OUString SAL_CALL
AccessibleShape::getAccessibleDescription()
290 if( m_pShape
&& !m_pShape
->GetDescription().isEmpty())
291 return m_pShape
->GetDescription() ;
296 // XAccessibleContext
297 /** The children of this shape come from two sources: The children from
298 group or scene shapes and the paragraphs of text.
301 AccessibleShape::getAccessibleChildCount ()
308 sal_Int64 nChildCount
= 0;
310 // Add the number of shapes that are children of this shape.
311 if (mpChildrenManager
!= nullptr)
312 nChildCount
+= mpChildrenManager
->GetChildCount ();
313 // Add the number text paragraphs.
314 if (mpText
!= nullptr)
315 nChildCount
+= mpText
->GetChildCount ();
321 /** Forward the request to the shape. Return the requested shape or throw
322 an exception for a wrong index.
324 uno::Reference
<XAccessible
> SAL_CALL
325 AccessibleShape::getAccessibleChild (sal_Int64 nIndex
)
329 uno::Reference
<XAccessible
> xChild
;
331 // Depending on the index decide whether to delegate this call to the
332 // children manager or the edit engine.
333 if ((mpChildrenManager
!= nullptr)
334 && (nIndex
< mpChildrenManager
->GetChildCount()))
336 xChild
= mpChildrenManager
->GetChild (nIndex
);
338 else if (mpText
!= nullptr)
340 sal_Int64 nI
= nIndex
;
341 if (mpChildrenManager
!= nullptr)
342 nI
-= mpChildrenManager
->GetChildCount();
343 xChild
= mpText
->GetChild (nI
);
346 throw lang::IndexOutOfBoundsException (
347 "shape has no child with index " + OUString::number(nIndex
),
353 uno::Reference
<XAccessibleRelationSet
> SAL_CALL
354 AccessibleShape::getAccessibleRelationSet()
356 ::osl::MutexGuard
aGuard (m_aMutex
);
357 if (mpParent
== nullptr)
358 return uno::Reference
<XAccessibleRelationSet
>();
360 rtl::Reference
<::utl::AccessibleRelationSetHelper
> pRelationSet
= new utl::AccessibleRelationSetHelper
;
362 //this mxshape is the captioned shape
363 uno::Sequence
<uno::Reference
<css::accessibility::XAccessible
>> aSequence
{ mpParent
->GetAccessibleCaption(mxShape
) };
366 pRelationSet
->AddRelation(
367 AccessibleRelation(AccessibleRelationType_DESCRIBED_BY
, aSequence
));
372 /** Return a copy of the state set.
379 AccessibleShape::getAccessibleStateSet()
381 ::osl::MutexGuard
aGuard (m_aMutex
);
385 // Return a minimal state set that only contains the DEFUNC state.
386 return AccessibleContextBase::getAccessibleStateSet ();
389 // Merge current FOCUSED state from edit engine.
392 if (mpText
->HaveFocus())
393 mnStateSet
|= AccessibleStateType::FOCUSED
;
395 mnStateSet
&= ~AccessibleStateType::FOCUSED
;
397 //Just when the document is not read-only,set states EDITABLE,RESIZABLE,MOVEABLE
398 css::uno::Reference
<XAccessible
> xTempAcc
= getAccessibleParent();
401 css::uno::Reference
<XAccessibleContext
>
402 xTempAccContext
= xTempAcc
->getAccessibleContext();
403 if( xTempAccContext
.is() )
405 sal_Int64 nState
= xTempAccContext
->getAccessibleStateSet();
406 if (nState
& AccessibleStateType::EDITABLE
)
408 mnStateSet
|= AccessibleStateType::EDITABLE
;
409 mnStateSet
|= AccessibleStateType::RESIZABLE
;
410 mnStateSet
|= AccessibleStateType::MOVEABLE
;
415 sal_Int64 nRetStateSet
= mnStateSet
;
417 if (mpParent
&& mpParent
->IsDocumentSelAll())
419 nRetStateSet
|= AccessibleStateType::SELECTED
;
425 // XAccessibleComponent
426 /** The implementation below is at the moment straightforward. It iterates
427 over all children (and thereby instances all children which have not
428 been already instantiated) until a child covering the specified point is
430 This leaves room for improvement. For instance, first iterate only over
431 the already instantiated children and only if no match is found
432 instantiate the remaining ones.
434 uno::Reference
<XAccessible
> SAL_CALL
435 AccessibleShape::getAccessibleAtPoint (
436 const awt::Point
& aPoint
)
438 ::osl::MutexGuard
aGuard (m_aMutex
);
440 sal_Int64 nChildCount
= getAccessibleChildCount ();
441 for (sal_Int64 i
= 0; i
< nChildCount
; ++i
)
443 Reference
<XAccessible
> xChild (getAccessibleChild (i
));
446 Reference
<XAccessibleComponent
> xChildComponent (
447 xChild
->getAccessibleContext(), uno::UNO_QUERY
);
448 if (xChildComponent
.is())
450 awt::Rectangle
aBBox (xChildComponent
->getBounds());
451 if ( (aPoint
.X
>= aBBox
.X
)
452 && (aPoint
.Y
>= aBBox
.Y
)
453 && (aPoint
.X
< aBBox
.X
+aBBox
.Width
)
454 && (aPoint
.Y
< aBBox
.Y
+aBBox
.Height
) )
460 // Have not found a child under the given point. Returning empty
461 // reference to indicate this.
462 return uno::Reference
<XAccessible
>();
466 awt::Rectangle SAL_CALL
AccessibleShape::getBounds()
468 SolarMutexGuard aSolarGuard
;
469 ::osl::MutexGuard
aGuard (m_aMutex
);
472 awt::Rectangle aBoundingBox
;
476 static constexpr OUString sBoundRectName
= u
"BoundRect"_ustr
;
477 static constexpr OUString sAnchorPositionName
= u
"AnchorPosition"_ustr
;
479 // Get the shape's bounding box in internal coordinates (in 100th of
480 // mm). Use the property BoundRect. Only if that is not supported ask
481 // the shape for its position and size directly.
482 Reference
<beans::XPropertySet
> xSet (mxShape
, uno::UNO_QUERY
);
483 Reference
<beans::XPropertySetInfo
> xSetInfo
;
484 bool bFoundBoundRect
= false;
487 xSetInfo
= xSet
->getPropertySetInfo ();
490 if (xSetInfo
->hasPropertyByName (sBoundRectName
))
494 uno::Any aValue
= xSet
->getPropertyValue (sBoundRectName
);
495 aValue
>>= aBoundingBox
;
496 bFoundBoundRect
= true;
498 catch (beans::UnknownPropertyException
const&)
500 // Handled below (bFoundBoundRect stays false).
504 SAL_WARN("svx", "no property BoundRect");
508 // Fallback when there is no BoundRect Property.
509 if ( ! bFoundBoundRect
)
511 awt::Point
aPosition (mxShape
->getPosition());
512 awt::Size
aSize (mxShape
->getSize());
513 aBoundingBox
= awt::Rectangle (
514 aPosition
.X
, aPosition
.Y
,
515 aSize
.Width
, aSize
.Height
);
517 // While BoundRects have absolute positions, the position returned
518 // by XPosition::getPosition is relative. Get the anchor position
519 // (usually not (0,0) for Writer shapes).
522 if (xSetInfo
->hasPropertyByName (sAnchorPositionName
))
524 uno::Any aPos
= xSet
->getPropertyValue (sAnchorPositionName
);
525 awt::Point aAnchorPosition
;
526 aPos
>>= aAnchorPosition
;
527 aBoundingBox
.X
+= aAnchorPosition
.X
;
528 aBoundingBox
.Y
+= aAnchorPosition
.Y
;
533 // Transform coordinates from internal to pixel.
534 if (maShapeTreeInfo
.GetViewForwarder() == nullptr)
535 throw uno::RuntimeException (
536 u
"AccessibleShape has no valid view forwarder"_ustr
,
538 ::Size aPixelSize
= maShapeTreeInfo
.GetViewForwarder()->LogicToPixel (
539 ::Size (aBoundingBox
.Width
, aBoundingBox
.Height
));
540 ::Point aPixelPosition
= maShapeTreeInfo
.GetViewForwarder()->LogicToPixel (
541 ::Point (aBoundingBox
.X
, aBoundingBox
.Y
));
543 // Clip the shape's bounding box with the bounding box of its parent.
544 Reference
<XAccessibleComponent
> xParentComponent (
545 getAccessibleParent(), uno::UNO_QUERY
);
546 if (xParentComponent
.is())
548 // Make the coordinates relative to the parent.
549 awt::Point
aParentLocation (xParentComponent
->getLocationOnScreen());
550 int x
= aPixelPosition
.getX() - aParentLocation
.X
;
551 int y
= aPixelPosition
.getY() - aParentLocation
.Y
;
553 // Clip with parent (with coordinates relative to itself).
554 ::tools::Rectangle
aBBox (
555 x
, y
, x
+ aPixelSize
.getWidth(), y
+ aPixelSize
.getHeight());
556 awt::Size
aParentSize (xParentComponent
->getSize());
557 ::tools::Rectangle
aParentBBox (0,0, aParentSize
.Width
, aParentSize
.Height
);
558 aBBox
= aBBox
.GetIntersection (aParentBBox
);
559 aBoundingBox
= awt::Rectangle (
562 aBBox
.getOpenWidth(),
563 aBBox
.getOpenHeight());
567 SAL_INFO("svx", "parent does not support component");
568 aBoundingBox
= awt::Rectangle (
569 aPixelPosition
.getX(), aPixelPosition
.getY(),
570 aPixelSize
.getWidth(), aPixelSize
.getHeight());
578 awt::Point SAL_CALL
AccessibleShape::getLocation()
581 awt::Rectangle
aBoundingBox (getBounds());
582 return awt::Point (aBoundingBox
.X
, aBoundingBox
.Y
);
586 awt::Point SAL_CALL
AccessibleShape::getLocationOnScreen()
590 // Get relative position...
591 awt::Point
aLocation (getLocation ());
593 // ... and add absolute position of the parent.
594 uno::Reference
<XAccessibleComponent
> xParentComponent (
595 getAccessibleParent(), uno::UNO_QUERY
);
596 if (xParentComponent
.is())
598 awt::Point
aParentLocation (xParentComponent
->getLocationOnScreen());
599 aLocation
.X
+= aParentLocation
.X
;
600 aLocation
.Y
+= aParentLocation
.Y
;
603 SAL_WARN("svx", "parent does not support XAccessibleComponent");
608 awt::Size SAL_CALL
AccessibleShape::getSize()
611 awt::Rectangle
aBoundingBox (getBounds());
612 return awt::Size (aBoundingBox
.Width
, aBoundingBox
.Height
);
616 sal_Int32 SAL_CALL
AccessibleShape::getForeground()
619 sal_Int32
nColor (0x0ffffffL
);
623 uno::Reference
<beans::XPropertySet
> aSet (mxShape
, uno::UNO_QUERY
);
627 aColor
= aSet
->getPropertyValue (u
"LineColor"_ustr
);
631 catch (const css::beans::UnknownPropertyException
&)
633 // Ignore exception and return default color.
639 sal_Int32 SAL_CALL
AccessibleShape::getBackground()
646 uno::Reference
<beans::XPropertySet
> aSet (mxShape
, uno::UNO_QUERY
);
650 aColor
= aSet
->getPropertyValue (u
"FillColor"_ustr
);
652 aColor
= aSet
->getPropertyValue (u
"FillTransparence"_ustr
);
662 nTrans
= short(256 - nTrans
/ 100. * 256);
663 crBk
.SetAlpha(255 - sal_uInt8(nTrans
));
668 catch (const css::beans::UnknownPropertyException
&)
670 // Ignore exception and return default color.
672 return sal_Int32(nColor
);
675 // XAccessibleEventBroadcaster
676 void SAL_CALL
AccessibleShape::addAccessibleEventListener (
677 const Reference
<XAccessibleEventListener
>& rxListener
)
679 if (rBHelper
.bDisposed
|| rBHelper
.bInDispose
)
681 uno::Reference
<uno::XInterface
> xThis (
682 static_cast<lang::XComponent
*>(this), uno::UNO_QUERY
);
683 rxListener
->disposing (lang::EventObject (xThis
));
687 AccessibleContextBase::addAccessibleEventListener (rxListener
);
688 if (mpText
!= nullptr)
689 mpText
->AddEventListener (rxListener
);
694 void SAL_CALL
AccessibleShape::removeAccessibleEventListener (
695 const Reference
<XAccessibleEventListener
>& rxListener
)
697 AccessibleContextBase::removeAccessibleEventListener (rxListener
);
698 if (mpText
!= nullptr)
699 mpText
->RemoveEventListener (rxListener
);
703 css::uno::Any SAL_CALL
704 AccessibleShape::queryInterface (const css::uno::Type
& rType
)
706 css::uno::Any aReturn
= AccessibleContextBase::queryInterface (rType
);
707 if ( ! aReturn
.hasValue())
708 aReturn
= ::cppu::queryInterface (rType
,
709 static_cast<XAccessibleComponent
*>(this),
710 static_cast<XAccessibleExtendedComponent
*>(this),
711 static_cast< css::accessibility::XAccessibleSelection
* >(this),
712 static_cast< css::accessibility::XAccessibleExtendedAttributes
* >(this),
713 static_cast<document::XShapeEventListener
*>(this),
714 static_cast<lang::XUnoTunnel
*>(this),
715 static_cast<XAccessibleGroupPosition
*>(this),
716 static_cast<XAccessibleHypertext
*>(this)
723 AccessibleShape::acquire()
726 AccessibleContextBase::acquire ();
731 AccessibleShape::release()
734 AccessibleContextBase::release ();
737 // XAccessibleSelection
738 void SAL_CALL
AccessibleShape::selectAccessibleChild( sal_Int64
)
743 sal_Bool SAL_CALL
AccessibleShape::isAccessibleChildSelected( sal_Int64 nChildIndex
)
745 uno::Reference
<XAccessible
> xAcc
= getAccessibleChild( nChildIndex
);
746 uno::Reference
<XAccessibleContext
> xContext
;
749 xContext
= xAcc
->getAccessibleContext();
754 if( xContext
->getAccessibleRole() == AccessibleRole::PARAGRAPH
)
756 uno::Reference
< css::accessibility::XAccessibleText
>
757 xText(xAcc
, uno::UNO_QUERY
);
760 if( xText
->getSelectionStart() >= 0 ) return true;
763 else if( xContext
->getAccessibleRole() == AccessibleRole::SHAPE
)
765 sal_Int64 pRState
= xContext
->getAccessibleStateSet();
767 return bool(pRState
& AccessibleStateType::SELECTED
);
775 void SAL_CALL
AccessibleShape::clearAccessibleSelection( )
780 void SAL_CALL
AccessibleShape::selectAllAccessibleChildren( )
785 sal_Int64 SAL_CALL
AccessibleShape::getSelectedAccessibleChildCount()
787 sal_Int64 nCount
= 0;
788 sal_Int64 TotalCount
= getAccessibleChildCount();
789 for( sal_Int64 i
= 0; i
< TotalCount
; i
++ )
790 if( isAccessibleChildSelected(i
) ) nCount
++;
796 Reference
<XAccessible
> SAL_CALL
AccessibleShape::getSelectedAccessibleChild( sal_Int64 nSelectedChildIndex
)
798 if ( nSelectedChildIndex
> getSelectedAccessibleChildCount() )
799 throw IndexOutOfBoundsException();
800 for (sal_Int64 i1
= 0, i2
= 0; i1
< getAccessibleChildCount(); i1
++)
801 if( isAccessibleChildSelected(i1
) )
803 if( i2
== nSelectedChildIndex
)
804 return getAccessibleChild( i1
);
807 return Reference
<XAccessible
>();
811 void SAL_CALL
AccessibleShape::deselectAccessibleChild( sal_Int64
)
816 // XAccessibleExtendedAttributes
817 uno::Any SAL_CALL
AccessibleShape::getExtendedAttributes()
821 if( getAccessibleRole() != AccessibleRole::SHAPE
) return strRet
;
824 style
= "style:" + GetStyle();
833 AccessibleShape::getImplementationName()
835 return u
"AccessibleShape"_ustr
;
839 uno::Sequence
<OUString
> SAL_CALL
840 AccessibleShape::getSupportedServiceNames()
843 const css::uno::Sequence
<OUString
> vals
{ u
"com.sun.star.drawing.AccessibleShape"_ustr
};
844 return comphelper::concatSequences(AccessibleContextBase::getSupportedServiceNames(), vals
);
848 uno::Sequence
<uno::Type
> SAL_CALL
849 AccessibleShape::getTypes()
852 // Get list of types from the context base implementation, ...
853 uno::Sequence
<uno::Type
> aTypeList (AccessibleContextBase::getTypes());
854 // ... get list of types from component base implementation, ...
855 uno::Sequence
<uno::Type
> aComponentTypeList (AccessibleComponentBase::getTypes());
856 // ... define local types
857 uno::Sequence
<uno::Type
> localTypesList
= {
858 cppu::UnoType
<lang::XEventListener
>::get(),
859 cppu::UnoType
<document::XEventListener
>::get(),
860 cppu::UnoType
<lang::XUnoTunnel
>::get()
863 return comphelper::concatSequences(aTypeList
, aComponentTypeList
, localTypesList
);
866 // lang::XEventListener
867 /** Disposing calls are accepted only from the model: Just reset the
868 reference to the model in the shape tree info. Otherwise this object
871 void AccessibleShape::disposing (const lang::EventObject
& aEvent
)
873 SolarMutexGuard aSolarGuard
;
874 ::osl::MutexGuard
aGuard (m_aMutex
);
878 if (aEvent
.Source
== maShapeTreeInfo
.GetModelBroadcaster())
880 // Remove reference to model broadcaster to allow it to pass
882 maShapeTreeInfo
.SetModelBroadcaster(nullptr);
886 catch (uno::RuntimeException
const&)
888 TOOLS_WARN_EXCEPTION("svx", "caught exception while disposing");
890 mpChildrenManager
.reset();
892 maShapeTreeInfo
.dispose();
896 // document::XShapeEventListener
898 AccessibleShape::notifyShapeEvent (const document::EventObject
& rEventObject
)
900 if (rEventObject
.EventName
!= "ShapeModified")
903 //Need to update text children when receiving ShapeModified hint when exiting edit mode for text box
905 mpText
->UpdateChildren();
908 // Some property of a shape has been modified. Send an event
909 // that indicates a change of the visible data to all listeners.
911 AccessibleEventId::VISIBLE_DATA_CHANGED
,
915 // Name and Description may have changed. Update the local
916 // values accordingly.
917 UpdateNameAndDescription();
921 UNO3_GETIMPLEMENTATION_IMPL(AccessibleShape
)
923 // IAccessibleViewForwarderListener
924 void AccessibleShape::ViewForwarderChanged()
926 // Inform all listeners that the graphical representation (i.e. size
927 // and/or position) of the shape has changed.
928 CommitChange (AccessibleEventId::VISIBLE_DATA_CHANGED
,
932 // Tell children manager of the modified view forwarder.
933 if (mpChildrenManager
!= nullptr)
934 mpChildrenManager
->ViewForwarderChanged();
936 // update our children that our screen position might have changed
938 mpText
->UpdateChildren();
941 // protected internal
942 // Set this object's name if is different to the current name.
943 OUString
AccessibleShape::CreateAccessibleBaseName()
945 return ShapeTypeHandler::CreateAccessibleBaseName( mxShape
);
949 OUString
AccessibleShape::CreateAccessibleName()
951 return GetFullAccessibleName(this);
954 OUString
AccessibleShape::GetFullAccessibleName (AccessibleShape
*shape
)
956 OUString
sName (shape
->CreateAccessibleBaseName());
957 // Append the shape's index to the name to disambiguate between shapes
958 // of the same type. If such an index where not given to the
959 // constructor then use the z-order instead. If even that does not exist
960 // we throw an exception.
963 nameStr
= shape
->m_pShape
->GetName();
964 if (nameStr
.isEmpty())
973 //If the new produced name if not the same with last,notify name changed
975 if (aAccName
!= sName
&& !aAccName
.isEmpty())
977 uno::Any aOldValue
, aNewValue
;
978 aOldValue
<<= aAccName
;
981 AccessibleEventId::NAME_CHANGED
,
990 void AccessibleShape::disposing()
992 SolarMutexGuard aSolarGuard
;
993 ::osl::MutexGuard
aGuard (m_aMutex
);
995 // Make sure to send an event that this object loses the focus in the
996 // case that it has the focus.
997 mnStateSet
&= ~AccessibleStateType::FOCUSED
;
999 // Unregister from model.
1000 if (mxShape
.is() && maShapeTreeInfo
.GetModelBroadcaster().is())
1001 maShapeTreeInfo
.GetModelBroadcaster()->removeShapeEventListener(mxShape
,
1002 static_cast<document::XShapeEventListener
*>(this));
1004 // Release the child containers.
1005 if (mpChildrenManager
!= nullptr)
1007 mpChildrenManager
.reset();
1009 if (mpText
!= nullptr)
1015 // Cleanup. Remove references to objects to allow them to be
1018 maShapeTreeInfo
.dispose();
1020 // Call base classes.
1021 AccessibleContextBase::disposing();
1025 AccessibleShape::getAccessibleIndexInParent()
1028 // Use a simple but slow solution for now. Optimize later.
1030 sal_Int64 nIndex
= m_nIndexInParent
;
1032 nIndex
= AccessibleContextBase::getAccessibleIndexInParent();
1037 void AccessibleShape::UpdateNameAndDescription()
1039 // Ignore missing title, name, or description. There are fallbacks for
1043 Reference
<beans::XPropertySet
> xSet (mxShape
, uno::UNO_QUERY_THROW
);
1045 // Get the accessible name.
1046 OUString sString
= GetOptionalProperty(xSet
, u
"Title"_ustr
);
1047 if (!sString
.isEmpty())
1049 SetAccessibleName(sString
, AccessibleContextBase::FromShape
);
1053 sString
= GetOptionalProperty(xSet
, u
"Name"_ustr
);
1054 if (!sString
.isEmpty())
1055 SetAccessibleName(sString
, AccessibleContextBase::FromShape
);
1058 // Get the accessible description.
1059 sString
= GetOptionalProperty(xSet
, u
"Description"_ustr
);
1060 if (!sString
.isEmpty())
1061 SetAccessibleDescription(sString
, AccessibleContextBase::FromShape
);
1063 catch (uno::RuntimeException
&)
1068 // Return this object's role.
1069 sal_Int16 SAL_CALL
AccessibleShape::getAccessibleRole()
1071 sal_Int16 nAccessibleRole
= AccessibleRole::SHAPE
;
1072 switch (ShapeTypeHandler::Instance().GetTypeId (mxShape
))
1074 case DRAWING_GRAPHIC_OBJECT
:
1075 nAccessibleRole
= AccessibleRole::GRAPHIC
; break;
1077 nAccessibleRole
= AccessibleRole::EMBEDDED_OBJECT
; break;
1080 nAccessibleRole
= AccessibleContextBase::getAccessibleRole();
1084 return nAccessibleRole
;
1089 //sort the drawing objects from up to down, from left to right
1090 struct XShapePosCompareHelper
1092 bool operator() ( const uno::Reference
<drawing::XShape
>& xshape1
,
1093 const uno::Reference
<drawing::XShape
>& xshape2
) const
1095 SdrObject
* pObj1
= SdrObject::getSdrObjectFromXShape(xshape1
);
1096 SdrObject
* pObj2
= SdrObject::getSdrObjectFromXShape(xshape2
);
1098 return pObj1
->GetOrdNum() < pObj2
->GetOrdNum();
1105 //end of group position
1107 // XAccessibleGroupPosition
1108 uno::Sequence
< sal_Int32
> SAL_CALL
1109 AccessibleShape::getGroupPosition( const uno::Any
& )
1111 // we will return the:
1113 // [1] similar items counts in the group
1114 // [2] the position of the object in the group
1115 uno::Sequence
< sal_Int32
> aRet
{ 0, 0, 0 };
1117 css::uno::Reference
<XAccessible
> xParent
= getAccessibleParent();
1122 SdrObject
*pObj
= SdrObject::getSdrObjectFromXShape(mxShape
);
1125 if(pObj
== nullptr )
1130 // Compute object's group level.
1131 sal_Int32 nGroupLevel
= 0;
1132 SdrObject
* pUper
= pObj
->getParentSdrObjectFromSdrObject();
1136 pUper
= pUper
->getParentSdrObjectFromSdrObject();
1139 css::uno::Reference
<XAccessibleContext
> xParentContext
= xParent
->getAccessibleContext();
1140 if( xParentContext
->getAccessibleRole() == AccessibleRole::DOCUMENT
||
1141 xParentContext
->getAccessibleRole() == AccessibleRole::DOCUMENT_PRESENTATION
||
1142 xParentContext
->getAccessibleRole() == AccessibleRole::DOCUMENT_SPREADSHEET
||
1143 xParentContext
->getAccessibleRole() == AccessibleRole::DOCUMENT_TEXT
)//Document
1145 Reference
< XAccessibleGroupPosition
> xGroupPosition( xParent
,uno::UNO_QUERY
);
1146 if ( xGroupPosition
.is() )
1148 aRet
= xGroupPosition
->getGroupPosition( uno::Any( getAccessibleContext() ) );
1152 if (xParentContext
->getAccessibleRole() != AccessibleRole::SHAPE
)
1157 SdrObjList
*pGrpList
= nullptr;
1158 if( pObj
->getParentSdrObjectFromSdrObject() )
1159 pGrpList
= pObj
->getParentSdrObjectFromSdrObject()->GetSubList();
1163 std::vector
< uno::Reference
<drawing::XShape
> > vXShapes
;
1166 const size_t nObj
= pGrpList
->GetObjCount();
1167 for(size_t i
= 0 ; i
< nObj
; ++i
)
1169 SdrObject
*pSubObj
= pGrpList
->GetObj(i
);
1171 xParentContext
->getAccessibleChild(i
)->getAccessibleContext()->getAccessibleRole() != AccessibleRole::GROUP_BOX
)
1173 vXShapes
.push_back( GetXShapeForSdrObject(pSubObj
) );
1178 std::sort( vXShapes
.begin(), vXShapes
.end(), XShapePosCompareHelper() );
1180 //get the index of the selected object in the group
1181 //we start counting position from 1
1183 for ( const auto& rpShape
: vXShapes
)
1185 if ( rpShape
.get() == mxShape
.get() )
1187 sal_Int32
* pArray
= aRet
.getArray();
1188 pArray
[0] = nGroupLevel
;
1189 pArray
[1] = vXShapes
.size();
1199 OUString
AccessibleShape::getObjectLink( const uno::Any
& )
1203 SdrObject
*pObj
= SdrObject::getSdrObjectFromXShape(mxShape
);
1204 if(pObj
== nullptr )
1208 if (maShapeTreeInfo
.GetDocumentWindow().is())
1210 Reference
< XAccessibleGroupPosition
> xGroupPosition( maShapeTreeInfo
.GetDocumentWindow(), uno::UNO_QUERY
);
1211 if (xGroupPosition
.is())
1213 aRet
= xGroupPosition
->getObjectLink( uno::Any( getAccessibleContext() ) );
1219 // XAccessibleHypertext
1220 sal_Int32 SAL_CALL
AccessibleShape::getHyperLinkCount()
1222 // MT: Introduced with IA2 CWS, but SvxAccessibleHyperlink was redundant to svx::AccessibleHyperlink which we introduced meanwhile.
1223 // Code need to be adapted...
1227 SvxAccessibleHyperlink* pLink = new SvxAccessibleHyperlink(m_pShape,this);
1228 if (pLink->IsValidHyperlink())
1234 uno::Reference
< XAccessibleHyperlink
> SAL_CALL
1235 AccessibleShape::getHyperLink( sal_Int32
)
1237 uno::Reference
< XAccessibleHyperlink
> xRet
;
1238 // MT: Introduced with IA2 CWS, but SvxAccessibleHyperlink was redundant to svx::AccessibleHyperlink which we introduced meanwhile.
1239 // Code need to be adapted...
1241 SvxAccessibleHyperlink* pLink = new SvxAccessibleHyperlink(m_pShape,this);
1242 if (pLink->IsValidHyperlink())
1245 throw css::lang::IndexOutOfBoundsException();
1249 sal_Int32 SAL_CALL
AccessibleShape::getHyperLinkIndex( sal_Int32
)
1254 sal_Int32 SAL_CALL
AccessibleShape::getCaretPosition( ){return 0;}
1255 sal_Bool SAL_CALL
AccessibleShape::setCaretPosition( sal_Int32
){return false;}
1256 sal_Unicode SAL_CALL
AccessibleShape::getCharacter( sal_Int32
){return 0;}
1257 css::uno::Sequence
< css::beans::PropertyValue
> SAL_CALL
AccessibleShape::getCharacterAttributes( sal_Int32
, const css::uno::Sequence
< OUString
>& )
1259 uno::Sequence
< css::beans::PropertyValue
> aValues(0);
1262 css::awt::Rectangle SAL_CALL
AccessibleShape::getCharacterBounds( sal_Int32
)
1264 return css::awt::Rectangle(0, 0, 0, 0 );
1266 sal_Int32 SAL_CALL
AccessibleShape::getCharacterCount( ){return 0;}
1267 sal_Int32 SAL_CALL
AccessibleShape::getIndexAtPoint( const css::awt::Point
& ){return 0;}
1268 OUString SAL_CALL
AccessibleShape::getSelectedText( ){return OUString();}
1269 sal_Int32 SAL_CALL
AccessibleShape::getSelectionStart( ){return 0;}
1270 sal_Int32 SAL_CALL
AccessibleShape::getSelectionEnd( ){return 0;}
1271 sal_Bool SAL_CALL
AccessibleShape::setSelection( sal_Int32
, sal_Int32
){return true;}
1272 OUString SAL_CALL
AccessibleShape::getText( ){return OUString();}
1273 OUString SAL_CALL
AccessibleShape::getTextRange( sal_Int32
, sal_Int32
){return OUString();}
1274 css::accessibility::TextSegment SAL_CALL
AccessibleShape::getTextAtIndex( sal_Int32
, sal_Int16
)
1276 css::accessibility::TextSegment aResult
;
1279 css::accessibility::TextSegment SAL_CALL
AccessibleShape::getTextBeforeIndex( sal_Int32
, sal_Int16
)
1281 css::accessibility::TextSegment aResult
;
1284 css::accessibility::TextSegment SAL_CALL
AccessibleShape::getTextBehindIndex( sal_Int32
, sal_Int16
)
1286 css::accessibility::TextSegment aResult
;
1289 sal_Bool SAL_CALL
AccessibleShape::copyText( sal_Int32
, sal_Int32
){return true;}
1290 sal_Bool SAL_CALL
AccessibleShape::scrollSubstringTo( sal_Int32
, sal_Int32
, AccessibleScrollType
){return false;}
1292 } // end of namespace accessibility
1294 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */