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