32#include <com/sun/star/accessibility/AccessibleRole.hpp>
33#include <com/sun/star/accessibility/AccessibleStateType.hpp>
34#include <com/sun/star/accessibility/AccessibleEventId.hpp>
35#include <com/sun/star/beans/XPropertySet.hpp>
36#include <com/sun/star/document/XShapeEventBroadcaster.hpp>
37#include <com/sun/star/frame/XController.hpp>
38#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
39#include <com/sun/star/view/XSelectionSupplier.hpp>
40#include <com/sun/star/container/XChild.hpp>
44#include <rtl/ustring.hxx>
51using ::com::sun::star::uno::Reference;
60 for (
auto& rItem : _rList)
62 rItem.setIndexAtAccessibleShape(i);
70 uno::Reference<XAccessible> xParent,
71 uno::Reference<drawing::XShapes> xShapeList,
72 const AccessibleShapeTreeInfo& rShapeTreeInfo,
73 AccessibleContextBase& rContext)
74 : mxShapeList (
std::move(xShapeList)),
76 maShapeTreeInfo (rShapeTreeInfo),
78 mpFocusedShape(nullptr)
83ChildrenManagerImpl::~ChildrenManagerImpl()
89void ChildrenManagerImpl::Init()
92 Reference<frame::XController>
xController(maShapeTreeInfo.GetController());
93 Reference<view::XSelectionSupplier> xSelectionSupplier (
95 if (xSelectionSupplier.is())
98 static_cast<document::XEventListener*
>(
this));
100 xSelectionSupplier->addSelectionChangeListener (
101 static_cast<view::XSelectionChangeListener*
>(
this));
105 if (maShapeTreeInfo.GetModelBroadcaster().is())
106 maShapeTreeInfo.GetModelBroadcaster()->addEventListener (
107 static_cast<document::XEventListener*
>(
this));
111sal_Int64 ChildrenManagerImpl::GetChildCount() const noexcept
113 return maVisibleChildren.size();
117const css::uno::Reference<css::drawing::XShape>& ChildrenManagerImpl::GetChildShape(sal_Int64 nIndex)
121 throw lang::IndexOutOfBoundsException (
122 "no accessible child with index " + OUString::number(
nIndex),
124 return maVisibleChildren[
nIndex].mxShape;
130uno::Reference<XAccessible>
131 ChildrenManagerImpl::GetChild (sal_Int64 nIndex)
135 throw lang::IndexOutOfBoundsException (
136 "no accessible child with index " + OUString::number(
nIndex),
146uno::Reference<XAccessible>
163 ShapeTypeHandler::Instance().CreateAccessibleObject (
170 pShape->setIndexInParent(_nIndex);
189void ChildrenManagerImpl::Update (
bool bCreateNewObjectsOnDemand)
191 if (maShapeTreeInfo.GetViewForwarder() ==
nullptr)
193 tools::Rectangle aVisibleArea = maShapeTreeInfo.GetViewForwarder()->GetVisibleArea();
197 CreateListOfVisibleShapes (aChildList);
205 maVisibleChildren.swap (aChildList);
210 std::vector<ChildDescriptor*> aUnusedChildList = MergeAccessibilityInformation (aChildList);
212 adjustIndexInParentOfShapes(maVisibleChildren);
235 RemoveNonVisibleChildren (aUnusedChildList);
237 aUnusedChildList.clear();
240 maVisibleArea = aVisibleArea;
246 if (maVisibleArea != aVisibleArea)
247 SendVisibleAreaEvents (maVisibleChildren);
251 if (bCreateNewObjectsOnDemand)
263 maVisibleChildren.swap(aChildList);
264 CreateAccessibilityObjects(aChildList);
265 maVisibleChildren.swap(aChildList);
268void ChildrenManagerImpl::CreateListOfVisibleShapes (
273 OSL_ASSERT (maShapeTreeInfo.GetViewForwarder() !=
nullptr);
275 tools::Rectangle aVisibleArea = maShapeTreeInfo.GetViewForwarder()->GetVisibleArea();
278 for (
const auto& rpShape : maAccessibleShapes)
282 uno::Reference<XAccessibleComponent> xComponent (
283 rpShape->getAccessibleContext(), uno::UNO_QUERY);
289 awt::Rectangle aPixelBBox (xComponent->getBounds());
290 if ((aPixelBBox.Width > 0) && (aPixelBBox.Height > 0))
291 raDescriptorList.emplace_back(rpShape);
297 if (!mxShapeList.is() || !mxShapeList->hasElements())
300 sal_Int32 nShapeCount = mxShapeList->getCount();
301 raDescriptorList.reserve( nShapeCount );
305 uno::Reference<drawing::XShape> xShape;
306 for (sal_Int32
i=0;
i<nShapeCount; ++
i)
308 mxShapeList->getByIndex(
i) >>= xShape;
309 aPos = xShape->getPosition();
310 aSize = xShape->getSize();
312 aBoundingBox.
SetLeft( aPos.X );
313 aBoundingBox.
SetTop( aPos.Y );
314 aBoundingBox.
SetRight( aPos.X + aSize.Width );
315 aBoundingBox.
SetBottom( aPos.Y + aSize.Height );
319 if ( aBoundingBox.
Overlaps(aVisibleArea) )
320 raDescriptorList.emplace_back(xShape);
330 auto pLhsShape = lhs.
mxShape.get();
331 auto pRhsShape = rhs.
mxShape.get();
332 if (pLhsShape || pRhsShape)
333 return pLhsShape < pRhsShape;
337bool childDescriptorPtrLess(
const ChildDescriptor* lhs,
const ChildDescriptor* rhs)
339 return childDescriptorLess(*lhs, *rhs);
344void ChildrenManagerImpl::RemoveNonVisibleChildren (
345 const std::vector<ChildDescriptor*>& rNonVisibleChildren)
353 if (pChild->mxShape.is())
355 UnregisterAsDisposeListener (pChild->mxShape);
356 pChild->disposeAccessibleObject (
mrContext);
361 pAccessibleShape->
ResetState (AccessibleStateType::VISIBLE);
362 pChild->mxAccessibleShape =
nullptr;
367std::vector<ChildDescriptor*> ChildrenManagerImpl::MergeAccessibilityInformation (
375 std::vector<ChildDescriptor*> aSortedVisibleChildren(maVisibleChildren.size());
376 std::transform(maVisibleChildren.begin(), maVisibleChildren.end(),
377 aSortedVisibleChildren.begin(), [](
auto& e) {return &e;});
378 std::sort(aSortedVisibleChildren.begin(), aSortedVisibleChildren.end(), childDescriptorPtrLess);
381 std::sort(raOldChildList.begin(), raOldChildList.end(), childDescriptorLess);
383 ChildDescriptorListType::const_iterator aOldChildDescriptor = raOldChildList.begin();
384 ChildDescriptorListType::const_iterator aEndOldChildren = raOldChildList.end();
387 while (aOldChildDescriptor != aEndOldChildren && childDescriptorLess(*aOldChildDescriptor, *pChild))
389 aOldChildDescriptor++;
393 if (aOldChildDescriptor != aEndOldChildren && *aOldChildDescriptor == *pChild &&
394 aOldChildDescriptor->mxAccessibleShape.is())
396 pChild->mxAccessibleShape = aOldChildDescriptor->mxAccessibleShape;
397 pChild->mbCreateEventPending =
false;
400 RegisterAsDisposeListener (pChild->mxShape);
404 std::vector<ChildDescriptor*> aObsoleteChildren;
406 auto newIt = aSortedVisibleChildren.begin();
407 auto newEnd = aSortedVisibleChildren.end();
410 while (newIt != newEnd && childDescriptorLess(**newIt, rOldChild))
412 if (newIt == newEnd || !(**newIt == rOldChild) )
413 aObsoleteChildren.push_back(&rOldChild);
416 return aObsoleteChildren;
419void ChildrenManagerImpl::SendVisibleAreaEvents (
422 for (
const auto& rChild : raNewChildList)
428 if (pShape !=
nullptr)
434void ChildrenManagerImpl::CreateAccessibilityObjects (
438 for (
auto& rChild : raNewChildList)
442 if ( ! rChild.mxAccessibleShape.is() )
443 GetChild (rChild,
nPos);
444 if (rChild.mxAccessibleShape.is() && rChild.mbCreateEventPending)
446 rChild.mbCreateEventPending =
false;
448 AccessibleEventId::CHILD,
449 uno::Any(uno::Reference<XAccessible>(rChild.mxAccessibleShape)),
457void ChildrenManagerImpl::AddShape (
const Reference<drawing::XShape>& rxShape)
465 tools::Rectangle aVisibleArea = maShapeTreeInfo.GetViewForwarder()->GetVisibleArea();
466 awt::Point aPos = rxShape->getPosition();
467 awt::Size aSize = rxShape->getSize();
472 aPos.X + aSize.Width,
473 aPos.Y + aSize.Height);
477 Reference<container::XChild> xChild (rxShape, uno::UNO_QUERY);
481 Reference<drawing::XShapes> xParent (xChild->getParent(), uno::UNO_QUERY);
482 if (xParent != mxShapeList)
485 if (!aBoundingBox.
Overlaps(aVisibleArea))
489 maVisibleChildren.emplace_back(rxShape);
493 GetChild (rDescriptor, maVisibleChildren.size()-1);
500 AccessibleEventId::CHILD,
503 RegisterAsDisposeListener(rxShape);
507void ChildrenManagerImpl::RemoveShape (
const Reference<drawing::XShape>& rxShape)
515 ChildDescriptorListType::iterator
I (
516 ::std::find (maVisibleChildren.begin(), maVisibleChildren.end(),
518 if (
I == maVisibleChildren.end())
522 Reference<XAccessible> xHoldAlive(
I->mxAccessibleShape);
524 UnregisterAsDisposeListener (
I->mxShape);
530 maVisibleChildren.erase (
I);
532 adjustIndexInParentOfShapes(maVisibleChildren);
536void ChildrenManagerImpl::SetShapeList (
const css::uno::Reference<css::drawing::XShapes>& xShapeList)
538 mxShapeList = xShapeList;
545 maAccessibleShapes.push_back (shape);
549void ChildrenManagerImpl::ClearAccessibleShapeList()
554 aLocalVisibleChildren.swap(maVisibleChildren);
556 aLocalAccessibleShapes.swap(maAccessibleShapes);
560 AccessibleEventId::INVALIDATE_ALL_CHILDREN,
569 for (
auto& rChild : aLocalVisibleChildren)
570 if ( rChild.mxAccessibleShape.is() && rChild.mxShape.is() )
572 rChild.mxAccessibleShape->dispose();
573 rChild.mxAccessibleShape =
nullptr;
577 for (
auto& rpShape : aLocalAccessibleShapes)
593 Reference<document::XEventBroadcaster> xCurrentBroadcaster;
594 Reference<frame::XController> xCurrentController;
595 Reference<view::XSelectionSupplier> xCurrentSelectionSupplier;
598 xCurrentBroadcaster = maShapeTreeInfo.GetModelBroadcaster();
599 xCurrentController = maShapeTreeInfo.GetController();
600 xCurrentSelectionSupplier.set( xCurrentController, uno::UNO_QUERY);
601 maShapeTreeInfo = rShapeTreeInfo;
605 if (maShapeTreeInfo.GetModelBroadcaster() != xCurrentBroadcaster)
608 if (maShapeTreeInfo.GetModelBroadcaster().is())
610 static_cast<document::XEventListener*
>(
this));
613 if (xCurrentBroadcaster.is())
614 xCurrentBroadcaster->removeEventListener (
615 static_cast<document::XEventListener*
>(
this));
619 Reference<frame::XController> xNewController(maShapeTreeInfo.GetController());
620 Reference<view::XSelectionSupplier> xNewSelectionSupplier (
621 xNewController, uno::UNO_QUERY);
622 if (xNewSelectionSupplier == xCurrentSelectionSupplier)
626 if (xNewSelectionSupplier.is())
628 xNewController->addEventListener(
629 static_cast<document::XEventListener*
>(
this));
631 xNewSelectionSupplier->addSelectionChangeListener (
632 static_cast<view::XSelectionChangeListener*
>(
this));
636 if (xCurrentSelectionSupplier.is())
638 xCurrentSelectionSupplier->removeSelectionChangeListener (
639 static_cast<view::XSelectionChangeListener*
>(
this));
641 xCurrentController->removeEventListener(
642 static_cast<document::XEventListener*
>(
this));
648 ChildrenManagerImpl::disposing (
const lang::EventObject& rEventObject)
650 if (rEventObject.Source == maShapeTreeInfo.GetModelBroadcaster()
651 || rEventObject.Source == maShapeTreeInfo.GetController())
659 Reference<drawing::XShape> xShape (rEventObject.Source, uno::UNO_QUERY);
662 ChildDescriptorListType::iterator
I (
663 ::std::find (maVisibleChildren.begin(), maVisibleChildren.end(),
664 ChildDescriptor (xShape)));
665 if (I != maVisibleChildren.end())
668 I->disposeAccessibleObject (mrContext);
669 I->mxShape =
nullptr;
678 ChildrenManagerImpl::notifyEvent (
679 const document::EventObject& rEventObject)
681 if (rEventObject.EventName ==
"ShapeInserted")
682 AddShape (Reference<drawing::XShape>(rEventObject.Source, uno::UNO_QUERY));
683 else if (rEventObject.EventName ==
"ShapeRemoved")
684 RemoveShape (Reference<drawing::XShape>(rEventObject.Source, uno::UNO_QUERY));
690 ChildrenManagerImpl::selectionChanged (
const lang::EventObject& )
696void ChildrenManagerImpl::impl_dispose()
698 Reference<frame::XController>
xController(maShapeTreeInfo.GetController());
702 Reference<view::XSelectionSupplier> xSelectionSupplier (
704 if (xSelectionSupplier.is())
706 xSelectionSupplier->removeSelectionChangeListener (
707 static_cast<view::XSelectionChangeListener*
>(
this));
710 catch( uno::RuntimeException&)
717 static_cast<document::XEventListener*
>(
this));
719 catch( uno::RuntimeException&)
722 maShapeTreeInfo.SetController (
nullptr);
727 if (maShapeTreeInfo.GetModelBroadcaster().is())
728 maShapeTreeInfo.GetModelBroadcaster()->removeEventListener (
729 static_cast<document::XEventListener*
>(
this));
730 maShapeTreeInfo.SetModelBroadcaster (
nullptr);
732 catch( uno::RuntimeException& )
735 ClearAccessibleShapeList ();
736 SetShapeList (
nullptr);
740void ChildrenManagerImpl::disposing(std::unique_lock<std::mutex>&)
746void ChildrenManagerImpl::ViewForwarderChanged()
752bool ChildrenManagerImpl::ReplaceChild (
754 const css::uno::Reference< css::drawing::XShape >& _rxShape,
763 auto I = std::find_if(maVisibleChildren.begin(), maVisibleChildren.end(),
764 [&pCurrentChild](
const ChildDescriptor& rChild) { return rChild.GetAccessibleShape() == pCurrentChild; });
766 if (
I != maVisibleChildren.end())
769 pCurrentChild->dispose();
771 AccessibleEventId::CHILD,
773 uno::Any (uno::Reference<XAccessible>(
I->mxAccessibleShape)));
783 if ( pNewChild.is() )
786 I->mxAccessibleShape = pNewChild.get();
788 AccessibleEventId::CHILD,
789 uno::Any (uno::Reference<XAccessible>(
I->mxAccessibleShape)),
803 sal_Int64
count = GetChildCount();
810 if (pCtlAccShape->GetControlModel() == pSet)
816uno::Reference<XAccessible>
817 ChildrenManagerImpl::GetAccessibleCaption (
const uno::Reference<drawing::XShape>& xShape)
819 auto I = std::find_if(maVisibleChildren.begin(), maVisibleChildren.end(),
820 [&xShape](
const ChildDescriptor& rChild) { return rChild.mxShape.get() == xShape.get(); });
821 if (
I != maVisibleChildren.end())
822 return I->mxAccessibleShape;
823 return uno::Reference<XAccessible> ();
836void ChildrenManagerImpl::UpdateSelection()
841 typedef std::pair< AccessibleShape* , sal_Bool > PAIR_SHAPE;
842 typedef std::vector< PAIR_SHAPE > VEC_SHAPE;
845 bool bHasSelectedShape=
false;
846 if (!maVisibleChildren.empty())
848 Reference<frame::XController>
xController(maShapeTreeInfo.GetController());
849 Reference<view::XSelectionSupplier> xSelectionSupplier (
854 Reference<container::XIndexAccess> xSelectedShapeAccess;
855 Reference<drawing::XShape> xSelectedShape;
856 if (xSelectionSupplier.is())
858 xSelectedShapeAccess.set( xSelectionSupplier->getSelection(), uno::UNO_QUERY);
859 xSelectedShape.set( xSelectionSupplier->getSelection(), uno::UNO_QUERY);
864 if (!xSelectedShape.is() && xSelectedShapeAccess.is())
866 sal_Int32
nCount = xSelectedShapeAccess->getCount();
870 css::uno::Reference<css::drawing::XShape> xShape(xSelectedShapeAccess->getByIndex(
i), uno::UNO_QUERY);
871 aSortedSelectedShapes.
insert(xShape);
875 for (
const auto& rChild : maVisibleChildren)
878 if (rChild.mxAccessibleShape.is() && rChild.mxShape.is() && pAccessibleShape!=
nullptr)
882 nRole == AccessibleRole::GRAPHIC ||
883 nRole == AccessibleRole::EMBEDDED_OBJECT ||
884 nRole == AccessibleRole::SHAPE ||
885 nRole == AccessibleRole::IMAGE_MAP ||
886 nRole == AccessibleRole::TABLE_CELL ||
887 nRole == AccessibleRole::TABLE );
888 bool bShapeIsSelected =
false;
891 if (xSelectedShape.is())
893 if (rChild.mxShape == xSelectedShape)
895 bShapeIsSelected =
true;
896 pNewFocusedShape = pAccessibleShape;
899 else if (!aSortedSelectedShapes.
empty())
901 if (aSortedSelectedShapes.
find(rChild.mxShape) != aSortedSelectedShapes.
end())
903 bShapeIsSelected =
true;
905 if (aSortedSelectedShapes.
size() == 1)
906 pNewFocusedShape = pAccessibleShape;
911 if (bShapeIsSelected)
913 if (pAccessibleShape->
SetState (AccessibleStateType::SELECTED))
917 vecSelect.emplace_back(pAccessibleShape,
true);
923 bHasSelectedShape=
true;
929 if(pAccessibleShape->
ResetState (AccessibleStateType::SELECTED))
933 vecSelect.emplace_back(pAccessibleShape,
false);
938 if (pAccessibleShape->
GetState (AccessibleStateType::FOCUSED))
939 pCurrentlyFocusedShape = pAccessibleShape;
944 vcl::Window *pParentWindow = maShapeTreeInfo.GetWindow();
945 bool bShapeActive=
false;
954 if (pCurrentlyFocusedShape != pNewFocusedShape)
956 if (pCurrentlyFocusedShape !=
nullptr)
957 pCurrentlyFocusedShape->
ResetState (AccessibleStateType::FOCUSED);
958 if (pNewFocusedShape !=
nullptr && bShapeActive)
959 pNewFocusedShape->
SetState (AccessibleStateType::FOCUSED);
962 if (nAddSelect >= 10 )
967 for (VEC_SHAPE::reverse_iterator vi = vecSelect.rbegin(), aEndVecSelect = vecSelect.rend(); vi != aEndVecSelect ;++vi)
969 PAIR_SHAPE &pairShape= *vi;
970 Reference< XAccessible > xShape(pairShape.first);
974 if (pairShape.second)
976 if (bHasSelectedShape)
978 if ( nAddSelect > 0 )
980 mrContext.CommitChange(AccessibleEventId::SELECTION_CHANGED_ADD,anyShape,
uno::Any());
988 mrContext.CommitChange(AccessibleEventId::SELECTION_CHANGED,anyShape,
uno::Any());
992 bHasSelectedShape=
true;
998 mrContext.CommitChange(AccessibleEventId::SELECTION_CHANGED_REMOVE,anyShape,
uno::Any());
1003 mpFocusedShape = pNewFocusedShape;
1007bool ChildrenManagerImpl::HasFocus()
const
1009 return mpFocusedShape !=
nullptr;
1013void ChildrenManagerImpl::RemoveFocus()
1015 if (mpFocusedShape !=
nullptr)
1017 mpFocusedShape->
ResetState (AccessibleStateType::FOCUSED);
1018 mpFocusedShape =
nullptr;
1023void ChildrenManagerImpl::RegisterAsDisposeListener (
1024 const Reference<drawing::XShape>& xShape)
1026 Reference<lang::XComponent> xComponent (xShape, uno::UNO_QUERY);
1027 if (xComponent.is())
1028 xComponent->addEventListener (
1029 static_cast<document::XEventListener*
>(
this));
1033void ChildrenManagerImpl::UnregisterAsDisposeListener (
1034 const Reference<drawing::XShape>& xShape)
1036 Reference<lang::XComponent> xComponent (xShape, uno::UNO_QUERY);
1037 if (xComponent.is())
1038 xComponent->removeEventListener (
1039 static_cast<document::XEventListener*
>(
this));
1043ChildDescriptor::ChildDescriptor (
const Reference<drawing::XShape>& xShape)
1045 mbCreateEventPending (true)
1052 : mxAccessibleShape (rxAccessibleShape),
1053 mbCreateEventPending (true)
1058 pAccessibleShape->
SetState (AccessibleStateType::VISIBLE);
1078 AccessibleEventId::CHILD,
const NodeContext & mrContext
unotools::WeakReference< AnimationNode > mxParent
void CommitChange(sal_Int16 aEventId, const css::uno::Any &rNewValue, const css::uno::Any &rOldValue)
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleParent() override
@descr This class is a container for the information specific for a single shape that is passed to th...
This class bundles all information that is passed down the tree of accessible shapes so that each sha...
const css::uno::Reference< css::document::XShapeEventBroadcaster > & GetModelBroadcaster() const
Return the current model broadcaster.
This base class provides a base implementation for all shapes.
virtual bool ResetState(sal_Int64 aState) override
Reset the specified state.
bool GetState(sal_Int64 aState)
Return the state of the specified state.
const css::uno::Reference< css::drawing::XShape > & GetXShape() const
void setIndexInParent(sal_Int32 _nIndex)
set the index _nIndex at the accessible shape
virtual void ViewForwarderChanged() override
This method is called to indicate a change of the specified view forwarder, specifically,...
virtual bool SetState(sal_Int64 aState) override
Set the specified state.
virtual sal_Int16 SAL_CALL getAccessibleRole() override
Return this object's role.
A child descriptor holds a reference to a UNO shape and the corresponding accessible object.
AccessibleShape * GetAccessibleShape() const
Return a pointer to the implementation object of the accessible shape of this descriptor.
ChildDescriptor(const css::uno::Reference< css::drawing::XShape > &xShape)
Create a new descriptor for the specified shape with empty reference to accessible object.
css::uno::Reference< css::drawing::XShape > mxShape
Reference to a (partially) visible shape.
void disposeAccessibleObject(AccessibleContextBase &rParent)
Dispose the accessible object of this descriptor.
rtl::Reference< AccessibleShape > mxAccessibleShape
The corresponding accessible object.
void setIndexAtAccessibleShape(sal_Int32 _nIndex)
set the index _nIndex at the accessible shape
ChildrenManagerImpl(css::uno::Reference< css::accessibility::XAccessible > xParent, css::uno::Reference< css::drawing::XShapes > xShapeList, const AccessibleShapeTreeInfo &rShapeTreeInfo, AccessibleContextBase &rContext)
Create a children manager, which manages the children of the given parent.
std::vector< rtl::Reference< AccessibleShape > > AccessibleShapeList
This list of additional accessible shapes that can or shall not be created by the shape factory.
static ShapeTypeHandler & Instance()
This function returns a reference to the only instance of this class.
void reserve(size_type amount)
const_iterator find(const Value &x) const
const_iterator end() const
std::pair< const_iterator, bool > insert(Value &&x)
vcl::Window * GetParent() const
#define DBG_ASSERT(sCon, aError)
::std::vector< ChildDescriptor > ChildDescriptorListType
class SAL_NO_VTABLE XPropertySet
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
uno::Reference< drawing::XShape > const mxShape
Reference< XController > xController