michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef nsNumberControlFrame_h__ michael@0: #define nsNumberControlFrame_h__ michael@0: michael@0: #include "mozilla/Attributes.h" michael@0: #include "nsContainerFrame.h" michael@0: #include "nsIFormControlFrame.h" michael@0: #include "nsITextControlFrame.h" michael@0: #include "nsIAnonymousContentCreator.h" michael@0: #include "nsCOMPtr.h" michael@0: michael@0: class nsPresContext; michael@0: michael@0: namespace mozilla { michael@0: class WidgetEvent; michael@0: class WidgetGUIEvent; michael@0: namespace dom { michael@0: class HTMLInputElement; michael@0: } michael@0: } michael@0: michael@0: /** michael@0: * This frame type is used for . michael@0: */ michael@0: class nsNumberControlFrame MOZ_FINAL : public nsContainerFrame michael@0: , public nsIAnonymousContentCreator michael@0: , public nsITextControlFrame michael@0: { michael@0: friend nsIFrame* michael@0: NS_NewNumberControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); michael@0: michael@0: typedef mozilla::dom::Element Element; michael@0: typedef mozilla::dom::HTMLInputElement HTMLInputElement; michael@0: typedef mozilla::WidgetEvent WidgetEvent; michael@0: typedef mozilla::WidgetGUIEvent WidgetGUIEvent; michael@0: michael@0: nsNumberControlFrame(nsStyleContext* aContext); michael@0: michael@0: public: michael@0: NS_DECL_QUERYFRAME_TARGET(nsNumberControlFrame) michael@0: NS_DECL_QUERYFRAME michael@0: NS_DECL_FRAMEARENA_HELPERS michael@0: michael@0: virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE; michael@0: virtual void ContentStatesChanged(mozilla::EventStates aStates) MOZ_OVERRIDE; michael@0: virtual bool IsLeaf() const MOZ_OVERRIDE { return true; } michael@0: michael@0: #ifdef ACCESSIBILITY michael@0: virtual mozilla::a11y::AccType AccessibleType() MOZ_OVERRIDE; michael@0: #endif michael@0: michael@0: virtual nscoord GetMinWidth(nsRenderingContext* aRenderingContext) MOZ_OVERRIDE; michael@0: michael@0: virtual nscoord GetPrefWidth(nsRenderingContext* aRenderingContext) MOZ_OVERRIDE; michael@0: michael@0: virtual nsresult Reflow(nsPresContext* aPresContext, michael@0: nsHTMLReflowMetrics& aDesiredSize, michael@0: const nsHTMLReflowState& aReflowState, michael@0: nsReflowStatus& aStatus) MOZ_OVERRIDE; michael@0: michael@0: virtual nsresult AttributeChanged(int32_t aNameSpaceID, michael@0: nsIAtom* aAttribute, michael@0: int32_t aModType) MOZ_OVERRIDE; michael@0: michael@0: // nsIAnonymousContentCreator michael@0: virtual nsresult CreateAnonymousContent(nsTArray& aElements) MOZ_OVERRIDE; michael@0: virtual void AppendAnonymousContentTo(nsBaseContentList& aElements, michael@0: uint32_t aFilter) MOZ_OVERRIDE; michael@0: michael@0: #ifdef DEBUG_FRAME_DUMP michael@0: virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE { michael@0: return MakeFrameName(NS_LITERAL_STRING("NumberControl"), aResult); michael@0: } michael@0: #endif michael@0: michael@0: virtual nsIAtom* GetType() const MOZ_OVERRIDE; michael@0: michael@0: virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE michael@0: { michael@0: return nsContainerFrame::IsFrameOfType(aFlags & michael@0: ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock)); michael@0: } michael@0: michael@0: // nsITextControlFrame michael@0: NS_IMETHOD GetEditor(nsIEditor **aEditor) MOZ_OVERRIDE; michael@0: michael@0: NS_IMETHOD SetSelectionStart(int32_t aSelectionStart) MOZ_OVERRIDE; michael@0: NS_IMETHOD SetSelectionEnd(int32_t aSelectionEnd) MOZ_OVERRIDE; michael@0: michael@0: NS_IMETHOD SetSelectionRange(int32_t aSelectionStart, michael@0: int32_t aSelectionEnd, michael@0: SelectionDirection aDirection = eNone) MOZ_OVERRIDE; michael@0: michael@0: NS_IMETHOD GetSelectionRange(int32_t* aSelectionStart, michael@0: int32_t* aSelectionEnd, michael@0: SelectionDirection* aDirection = nullptr) MOZ_OVERRIDE; michael@0: michael@0: NS_IMETHOD GetOwnedSelectionController(nsISelectionController** aSelCon) MOZ_OVERRIDE; michael@0: virtual nsFrameSelection* GetOwnedFrameSelection() MOZ_OVERRIDE; michael@0: michael@0: virtual nsresult GetPhonetic(nsAString& aPhonetic) MOZ_OVERRIDE; michael@0: michael@0: /** michael@0: * Ensure mEditor is initialized with the proper flags and the default value. michael@0: * @throws NS_ERROR_NOT_INITIALIZED if mEditor has not been created michael@0: * @throws various and sundry other things michael@0: */ michael@0: virtual nsresult EnsureEditorInitialized() MOZ_OVERRIDE; michael@0: michael@0: virtual nsresult ScrollSelectionIntoView() MOZ_OVERRIDE; michael@0: michael@0: // nsIFormControlFrame michael@0: virtual void SetFocus(bool aOn, bool aRepaint) MOZ_OVERRIDE; michael@0: virtual nsresult SetFormProperty(nsIAtom* aName, const nsAString& aValue) MOZ_OVERRIDE; michael@0: michael@0: /** michael@0: * This method attempts to localizes aValue and then sets the result as the michael@0: * value of our anonymous text control. It's called when our michael@0: * HTMLInputElement's value changes, when we need to sync up the value michael@0: * displayed in our anonymous text control. michael@0: */ michael@0: void SetValueOfAnonTextControl(const nsAString& aValue); michael@0: michael@0: /** michael@0: * This method gets the string value of our anonymous text control, michael@0: * attempts to normalizes (de-localizes) it, then sets the outparam aValue to michael@0: * the result. It's called when user input changes the text value of our michael@0: * anonymous text control so that we can sync up the internal value of our michael@0: * HTMLInputElement. michael@0: */ michael@0: void GetValueOfAnonTextControl(nsAString& aValue); michael@0: michael@0: bool AnonTextControlIsEmpty(); michael@0: michael@0: /** michael@0: * Called to notify this frame that its HTMLInputElement is currently michael@0: * processing a DOM 'input' event. michael@0: */ michael@0: void HandlingInputEvent(bool aHandlingEvent) michael@0: { michael@0: mHandlingInputEvent = aHandlingEvent; michael@0: } michael@0: michael@0: HTMLInputElement* GetAnonTextControl(); michael@0: michael@0: /** michael@0: * If the frame is the frame for an nsNumberControlFrame's anonymous text michael@0: * field, returns the nsNumberControlFrame. Else returns nullptr. michael@0: */ michael@0: static nsNumberControlFrame* GetNumberControlFrameForTextField(nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * If the frame is the frame for an nsNumberControlFrame's up or down spin michael@0: * button, returns the nsNumberControlFrame. Else returns nullptr. michael@0: */ michael@0: static nsNumberControlFrame* GetNumberControlFrameForSpinButton(nsIFrame* aFrame); michael@0: michael@0: enum SpinButtonEnum { michael@0: eSpinButtonNone, michael@0: eSpinButtonUp, michael@0: eSpinButtonDown michael@0: }; michael@0: michael@0: /** michael@0: * Returns one of the SpinButtonEnum values to depending on whether the michael@0: * pointer event is over the spin-up button, the spin-down button, or michael@0: * neither. michael@0: */ michael@0: int32_t GetSpinButtonForPointerEvent(WidgetGUIEvent* aEvent) const; michael@0: michael@0: void SpinnerStateChanged() const; michael@0: michael@0: bool SpinnerUpButtonIsDepressed() const; michael@0: bool SpinnerDownButtonIsDepressed() const; michael@0: michael@0: bool IsFocused() const; michael@0: michael@0: void HandleFocusEvent(WidgetEvent* aEvent); michael@0: michael@0: /** michael@0: * Our element had HTMLInputElement::Select() called on it. michael@0: */ michael@0: nsresult HandleSelectCall(); michael@0: michael@0: virtual Element* GetPseudoElement(nsCSSPseudoElements::Type aType) MOZ_OVERRIDE; michael@0: michael@0: bool ShouldUseNativeStyleForSpinner() const; michael@0: michael@0: private: michael@0: michael@0: nsITextControlFrame* GetTextFieldFrame(); michael@0: nsresult MakeAnonymousElement(Element** aResult, michael@0: nsTArray& aElements, michael@0: nsIAtom* aTagName, michael@0: nsCSSPseudoElements::Type aPseudoType, michael@0: nsStyleContext* aParentContext); michael@0: michael@0: class SyncDisabledStateEvent; michael@0: friend class SyncDisabledStateEvent; michael@0: class SyncDisabledStateEvent : public nsRunnable michael@0: { michael@0: public: michael@0: SyncDisabledStateEvent(nsNumberControlFrame* aFrame) michael@0: : mFrame(aFrame) michael@0: {} michael@0: michael@0: NS_IMETHOD Run() MOZ_OVERRIDE michael@0: { michael@0: nsNumberControlFrame* frame = michael@0: static_cast(mFrame.GetFrame()); michael@0: NS_ENSURE_STATE(frame); michael@0: michael@0: frame->SyncDisabledState(); michael@0: return NS_OK; michael@0: } michael@0: michael@0: private: michael@0: nsWeakFrame mFrame; michael@0: }; michael@0: michael@0: /** michael@0: * Sync the disabled state of the anonymous children up with our content's. michael@0: */ michael@0: void SyncDisabledState(); michael@0: michael@0: /** michael@0: * The text field used to edit and show the number. michael@0: * @see nsNumberControlFrame::CreateAnonymousContent. michael@0: */ michael@0: nsCOMPtr mOuterWrapper; michael@0: nsCOMPtr mTextField; michael@0: nsCOMPtr mSpinBox; michael@0: nsCOMPtr mSpinUp; michael@0: nsCOMPtr mSpinDown; michael@0: bool mHandlingInputEvent; michael@0: }; michael@0: michael@0: #endif // nsNumberControlFrame_h__