|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #ifndef nsTextControlFrame_h___ |
|
7 #define nsTextControlFrame_h___ |
|
8 |
|
9 #include "mozilla/Attributes.h" |
|
10 #include "nsContainerFrame.h" |
|
11 #include "nsIAnonymousContentCreator.h" |
|
12 #include "nsITextControlFrame.h" |
|
13 #include "nsITextControlElement.h" |
|
14 #include "nsIStatefulFrame.h" |
|
15 |
|
16 class nsISelectionController; |
|
17 class EditorInitializerEntryTracker; |
|
18 class nsTextEditorState; |
|
19 class nsIEditor; |
|
20 namespace mozilla { |
|
21 namespace dom { |
|
22 class Element; |
|
23 } |
|
24 } |
|
25 |
|
26 class nsTextControlFrame : public nsContainerFrame, |
|
27 public nsIAnonymousContentCreator, |
|
28 public nsITextControlFrame, |
|
29 public nsIStatefulFrame |
|
30 { |
|
31 public: |
|
32 NS_DECL_FRAMEARENA_HELPERS |
|
33 |
|
34 NS_DECLARE_FRAME_PROPERTY(ContentScrollPos, DestroyPoint) |
|
35 |
|
36 nsTextControlFrame(nsIPresShell* aShell, nsStyleContext* aContext); |
|
37 virtual ~nsTextControlFrame(); |
|
38 |
|
39 virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE; |
|
40 |
|
41 virtual nsIScrollableFrame* GetScrollTargetFrame() MOZ_OVERRIDE { |
|
42 return do_QueryFrame(GetFirstPrincipalChild()); |
|
43 } |
|
44 |
|
45 virtual nscoord GetMinWidth(nsRenderingContext* aRenderingContext) MOZ_OVERRIDE; |
|
46 virtual nscoord GetPrefWidth(nsRenderingContext* aRenderingContext) MOZ_OVERRIDE; |
|
47 |
|
48 virtual nsSize ComputeAutoSize(nsRenderingContext *aRenderingContext, |
|
49 nsSize aCBSize, nscoord aAvailableWidth, |
|
50 nsSize aMargin, nsSize aBorder, |
|
51 nsSize aPadding, bool aShrinkWrap) MOZ_OVERRIDE; |
|
52 |
|
53 virtual nsresult Reflow(nsPresContext* aPresContext, |
|
54 nsHTMLReflowMetrics& aDesiredSize, |
|
55 const nsHTMLReflowState& aReflowState, |
|
56 nsReflowStatus& aStatus) MOZ_OVERRIDE; |
|
57 |
|
58 virtual nsSize GetMinSize(nsBoxLayoutState& aBoxLayoutState) MOZ_OVERRIDE; |
|
59 virtual bool IsCollapsed() MOZ_OVERRIDE; |
|
60 |
|
61 virtual bool IsLeaf() const MOZ_OVERRIDE; |
|
62 |
|
63 #ifdef ACCESSIBILITY |
|
64 virtual mozilla::a11y::AccType AccessibleType() MOZ_OVERRIDE; |
|
65 #endif |
|
66 |
|
67 #ifdef DEBUG_FRAME_DUMP |
|
68 virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE |
|
69 { |
|
70 aResult.AssignLiteral("nsTextControlFrame"); |
|
71 return NS_OK; |
|
72 } |
|
73 #endif |
|
74 |
|
75 virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE |
|
76 { |
|
77 // nsStackFrame is already both of these, but that's somewhat bogus, |
|
78 // and we really mean it. |
|
79 return nsContainerFrame::IsFrameOfType(aFlags & |
|
80 ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock)); |
|
81 } |
|
82 |
|
83 // nsIAnonymousContentCreator |
|
84 virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) MOZ_OVERRIDE; |
|
85 virtual void AppendAnonymousContentTo(nsBaseContentList& aElements, |
|
86 uint32_t aFilter) MOZ_OVERRIDE; |
|
87 |
|
88 // Utility methods to set current widget state |
|
89 |
|
90 virtual nsresult SetInitialChildList(ChildListID aListID, |
|
91 nsFrameList& aChildList) MOZ_OVERRIDE; |
|
92 |
|
93 virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, |
|
94 const nsRect& aDirtyRect, |
|
95 const nsDisplayListSet& aLists) MOZ_OVERRIDE; |
|
96 |
|
97 virtual mozilla::dom::Element* GetPseudoElement(nsCSSPseudoElements::Type aType) MOZ_OVERRIDE; |
|
98 |
|
99 //==== BEGIN NSIFORMCONTROLFRAME |
|
100 virtual void SetFocus(bool aOn , bool aRepaint) MOZ_OVERRIDE; |
|
101 virtual nsresult SetFormProperty(nsIAtom* aName, const nsAString& aValue) MOZ_OVERRIDE; |
|
102 |
|
103 //==== END NSIFORMCONTROLFRAME |
|
104 |
|
105 //==== NSITEXTCONTROLFRAME |
|
106 |
|
107 NS_IMETHOD GetEditor(nsIEditor **aEditor) MOZ_OVERRIDE; |
|
108 NS_IMETHOD SetSelectionStart(int32_t aSelectionStart) MOZ_OVERRIDE; |
|
109 NS_IMETHOD SetSelectionEnd(int32_t aSelectionEnd) MOZ_OVERRIDE; |
|
110 NS_IMETHOD SetSelectionRange(int32_t aSelectionStart, |
|
111 int32_t aSelectionEnd, |
|
112 SelectionDirection aDirection = eNone) MOZ_OVERRIDE; |
|
113 NS_IMETHOD GetSelectionRange(int32_t* aSelectionStart, |
|
114 int32_t* aSelectionEnd, |
|
115 SelectionDirection* aDirection = nullptr) MOZ_OVERRIDE; |
|
116 NS_IMETHOD GetOwnedSelectionController(nsISelectionController** aSelCon) MOZ_OVERRIDE; |
|
117 virtual nsFrameSelection* GetOwnedFrameSelection() MOZ_OVERRIDE; |
|
118 |
|
119 nsresult GetPhonetic(nsAString& aPhonetic) MOZ_OVERRIDE; |
|
120 |
|
121 /** |
|
122 * Ensure mEditor is initialized with the proper flags and the default value. |
|
123 * @throws NS_ERROR_NOT_INITIALIZED if mEditor has not been created |
|
124 * @throws various and sundry other things |
|
125 */ |
|
126 virtual nsresult EnsureEditorInitialized() MOZ_OVERRIDE; |
|
127 |
|
128 //==== END NSITEXTCONTROLFRAME |
|
129 |
|
130 //==== NSISTATEFULFRAME |
|
131 |
|
132 NS_IMETHOD SaveState(nsPresState** aState) MOZ_OVERRIDE; |
|
133 NS_IMETHOD RestoreState(nsPresState* aState) MOZ_OVERRIDE; |
|
134 |
|
135 //=== END NSISTATEFULFRAME |
|
136 |
|
137 //==== OVERLOAD of nsIFrame |
|
138 virtual nsIAtom* GetType() const MOZ_OVERRIDE; |
|
139 |
|
140 /** handler for attribute changes to mContent */ |
|
141 virtual nsresult AttributeChanged(int32_t aNameSpaceID, |
|
142 nsIAtom* aAttribute, |
|
143 int32_t aModType) MOZ_OVERRIDE; |
|
144 |
|
145 nsresult GetText(nsString& aText); |
|
146 |
|
147 virtual nsresult PeekOffset(nsPeekOffsetStruct *aPos) MOZ_OVERRIDE; |
|
148 |
|
149 NS_DECL_QUERYFRAME |
|
150 |
|
151 // Temp reference to scriptrunner |
|
152 // We could make these auto-Revoking via the "delete" entry for safety |
|
153 NS_DECLARE_FRAME_PROPERTY(TextControlInitializer, nullptr) |
|
154 |
|
155 protected: |
|
156 /** |
|
157 * Launch the reflow on the child frames - see nsTextControlFrame::Reflow() |
|
158 */ |
|
159 void ReflowTextControlChild(nsIFrame* aFrame, |
|
160 nsPresContext* aPresContext, |
|
161 const nsHTMLReflowState& aReflowState, |
|
162 nsReflowStatus& aStatus, |
|
163 nsHTMLReflowMetrics& aParentDesiredSize); |
|
164 |
|
165 public: //for methods who access nsTextControlFrame directly |
|
166 void SetValueChanged(bool aValueChanged); |
|
167 |
|
168 // called by the focus listener |
|
169 nsresult MaybeBeginSecureKeyboardInput(); |
|
170 void MaybeEndSecureKeyboardInput(); |
|
171 |
|
172 #define DEFINE_TEXTCTRL_FORWARDER(type, name) \ |
|
173 type name() { \ |
|
174 nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent()); \ |
|
175 NS_ASSERTION(txtCtrl, "Content not a text control element"); \ |
|
176 return txtCtrl->name(); \ |
|
177 } |
|
178 #define DEFINE_TEXTCTRL_CONST_FORWARDER(type, name) \ |
|
179 type name() const { \ |
|
180 nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent()); \ |
|
181 NS_ASSERTION(txtCtrl, "Content not a text control element"); \ |
|
182 return txtCtrl->name(); \ |
|
183 } |
|
184 |
|
185 DEFINE_TEXTCTRL_CONST_FORWARDER(bool, IsSingleLineTextControl) |
|
186 DEFINE_TEXTCTRL_CONST_FORWARDER(bool, IsTextArea) |
|
187 DEFINE_TEXTCTRL_CONST_FORWARDER(bool, IsPlainTextControl) |
|
188 DEFINE_TEXTCTRL_CONST_FORWARDER(bool, IsPasswordTextControl) |
|
189 DEFINE_TEXTCTRL_FORWARDER(int32_t, GetCols) |
|
190 DEFINE_TEXTCTRL_FORWARDER(int32_t, GetWrapCols) |
|
191 DEFINE_TEXTCTRL_FORWARDER(int32_t, GetRows) |
|
192 |
|
193 #undef DEFINE_TEXTCTRL_CONST_FORWARDER |
|
194 #undef DEFINE_TEXTCTRL_FORWARDER |
|
195 |
|
196 protected: |
|
197 class EditorInitializer; |
|
198 friend class EditorInitializer; |
|
199 friend class nsTextEditorState; // needs access to UpdateValueDisplay |
|
200 |
|
201 class EditorInitializer : public nsRunnable { |
|
202 public: |
|
203 EditorInitializer(nsTextControlFrame* aFrame) : |
|
204 mFrame(aFrame) {} |
|
205 |
|
206 NS_IMETHOD Run() MOZ_OVERRIDE; |
|
207 |
|
208 // avoids use of nsWeakFrame |
|
209 void Revoke() { |
|
210 mFrame = nullptr; |
|
211 } |
|
212 |
|
213 private: |
|
214 nsTextControlFrame* mFrame; |
|
215 }; |
|
216 |
|
217 class ScrollOnFocusEvent; |
|
218 friend class ScrollOnFocusEvent; |
|
219 |
|
220 class ScrollOnFocusEvent : public nsRunnable { |
|
221 public: |
|
222 ScrollOnFocusEvent(nsTextControlFrame* aFrame) : |
|
223 mFrame(aFrame) {} |
|
224 |
|
225 NS_DECL_NSIRUNNABLE |
|
226 |
|
227 void Revoke() { |
|
228 mFrame = nullptr; |
|
229 } |
|
230 |
|
231 private: |
|
232 nsTextControlFrame* mFrame; |
|
233 }; |
|
234 |
|
235 nsresult OffsetToDOMPoint(int32_t aOffset, nsIDOMNode** aResult, int32_t* aPosition); |
|
236 |
|
237 /** |
|
238 * Update the textnode under our anonymous div to show the new |
|
239 * value. This should only be called when we have no editor yet. |
|
240 * @throws NS_ERROR_UNEXPECTED if the div has no text content |
|
241 */ |
|
242 nsresult UpdateValueDisplay(bool aNotify, |
|
243 bool aBeforeEditorInit = false, |
|
244 const nsAString *aValue = nullptr); |
|
245 |
|
246 /** |
|
247 * Get the maxlength attribute |
|
248 * @param aMaxLength the value of the max length attr |
|
249 * @returns false if attr not defined |
|
250 */ |
|
251 bool GetMaxLength(int32_t* aMaxLength); |
|
252 |
|
253 /** |
|
254 * Find out whether an attribute exists on the content or not. |
|
255 * @param aAtt the attribute to determine the existence of |
|
256 * @returns false if it does not exist |
|
257 */ |
|
258 bool AttributeExists(nsIAtom *aAtt) const |
|
259 { return mContent && mContent->HasAttr(kNameSpaceID_None, aAtt); } |
|
260 |
|
261 /** |
|
262 * We call this when we are being destroyed or removed from the PFM. |
|
263 * @param aPresContext the current pres context |
|
264 */ |
|
265 void PreDestroy(); |
|
266 |
|
267 // Compute our intrinsic size. This does not include any borders, paddings, |
|
268 // etc. Just the size of our actual area for the text (and the scrollbars, |
|
269 // for <textarea>). |
|
270 nsresult CalcIntrinsicSize(nsRenderingContext* aRenderingContext, |
|
271 nsSize& aIntrinsicSize, |
|
272 float aFontSizeInflation); |
|
273 |
|
274 nsresult ScrollSelectionIntoView() MOZ_OVERRIDE; |
|
275 |
|
276 private: |
|
277 //helper methods |
|
278 nsresult SetSelectionInternal(nsIDOMNode *aStartNode, int32_t aStartOffset, |
|
279 nsIDOMNode *aEndNode, int32_t aEndOffset, |
|
280 SelectionDirection aDirection = eNone); |
|
281 nsresult SelectAllOrCollapseToEndOfText(bool aSelect); |
|
282 nsresult SetSelectionEndPoints(int32_t aSelStart, int32_t aSelEnd, |
|
283 SelectionDirection aDirection = eNone); |
|
284 |
|
285 /** |
|
286 * Return the root DOM element, and implicitly initialize the editor if needed. |
|
287 */ |
|
288 mozilla::dom::Element* GetRootNodeAndInitializeEditor(); |
|
289 nsresult GetRootNodeAndInitializeEditor(nsIDOMElement **aRootElement); |
|
290 |
|
291 void FinishedInitializer() { |
|
292 Properties().Delete(TextControlInitializer()); |
|
293 } |
|
294 |
|
295 private: |
|
296 // these packed bools could instead use the high order bits on mState, saving 4 bytes |
|
297 bool mEditorHasBeenInitialized; |
|
298 bool mIsProcessing; |
|
299 // Keep track if we have asked a placeholder node creation. |
|
300 bool mUsePlaceholder; |
|
301 |
|
302 #ifdef DEBUG |
|
303 bool mInEditorInitialization; |
|
304 friend class EditorInitializerEntryTracker; |
|
305 #endif |
|
306 |
|
307 nsRevocableEventPtr<ScrollOnFocusEvent> mScrollEvent; |
|
308 }; |
|
309 |
|
310 #endif |
|
311 |
|
312 |