xref: /trunk/main/svx/source/accessibility/ChildrenManagerImpl.hxx (revision 4437c02e18a852c4a5e7d7e7c198180f06b2b9fc)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 #ifndef _SVX_ACCESSIBILITY_CHILDREN_MANAGER_IMPL_HXX
23 
24 #include <svx/IAccessibleViewForwarderListener.hxx>
25 #include <svx/IAccessibleParent.hxx>
26 #include <svx/AccessibleShapeTreeInfo.hxx>
27 #include <editeng/AccessibleContextBase.hxx>
28 #include <cppuhelper/compbase2.hxx>
29 #include <vos/mutex.hxx>
30 #include <vector>
31 #include <memory>
32 #include <com/sun/star/drawing/XShape.hpp>
33 #include <com/sun/star/drawing/XShapes.hpp>
34 #include <com/sun/star/document/XEventListener.hpp>
35 #include <com/sun/star/view/XSelectionChangeListener.hpp>
36 #include <com/sun/star/accessibility/XAccessible.hpp>
37 
38 using namespace ::com::sun::star;
39 
40 namespace accessibility {
41 
42 class AccessibleShape;
43 
44 class ChildDescriptor; // See below for declaration.
45 typedef ::std::vector<ChildDescriptor> ChildDescriptorListType;
46 
47 // Re-using MutexOwner class defined in AccessibleContextBase.hxx
48 
49 /** This class contains the actual implementation of the children manager.
50 
51     <p>It maintains a set of visible accessible shapes in
52     <member>maVisibleChildren</member>.  The objects in this list stem from
53     two sources.  The first is a list of UNO shapes like the list of shapes
54     in a draw page.  A reference to this list is held in
55     <member>maShapeList</member>.  Accessible objects for these shapes are
56     created on demand.  The list can be replaced by calls to the
57     <member>SetShapeList</member> method.  The second source is a list of
58     already accessible objects.  It can be modified by calls to the
59     <member>AddAccessibleShape</member> and
60     <member>ClearAccessibleShapeList</member> methods.</p>
61 
62     <p>Each call of the <member>Update</member> method leads to a
63     re-calculation of the visible shapes which then can be queried with the
64     <member>GetChildCount</member> and <member>GetChild</member> methods.
65     Events are send informing all listeners about the removed shapes which are
66     not visible anymore and about the added shapes.</p>
67 
68     <p> The visible area which is used to determine the visibility of the
69     shapes is taken from the view forwarder.  Thus, to signal a change of
70     the visible area call <member>ViewForwarderChanged</member>.</p>
71 
72     <p>The children manager adds itself as disposing() listener at every UNO
73     shape it creates an accessible object for so that when the UNO shape
74     passes away it can dispose() the associated accessible object.</p>
75 
76     @see ChildrenManager
77 */
78 class ChildrenManagerImpl
79     :   public MutexOwner,
80         public cppu::WeakComponentImplHelper2<
81             ::com::sun::star::document::XEventListener,
82             ::com::sun::star::view::XSelectionChangeListener>,
83         public IAccessibleViewForwarderListener,
84         public IAccessibleParent
85 {
86 public:
87     /** Create a children manager, which manages the children of the given
88         parent.  The parent is used for creating accessible objects.  The
89         list of shapes for which to create those objects is not derived from
90         the parent and has to be provided separately by calling one of the
91         update methods.
92         @param rxParent
93             The parent of the accessible objects which will be created
94             on demand at some point of time in the future.
95         @param rxShapeList
96             List of UNO shapes to manage.
97         @param rShapeTreeInfo
98             Bundle of information passed down the shape tree.
99         @param rContext
100             An accessible context object that is called for firing events
101             for new and deleted children, i.e. that holds a list of
102             listeners to be informed.
103     */
104     ChildrenManagerImpl (const ::com::sun::star::uno::Reference<
105             ::com::sun::star::accessibility::XAccessible>& rxParent,
106         const ::com::sun::star::uno::Reference<
107             ::com::sun::star::drawing::XShapes>& rxShapeList,
108         const AccessibleShapeTreeInfo& rShapeTreeInfo,
109         AccessibleContextBase& rContext);
110 
111     /** If there still are managed children these are disposed and
112         released.
113     */
114     ~ChildrenManagerImpl (void);
115 
116     /** Do that part of the initialization that you can not or should not do
117         in the constructor like registering at broadcasters.
118     */
119     void Init (void);
120 
121     /** Return the number of currently visible accessible children.
122         @return
123             If there are no children a 0 is returned.
124     */
125     long GetChildCount (void) const throw ();
126 
127     ::com::sun::star::uno::Reference<
128         ::com::sun::star::drawing::XShape> GetChildShape(long nIndex)
129         throw (::com::sun::star::uno::RuntimeException);
130     /** Return the requested accessible child or throw and
131         IndexOutOfBoundsException if the given index is invalid.
132         @param nIndex
133             Index of the requested child.  Call getChildCount for obtaining
134             the number of children.
135         @return
136             In case of a valid index this method returns a reference to the
137             requested accessible child.  This reference is empty if it has
138             not been possible to create the accessible object of the
139             corresponding shape.
140         @raises
141             Throws an IndexOutOfBoundsException if the index is not valid.
142     */
143     ::com::sun::star::uno::Reference<
144             ::com::sun::star::accessibility::XAccessible>
145         GetChild (long nIndex)
146         throw (::com::sun::star::uno::RuntimeException,
147                ::com::sun::star::lang::IndexOutOfBoundsException);
148 
149     /** Return the requested accessible child.
150         @param aChildDescriptor
151             This object contains references to the original shape and its
152             associated accessible object.
153         @param  _nIndex
154             The index which will be used in getAccessibleIndexInParent of the accessible shape.
155         @return
156             Returns a reference to the requested accessible child.  This
157             reference is empty if it has not been possible to create the
158             accessible object of the corresponding shape.
159     */
160     ::com::sun::star::uno::Reference<
161             ::com::sun::star::accessibility::XAccessible>
162         GetChild (ChildDescriptor& aChildDescriptor,sal_Int32 _nIndex)
163         throw (::com::sun::star::uno::RuntimeException);
164 
165     /** Return the requested accessible child given a shape.  This method
166         searches the list of descriptors for the one that holds the
167         association of the given shape to the requested accessible object
168         and returns that.  If no such descriptor is found that is
169         interpreted so that the specified shape is not visible at the moment.
170         @param xShape
171             The shape for which to return the associated accessible object.
172         @return
173             Returns a reference to the requested accessible child.  The
174             reference is empty if there is no shape descriptor that
175             associates the shape with an accessible object.
176     */
177     ::com::sun::star::uno::Reference<
178             ::com::sun::star::accessibility::XAccessible>
179         GetChild (const ::com::sun::star::uno::Reference<
180             ::com::sun::star::drawing::XShape>& xShape)
181         throw (::com::sun::star::uno::RuntimeException);
182 
183     /** Update the child manager.  Take care of a modified set of children
184         and modified visible area.  This method can optimize the update
185         process with respect separate updates of a modified children list
186         and visible area.
187         @param bCreateNewObjectsOnDemand
188             If </true> then accessible objects associated with the visible
189             shapes are created only when asked for.  No event is sent on
190             creation.  If </false> then the accessible objects are created
191             before this method returns and events are sent to inform the
192             listeners of the new object.
193     */
194     void Update (bool bCreateNewObjectsOnDemand = true);
195 
196     /** Set the list of UNO shapes to the given list.  This removes the old
197         list and does not add to it.  The list of accessible shapes that is
198         build up by calls to <member>AddAccessibleShape</member> is not
199         modified.  Neither is the list of visible children.  Accessible
200         objects are created on demand.
201         @param xShapeList
202             The list of UNO shapes that replaces the old list.
203     */
204     void SetShapeList (const ::com::sun::star::uno::Reference<
205         ::com::sun::star::drawing::XShapes>& xShapeList);
206 
207     /** Add a accessible shape.  This does not modify the list of UNO shapes
208         or the list of visible shapes.  Accessible shapes are, at the
209         moment, not tested against the visible area but are always appended
210         to the list of visible children.
211         @param pShape
212             The new shape that is added to the list of accessible shapes.
213     */
214     void AddAccessibleShape (std::auto_ptr<AccessibleShape> pShape);
215 
216     /** Clear the lists of accessible shapes and that of visible accessible
217         shapes.  The list of UNO shapes is not modified.
218     */
219     void ClearAccessibleShapeList (void);
220 
221     /** Set a new event shape tree info.  Call this method to inform the
222         children manager of a change of the info bundle.
223         @param rShapeTreeInfo
224             The new info that replaces the current one.
225     */
226     void SetInfo (const AccessibleShapeTreeInfo& rShapeTreeInfo);
227 
228     /** Update the SELECTED and FOCUSED states of all visible children
229         according to the given selection.  This includes setting
230         <em>and</em> resetting the states.
231     */
232     void UpdateSelection (void);
233 
234     /** Return whether one of the shapes managed by this object has
235         currently the focus.
236         @return
237             Returns <true/> when there is a shape that has the focus and
238             <false/> when there is no such shape.
239     */
240     bool HasFocus (void);
241 
242     /** When there is a shape that currently has the focus,
243         i.e. <member>HasFocus()</member> returns <true/> then remove the
244         focus from that shape.  Otherwise nothing changes.
245     */
246     void RemoveFocus (void);
247 
248     //=====  lang::XEventListener  ============================================
249 
250     virtual void SAL_CALL
251         disposing (const ::com::sun::star::lang::EventObject& rEventObject)
252         throw (::com::sun::star::uno::RuntimeException);
253 
254 
255     //=====  document::XEventListener  ========================================
256 
257     virtual void SAL_CALL
258         notifyEvent (const ::com::sun::star::document::EventObject& rEventObject)
259         throw (::com::sun::star::uno::RuntimeException);
260 
261 
262     //=====  view::XSelectionChangeListener  ==================================
263 
264     virtual void  SAL_CALL
265         selectionChanged (const ::com::sun::star::lang::EventObject& rEvent)
266         throw (::com::sun::star::uno::RuntimeException);
267 
268 
269     //=====  IAccessibleViewForwarderListener  ================================
270 
271     /** Informs this children manager and its children about a change of one
272         (or more) aspect of the view forwarder.
273         @param aChangeType
274             A change type of <const>VISIBLE_AREA</const> leads to a call to
275             the <member>Update</member> which creates accessible objects of
276             new shapes immediately.  Other change types are passed to the
277             visible accessible children without calling
278             <member>Update</member>.
279         @param pViewForwarder
280             The modified view forwarder.  Use this one from now on.
281     */
282     virtual void ViewForwarderChanged (ChangeType aChangeType,
283         const IAccessibleViewForwarder* pViewForwarder);
284 
285     //=====  IAccessibleParent  ===============================================
286 
287     /** Replace the specified child with a replacement.
288         @param pCurrentChild
289             This child is to be replaced.
290         @param pReplacement
291             The replacement for the current child.
292         @return
293             The returned value indicates whether the replacement has been
294             finished successfully.
295     */
296     virtual sal_Bool ReplaceChild (
297         AccessibleShape* pCurrentChild,
298         const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& _rxShape,
299         const long _nIndex,
300         const AccessibleShapeTreeInfo& _rShapeTreeInfo
301     )   throw (::com::sun::star::uno::RuntimeException);
302     // Add the impl method for IAccessibleParent interface
303     virtual AccessibleControlShape* GetAccControlShapeFromModel
304         (::com::sun::star::beans::XPropertySet* pSet)
305         throw (::com::sun::star::uno::RuntimeException);
306     virtual ::com::sun::star::uno::Reference<
307             ::com::sun::star::accessibility::XAccessible>
308         GetAccessibleCaption (const ::com::sun::star::uno::Reference<
309             ::com::sun::star::drawing::XShape>& xShape)
310         throw (::com::sun::star::uno::RuntimeException);
311 protected:
312     /** This list holds the descriptors of all currently visible shapes and
313         associated accessible object.
314 
315         <p>With the descriptors it maintains a mapping of shapes to
316         accessible objects.  It acts as a cache in that accessible objects
317         are only created on demand and released with every update (where the
318         latter may be optimized by the update methods).<p>
319 
320         <p>The list is realized as a vector because it remains unchanged
321         between updates (i.e. complete rebuilds of the list) and allows a
322         fast (constant time) access to its elements for given indices.</p>
323     */
324     ChildDescriptorListType maVisibleChildren;
325 
326     /** The original list of UNO shapes.  The visible shapes are inserted
327         into the list of visible children
328         <member>maVisibleChildren</member>.
329     */
330     ::com::sun::star::uno::Reference<
331         ::com::sun::star::drawing::XShapes> mxShapeList;
332 
333     /** This list of additional accessible shapes that can or shall not be
334         created by the shape factory.
335     */
336     typedef std::vector< ::com::sun::star::uno::Reference<
337         ::com::sun::star::accessibility::XAccessible> > AccessibleShapeList;
338     AccessibleShapeList maAccessibleShapes;
339 
340     /** Rectangle that describes the visible area in which a shape has to lie
341         at least partly, to be accessible through this class.  Used to
342         detect changes of the visible area after changes of the view forwarder.
343     */
344     Rectangle maVisibleArea;
345 
346     /** The parent of the shapes.  It is used for creating accessible
347         objects for given shapes.
348     */
349     ::com::sun::star::uno::Reference<
350         ::com::sun::star::accessibility::XAccessible> mxParent;
351 
352     /** Bundel of information passed down the shape tree.
353     */
354     AccessibleShapeTreeInfo maShapeTreeInfo;
355 
356     /** Reference to an accessible context object that is used to inform its
357         listeners of new and removed children.
358     */
359     AccessibleContextBase& mrContext;
360 
361     /** This method is called from the component helper base class while
362         disposing.
363     */
364     virtual void SAL_CALL disposing (void);
365 
366     /** Experimental: Get the index of the specified accessible object with
367         respect to the list of children maintained by this object.
368 
369         @return
370             Return the index of the given child or -1 to indicate that the
371             child is unknown.
372     */
373     long GetChildIndex (const ::com::sun::star::uno::Reference<
374         ::com::sun::star::accessibility::XAccessible>& xChild) const
375         throw (::com::sun::star::uno::RuntimeException);
376 
377     void impl_dispose (void);
378 
379 private:
380     /** Names of new accessible objects are disambiguated with this index.
381         It gets increased every time a new object is created and (at the
382         moment) never reset.
383     */
384     sal_Int32 mnNewNameIndex;
385 
386     // Don't use the copy constructor or the assignment operator.  They are
387     // not implemented (and are not intended to be).
388     ChildrenManagerImpl (const ChildrenManagerImpl&);
389     ChildrenManagerImpl& operator= (const ChildrenManagerImpl&);
390 
391     /** This member points to the currently focused shape.  It is NULL when
392         there is no focused shape.
393     */
394     AccessibleShape* mpFocusedShape;
395 
396     /** Three helper functions for the <member>Update</member> method.
397     */
398 
399     /** Create a list of visible shapes from the list of UNO shapes
400         <member>maShapeList</member> and the list of accessible objects.
401         @param raChildList
402             For every visible shape from the two sources mentioned above one
403             descriptor is added to this list.
404     */
405     void CreateListOfVisibleShapes (ChildDescriptorListType& raChildList);
406 
407     /** From the old list of (former) visible shapes remove those that
408         are not member of the new list.  Send appropriate events for every
409         such shape.
410         @param raNewChildList
411             The new list of visible children against which the old one
412             is compared.
413         @param raOldChildList
414             The old list of visible children against which the new one
415             is compared.
416     */
417     void RemoveNonVisibleChildren (
418         const ChildDescriptorListType& raNewChildList,
419         ChildDescriptorListType& raOldChildList);
420 
421     /** Merge the information that is already known about the visible shapes
422         from the current list into the new list.
423         @param raChildList
424             Information is merged from the current list of visible children
425             to this list.
426     */
427     void MergeAccessibilityInformation (ChildDescriptorListType& raChildList);
428 
429     /** If the visible area has changed then send events that signal a
430         change of their bounding boxes for all shapes that are members of
431         both the current and the new list of visible shapes.
432         @param raChildList
433             Events are sent to all entries of this list that already contain
434             an accessible object.
435     */
436     void SendVisibleAreaEvents (ChildDescriptorListType& raChildList);
437 
438     /** If children have to be created immediately and not on demand the
439         create the missing accessible objects now.
440         @param raDescriptorList
441             Create an accessible object for every member of this list where
442             that object does not already exist.
443     */
444     void CreateAccessibilityObjects (ChildDescriptorListType& raChildList);
445 
446     /** Add a single shape.  Update all relevant data structures
447         accordingly.  Use this method instead of <member>Update()</member>
448         when only a single shape has been added.
449     */
450     void AddShape (const ::com::sun::star::uno::Reference<
451         ::com::sun::star::drawing::XShape>& xShape);
452 
453     /** Remove a single shape.  Update all relevant data structures
454         accordingly.  Use this method instead of <member>Update()</member>
455         when only a single shape has been removed.
456     */
457     void RemoveShape (const ::com::sun::star::uno::Reference<
458         ::com::sun::star::drawing::XShape>& xShape);
459 
460     /** Add the children manager as dispose listener at the given shape so
461         that the associated accessible object can be disposed when the shape
462         is disposed.
463         @param xShape
464             Register at this shape as dispose listener.
465     */
466     void RegisterAsDisposeListener (const ::com::sun::star::uno::Reference<
467         ::com::sun::star::drawing::XShape>& xShape);
468 
469     /** Remove the children manager as dispose listener at the given shape
470         @param xShape
471             Unregister at this shape as dispose listener.
472     */
473     void UnregisterAsDisposeListener (const ::com::sun::star::uno::Reference<
474         ::com::sun::star::drawing::XShape>& xShape);
475 };
476 
477 
478 
479 
480 /** A child descriptor holds a reference to a UNO shape and the
481     corresponding accessible object.  There are two use cases:
482     <ol><li>The accessible object is only created on demand and is then
483     initially empty.</li>
484     <li>There is no UNO shape.  The accessible object is given as argument
485     to the constructor.</li>
486     </ol>
487     In both cases the child descriptor assumes ownership over the accessible
488     object.
489 */
490 class ChildDescriptor
491 {
492 public:
493     /** Reference to a (partially) visible shape.
494     */
495     ::com::sun::star::uno::Reference<
496         ::com::sun::star::drawing::XShape> mxShape;
497 
498     /** The corresponding accessible object.  This reference is initially
499         empty and only replaced by a reference to a new object when that is
500         requested from the outside.
501     */
502     ::com::sun::star::uno::Reference<
503         ::com::sun::star::accessibility::XAccessible> mxAccessibleShape;
504 
505     /** Return a pointer to the implementation object of the accessible
506         shape of this descriptor.
507         @return
508             The result is NULL if either the UNO reference to the accessible
509             shape is empty or it can not be transformed into a pointer to
510             the desired class.
511     */
512     AccessibleShape* GetAccessibleShape (void) const;
513 
514     /** set the index _nIndex at the accessible shape
515         @param  _nIndex
516             The new index in parent.
517     */
518     void setIndexAtAccessibleShape(sal_Int32 _nIndex);
519 
520     /** This flag is set during the visibility calculation and indicates
521         that at one time in this process an event is sent that informs the
522         listeners of the creation of a new accessible object.  This flags is
523         not reset afterwards.  Don't use it unless you know exactly what you
524         are doing.
525     */
526     bool mbCreateEventPending;
527 
528     /** Create a new descriptor for the specified shape with empty reference
529         to accessible object.
530     */
531     explicit ChildDescriptor (const ::com::sun::star::uno::Reference<
532         ::com::sun::star::drawing::XShape>& xShape);
533 
534     /** Create a new descriptor for the specified shape with empty reference
535         to the original shape.
536     */
537     explicit ChildDescriptor (const ::com::sun::star::uno::Reference<
538         ::com::sun::star::accessibility::XAccessible>& rxAccessibleShape);
539 
540     ~ChildDescriptor (void);
541 
542     /** Dispose the accessible object of this descriptor.  If that object
543         does not exist then do nothing.
544         @param rParent
545             The parent of the accessible object to dispose.  A child event
546             is sent in its name.
547     */
548     void disposeAccessibleObject (AccessibleContextBase& rParent);
549 
550     /** Compare two child descriptors.  Take into account that a child
551         descriptor may be based on a UNO shape or, already, on an accessible
552         shape.
553     */
554     inline bool operator == (const ChildDescriptor& aDescriptor) const
555     {
556         return (
557                 this == &aDescriptor ||
558                 (
559                  (mxShape.get() == aDescriptor.mxShape.get() ) &&
560                  (mxShape.is() || mxAccessibleShape.get() == aDescriptor.mxAccessibleShape.get())
561                 )
562                );
563     }
564 
565     /** The ordering defined by this operator is only used in order to be able
566         to put child descriptors in some STL containers.  The ordering itself is
567         not so important, its 'features' are not used.
568     */
569     inline bool operator < (const ChildDescriptor& aDescriptor) const
570     {
571         return (mxShape.get() < aDescriptor.mxShape.get());
572     }
573 
574 };
575 
576 
577 
578 } // end of namespace accessibility
579 
580 #endif
581 
582 /* vim: set noet sw=4 ts=4: */
583