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
26 #include <com/sun/star/uno/Reference.hxx>
27 #include <sal/types.h>
28 #include <svx/svxdllapi.h>
30 namespace com::sun::star
32 namespace accessibility
36 namespace accessibility
38 class XAccessibleEventListener
;
49 namespace accessibility
51 class AccessibleTextHelper_Impl
;
53 /** Helper class for objects containing EditEngine/Outliner text
55 This class provides the methods from the XAccessibleContext,
56 XAccessibleEventBroadcaster and XAccessibleComponent
57 interfaces, that are common to all accessible objects
58 containing an edit engine.
60 The text contained in the EditEngine/Outliner is presented as
61 children of this class, namely for every text paragraph a
62 AccessibleEditableTextPara child object is generated. As this
63 class manages these children for itself, it has to send out
64 AccessibleEventId::CHILD events on your
65 behalf. Thus, you must forward every call to your
66 addEventListener()/removeEventListener() methods to the
67 AccessibleTextHelper (methods
68 AddEventListener/RemoveEventListener), otherwise none or not
69 everyone of your event listener will notice child changes.
71 You have to implement the SvxEditSource, SvxTextForwarder,
72 SvxViewForwarder and SvxEditViewForwarder interfaces in order
73 to enable your object to cooperate with this
74 class. SvxTextForwarder encapsulates the fact that text
75 objects do not necessarily have an EditEngine at their
76 disposal, SvxViewForwarder and SvxEditViewForwarder do the
77 same for the document and the edit view. The three mentioned
78 forwarder objects are not stored by the AccessibleTextHelper,
79 but fetched every time from the SvxEditSource. So you are best
80 off making your SvxEditSource::Get*Forwarder methods cache the
83 To support changes in edit mode or conversion of fixed text
84 into EditEngine text, you can change the SvxEditSource this
85 class is referring to. This might render all children invalid
86 and change the child count, since the AccessibleTextHelper
87 reinitializes itself from scratch.
89 This class registers itself at the SvxEditSource as a state
90 listener and manages the state of its children (i.e. the
91 paragraphs). See the method documentation of
92 AccessibleTextHelper::SetEditSource for the expected
93 events. Generally, be prepared that when sending any of these
94 events via SvxEditSource::GetBroadcaster() broadcaster, the
95 AccessibleTextHelper will call the SvxEditSource and their
96 forwarder to update it's state. Avoid being inconsistent in
97 the facts you tell in the events, e.g. when sending a
98 SfxHintId::TextParaInserted event, the
99 SvxEditSource::GetTextForwarder().GetParagraphCount() should
100 already include the newly inserted paragraph.
102 @attention All public methods must not be called with any
103 mutex hold, except when calling from the main thread (with
104 holds the solar mutex), unless stated otherwise. This is
105 because they themselves might need the solar mutex in addition
106 to the object mutex, and the ordering of the locking must be:
107 first solar mutex, then object mutex. Furthermore, state
108 change events might be fired internally.
110 @derive Use this class in an aggregation and forward, or
111 derive from it and overwrite.
115 @see SvxTextForwarder
116 @see SvxViewForwarder
117 @see SvxEditViewForwarder
119 class SVX_DLLPUBLIC AccessibleTextHelper final
122 typedef ::std::vector
<sal_Int16
> VectorOfStates
;
124 /** Create accessible text object for given edit source
127 The edit source to use. Object ownership is transferred
128 from the caller to the callee. The object listens on the
129 SvxEditSource for object disposal, so no provisions have
130 to be taken if the caller destroys the data (e.g. the
131 model) contained in the given SvxEditSource.
134 explicit AccessibleTextHelper(::std::unique_ptr
<SvxEditSource
>&& pEditSource
);
136 ~AccessibleTextHelper();
138 AccessibleTextHelper(const AccessibleTextHelper
&) = delete;
139 AccessibleTextHelper
& operator=(const AccessibleTextHelper
&) = delete;
141 /** Query the current edit source
143 @attention This method returns by reference, so you are
144 responsible for serialization (typically, you acquired the
145 solar mutex when calling this method). Thus, the method
146 should only be called from the main office thread.
149 const SvxEditSource
& GetEditSource() const;
151 /** Set the current edit source
153 @attention Might fire state change events, therefore,
154 don't hold any mutex except solar mutex, which you are
155 required to lock before. This method should only be called
156 from the main office thread.
158 The EditSource set here is required to broadcast out the
159 following hints: SfxHintId::EditSourceParasMoved,
160 SfxHintId::EditSourceSelectionChanged, SfxHintId::TextModified,
161 SfxHintId::TextParaInserted, SfxHintId::TextParaRemoved,
162 SfxHintId::TextHeightChanged,
163 SfxHintId::TextViewScrolled. Otherwise, not all state changes
164 will get noticed by the accessibility object. Further
165 more, when the corresponding core object or the model is
166 dying, either the edit source must be set to NULL or it
167 has to broadcast a SfxHintId::Dying hint.
169 If the SvxEditSource's managed text can change between
170 edit/non-edit mode (i.e. there are times when
171 SvxEditSource::GetEditViewForwarder(sal_False) returns
172 NULL), then the two additional hints are required:
173 SdrHintKind::BeginEdit and SdrHintKind::EndEdit. When the
174 AccessibleTextHelper receives a SdrHintKind::BeginEdit, it expects
175 the SvxEditSource already in edit mode. On a SdrHintKind::EndEdit,
176 edit mode must already been left. The rationale for these
177 events are the fact that focus and selection have to be
178 updated in edit mode, and completely relinquished and
179 reset to the parent (for the focus) in non-edit mode.
181 This class does not have a dispose method, since it is not
182 a UNO component. Nevertheless, it holds C++ references to
183 several core objects, so you should issue a
184 SetEditSource(::std::unique_ptr<SvxEditSource>()) in
185 your dispose() method.
188 The new edit source to set. Object ownership is transferred
189 from the caller to the callee.
191 void SetEditSource(::std::unique_ptr
<SvxEditSource
>&& pEditSource
);
193 /** Set the event source
195 You should set the event source before registering any
196 event listener and before requesting any child. Children
197 of this object receive the event source as their parent
198 accessible object. That is, the event source is best set
199 in your object's init method.
201 @attention When setting a reference here, you should call
202 Dispose() when you as the owner are disposing, since until
203 then this object will hold that reference
206 The interface that should be set as the source for
207 accessibility events sent by this object.
209 void SetEventSource(const css::uno::Reference
<css::accessibility::XAccessible
>& rInterface
);
211 /** Set offset of EditEngine/Outliner from parent
213 If the origin of the underlying EditEngine/Outliner does
214 not correspond to the upper left corner of the object
215 using this class, you have to specify the offset.
217 @attention Might fire state change events, therefore,
218 don't hold any mutex except solar mutex, which you are
219 required to lock before. This method should only be called
220 from the main office thread.
223 The offset in screen coordinates (i.e. pixel)
225 void SetOffset(const Point
& rPoint
);
227 /** Set offset the object adds to all children's indices
229 This can be used if the owner of this object has children
230 handled by itself. Setting an offset different from 0
231 leads to this object mimicking that all its children are
232 within the range [nOffset, GetChildCount()+nOffset). That
233 means, GetChild() also expects the index to be in this
236 @attention Might fire state change events, therefore,
237 don't hold any mutex except solar mutex, which you are
238 required to lock before. This method should only be called
239 from the main office thread.
242 The offset to add to every children's index.
244 void SetStartIndex(sal_Int32 nOffset
);
246 /** Query offset the object adds to all children's indices
248 @return the offset to add to every children's index.
250 sal_Int32
GetStartIndex() const;
252 /** Sets a bitset of additional accessible states.
254 The states are passed to every created child object
255 (text paragraph). The state values are defined in
256 css::accessibility::AccessibleStateType.
258 This function has to be called before querying for
259 any children (e.g. with GetChild()).
261 void SetAdditionalChildStates(sal_Int64 rChildStates
);
263 /** Update the visible children
265 @attention Might fire state change events, therefore,
266 don't hold any mutex except solar mutex, which you are
267 required to lock before. This method should only be called
268 from the main office thread.
270 This method reevaluates the visibility of all
271 children. Call this method if your visibility state has
272 changed somehow, e.g. if the visible area has changed and
273 the AccessibleTextHelper isn't notified internally
274 (e.g. via SfxHintId::TextViewScrolled). Normally, there should
275 not be a need to call this method.
277 void UpdateChildren();
279 /** Update the selection.
281 @attention Might fire state change events, therefore,
282 don't hold any mutex except solar mutex, which you are
283 required to lock before. This method should only be called
284 from the main office thread.
286 Call this method if the selection has changed and the
287 the AccessibleTextHelper isn't notified internally.
289 void UpdateSelection();
291 /** Drop all references and enter disposed state
293 This method drops all references to external objects (also
294 the event source reference set via SetEventSource()) and
295 sets the object into the disposed state (i.e. the methods
296 return default values or throw a uno::DisposedException
301 /** Set the focus state of the accessibility object
303 Since this class handles children which also might get the
304 focus, the user of this class is encouraged to delegate
305 focus handling. Whenever the focus state of the
306 surrounding object changes, this method has to be called.
308 The protocol of focus handling for a user of this class is
309 then to call SetFocus() with the appropriate focus state,
310 and HaveFocus() to determine the focus state you tell the
313 @attention Might fire state change events, therefore,
314 don't hold any mutex except solar mutex, which you are
315 required to lock before. This method should only be called
316 from the main office thread.
319 Whether we got or we lost the focus. Set to true if
320 focus is gotten, false otherwise.
324 void SetFocus(bool bHaveFocus
= true);
326 /** Query the focus state of the surrounding object
328 If focus handling is delegated to this class, determine
329 focus state with this method. Be prepared that even if you
330 set the focus with SetFocus(true), this method might
331 return false. This is the case if one of the children
332 actually got the focus.
334 @return the state of the focus ownership
338 // XAccessibleContext child handling methods
340 /** Implements getAccessibleChildCount
342 @attention Don't call with locked mutexes. You may hold
343 the solar mutex, but this method acquires it anyway.
345 sal_Int64
GetChildCount() const;
346 /** Implements getAccessibleChild
348 @attention Don't call with locked mutexes. You may hold
349 the solar mutex, but this method acquires it anyway.
351 css::uno::Reference
<css::accessibility::XAccessible
> GetChild(sal_Int64 i
);
353 // XAccessibleEventBroadcaster child related methods
355 /** Implements addEventListener
357 @attention Don't call with locked mutexes
359 void AddEventListener(
360 const css::uno::Reference
<css::accessibility::XAccessibleEventListener
>& xListener
);
361 /** Implements removeEventListener
363 @attention Don't call with locked mutexes
365 void RemoveEventListener(
366 const css::uno::Reference
<css::accessibility::XAccessibleEventListener
>& xListener
);
368 // XAccessibleComponent child related methods
370 /** Implements getAccessibleAt
372 @attention Don't call with locked mutexes. You may hold
373 the solar mutex, but this method acquires it anyway.
375 css::uno::Reference
<css::accessibility::XAccessible
> GetAt(const css::awt::Point
& aPoint
);
379 const std::unique_ptr
<AccessibleTextHelper_Impl
> mpImpl
;
382 } // end of namespace accessibility
384 #endif // INCLUDED_SVX_ACCESSIBLETEXTHELPER_HXX
386 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */