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