Bumping gaia.json for 8 gaia revision(s) a=gaia-bump
[gecko.git] / dom / html / nsTextEditorState.h
blob3e4f99292f6823e3b3f98755e636318574e601fa
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 ts=2 et tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef nsTextEditorState_h__
8 #define nsTextEditorState_h__
10 #include "nsAutoPtr.h"
11 #include "nsString.h"
12 #include "nsITextControlElement.h"
13 #include "nsITextControlFrame.h"
14 #include "nsCycleCollectionParticipant.h"
15 #include "mozilla/dom/Element.h"
16 #include "mozilla/WeakPtr.h"
18 class nsTextInputListener;
19 class nsTextControlFrame;
20 class nsTextInputSelectionImpl;
21 class nsAnonDivObserver;
22 class nsISelectionController;
23 class nsFrameSelection;
24 class nsIEditor;
25 class nsITextControlElement;
26 class nsFrame;
28 namespace mozilla {
29 namespace dom {
30 class HTMLInputElement;
34 /**
35 * nsTextEditorState is a class which is responsible for managing the state of
36 * plaintext controls. This currently includes the following HTML elements:
37 * <input type=text>
38 * <input type=password>
39 * <textarea>
40 * and also XUL controls such as <textbox> which use one of these elements behind
41 * the scenes.
43 * This class is held as a member of HTMLInputElement and nsHTMLTextAreaElement.
44 * The public functions in this class include the public APIs which content/ uses.
45 * Layout code uses the nsITextControlElement interface to invoke functions on this
46 * class.
48 * The design motivation behind this class is maintaining all of the things which
49 * collectively are considered the "state" of the text control in a single location.
50 * This state includes several things:
52 * * The control's value. This value is stored in the mValue member, and is only
53 * used when there is no frame for the control, or when the editor object has
54 * not been initialized yet.
56 * * The control's associated frame. This value is stored in the mBoundFrame member.
57 * A text control might never have an associated frame during its life cycle,
58 * or might have several different ones, but at any given moment in time there is
59 * a maximum of 1 bound frame to each text control.
61 * * The control's associated editor. This value is stored in the mEditor member.
62 * An editor is initilized for the control only when necessary (that is, when either
63 * the user is about to interact with the text control, or when some other code
64 * needs to access the editor object. Without a frame bound to the control, an
65 * editor is never initialzied. Once initialized, the editor might outlive the frame,
66 * in which case the same editor will be used if a new frame gets bound to the
67 * text control.
69 * * The anonymous content associated with the text control's frame, including the
70 * value div (the DIV element responsible for holding the value of the text control)
71 * and the placeholder div (the DIV element responsible for holding the placeholder
72 * value of the text control.) These values are stored in the mRootNode and
73 * mPlaceholderDiv members, respectively. They will be created when a
74 * frame is bound to the text control. They will be destroyed when the frame is
75 * unbound from the object. We could try and hold on to the anonymous content
76 * between different frames, but unfortunately that is not currently possible
77 * because they are not unbound from the document in time.
79 * * The frame selection controller. This value is stored in the mSelCon member.
80 * The frame selection controller is responsible for maintaining the selection state
81 * on a frame. It is created when a frame is bound to the text control element,
82 * and will be destroy when the frame is being unbound from the text control element.
83 * It is created alongside with the frame selection object which is stored in the
84 * mFrameSel member.
86 * * The editor text listener. This value is stored in the mTextListener member.
87 * Its job is to listen to selection and keyboard events, and act accordingly.
88 * It is created when an a frame is first bound to the control, and will be destroyed
89 * when the frame is unbound from the text control element.
91 * * The editor's cached value. This value is stored in the mCachedValue member.
92 * It is used to improve the performance of append operations to the text
93 * control. A mutation observer stored in the mMutationObserver has the job of
94 * invalidating this cache when the anonymous contect containing the value is
95 * changed.
97 * * The editor's cached selection properties. These vales are stored in the
98 * mSelectionProperties member, and include the selection's start, end and
99 * direction. They are only used when there is no frame available for the
100 * text field.
103 * As a general rule, nsTextEditorState objects own the value of the text control, and any
104 * attempt to retrieve or set the value must be made through those objects. Internally,
105 * the value can be represented in several different ways, based on the state the control is
106 * in.
108 * * When the control is first initialized, its value is equal to the default value of
109 * the DOM node. For <input> text controls, this default value is the value of the
110 * value attribute. For <textarea> elements, this default value is the value of the
111 * text node children of the element.
113 * * If the value has been changed through the DOM node (before the editor for the object
114 * is initialized), the value is stored as a simple string inside the mValue member of
115 * the nsTextEditorState object.
117 * * If an editor has been initialized for the control, the value is set and retrievd via
118 * the nsIPlaintextEditor interface, and is internally managed by the editor as the
119 * native anonymous content tree attached to the control's frame.
121 * * If the text editor state object is unbound from the control's frame, the value is
122 * transferred to the mValue member variable, and will be managed there until a new
123 * frame is bound to the text editor state object.
126 class RestoreSelectionState;
128 class nsTextEditorState : public mozilla::SupportsWeakPtr<nsTextEditorState> {
129 public:
130 MOZ_DECLARE_REFCOUNTED_TYPENAME(nsTextEditorState)
131 explicit nsTextEditorState(nsITextControlElement* aOwningElement);
132 ~nsTextEditorState();
134 void Traverse(nsCycleCollectionTraversalCallback& cb);
135 void Unlink();
137 nsIEditor* GetEditor();
138 nsISelectionController* GetSelectionController() const;
139 nsFrameSelection* GetConstFrameSelection();
140 nsresult BindToFrame(nsTextControlFrame* aFrame);
141 void UnbindFromFrame(nsTextControlFrame* aFrame);
142 nsresult PrepareEditor(const nsAString *aValue = nullptr);
143 void InitializeKeyboardEventListeners();
145 void SetValue(const nsAString& aValue, bool aUserInput,
146 bool aSetValueAsChanged);
147 void GetValue(nsAString& aValue, bool aIgnoreWrap) const;
148 void EmptyValue() { if (mValue) mValue->Truncate(); }
149 bool IsEmpty() const { return mValue ? mValue->IsEmpty() : true; }
151 nsresult CreatePlaceholderNode();
153 mozilla::dom::Element* GetRootNode() {
154 if (!mRootNode)
155 CreateRootNode();
156 return mRootNode;
158 mozilla::dom::Element* GetPlaceholderNode() {
159 return mPlaceholderDiv;
162 bool IsSingleLineTextControl() const {
163 return mTextCtrlElement->IsSingleLineTextControl();
165 bool IsTextArea() const {
166 return mTextCtrlElement->IsTextArea();
168 bool IsPlainTextControl() const {
169 return mTextCtrlElement->IsPlainTextControl();
171 bool IsPasswordTextControl() const {
172 return mTextCtrlElement->IsPasswordTextControl();
174 int32_t GetCols() {
175 return mTextCtrlElement->GetCols();
177 int32_t GetWrapCols() {
178 return mTextCtrlElement->GetWrapCols();
180 int32_t GetRows() {
181 return mTextCtrlElement->GetRows();
184 // placeholder methods
185 void UpdatePlaceholderVisibility(bool aNotify);
186 bool GetPlaceholderVisibility() {
187 return mPlaceholderVisibility;
189 void UpdatePlaceholderText(bool aNotify);
192 * Get the maxlength attribute
193 * @param aMaxLength the value of the max length attr
194 * @returns false if attr not defined
196 bool GetMaxLength(int32_t* aMaxLength);
198 void ClearValueCache() { mCachedValue.Truncate(); }
200 void HideSelectionIfBlurred();
202 struct SelectionProperties {
203 SelectionProperties() : mStart(0), mEnd(0),
204 mDirection(nsITextControlFrame::eForward) {}
205 bool IsDefault() const {
206 return mStart == 0 && mEnd == 0 &&
207 mDirection == nsITextControlFrame::eForward;
209 int32_t mStart, mEnd;
210 nsITextControlFrame::SelectionDirection mDirection;
213 bool IsSelectionCached() const;
214 SelectionProperties& GetSelectionProperties();
215 void WillInitEagerly() { mSelectionRestoreEagerInit = true; }
216 bool HasNeverInitializedBefore() const { return !mEverInited; }
218 void UpdateEditableState(bool aNotify) {
219 if (mRootNode) {
220 mRootNode->UpdateEditableState(aNotify);
224 private:
225 friend class RestoreSelectionState;
227 // not copy constructible
228 nsTextEditorState(const nsTextEditorState&);
229 // not assignable
230 void operator= (const nsTextEditorState&);
232 nsresult CreateRootNode();
234 void ValueWasChanged(bool aNotify);
236 void DestroyEditor();
237 void Clear();
239 nsresult InitializeRootNode();
241 void FinishedRestoringSelection() { mRestoringSelection = nullptr; }
243 mozilla::dom::HTMLInputElement* GetParentNumberControl(nsFrame* aFrame) const;
245 class InitializationGuard {
246 public:
247 explicit InitializationGuard(nsTextEditorState& aState) :
248 mState(aState),
249 mGuardSet(false)
251 if (!mState.mInitializing) {
252 mGuardSet = true;
253 mState.mInitializing = true;
256 ~InitializationGuard() {
257 if (mGuardSet) {
258 mState.mInitializing = false;
261 bool IsInitializingRecursively() const {
262 return !mGuardSet;
264 private:
265 nsTextEditorState& mState;
266 bool mGuardSet;
268 friend class InitializationGuard;
269 friend class PrepareEditorEvent;
271 nsITextControlElement* const mTextCtrlElement;
272 nsRefPtr<nsTextInputSelectionImpl> mSelCon;
273 RestoreSelectionState* mRestoringSelection;
274 nsCOMPtr<nsIEditor> mEditor;
275 nsCOMPtr<mozilla::dom::Element> mRootNode;
276 nsCOMPtr<mozilla::dom::Element> mPlaceholderDiv;
277 nsTextControlFrame* mBoundFrame;
278 nsTextInputListener* mTextListener;
279 nsAutoPtr<nsCString> mValue;
280 nsRefPtr<nsAnonDivObserver> mMutationObserver;
281 mutable nsString mCachedValue; // Caches non-hard-wrapped value on a multiline control.
282 bool mEverInited; // Have we ever been initialized?
283 bool mEditorInitialized;
284 bool mInitializing; // Whether we're in the process of initialization
285 bool mValueTransferInProgress; // Whether a value is being transferred to the frame
286 bool mSelectionCached; // Whether mSelectionProperties is valid
287 mutable bool mSelectionRestoreEagerInit; // Whether we're eager initing because of selection restore
288 SelectionProperties mSelectionProperties;
289 bool mPlaceholderVisibility;
292 inline void
293 ImplCycleCollectionUnlink(nsTextEditorState& aField)
295 aField.Unlink();
298 inline void
299 ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
300 nsTextEditorState& aField,
301 const char* aName,
302 uint32_t aFlags = 0)
304 aField.Traverse(aCallback);
307 #endif