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