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();
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();
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() 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();
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();
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();
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();
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() SAL_OVERRIDE;
356 :
357 : void impl_dispose();
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 : ChildrenManagerImpl (const ChildrenManagerImpl&) SAL_DELETED_FUNCTION;
367 : ChildrenManagerImpl& operator= (const ChildrenManagerImpl&) SAL_DELETED_FUNCTION;
368 :
369 : /** This member points to the currently focused shape. It is NULL when
370 : there is no focused shape.
371 : */
372 : AccessibleShape* mpFocusedShape;
373 :
374 : /** Three helper functions for the <member>Update</member> method.
375 : */
376 :
377 : /** Create a list of visible shapes from the list of UNO shapes
378 : <member>maShapeList</member> and the list of accessible objects.
379 : @param raChildList
380 : For every visible shape from the two sources mentioned above one
381 : descriptor is added to this list.
382 : */
383 : void CreateListOfVisibleShapes (ChildDescriptorListType& raChildList);
384 :
385 : /** From the old list of (former) visible shapes remove those that
386 : are not member of the new list. Send appropriate events for every
387 : such shape.
388 : @param raNewChildList
389 : The new list of visible children against which the old one
390 : is compared.
391 : @param raOldChildList
392 : The old list of visible children against which the new one
393 : is compared.
394 : */
395 : void RemoveNonVisibleChildren (
396 : const ChildDescriptorListType& raNewChildList,
397 : ChildDescriptorListType& raOldChildList);
398 :
399 : /** Merge the information that is already known about the visible shapes
400 : from the current list into the new list.
401 : @param raChildList
402 : Information is merged from the current list of visible children
403 : to this list.
404 : */
405 : void MergeAccessibilityInformation (ChildDescriptorListType& raChildList);
406 :
407 : /** If the visible area has changed then send events that signal a
408 : change of their bounding boxes for all shapes that are members of
409 : both the current and the new list of visible shapes.
410 : @param raChildList
411 : Events are sent to all entries of this list that already contain
412 : an accessible object.
413 : */
414 : void SendVisibleAreaEvents (ChildDescriptorListType& raChildList);
415 :
416 : /** If children have to be created immediately and not on demand the
417 : create the missing accessible objects now.
418 : @param raDescriptorList
419 : Create an accessible object for every member of this list where
420 : that object does not already exist.
421 : */
422 : void CreateAccessibilityObjects (ChildDescriptorListType& raChildList);
423 :
424 : /** Add a single shape. Update all relevant data structures
425 : accordingly. Use this method instead of <member>Update()</member>
426 : when only a single shape has been added.
427 : */
428 : void AddShape (const ::com::sun::star::uno::Reference<
429 : ::com::sun::star::drawing::XShape>& xShape);
430 :
431 : /** Remove a single shape. Update all relevant data structures
432 : accordingly. Use this method instead of <member>Update()</member>
433 : when only a single shape has been removed.
434 : */
435 : void RemoveShape (const ::com::sun::star::uno::Reference<
436 : ::com::sun::star::drawing::XShape>& xShape);
437 :
438 : /** Add the children manager as dispose listener at the given shape so
439 : that the associated accessible object can be disposed when the shape
440 : is disposed.
441 : @param xShape
442 : Register at this shape as dispose listener.
443 : */
444 : void RegisterAsDisposeListener (const ::com::sun::star::uno::Reference<
445 : ::com::sun::star::drawing::XShape>& xShape);
446 :
447 : /** Remove the children manager as dispose listener at the given shape
448 : @param xShape
449 : Unregister at this shape as dispose listener.
450 : */
451 : void UnregisterAsDisposeListener (const ::com::sun::star::uno::Reference<
452 : ::com::sun::star::drawing::XShape>& xShape);
453 : };
454 :
455 :
456 :
457 :
458 : /** A child descriptor holds a reference to a UNO shape and the
459 : corresponding accessible object. There are two use cases:
460 : <ol><li>The accessible object is only created on demand and is then
461 : initially empty.</li>
462 : <li>There is no UNO shape. The accessible object is given as argument
463 : to the constructor.</li>
464 : </ol>
465 : In both cases the child descriptor assumes ownership over the accessible
466 : object.
467 : */
468 31 : class ChildDescriptor
469 : {
470 : public:
471 : /** Reference to a (partially) visible shape.
472 : */
473 : ::com::sun::star::uno::Reference<
474 : ::com::sun::star::drawing::XShape> mxShape;
475 :
476 : /** The corresponding accessible object. This reference is initially
477 : empty and only replaced by a reference to a new object when that is
478 : requested from the outside.
479 : */
480 : ::com::sun::star::uno::Reference<
481 : ::com::sun::star::accessibility::XAccessible> mxAccessibleShape;
482 :
483 : /** Return a pointer to the implementation object of the accessible
484 : shape of this descriptor.
485 : @return
486 : The result is NULL if either the UNO reference to the accessible
487 : shape is empty or it can not be transformed into a pointer to
488 : the desired class.
489 : */
490 : AccessibleShape* GetAccessibleShape() const;
491 :
492 : /** set the index _nIndex at the accessible shape
493 : @param _nIndex
494 : The new index in parent.
495 : */
496 : void setIndexAtAccessibleShape(sal_Int32 _nIndex);
497 :
498 : /** This flag is set during the visibility calculation and indicates
499 : that at one time in this process an event is sent that informs the
500 : listeners of the creation of a new accessible object. This flags is
501 : not reset afterwards. Don't use it unless you know exactly what you
502 : are doing.
503 : */
504 : bool mbCreateEventPending;
505 :
506 : /** Create a new descriptor for the specified shape with empty reference
507 : to accessible object.
508 : */
509 : explicit ChildDescriptor (const ::com::sun::star::uno::Reference<
510 : ::com::sun::star::drawing::XShape>& xShape);
511 :
512 : /** Create a new descriptor for the specified shape with empty reference
513 : to the original shape.
514 : */
515 : explicit ChildDescriptor (const ::com::sun::star::uno::Reference<
516 : ::com::sun::star::accessibility::XAccessible>& rxAccessibleShape);
517 :
518 : ~ChildDescriptor();
519 :
520 : /** Dispose the accessible object of this descriptor. If that object
521 : does not exist then do nothing.
522 : @param rParent
523 : The parent of the accessible object to dispose. A child event
524 : is sent in its name.
525 : */
526 : void disposeAccessibleObject (AccessibleContextBase& rParent);
527 :
528 : /** Compare two child descriptors. Take into account that a child
529 : descriptor may be based on a UNO shape or, already, on an accessible
530 : shape.
531 : */
532 32 : inline bool operator == (const ChildDescriptor& aDescriptor) const
533 : {
534 : return (
535 88 : this == &aDescriptor ||
536 : (
537 56 : (mxShape.get() == aDescriptor.mxShape.get() ) &&
538 40 : (mxShape.is() || mxAccessibleShape.get() == aDescriptor.mxAccessibleShape.get())
539 : )
540 32 : );
541 : }
542 :
543 : /** The ordering defined by this operator is only used in order to be able
544 : to put child descriptors in some STL containers. The ordering itself is
545 : not so important, its 'features' are not used.
546 : */
547 : inline bool operator < (const ChildDescriptor& aDescriptor) const
548 : {
549 : return (mxShape.get() < aDescriptor.mxShape.get());
550 : }
551 :
552 : };
553 :
554 :
555 :
556 : } // end of namespace accessibility
557 :
558 : #endif
559 :
560 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|