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