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