1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #ifndef INCLUDED_SVX_ACCESSIBLETEXTHELPER_HXX
21 #define INCLUDED_SVX_ACCESSIBLETEXTHELPER_HXX
24 #include <sal/types.h>
25 #include <tools/gen.hxx>
26 #include <com/sun/star/uno/Any.hxx>
27 #include <com/sun/star/uno/Reference.hxx>
28 #include <com/sun/star/accessibility/XAccessible.hpp>
29 #include <com/sun/star/accessibility/XAccessibleContext.hpp>
30 #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
31 #include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
32 #include <svx/svxdllapi.h>
35 class SvxTextForwarder
;
36 class SvxViewForwarder
;
39 namespace accessibility
42 class AccessibleTextHelper_Impl
;
44 /** Helper class for objects containing EditEngine/Outliner text
46 This class provides the methods from the XAccessibleContext,
47 XAccessibleEventBroadcaster and XAccessibleComponent
48 interfaces, that are common to all accessible objects
49 containing an edit engine.
51 The text contained in the EditEngine/Outliner is presented as
52 children of this class, namely for every text paragraph a
53 AccessibleEditableTextPara child object is generated. As this
54 class manages these children for itself, it has to send out
55 AccessibleEventId::CHILD events on your
56 behalf. Thus, you must forward every call to your
57 addEventListener()/removeEventListener() methods to the
58 AccessibleTextHelper (methods
59 AddEventListener/RemoveEventListener), otherwise none or not
60 every one of your event listener will notice child changes.
62 You have to implement the SvxEditSource, SvxTextForwarder,
63 SvxViewForwarder and SvxEditViewForwarder interfaces in order
64 to enable your object to cooperate with this
65 class. SvxTextForwarder encapsulates the fact that text
66 objects do not necessarily have an EditEngine at their
67 disposal, SvxViewForwarder and SvxEditViewForwarder do the
68 same for the document and the edit view. The three mentioned
69 forwarder objects are not stored by the AccessibleTextHelper,
70 but fetched every time from the SvxEditSource. So you are best
71 off making your SvxEditSource::Get*Forwarder methods cache the
74 To support changes in edit mode or conversion of fixed text
75 into EditEngine text, you can change the SvxEditSource this
76 class is referring to. This might render all children invalid
77 and change the child count, since the AccessibleTextHelper
78 reinitializes itself from scratch.
80 This class registers itself at the SvxEditSource as a state
81 listener and manages the state of its children (i.e. the
82 paragraphs). See the method documentation of
83 AccessibleTextHelper::SetEditSource for the expected
84 events. Generally, be prepared that when sending any of these
85 events via SvxEditSource::GetBroadcaster() broadcaster, the
86 AccessibleTextHelper will call the SvxEditSource and their
87 forwarder to update it's state. Avoid being inconsistent in
88 the facts you tell in the events, e.g. when sending a
89 TEXT_HINT_PARAINSERTED event, the
90 SvxEditSource::GetTextForwarder().GetParagraphCount() should
91 already include the newly inserted paragraph.
93 @attention All public methods must not be called with any
94 mutex hold, except when calling from the main thread (with
95 holds the solar mutex), unless stated otherwise. This is
96 because they themselves might need the solar mutex in addition
97 to the object mutex, and the ordering of the locking must be:
98 first solar mutex, then object mutex. Furthermore, state
99 change events might be fired internally.
101 @derive Use this class in an aggregation and forward, or
102 derive from it and overwrite.
106 @see SvxTextForwarder
107 @see SvxViewForwarder
108 @see SvxEditViewForwarder
110 class SVX_DLLPUBLIC AccessibleTextHelper
114 typedef ::std::vector
< sal_Int16
> VectorOfStates
;
116 /** Create accessible text object for given edit source
119 The edit source to use. Object ownership is transferred
120 from the caller to the callee. The object listens on the
121 SvxEditSource for object disposal, so no provisions have
122 to be taken if the caller destroys the data (e.g. the
123 model) contained in the given SvxEditSource.
126 explicit AccessibleTextHelper( ::std::unique_ptr
< SvxEditSource
> && pEditSource
);
128 virtual ~AccessibleTextHelper();
132 // declared, but not defined
133 AccessibleTextHelper( const AccessibleTextHelper
& );
134 // declared, but not defined
135 AccessibleTextHelper
& operator= ( const AccessibleTextHelper
& );
138 /** Query the current edit source
140 @attention This method returns by reference, so you are
141 responsible for serialization (typically, you acquired the
142 solar mutex when calling this method). Thus, the method
143 should only be called from the main office thread.
146 const SvxEditSource
& GetEditSource() const;
148 /** Set the current edit source
150 @attention Might fire state change events, therefore,
151 don't hold any mutex except solar mutex, which you are
152 required to lock before. This method should only be called
153 from the main office thread.
155 The EditSource set here is required to broadcast out the
156 following hints: EDITSOURCE_HINT_PARASMOVED,
157 EDITSOURCE_HINT_SELECTIONCHANGED, TEXT_HINT_MODIFIED,
158 TEXT_HINT_PARAINSERTED, TEXT_HINT_PARAREMOVED,
159 TEXT_HINT_TEXTHEIGHTCHANGED,
160 TEXT_HINT_VIEWSCROLLED. Otherwise, not all state changes
161 will get noticed by the accessibility object. Further
162 more, when the corresponding core object or the model is
163 dying, either the edit source must be set to NULL or it
164 has to broadcast a SFX_HINT_DYING hint.
166 If the SvxEditSource's managed text can change between
167 edit/non-edit mode (i.e. there are times when
168 SvxEditSource::GetEditViewForwarder(sal_False) returns
169 NULL), then the two additional hints are required:
170 HINT_BEGEDIT and HINT_ENDEDIT. When the
171 AccessibleTextHelper receives a HINT_BEGEDIT, it expects
172 the SvxEditSource already in edit mode. On a HINT_ENDEDIT,
173 edit mode must already been left. The rationale for these
174 events are the fact that focus and selection have to be
175 updated in edit mode, and completely relinquished and
176 reset to the parent (for the focus) in non-edit mode.
178 This class does not have a dispose method, since it is not
179 a UNO component. Nevertheless, it holds C++ references to
180 several core objects, so you should issue a
181 SetEditSource(::std::unique_ptr<SvxEditSource>()) in
182 your dispose() method.
185 The new edit source to set. Object ownership is transferred
186 from the caller to the callee.
188 void SetEditSource( ::std::unique_ptr
< SvxEditSource
> && pEditSource
);
190 /** Set the event source
192 You should set the event source before registering any
193 event listener and before requesting any child. Children
194 of this object receive the event source as their parent
195 accessible object. That is, the event source is best set
196 in your object's init method.
198 @attention When setting a reference here, you should call
199 Dispose() when you as the owner are disposing, since until
200 then this object will hold that reference
203 The interface that should be set as the source for
204 accessibility events sent by this object.
206 void SetEventSource( const ::com::sun::star::uno::Reference
< ::com::sun::star::accessibility::XAccessible
>& rInterface
);
208 /** Set offset of EditEngine/Outliner from parent
210 If the origin of the underlying EditEngine/Outliner does
211 not correspond to the upper left corner of the object
212 using this class, you have to specify the offset.
214 @attention Might fire state change events, therefore,
215 don't hold any mutex except solar mutex, which you are
216 required to lock before. This method should only be called
217 from the main office thread.
220 The offset in screen coordinates (i.e. pixel)
222 void SetOffset( const Point
& rPoint
);
224 /** Set offset the object adds to all children's indices
226 This can be used if the owner of this object has children
227 handled by itself. Setting an offset different from 0
228 leads to this object mimicking that all its children are
229 within the range [nOffset, GetChildCount()+nOffset). That
230 means, GetChild() also expects the index to be in this
233 @attention Might fire state change events, therefore,
234 don't hold any mutex except solar mutex, which you are
235 required to lock before. This method should only be called
236 from the main office thread.
239 The offset to add to every children's index.
241 void SetStartIndex( sal_Int32 nOffset
);
243 /** Query offset the object adds to all children's indices
245 @return the offset to add to every children's index.
247 sal_Int32
GetStartIndex() const;
249 /** Sets a vector of additional accessible states.
251 The states are passed to every created child object
252 (text paragraph). The state values are defined in
253 com::sun::star::accessibility::AccessibleStateType.
255 This function has to be called before querying for
256 any children (e.g. with GetChild()).
258 void SetAdditionalChildStates( const VectorOfStates
& rChildStates
);
260 /** Update the visible children
262 @attention Might fire state change events, therefore,
263 don't hold any mutex except solar mutex, which you are
264 required to lock before. This method should only be called
265 from the main office thread.
267 This method reevaluates the visibility of all
268 children. Call this method if your visibility state has
269 changed somehow, e.g. if the visible area has changed and
270 the AccessibleTextHelper isn't notified internally
271 (e.g. via TEXT_HINT_VIEWSCROLLED). Normally, there should
272 not be a need to call this method.
274 void UpdateChildren();
276 /** Drop all references and enter disposed state
278 This method drops all references to external objects (also
279 the event source reference set via SetEventSource()) and
280 sets the object into the disposed state (i.e. the methods
281 return default values or throw a uno::DisposedException
286 /** Set the focus state of the accessibility object
288 Since this class handles children which also might get the
289 focus, the user of this class is encouraged to delegate
290 focus handling. Whenever the focus state of the
291 surrounding object changes, this method has to be called.
293 The protocol of focus handling for a user of this class is
294 then to call SetFocus() with the appropriate focus state,
295 and HaveFocus() to determine the focus state you tell the
298 @attention Might fire state change events, therefore,
299 don't hold any mutex except solar mutex, which you are
300 required to lock before. This method should only be called
301 from the main office thread.
304 Whether we got or we lost the focus. Set to true if
305 focus is gotten, false otherwise.
309 void SetFocus( bool bHaveFocus
= true );
311 /** Query the focus state of the surrounding object
313 If focus handling is delegated to this class, determine
314 focus state with this method. Be prepared that even if you
315 set the focus with SetFocus(true), this method might
316 return false. This is the case if one of the children
317 actually got the focus.
319 @return the state of the focus ownership
323 // XAccessibleContext child handling methods
325 /** Implements getAccessibleChildCount
327 @attention Don't call with locked mutexes. You may hold
328 the solar mutex, but this method acquires it anyway.
330 sal_Int32
GetChildCount();
331 /** Implements getAccessibleChild
333 @attention Don't call with locked mutexes. You may hold
334 the solar mutex, but this method acuires it anyway.
336 ::com::sun::star::uno::Reference
< ::com::sun::star::accessibility::XAccessible
> GetChild( sal_Int32 i
);
338 // XAccessibleEventBroadcaster child related methods
340 /** Implements addEventListener
342 @attention Don't call with locked mutexes
344 void AddEventListener( const ::com::sun::star::uno::Reference
< ::com::sun::star::accessibility::XAccessibleEventListener
>& xListener
);
345 /** Implements removeEventListener
347 @attention Don't call with locked mutexes
349 void RemoveEventListener( const ::com::sun::star::uno::Reference
< ::com::sun::star::accessibility::XAccessibleEventListener
>& xListener
);
351 // XAccessibleComponent child related methods
353 /** Implements getAccessibleAt
355 @attention Don't call with locked mutexes. You may hold
356 the solar mutex, but this method acquires it anyway.
358 ::com::sun::star::uno::Reference
< ::com::sun::star::accessibility::XAccessible
> SAL_CALL
GetAt( const ::com::sun::star::awt::Point
& aPoint
);
363 const std::unique_ptr
< AccessibleTextHelper_Impl
> mpImpl
;
367 } // end of namespace accessibility
369 #endif // INCLUDED_SVX_ACCESSIBLETEXTHELPER_HXX
371 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */