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