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