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