xref: /trunk/main/svx/source/accessibility/ChildrenManagerImpl.hxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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     /** Return the requested accessible child or throw and
130         IndexOutOfBoundsException if the given index is invalid.
131         @param nIndex
132             Index of the requested child.  Call getChildCount for obtaining
133             the number of children.
134         @return
135             In case of a valid index this method returns a reference to the
136             requested accessible child.  This reference is empty if it has
137             not been possible to create the accessible object of the
138             corresponding shape.
139         @raises
140             Throws an IndexOutOfBoundsException if the index is not valid.
141     */
142     ::com::sun::star::uno::Reference<
143             ::com::sun::star::accessibility::XAccessible>
144         GetChild (long nIndex);
145 
146     /** Return the requested accessible child.
147         @param aChildDescriptor
148             This object contains references to the original shape and its
149             associated accessible object.
150         @param  _nIndex
151             The index which will be used in getAccessibleIndexInParent of the accessible shape.
152         @return
153             Returns a reference to the requested accessible child.  This
154             reference is empty if it has not been possible to create the
155             accessible object of the corresponding shape.
156     */
157     ::com::sun::star::uno::Reference<
158             ::com::sun::star::accessibility::XAccessible>
159         GetChild (ChildDescriptor& aChildDescriptor,sal_Int32 _nIndex);
160 
161     /** Return the requested accessible child given a shape.  This method
162         searches the list of descriptors for the one that holds the
163         association of the given shape to the requested accessible object
164         and returns that.  If no such descriptor is found that is
165         interpreted so that the specified shape is not visible at the moment.
166         @param xShape
167             The shape for which to return the associated accessible object.
168         @return
169             Returns a reference to the requested accessible child.  The
170             reference is empty if there is no shape descriptor that
171             associates the shape with an accessible object.
172     */
173     ::com::sun::star::uno::Reference<
174             ::com::sun::star::accessibility::XAccessible>
175         GetChild (const ::com::sun::star::uno::Reference<
176             ::com::sun::star::drawing::XShape>& xShape);
177 
178     /** Update the child manager.  Take care of a modified set of children
179         and modified visible area.  This method can optimize the update
180         process with respect separate updates of a modified children list
181         and visible area.
182         @param bCreateNewObjectsOnDemand
183             If </true> then accessible objects associated with the visible
184             shapes are created only when asked for.  No event is sent on
185             creation.  If </false> then the accessible objects are created
186             before this method returns and events are sent to inform the
187             listeners of the new object.
188     */
189     void Update (bool bCreateNewObjectsOnDemand = true);
190 
191     /** Set the list of UNO shapes to the given list.  This removes the old
192         list and does not add to it.  The list of accessible shapes that is
193         build up by calls to <member>AddAccessibleShape</member> is not
194         modified.  Neither is the list of visible children.  Accessible
195         objects are created on demand.
196         @param xShapeList
197             The list of UNO shapes that replaces the old list.
198     */
199     void SetShapeList (const ::com::sun::star::uno::Reference<
200         ::com::sun::star::drawing::XShapes>& xShapeList);
201 
202     /** Add a accessible shape.  This does not modify the list of UNO shapes
203         or the list of visible shapes.  Accessible shapes are, at the
204         moment, not tested against the visible area but are always appended
205         to the list of visible children.
206         @param pShape
207             The new shape that is added to the list of accessible shapes.
208     */
209     void AddAccessibleShape (std::auto_ptr<AccessibleShape> pShape);
210 
211     /** Clear the lists of accessible shapes and that of visible accessible
212         shapes.  The list of UNO shapes is not modified.
213     */
214     void ClearAccessibleShapeList (void);
215 
216     /** Set a new event shape tree info.  Call this method to inform the
217         children manager of a change of the info bundle.
218         @param rShapeTreeInfo
219             The new info that replaces the current one.
220     */
221     void SetInfo (const AccessibleShapeTreeInfo& rShapeTreeInfo);
222 
223     /** Update the SELECTED and FOCUSED states of all visible children
224         according to the given selection.  This includes setting
225         <em>and</em> resetting the states.
226     */
227     void UpdateSelection (void);
228 
229     /** Return whether one of the shapes managed by this object has
230         currently the focus.
231         @return
232             Returns <true/> when there is a shape that has the focus and
233             <false/> when there is no such shape.
234     */
235     bool HasFocus (void);
236 
237     /** When there is a shape that currently has the focus,
238         i.e. <member>HasFocus()</member> returns <true/> then remove the
239         focus from that shape.  Otherwise nothing changes.
240     */
241     void RemoveFocus (void);
242 
243     //=====  lang::XEventListener  ============================================
244 
245     virtual void SAL_CALL
246         disposing (const ::com::sun::star::lang::EventObject& rEventObject);
247 
248 
249     //=====  document::XEventListener  ========================================
250 
251     virtual void SAL_CALL
252         notifyEvent (const ::com::sun::star::document::EventObject& rEventObject);
253 
254 
255     //=====  view::XSelectionChangeListener  ==================================
256 
257     virtual void  SAL_CALL
258         selectionChanged (const ::com::sun::star::lang::EventObject& rEvent);
259 
260 
261     //=====  IAccessibleViewForwarderListener  ================================
262 
263     /** Informs this children manager and its children about a change of one
264         (or more) aspect of the view forwarder.
265         @param aChangeType
266             A change type of <const>VISIBLE_AREA</const> leads to a call to
267             the <member>Update</member> which creates accessible objects of
268             new shapes immediately.  Other change types are passed to the
269             visible accessible children without calling
270             <member>Update</member>.
271         @param pViewForwarder
272             The modified view forwarder.  Use this one from now on.
273     */
274     virtual void ViewForwarderChanged (ChangeType aChangeType,
275         const IAccessibleViewForwarder* pViewForwarder);
276 
277     //=====  IAccessibleParent  ===============================================
278 
279     /** Replace the specified child with a replacement.
280         @param pCurrentChild
281             This child is to be replaced.
282         @param pReplacement
283             The replacement for the current child.
284         @return
285             The returned value indicates whether the replacement has been
286             finished successfully.
287     */
288     virtual sal_Bool ReplaceChild (
289         AccessibleShape* pCurrentChild,
290         const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& _rxShape,
291         const long _nIndex,
292         const AccessibleShapeTreeInfo& _rShapeTreeInfo
293     );
294     // Add the impl method for IAccessibleParent interface
295     virtual AccessibleControlShape* GetAccControlShapeFromModel
296         (::com::sun::star::beans::XPropertySet* pSet);
297     virtual ::com::sun::star::uno::Reference<
298             ::com::sun::star::accessibility::XAccessible>
299         GetAccessibleCaption (const ::com::sun::star::uno::Reference<
300             ::com::sun::star::drawing::XShape>& xShape);
301 protected:
302     /** This list holds the descriptors of all currently visible shapes and
303         associated accessible object.
304 
305         <p>With the descriptors it maintains a mapping of shapes to
306         accessible objects.  It acts as a cache in that accessible objects
307         are only created on demand and released with every update (where the
308         latter may be optimized by the update methods).<p>
309 
310         <p>The list is realized as a vector because it remains unchanged
311         between updates (i.e. complete rebuilds of the list) and allows a
312         fast (constant time) access to its elements for given indices.</p>
313     */
314     ChildDescriptorListType maVisibleChildren;
315 
316     /** The original list of UNO shapes.  The visible shapes are inserted
317         into the list of visible children
318         <member>maVisibleChildren</member>.
319     */
320     ::com::sun::star::uno::Reference<
321         ::com::sun::star::drawing::XShapes> mxShapeList;
322 
323     /** This list of additional accessible shapes that can or shall not be
324         created by the shape factory.
325     */
326     typedef std::vector< ::com::sun::star::uno::Reference<
327         ::com::sun::star::accessibility::XAccessible> > AccessibleShapeList;
328     AccessibleShapeList maAccessibleShapes;
329 
330     /** Rectangle that describes the visible area in which a shape has to lie
331         at least partly, to be accessible through this class.  Used to
332         detect changes of the visible area after changes of the view forwarder.
333     */
334     Rectangle maVisibleArea;
335 
336     /** The parent of the shapes.  It is used for creating accessible
337         objects for given shapes.
338     */
339     ::com::sun::star::uno::Reference<
340         ::com::sun::star::accessibility::XAccessible> mxParent;
341 
342     /** Bundle of information passed down the shape tree.
343     */
344     AccessibleShapeTreeInfo maShapeTreeInfo;
345 
346     /** Reference to an accessible context object that is used to inform its
347         listeners of new and removed children.
348     */
349     AccessibleContextBase& mrContext;
350 
351     /** This method is called from the component helper base class while
352         disposing.
353     */
354     virtual void SAL_CALL disposing (void);
355 
356     /** Experimental: Get the index of the specified accessible object with
357         respect to the list of children maintained by this object.
358 
359         @return
360             Return the index of the given child or -1 to indicate that the
361             child is unknown.
362     */
363     long GetChildIndex (const ::com::sun::star::uno::Reference<
364         ::com::sun::star::accessibility::XAccessible>& xChild) const;
365 
366     void impl_dispose (void);
367 
368 private:
369     /** Names of new accessible objects are disambiguated with this index.
370         It gets increased every time a new object is created and (at the
371         moment) never reset.
372     */
373     sal_Int32 mnNewNameIndex;
374 
375     // Don't use the copy constructor or the assignment operator.  They are
376     // not implemented (and are not intended to be).
377     ChildrenManagerImpl (const ChildrenManagerImpl&);
378     ChildrenManagerImpl& operator= (const ChildrenManagerImpl&);
379 
380     /** This member points to the currently focused shape.  It is NULL when
381         there is no focused shape.
382     */
383     AccessibleShape* mpFocusedShape;
384 
385     /** Three helper functions for the <member>Update</member> method.
386     */
387 
388     /** Create a list of visible shapes from the list of UNO shapes
389         <member>maShapeList</member> and the list of accessible objects.
390         @param raChildList
391             For every visible shape from the two sources mentioned above one
392             descriptor is added to this list.
393     */
394     void CreateListOfVisibleShapes (ChildDescriptorListType& raChildList);
395 
396     /** From the old list of (former) visible shapes remove those that
397         are not member of the new list.  Send appropriate events for every
398         such shape.
399         @param raNewChildList
400             The new list of visible children against which the old one
401             is compared.
402         @param raOldChildList
403             The old list of visible children against which the new one
404             is compared.
405     */
406     void RemoveNonVisibleChildren (
407         const ChildDescriptorListType& raNewChildList,
408         ChildDescriptorListType& raOldChildList);
409 
410     /** Merge the information that is already known about the visible shapes
411         from the current list into the new list.
412         @param raChildList
413             Information is merged from the current list of visible children
414             to this list.
415     */
416     void MergeAccessibilityInformation (ChildDescriptorListType& raChildList);
417 
418     /** If the visible area has changed then send events that signal a
419         change of their bounding boxes for all shapes that are members of
420         both the current and the new list of visible shapes.
421         @param raChildList
422             Events are sent to all entries of this list that already contain
423             an accessible object.
424     */
425     void SendVisibleAreaEvents (ChildDescriptorListType& raChildList);
426 
427     /** If children have to be created immediately and not on demand the
428         create the missing accessible objects now.
429         @param raDescriptorList
430             Create an accessible object for every member of this list where
431             that object does not already exist.
432     */
433     void CreateAccessibilityObjects (ChildDescriptorListType& raChildList);
434 
435     /** Add a single shape.  Update all relevant data structures
436         accordingly.  Use this method instead of <member>Update()</member>
437         when only a single shape has been added.
438     */
439     void AddShape (const ::com::sun::star::uno::Reference<
440         ::com::sun::star::drawing::XShape>& xShape);
441 
442     /** Remove a single shape.  Update all relevant data structures
443         accordingly.  Use this method instead of <member>Update()</member>
444         when only a single shape has been removed.
445     */
446     void RemoveShape (const ::com::sun::star::uno::Reference<
447         ::com::sun::star::drawing::XShape>& xShape);
448 
449     /** Add the children manager as dispose listener at the given shape so
450         that the associated accessible object can be disposed when the shape
451         is disposed.
452         @param xShape
453             Register at this shape as dispose listener.
454     */
455     void RegisterAsDisposeListener (const ::com::sun::star::uno::Reference<
456         ::com::sun::star::drawing::XShape>& xShape);
457 
458     /** Remove the children manager as dispose listener at the given shape
459         @param xShape
460             Unregister at this shape as dispose listener.
461     */
462     void UnregisterAsDisposeListener (const ::com::sun::star::uno::Reference<
463         ::com::sun::star::drawing::XShape>& xShape);
464 };
465 
466 
467 
468 
469 /** A child descriptor holds a reference to a UNO shape and the
470     corresponding accessible object.  There are two use cases:
471     <ol><li>The accessible object is only created on demand and is then
472     initially empty.</li>
473     <li>There is no UNO shape.  The accessible object is given as argument
474     to the constructor.</li>
475     </ol>
476     In both cases the child descriptor assumes ownership over the accessible
477     object.
478 */
479 class ChildDescriptor
480 {
481 public:
482     /** Reference to a (partially) visible shape.
483     */
484     ::com::sun::star::uno::Reference<
485         ::com::sun::star::drawing::XShape> mxShape;
486 
487     /** The corresponding accessible object.  This reference is initially
488         empty and only replaced by a reference to a new object when that is
489         requested from the outside.
490     */
491     ::com::sun::star::uno::Reference<
492         ::com::sun::star::accessibility::XAccessible> mxAccessibleShape;
493 
494     /** Return a pointer to the implementation object of the accessible
495         shape of this descriptor.
496         @return
497             The result is NULL if either the UNO reference to the accessible
498             shape is empty or it can not be transformed into a pointer to
499             the desired class.
500     */
501     AccessibleShape* GetAccessibleShape (void) const;
502 
503     /** set the index _nIndex at the accessible shape
504         @param  _nIndex
505             The new index in parent.
506     */
507     void setIndexAtAccessibleShape(sal_Int32 _nIndex);
508 
509     /** This flag is set during the visibility calculation and indicates
510         that at one time in this process an event is sent that informs the
511         listeners of the creation of a new accessible object.  This flags is
512         not reset afterwards.  Don't use it unless you know exactly what you
513         are doing.
514     */
515     bool mbCreateEventPending;
516 
517     /** Create a new descriptor for the specified shape with empty reference
518         to accessible object.
519     */
520     explicit ChildDescriptor (const ::com::sun::star::uno::Reference<
521         ::com::sun::star::drawing::XShape>& xShape);
522 
523     /** Create a new descriptor for the specified shape with empty reference
524         to the original shape.
525     */
526     explicit ChildDescriptor (const ::com::sun::star::uno::Reference<
527         ::com::sun::star::accessibility::XAccessible>& rxAccessibleShape);
528 
529     ~ChildDescriptor (void);
530 
531     /** Dispose the accessible object of this descriptor.  If that object
532         does not exist then do nothing.
533         @param rParent
534             The parent of the accessible object to dispose.  A child event
535             is sent in its name.
536     */
537     void disposeAccessibleObject (AccessibleContextBase& rParent);
538 
539     /** Compare two child descriptors.  Take into account that a child
540         descriptor may be based on a UNO shape or, already, on an accessible
541         shape.
542     */
operator ==(const ChildDescriptor & aDescriptor) const543     inline bool operator == (const ChildDescriptor& aDescriptor) const
544     {
545         return (
546                 this == &aDescriptor ||
547                 (
548                  (mxShape.get() == aDescriptor.mxShape.get() ) &&
549                  (mxShape.is() || mxAccessibleShape.get() == aDescriptor.mxAccessibleShape.get())
550                 )
551                );
552     }
553 
554     /** The ordering defined by this operator is only used in order to be able
555         to put child descriptors in some STL containers.  The ordering itself is
556         not so important, its 'features' are not used.
557     */
operator <(const ChildDescriptor & aDescriptor) const558     inline bool operator < (const ChildDescriptor& aDescriptor) const
559     {
560         return (mxShape.get() < aDescriptor.mxShape.get());
561     }
562 
563 };
564 
565 
566 
567 } // end of namespace accessibility
568 
569 #endif
570 
571 /* vim: set noet sw=4 ts=4: */
572