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