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