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 aquired 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