summaryrefslogtreecommitdiffstats
path: root/svx/source/accessibility/ChildrenManagerImpl.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'svx/source/accessibility/ChildrenManagerImpl.hxx')
-rw-r--r--svx/source/accessibility/ChildrenManagerImpl.hxx497
1 files changed, 497 insertions, 0 deletions
diff --git a/svx/source/accessibility/ChildrenManagerImpl.hxx b/svx/source/accessibility/ChildrenManagerImpl.hxx
new file mode 100644
index 0000000000..2de34e10da
--- /dev/null
+++ b/svx/source/accessibility/ChildrenManagerImpl.hxx
@@ -0,0 +1,497 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_SVX_SOURCE_ACCESSIBILITY_CHILDRENMANAGERIMPL_HXX
+#define INCLUDED_SVX_SOURCE_ACCESSIBILITY_CHILDRENMANAGERIMPL_HXX
+
+#include <svx/IAccessibleViewForwarderListener.hxx>
+#include <svx/IAccessibleParent.hxx>
+#include <svx/AccessibleShapeTreeInfo.hxx>
+#include <editeng/AccessibleContextBase.hxx>
+#include <comphelper/compbase.hxx>
+#include <tools/gen.hxx>
+#include <vector>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
+#include <com/sun/star/document/XEventListener.hpp>
+#include <com/sun/star/view/XSelectionChangeListener.hpp>
+#include <com/sun/star/accessibility/XAccessible.hpp>
+
+namespace accessibility {
+
+class AccessibleShape;
+
+class ChildDescriptor; // See below for declaration.
+typedef ::std::vector<ChildDescriptor> ChildDescriptorListType;
+
+// Re-using MutexOwner class defined in AccessibleContextBase.hxx
+
+/** This class contains the actual implementation of the children manager.
+
+ <p>It maintains a set of visible accessible shapes in
+ <member>maVisibleChildren</member>. The objects in this list stem from
+ two sources. The first is a list of UNO shapes like the list of shapes
+ in a draw page. A reference to this list is held in
+ <member>maShapeList</member>. Accessible objects for these shapes are
+ created on demand. The list can be replaced by calls to the
+ <member>SetShapeList</member> method. The second source is a list of
+ already accessible objects. It can be modified by calls to the
+ <member>AddAccessibleShape</member> and
+ <member>ClearAccessibleShapeList</member> methods.</p>
+
+ <p>Each call of the <member>Update</member> method leads to a
+ re-calculation of the visible shapes which then can be queried with the
+ <member>GetChildCount</member> and <member>GetChild</member> methods.
+ Events are sent informing all listeners about the removed shapes which are
+ not visible anymore and about the added shapes.</p>
+
+ <p> The visible area which is used to determine the visibility of the
+ shapes is taken from the view forwarder. Thus, to signal a change of
+ the visible area call <member>ViewForwarderChanged</member>.</p>
+
+ <p>The children manager adds itself as disposing() listener at every UNO
+ shape it creates an accessible object for so that when the UNO shape
+ passes away it can dispose() the associated accessible object.</p>
+
+ @see ChildrenManager
+*/
+class ChildrenManagerImpl final
+ : public comphelper::WeakComponentImplHelper<
+ css::document::XEventListener,
+ css::view::XSelectionChangeListener>,
+ public IAccessibleViewForwarderListener,
+ public IAccessibleParent
+{
+public:
+ /** Create a children manager, which manages the children of the given
+ parent. The parent is used for creating accessible objects. The
+ list of shapes for which to create those objects is not derived from
+ the parent and has to be provided separately by calling one of the
+ update methods.
+ @param rxParent
+ The parent of the accessible objects which will be created
+ on demand at some point of time in the future.
+ @param rxShapeList
+ List of UNO shapes to manage.
+ @param rShapeTreeInfo
+ Bundle of information passed down the shape tree.
+ @param rContext
+ An accessible context object that is called for firing events
+ for new and deleted children, i.e. that holds a list of
+ listeners to be informed.
+ */
+ ChildrenManagerImpl (css::uno::Reference<css::accessibility::XAccessible> xParent,
+ css::uno::Reference<css::drawing::XShapes> xShapeList,
+ const AccessibleShapeTreeInfo& rShapeTreeInfo,
+ AccessibleContextBase& rContext);
+
+ /** If there still are managed children these are disposed and
+ released.
+ */
+ virtual ~ChildrenManagerImpl() override;
+
+ /** Do that part of the initialization that you can not or should not do
+ in the constructor like registering at broadcasters.
+ */
+ void Init();
+
+ /** Return the number of currently visible accessible children.
+ @return
+ If there are no children a 0 is returned.
+ */
+ sal_Int64 GetChildCount() const noexcept;
+
+ /// @throws css::uno::RuntimeException
+ /// @throws css::lang::IndexOutOfBoundsException
+ const css::uno::Reference<css::drawing::XShape>& GetChildShape(sal_Int64 nIndex);
+ /** Return the requested accessible child or throw and
+ IndexOutOfBoundsException if the given index is invalid.
+ @param nIndex
+ Index of the requested child. Call getChildCount for obtaining
+ the number of children.
+ @return
+ In case of a valid index this method returns a reference to the
+ requested accessible child. This reference is empty if it has
+ not been possible to create the accessible object of the
+ corresponding shape.
+ @throws
+ Throws an IndexOutOfBoundsException if the index is not valid.
+ */
+ css::uno::Reference<css::accessibility::XAccessible>
+ GetChild (sal_Int64 nIndex);
+
+ /** Return the requested accessible child.
+ @param aChildDescriptor
+ This object contains references to the original shape and its
+ associated accessible object.
+ @param _nIndex
+ The index which will be used in getAccessibleIndexInParent of the accessible shape.
+ @return
+ Returns a reference to the requested accessible child. This
+ reference is empty if it has not been possible to create the
+ accessible object of the corresponding shape.
+ @throws css::uno::RuntimeException
+ */
+ css::uno::Reference<css::accessibility::XAccessible>
+ GetChild (ChildDescriptor& aChildDescriptor,sal_Int32 _nIndex);
+
+ /** Update the child manager. Take care of a modified set of children
+ and modified visible area. This method can optimize the update
+ process with respect separate updates of a modified children list
+ and visible area.
+ @param bCreateNewObjectsOnDemand
+ If </true> then accessible objects associated with the visible
+ shapes are created only when asked for. No event is sent on
+ creation. If </false> then the accessible objects are created
+ before this method returns and events are sent to inform the
+ listeners of the new object.
+ */
+ void Update (bool bCreateNewObjectsOnDemand);
+
+ /** Set the list of UNO shapes to the given list. This removes the old
+ list and does not add to it. The list of accessible shapes that is
+ build up by calls to <member>AddAccessibleShape</member> is not
+ modified. Neither is the list of visible children. Accessible
+ objects are created on demand.
+ @param xShapeList
+ The list of UNO shapes that replaces the old list.
+ */
+ void SetShapeList (const css::uno::Reference<css::drawing::XShapes>& xShapeList);
+
+ /** Add an accessible shape. This does not modify the list of UNO shapes
+ or the list of visible shapes. Accessible shapes are, at the
+ moment, not tested against the visible area but are always appended
+ to the list of visible children.
+ @param shape
+ The new shape that is added to the list of accessible shapes; must
+ be non-null.
+ */
+ void AddAccessibleShape (rtl::Reference<AccessibleShape> const & shape);
+
+ /** Clear the lists of accessible shapes and that of visible accessible
+ shapes. The list of UNO shapes is not modified.
+ */
+ void ClearAccessibleShapeList();
+
+ /** Set a new event shape tree info. Call this method to inform the
+ children manager of a change of the info bundle.
+ @param rShapeTreeInfo
+ The new info that replaces the current one.
+ */
+ void SetInfo (const AccessibleShapeTreeInfo& rShapeTreeInfo);
+
+ /** Update the SELECTED and FOCUSED states of all visible children
+ according to the given selection. This includes setting
+ <em>and</em> resetting the states.
+ */
+ void UpdateSelection();
+
+ /** Return whether one of the shapes managed by this object has
+ currently the focus.
+ @return
+ Returns <true/> when there is a shape that has the focus and
+ <false/> when there is no such shape.
+ */
+ bool HasFocus() const;
+
+ /** When there is a shape that currently has the focus,
+ i.e. <member>HasFocus()</member> returns <true/> then remove the
+ focus from that shape. Otherwise nothing changes.
+ */
+ void RemoveFocus();
+
+ // lang::XEventListener
+ virtual void SAL_CALL
+ disposing (const css::lang::EventObject& rEventObject) override;
+
+ // document::XEventListener
+ virtual void SAL_CALL
+ notifyEvent (const css::document::EventObject& rEventObject) override;
+
+ // view::XSelectionChangeListener
+ virtual void SAL_CALL
+ selectionChanged (const css::lang::EventObject& rEvent) override;
+
+ // IAccessibleViewForwarderListener
+ /** Informs this children manager and its children about a change of one
+ (or more) aspect of the view forwarder.
+ @param aChangeType
+ A change type of <const>VISIBLE_AREA</const> leads to a call to
+ the <member>Update</member> which creates accessible objects of
+ new shapes immediately. Other change types are passed to the
+ visible accessible children without calling
+ <member>Update</member>.
+ @param pViewForwarder
+ The modified view forwarder. Use this one from now on.
+ */
+ virtual void ViewForwarderChanged() override;
+
+ // IAccessibleParent
+ /** Replace the specified child with a replacement.
+ @param pCurrentChild
+ This child is to be replaced.
+ @param pReplacement
+ The replacement for the current child.
+ @return
+ The returned value indicates whether the replacement has been
+ finished successfully.
+ */
+ virtual bool ReplaceChild (
+ AccessibleShape* pCurrentChild,
+ const css::uno::Reference< css::drawing::XShape >& _rxShape,
+ const tools::Long _nIndex,
+ const AccessibleShapeTreeInfo& _rShapeTreeInfo
+ ) override;
+
+ // Add the impl method for IAccessibleParent interface
+ virtual AccessibleControlShape* GetAccControlShapeFromModel
+ (css::beans::XPropertySet* pSet) override;
+ virtual css::uno::Reference<css::accessibility::XAccessible>
+ GetAccessibleCaption (const css::uno::Reference<css::drawing::XShape>& xShape) override;
+
+private:
+ /** This list holds the descriptors of all currently visible shapes and
+ associated accessible object.
+
+ <p>With the descriptors it maintains a mapping of shapes to
+ accessible objects. It acts as a cache in that accessible objects
+ are only created on demand and released with every update (where the
+ latter may be optimized by the update methods).<p>
+
+ <p>The list is realized as a vector because it remains unchanged
+ between updates (i.e. complete rebuilds of the list) and allows a
+ fast (constant time) access to its elements for given indices.</p>
+ */
+ ChildDescriptorListType maVisibleChildren;
+
+ /** The original list of UNO shapes. The visible shapes are inserted
+ into the list of visible children
+ <member>maVisibleChildren</member>.
+ */
+ css::uno::Reference<css::drawing::XShapes> mxShapeList;
+
+ /** This list of additional accessible shapes that can or shall not be
+ created by the shape factory.
+ */
+ typedef std::vector< rtl::Reference< AccessibleShape> > AccessibleShapeList;
+ AccessibleShapeList maAccessibleShapes;
+
+ /** Rectangle that describes the visible area in which a shape has to lie
+ at least partly, to be accessible through this class. Used to
+ detect changes of the visible area after changes of the view forwarder.
+ */
+ tools::Rectangle maVisibleArea;
+
+ /** The parent of the shapes. It is used for creating accessible
+ objects for given shapes.
+ */
+ css::uno::Reference<css::accessibility::XAccessible> mxParent;
+
+ /** Bundle of information passed down the shape tree.
+ */
+ AccessibleShapeTreeInfo maShapeTreeInfo;
+
+ /** Reference to an accessible context object that is used to inform its
+ listeners of new and removed children.
+ */
+ AccessibleContextBase& mrContext;
+
+ /** This method is called from the component helper base class while
+ disposing.
+ */
+ virtual void disposing(std::unique_lock<std::mutex>&) override;
+
+ void impl_dispose();
+
+ ChildrenManagerImpl (const ChildrenManagerImpl&) = delete;
+ ChildrenManagerImpl& operator= (const ChildrenManagerImpl&) = delete;
+
+ /** This member points to the currently focused shape. It is NULL when
+ there is no focused shape.
+ */
+ AccessibleShape* mpFocusedShape;
+
+ /** Three helper functions for the <member>Update</member> method.
+ */
+
+ /** Create a list of visible shapes from the list of UNO shapes
+ <member>maShapeList</member> and the list of accessible objects.
+ @param raChildList
+ For every visible shape from the two sources mentioned above one
+ descriptor is added to this list.
+ */
+ void CreateListOfVisibleShapes (ChildDescriptorListType& raChildList);
+
+ /** From the old list of (former) visible shapes remove those that
+ are not member of the new list. Send appropriate events for every
+ such shape.
+ @param raNewChildList
+ The new list of visible children against which the old one
+ is compared.
+ @param raOldChildList
+ The old list of visible children against which the new one
+ is compared.
+ */
+ void RemoveNonVisibleChildren (
+ const std::vector<ChildDescriptor*>& rNonVisibleChildren);
+
+ /** Merge the information that is already known about the visible shapes
+ from the old list into the current list, and return a list of
+ children that are in the old list, but not the current one.
+ @param raChildList
+ Information is merged to the current list of visible children
+ from this list. The old list can get reordered.
+ @return
+ Vector of children that are in the old list, but not the current
+ one.
+ */
+ std::vector<ChildDescriptor*> MergeAccessibilityInformation (ChildDescriptorListType& raChildList);
+
+ /** If the visible area has changed then send events that signal a
+ change of their bounding boxes for all shapes that are members of
+ both the current and the new list of visible shapes.
+ @param raChildList
+ Events are sent to all entries of this list that already contain
+ an accessible object.
+ */
+ static void SendVisibleAreaEvents (ChildDescriptorListType& raChildList);
+
+ /** If children have to be created immediately and not on demand the
+ create the missing accessible objects now.
+ @param raDescriptorList
+ Create an accessible object for every member of this list where
+ that object does not already exist.
+ */
+ void CreateAccessibilityObjects (ChildDescriptorListType& raChildList);
+
+ /** Add a single shape. Update all relevant data structures
+ accordingly. Use this method instead of <member>Update()</member>
+ when only a single shape has been added.
+ */
+ void AddShape (const css::uno::Reference<css::drawing::XShape>& xShape);
+
+ /** Remove a single shape. Update all relevant data structures
+ accordingly. Use this method instead of <member>Update()</member>
+ when only a single shape has been removed.
+ */
+ void RemoveShape (const css::uno::Reference<css::drawing::XShape>& xShape);
+
+ /** Add the children manager as dispose listener at the given shape so
+ that the associated accessible object can be disposed when the shape
+ is disposed.
+ @param xShape
+ Register at this shape as dispose listener.
+ */
+ void RegisterAsDisposeListener (const css::uno::Reference<css::drawing::XShape>& xShape);
+
+ /** Remove the children manager as dispose listener at the given shape
+ @param xShape
+ Unregister at this shape as dispose listener.
+ */
+ void UnregisterAsDisposeListener (const css::uno::Reference<css::drawing::XShape>& xShape);
+};
+
+
+/** A child descriptor holds a reference to a UNO shape and the
+ corresponding accessible object. There are two use cases:
+ <ol><li>The accessible object is only created on demand and is then
+ initially empty.</li>
+ <li>There is no UNO shape. The accessible object is given as argument
+ to the constructor.</li>
+ </ol>
+ In both cases the child descriptor assumes ownership over the accessible
+ object.
+*/
+class ChildDescriptor
+{
+public:
+ /** Reference to a (partially) visible shape.
+ */
+ css::uno::Reference<css::drawing::XShape> mxShape;
+
+ /** The corresponding accessible object. This reference is initially
+ empty and only replaced by a reference to a new object when that is
+ requested from the outside.
+ */
+ rtl::Reference<AccessibleShape> mxAccessibleShape;
+
+ /** Return a pointer to the implementation object of the accessible
+ shape of this descriptor.
+ @return
+ The result is NULL if either the UNO reference to the accessible
+ shape is empty or it can not be transformed into a pointer to
+ the desired class.
+ */
+ AccessibleShape* GetAccessibleShape() const { return mxAccessibleShape.get(); }
+
+ /** set the index _nIndex at the accessible shape
+ @param _nIndex
+ The new index in parent.
+ */
+ void setIndexAtAccessibleShape(sal_Int32 _nIndex);
+
+ /** This flag is set during the visibility calculation and indicates
+ that at one time in this process an event is sent that informs the
+ listeners of the creation of a new accessible object. This flags is
+ not reset afterwards. Don't use it unless you know exactly what you
+ are doing.
+ */
+ bool mbCreateEventPending;
+
+ /** Create a new descriptor for the specified shape with empty reference
+ to accessible object.
+ */
+ explicit ChildDescriptor (const css::uno::Reference<css::drawing::XShape>& xShape);
+
+ /** Create a new descriptor for the specified shape with empty reference
+ to the original shape.
+ */
+ explicit ChildDescriptor (const rtl::Reference<AccessibleShape>& rxAccessibleShape);
+
+ /** Dispose the accessible object of this descriptor. If that object
+ does not exist then do nothing.
+ @param rParent
+ The parent of the accessible object to dispose. A child event
+ is sent in its name.
+ */
+ void disposeAccessibleObject (AccessibleContextBase& rParent);
+
+ /** Compare two child descriptors. Take into account that a child
+ descriptor may be based on a UNO shape or, already, on an accessible
+ shape.
+ */
+ bool operator == (const ChildDescriptor& aDescriptor) const
+ {
+ return (
+ this == &aDescriptor ||
+ (
+ (mxShape.get() == aDescriptor.mxShape.get() ) &&
+ (mxShape.is() || mxAccessibleShape.get() == aDescriptor.mxAccessibleShape.get())
+ )
+ );
+ }
+
+};
+
+
+} // end of namespace accessibility
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */