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