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