Line data Source code
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 nsNumberControlFrame_h__
7 : #define nsNumberControlFrame_h__
8 :
9 : #include "mozilla/Attributes.h"
10 : #include "nsContainerFrame.h"
11 : #include "nsIFormControlFrame.h"
12 : #include "nsIAnonymousContentCreator.h"
13 : #include "nsCOMPtr.h"
14 :
15 : class nsITextControlFrame;
16 : class nsPresContext;
17 :
18 : namespace mozilla {
19 : enum class CSSPseudoElementType : uint8_t;
20 : class WidgetEvent;
21 : class WidgetGUIEvent;
22 : namespace dom {
23 : class HTMLInputElement;
24 : } // namespace dom
25 : } // namespace mozilla
26 :
27 : /**
28 : * This frame type is used for <input type=number>.
29 : */
30 0 : class nsNumberControlFrame final : public nsContainerFrame
31 : , public nsIAnonymousContentCreator
32 : , public nsIFormControlFrame
33 : {
34 : friend nsIFrame*
35 : NS_NewNumberControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
36 :
37 : typedef mozilla::CSSPseudoElementType CSSPseudoElementType;
38 : typedef mozilla::dom::Element Element;
39 : typedef mozilla::dom::HTMLInputElement HTMLInputElement;
40 : typedef mozilla::WidgetEvent WidgetEvent;
41 : typedef mozilla::WidgetGUIEvent WidgetGUIEvent;
42 :
43 : explicit nsNumberControlFrame(nsStyleContext* aContext);
44 :
45 : public:
46 : NS_DECL_QUERYFRAME
47 0 : NS_DECL_FRAMEARENA_HELPERS(nsNumberControlFrame)
48 :
49 : virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
50 : virtual void ContentStatesChanged(mozilla::EventStates aStates) override;
51 :
52 : #ifdef ACCESSIBILITY
53 : virtual mozilla::a11y::AccType AccessibleType() override;
54 : #endif
55 :
56 : virtual nscoord GetMinISize(gfxContext* aRenderingContext) override;
57 :
58 : virtual nscoord GetPrefISize(gfxContext* aRenderingContext) override;
59 :
60 : virtual void Reflow(nsPresContext* aPresContext,
61 : ReflowOutput& aDesiredSize,
62 : const ReflowInput& aReflowInput,
63 : nsReflowStatus& aStatus) override;
64 :
65 : virtual nsresult AttributeChanged(int32_t aNameSpaceID,
66 : nsIAtom* aAttribute,
67 : int32_t aModType) override;
68 :
69 : // nsIAnonymousContentCreator
70 : virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) override;
71 : virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
72 : uint32_t aFilter) override;
73 :
74 : #ifdef DEBUG_FRAME_DUMP
75 0 : virtual nsresult GetFrameName(nsAString& aResult) const override {
76 0 : return MakeFrameName(NS_LITERAL_STRING("NumberControl"), aResult);
77 : }
78 : #endif
79 :
80 0 : virtual bool IsFrameOfType(uint32_t aFlags) const override
81 : {
82 0 : return nsContainerFrame::IsFrameOfType(aFlags &
83 0 : ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
84 : }
85 :
86 : // nsIFormControlFrame
87 : virtual void SetFocus(bool aOn, bool aRepaint) override;
88 : virtual nsresult SetFormProperty(nsIAtom* aName, const nsAString& aValue) override;
89 :
90 : /**
91 : * This method attempts to localizes aValue and then sets the result as the
92 : * value of our anonymous text control. It's called when our
93 : * HTMLInputElement's value changes, when we need to sync up the value
94 : * displayed in our anonymous text control.
95 : */
96 : void SetValueOfAnonTextControl(const nsAString& aValue);
97 :
98 : /**
99 : * This method gets the string value of our anonymous text control,
100 : * attempts to normalizes (de-localizes) it, then sets the outparam aValue to
101 : * the result. It's called when user input changes the text value of our
102 : * anonymous text control so that we can sync up the internal value of our
103 : * HTMLInputElement.
104 : */
105 : void GetValueOfAnonTextControl(nsAString& aValue);
106 :
107 : bool AnonTextControlIsEmpty();
108 :
109 : /**
110 : * Called to notify this frame that its HTMLInputElement is currently
111 : * processing a DOM 'input' event.
112 : */
113 0 : void HandlingInputEvent(bool aHandlingEvent)
114 : {
115 0 : mHandlingInputEvent = aHandlingEvent;
116 0 : }
117 :
118 : HTMLInputElement* GetAnonTextControl();
119 :
120 : /**
121 : * If the frame is the frame for an nsNumberControlFrame's anonymous text
122 : * field, returns the nsNumberControlFrame. Else returns nullptr.
123 : */
124 : static nsNumberControlFrame* GetNumberControlFrameForTextField(nsIFrame* aFrame);
125 :
126 : /**
127 : * If the frame is the frame for an nsNumberControlFrame's up or down spin
128 : * button, returns the nsNumberControlFrame. Else returns nullptr.
129 : */
130 : static nsNumberControlFrame* GetNumberControlFrameForSpinButton(nsIFrame* aFrame);
131 :
132 : enum SpinButtonEnum {
133 : eSpinButtonNone,
134 : eSpinButtonUp,
135 : eSpinButtonDown
136 : };
137 :
138 : /**
139 : * Returns one of the SpinButtonEnum values to depending on whether the
140 : * pointer event is over the spin-up button, the spin-down button, or
141 : * neither.
142 : */
143 : int32_t GetSpinButtonForPointerEvent(WidgetGUIEvent* aEvent) const;
144 :
145 : void SpinnerStateChanged() const;
146 :
147 : bool SpinnerUpButtonIsDepressed() const;
148 : bool SpinnerDownButtonIsDepressed() const;
149 :
150 : bool IsFocused() const;
151 :
152 : void HandleFocusEvent(WidgetEvent* aEvent);
153 :
154 : /**
155 : * Our element had HTMLInputElement::Select() called on it.
156 : */
157 : nsresult HandleSelectCall();
158 :
159 : virtual Element* GetPseudoElement(CSSPseudoElementType aType) override;
160 :
161 : bool ShouldUseNativeStyleForSpinner() const;
162 :
163 : private:
164 :
165 : nsITextControlFrame* GetTextFieldFrame();
166 : nsresult MakeAnonymousElement(Element** aResult,
167 : nsTArray<ContentInfo>& aElements,
168 : nsIAtom* aTagName,
169 : CSSPseudoElementType aPseudoType);
170 :
171 : class SyncDisabledStateEvent;
172 : friend class SyncDisabledStateEvent;
173 0 : class SyncDisabledStateEvent : public mozilla::Runnable
174 : {
175 : public:
176 0 : explicit SyncDisabledStateEvent(nsNumberControlFrame* aFrame)
177 0 : : mozilla::Runnable("nsNumberControlFrame::SyncDisabledStateEvent")
178 0 : , mFrame(aFrame)
179 0 : {}
180 :
181 0 : NS_IMETHOD Run() override
182 : {
183 : nsNumberControlFrame* frame =
184 0 : static_cast<nsNumberControlFrame*>(mFrame.GetFrame());
185 0 : NS_ENSURE_STATE(frame);
186 :
187 0 : frame->SyncDisabledState();
188 0 : return NS_OK;
189 : }
190 :
191 : private:
192 : WeakFrame mFrame;
193 : };
194 :
195 : /**
196 : * Sync the disabled state of the anonymous children up with our content's.
197 : */
198 : void SyncDisabledState();
199 :
200 : /**
201 : * The text field used to edit and show the number.
202 : * @see nsNumberControlFrame::CreateAnonymousContent.
203 : */
204 : nsCOMPtr<Element> mOuterWrapper;
205 : nsCOMPtr<Element> mTextField;
206 : nsCOMPtr<Element> mSpinBox;
207 : nsCOMPtr<Element> mSpinUp;
208 : nsCOMPtr<Element> mSpinDown;
209 : bool mHandlingInputEvent;
210 : };
211 :
212 : #endif // nsNumberControlFrame_h__
|