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_ACCESSILE_TEXT_HELPER_HXX_ 25 #define _SVX_ACCESSILE_TEXT_HELPER_HXX_ 26 27 #include <memory> 28 #include <sal/types.h> 29 #include <tools/gen.hxx> 30 #include <com/sun/star/uno/Any.hxx> 31 #include <com/sun/star/uno/Reference.hxx> 32 #include <com/sun/star/accessibility/XAccessible.hpp> 33 #include <com/sun/star/accessibility/XAccessibleContext.hpp> 34 #include <com/sun/star/accessibility/XAccessibleComponent.hpp> 35 #include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp> 36 #include "svx/svxdllapi.h" 37 38 39 class SvxTextForwarder; 40 class SvxViewForwarder; 41 class SvxEditSource; 42 43 namespace accessibility 44 { 45 46 class AccessibleTextHelper_Impl; 47 48 /** Helper class for objects containing EditEngine/Outliner text 49 50 This class provides the methods from the XAccessibleContext, 51 XAccessibleEventBroadcaster and XAccessibleComponent 52 interfaces, that are common to all accessible objects 53 containing an edit engine. 54 55 The text contained in the EditEngine/Outliner is presented as 56 children of this class, namely for every text paragraph a 57 AccessibleEditableTextPara child object is generated. As this 58 class manages these children for itself, it has to send out 59 AccessibleEventId::CHILD events on your 60 behalf. Thus, you must forward every call to your 61 addEventListener()/removeEventListener() methods to the 62 AccessibleTextHelper (methods 63 AddEventListener/RemoveEventListener), otherwise none or not 64 every one of your event listener will notice child changes. 65 66 You have to implement the SvxEditSource, SvxTextForwarder, 67 SvxViewForwarder and SvxEditViewForwarder interfaces in order 68 to enable your object to cooperate with this 69 class. SvxTextForwarder encapsulates the fact that text 70 objects do not necessarily have an EditEngine at their 71 disposal, SvxViewForwarder and SvxEditViewForwarder do the 72 same for the document and the edit view. The three mentioned 73 forwarder objects are not stored by the AccessibleTextHelper, 74 but fetched every time from the SvxEditSource. So you are best 75 off making your SvxEditSource::Get*Forwarder methods cache the 76 current forwarder. 77 78 To support changes in edit mode or conversion of fixed text 79 into EditEngine text, you can change the SvxEditSource this 80 class is referring to. This might render all children invalid 81 and change the child count, since the AccessibleTextHelper 82 reinitializes itself from scratch. 83 84 This class registers itself at the SvxEditSource as a state 85 listener and manages the state of its children (i.e. the 86 paragraphs). See the method documentation of 87 AccessibleTextHelper::SetEditSource for the expected 88 events. Generally, be prepared that when sending any of these 89 events via SvxEditSource::GetBroadcaster() broadcaster, the 90 AccessibleTextHelper will call the SvxEditSource and their 91 forwarder to update it's state. Avoid being inconsistent in 92 the facts you tell in the events, e.g. when sending a 93 TEXT_HINT_PARAINSERTED event, the 94 SvxEditSource::GetTextForwarder().GetParagraphCount() should 95 already include the newly inserted paragraph. 96 97 @attention All public methods must not be called with any 98 mutex hold, except when calling from the main thread (with 99 holds the solar mutex), unless stated otherwise. This is 100 because they themselves might need the solar mutex in addition 101 to the object mutex, and the ordering of the locking must be: 102 first solar mutex, then object mutex. Furthermore, state 103 change events might be fired internally. 104 105 @derive Use this class in an aggregation and forward, or 106 derive from it and overwrite. If the Remove/AddEventListener 107 methods are overwritten, make sure FireEvent is adapted, 108 too. 109 110 @see SvxEditSource 111 @see SvxTextForwarder 112 @see SvxViewForwarder 113 @see SvxEditViewForwarder 114 */ 115 class SVX_DLLPUBLIC AccessibleTextHelper 116 { 117 118 public: 119 typedef ::std::vector< sal_Int16 > VectorOfStates; 120 121 /** Create accessible text object for given edit source 122 123 @param pEditSource 124 The edit source to use. Object ownership is transferred 125 from the caller to the callee. The object listens on the 126 SvxEditSource for object disposal, so no provisions have 127 to be taken if the caller destroys the data (e.g. the 128 model) contained in the given SvxEditSource. 129 130 */ 131 explicit AccessibleTextHelper( ::std::auto_ptr< SvxEditSource > pEditSource ); 132 virtual ~AccessibleTextHelper(); 133 134 protected: 135 136 // declared, but not defined 137 AccessibleTextHelper( const AccessibleTextHelper& ); 138 // declared, but not defined 139 AccessibleTextHelper& operator= ( const AccessibleTextHelper& ); 140 141 public: 142 /** Query the current edit source 143 144 @attention This method returns by reference, so you are 145 responsible for serialization (typically, you acquired the 146 solar mutex when calling this method). Thus, the method 147 should only be called from the main office thread. 148 149 */ 150 virtual const SvxEditSource& GetEditSource() const SAL_THROW((::com::sun::star::uno::RuntimeException)); 151 152 /** Set the current edit source 153 154 @attention Might fire state change events, therefore, 155 don't hold any mutex except solar mutex, which you are 156 required to lock before. This method should only be called 157 from the main office thread. 158 159 The EditSource set here is required to broadcast out the 160 following hints: EDITSOURCE_HINT_PARASMOVED, 161 EDITSOURCE_HINT_SELECTIONCHANGED, TEXT_HINT_MODIFIED, 162 TEXT_HINT_PARAINSERTED, TEXT_HINT_PARAREMOVED, 163 TEXT_HINT_TEXTHEIGHTCHANGED, 164 TEXT_HINT_VIEWSCROLLED. Otherwise, not all state changes 165 will get noticed by the accessibility object. Further 166 more, when the corresponding core object or the model is 167 dying, either the edit source must be set to NULL or it 168 has to broadcast a SFX_HINT_DYING hint. 169 170 If the SvxEditSource's managed text can change between 171 edit/non-edit mode (i.e. there are times when 172 SvxEditSource::GetEditViewForwarder(sal_False) returns 173 NULL), then the two additional hints are required: 174 HINT_BEGEDIT and HINT_ENDEDIT. When the 175 AccessibleTextHelper receives a HINT_BEGEDIT, it expects 176 the SvxEditSource already in edit mode. On a HINT_ENDEDIT, 177 edit mode must already been left. The rationale for these 178 events are the fact that focus and selection have to be 179 updated in edit mode, and completely relinquished and 180 reset to the parent (for the focus) in non-edit mode. 181 182 This class does not have a dispose method, since it is not 183 a UNO component. Nevertheless, it holds C++ references to 184 several core objects, so you should issue a 185 SetEditSource(::std::auto_ptr<SvxEditSource>(NULL)) in 186 your dispose() method. 187 188 @param pEditSource 189 The new edit source to set. Object ownership is transferred 190 from the caller to the callee. 191 */ 192 virtual void SetEditSource( ::std::auto_ptr< SvxEditSource > pEditSource ) SAL_THROW((::com::sun::star::uno::RuntimeException)); 193 194 /** Set the event source 195 196 You should set the event source before registering any 197 event listener and before requesting any child. Children 198 of this object receive the event source as their parent 199 accessible object. That is, the event source is best set 200 in your object's init method. 201 202 @attention When setting a reference here, you should call 203 Dispose() when you as the owner are disposing, since until 204 then this object will hold that reference 205 206 @param rInterface 207 The interface that should be set as the source for 208 accessibility events sent by this object. 209 */ 210 virtual void SetEventSource( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& rInterface ); 211 212 /** Get the event source 213 214 @return the interface that is set as the source for 215 accessibility events sent by this object. 216 */ 217 virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > GetEventSource() const; 218 219 /** Set offset of EditEngine/Outliner from parent 220 221 If the origin of the underlying EditEngine/Outliner does 222 not correspond to the upper left corner of the object 223 using this class, you have to specify the offset. 224 225 @attention Might fire state change events, therefore, 226 don't hold any mutex except solar mutex, which you are 227 required to lock before. This method should only be called 228 from the main office thread. 229 230 @param rPoint 231 The offset in screen coordinates (i.e. pixel) 232 */ 233 virtual void SetOffset( const Point& rPoint ); 234 235 /** Query offset of EditEngine/Outliner from parent 236 237 @return the offset in screen coordinates (i.e. pixel) 238 */ 239 virtual Point GetOffset() const; 240 241 /** Set offset the object adds to all children's indices 242 243 This can be used if the owner of this object has children 244 handled by itself. Setting an offset different from 0 245 leads to this object mimicking that all it's children are 246 within the range [nOffset, GetChildCount()+nOffset). That 247 means, GetChild() also expects the index to be in this 248 range. 249 250 @attention Might fire state change events, therefore, 251 don't hold any mutex except solar mutex, which you are 252 required to lock before. This method should only be called 253 from the main office thread. 254 255 @param nOffset 256 The offset to add to every children's index. 257 */ 258 virtual void SetStartIndex( sal_Int32 nOffset ); 259 260 /** Query offset the object adds to all children's indices 261 262 @return the offset to add to every children's index. 263 */ 264 virtual sal_Int32 GetStartIndex() const; 265 266 /** Sets a vector of additional accessible states. 267 268 The states are passed to every created child object 269 (text paragraph). The state values are defined in 270 com::sun::star::accessibility::AccessibleStateType. 271 272 This function has to be called before querying for 273 any children (e.g. with GetChild()). 274 */ 275 void SetAdditionalChildStates( const VectorOfStates& rChildStates ); 276 277 /** Returns the additional accessible states for children. 278 */ 279 const VectorOfStates& GetAdditionalChildStates() const; 280 281 /** Update the visible children 282 283 @attention Might fire state change events, therefore, 284 don't hold any mutex except solar mutex, which you are 285 required to lock before. This method should only be called 286 from the main office thread. 287 288 This method reevaluates the visibility of all 289 childrens. Call this method if your visibility state has 290 changed somehow, e.g. if the visible area has changed and 291 the AccessibleTextHelper isn't notified internally 292 (e.g. via TEXT_HINT_VIEWSCROLLED). Normally, there should 293 not be a need to call this method. 294 */ 295 virtual void UpdateChildren() SAL_THROW((::com::sun::star::uno::RuntimeException)); 296 297 /** Drop all references and enter disposed state 298 299 This method drops all references to external objects (also 300 the event source reference set via SetEventSource()) and 301 sets the object into the disposed state (i.e. the methods 302 return default values or throw a uno::DisposedException 303 exception). 304 */ 305 virtual void Dispose(); 306 307 /** Set the focus state of the accessibility object 308 309 Since this class handles children which also might get the 310 focus, the user of this class is encouraged to delegate 311 focus handling. Whenever the focus state of the 312 surrounding object changes, this method has to be called. 313 314 The protocol of focus handling for a user of this class is 315 then to call SetFocus() with the appropriate focus state, 316 and HaveFocus() to determine the focus state you tell the 317 outside. 318 319 @attention Might fire state change events, therefore, 320 don't hold any mutex except solar mutex, which you are 321 required to lock before. This method should only be called 322 from the main office thread. 323 324 @param bHaveFocus 325 Whether we got or we lost the focus. Set to sal_True if 326 focus is gotten, sal_False otherwise. 327 328 @see HaveFocus() 329 */ 330 virtual void SetFocus( sal_Bool bHaveFocus = sal_True ) SAL_THROW((::com::sun::star::uno::RuntimeException)); 331 332 /** Query the focus state of the surrounding object 333 334 If focus handling is delegated to this class, determine 335 focus state with this method. Be prepared that even if you 336 set the focus with SetFocus(sal_True), this method might 337 return sal_False. This is the case if one of the children 338 actually got the focus. 339 340 @return the state of the focus ownership 341 */ 342 virtual sal_Bool HaveFocus() SAL_THROW((::com::sun::star::uno::RuntimeException)); 343 344 /** Call this method to invoke all event listeners with the given event 345 346 @attention Fires state change events, therefore, don't hold any mutex 347 348 @param nEventId 349 Id of the event to send, @see AccessibleEventId 350 351 @param rNewValue 352 The value we've changed into 353 354 @param rOldValue 355 The old value before the change 356 */ 357 virtual void FireEvent( const sal_Int16 nEventId, 358 const ::com::sun::star::uno::Any& rNewValue = ::com::sun::star::uno::Any(), 359 const ::com::sun::star::uno::Any& rOldValue = ::com::sun::star::uno::Any() ) const; 360 361 /** Call this method to invoke all event listeners with the given event 362 363 @attention Fires state change events, therefore, don't hold any mutex 364 365 @param rEvent 366 The event to send, @see AccessibleEventObject 367 368 */ 369 // TODO: make that virtual next time 370 void FireEvent( const ::com::sun::star::accessibility::AccessibleEventObject& rEvent ) const; 371 372 /** Query select state of the text managed by this object 373 374 @attention Don't call with locked mutexes. You may hold 375 the solar mutex, but this method aquires it anyway. 376 377 @return sal_True, if the text or parts of it are currently selected 378 */ 379 virtual sal_Bool IsSelected() const; 380 381 // XAccessibleContext child handling methods 382 //----------------------------------------------------------------- 383 /** Implements getAccessibleChildCount 384 385 @attention Don't call with locked mutexes. You may hold 386 the solar mutex, but this method aquires it anyway. 387 */ 388 virtual sal_Int32 GetChildCount() SAL_THROW((::com::sun::star::uno::RuntimeException)); 389 /** Implements getAccessibleChild 390 391 @attention Don't call with locked mutexes. You may hold 392 the solar mutex, but this method aquires it anyway. 393 */ 394 virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > GetChild( sal_Int32 i ) SAL_THROW((::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)); 395 396 // XAccessibleEventBroadcaster child related methods 397 //----------------------------------------------------------------- 398 /** Implements addEventListener 399 400 @attention Don't call with locked mutexes 401 */ 402 virtual void AddEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) SAL_THROW((::com::sun::star::uno::RuntimeException)); 403 /** Implements removeEventListener 404 405 @attention Don't call with locked mutexes 406 */ 407 virtual void RemoveEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) SAL_THROW((::com::sun::star::uno::RuntimeException)); 408 409 // XAccessibleComponent child related methods 410 //----------------------------------------------------------------- 411 /** Implements getAccessibleAt 412 413 @attention Don't call with locked mutexes. You may hold 414 the solar mutex, but this method aquires it anyway. 415 */ 416 virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL GetAt( const ::com::sun::star::awt::Point& aPoint ) SAL_THROW((::com::sun::star::uno::RuntimeException)); 417 418 private: 419 420 /// @dyn 421 const std::auto_ptr< AccessibleTextHelper_Impl > mpImpl; 422 423 }; 424 425 } // end of namespace accessibility 426 427 #endif /* _SVX_ACCESSILE_TEXT_HELPER_HXX_ */ 428