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