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__