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