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