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 nsTextControlFrame_h___ michael@0: #define nsTextControlFrame_h___ michael@0: michael@0: #include "mozilla/Attributes.h" michael@0: #include "nsContainerFrame.h" michael@0: #include "nsIAnonymousContentCreator.h" michael@0: #include "nsITextControlFrame.h" michael@0: #include "nsITextControlElement.h" michael@0: #include "nsIStatefulFrame.h" michael@0: michael@0: class nsISelectionController; michael@0: class EditorInitializerEntryTracker; michael@0: class nsTextEditorState; michael@0: class nsIEditor; michael@0: namespace mozilla { michael@0: namespace dom { michael@0: class Element; michael@0: } michael@0: } michael@0: michael@0: class nsTextControlFrame : public nsContainerFrame, michael@0: public nsIAnonymousContentCreator, michael@0: public nsITextControlFrame, michael@0: public nsIStatefulFrame michael@0: { michael@0: public: michael@0: NS_DECL_FRAMEARENA_HELPERS michael@0: michael@0: NS_DECLARE_FRAME_PROPERTY(ContentScrollPos, DestroyPoint) michael@0: michael@0: nsTextControlFrame(nsIPresShell* aShell, nsStyleContext* aContext); michael@0: virtual ~nsTextControlFrame(); michael@0: michael@0: virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE; michael@0: michael@0: virtual nsIScrollableFrame* GetScrollTargetFrame() MOZ_OVERRIDE { michael@0: return do_QueryFrame(GetFirstPrincipalChild()); michael@0: } michael@0: michael@0: virtual nscoord GetMinWidth(nsRenderingContext* aRenderingContext) MOZ_OVERRIDE; michael@0: virtual nscoord GetPrefWidth(nsRenderingContext* aRenderingContext) MOZ_OVERRIDE; michael@0: michael@0: virtual nsSize ComputeAutoSize(nsRenderingContext *aRenderingContext, michael@0: nsSize aCBSize, nscoord aAvailableWidth, michael@0: nsSize aMargin, nsSize aBorder, michael@0: nsSize aPadding, bool aShrinkWrap) 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 nsSize GetMinSize(nsBoxLayoutState& aBoxLayoutState) MOZ_OVERRIDE; michael@0: virtual bool IsCollapsed() MOZ_OVERRIDE; michael@0: michael@0: virtual bool IsLeaf() const MOZ_OVERRIDE; michael@0: michael@0: #ifdef ACCESSIBILITY michael@0: virtual mozilla::a11y::AccType AccessibleType() MOZ_OVERRIDE; michael@0: #endif michael@0: michael@0: #ifdef DEBUG_FRAME_DUMP michael@0: virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE michael@0: { michael@0: aResult.AssignLiteral("nsTextControlFrame"); michael@0: return NS_OK; michael@0: } michael@0: #endif michael@0: michael@0: virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE michael@0: { michael@0: // nsStackFrame is already both of these, but that's somewhat bogus, michael@0: // and we really mean it. michael@0: return nsContainerFrame::IsFrameOfType(aFlags & michael@0: ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock)); michael@0: } 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: // Utility methods to set current widget state michael@0: michael@0: virtual nsresult SetInitialChildList(ChildListID aListID, michael@0: nsFrameList& aChildList) MOZ_OVERRIDE; michael@0: michael@0: virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, michael@0: const nsRect& aDirtyRect, michael@0: const nsDisplayListSet& aLists) MOZ_OVERRIDE; michael@0: michael@0: virtual mozilla::dom::Element* GetPseudoElement(nsCSSPseudoElements::Type aType) MOZ_OVERRIDE; michael@0: michael@0: //==== BEGIN 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: //==== END NSIFORMCONTROLFRAME michael@0: michael@0: //==== NSITEXTCONTROLFRAME michael@0: michael@0: NS_IMETHOD GetEditor(nsIEditor **aEditor) MOZ_OVERRIDE; michael@0: NS_IMETHOD SetSelectionStart(int32_t aSelectionStart) MOZ_OVERRIDE; michael@0: NS_IMETHOD SetSelectionEnd(int32_t aSelectionEnd) MOZ_OVERRIDE; michael@0: NS_IMETHOD SetSelectionRange(int32_t aSelectionStart, michael@0: int32_t aSelectionEnd, michael@0: SelectionDirection aDirection = eNone) MOZ_OVERRIDE; michael@0: NS_IMETHOD GetSelectionRange(int32_t* aSelectionStart, michael@0: int32_t* aSelectionEnd, michael@0: SelectionDirection* aDirection = nullptr) MOZ_OVERRIDE; michael@0: NS_IMETHOD GetOwnedSelectionController(nsISelectionController** aSelCon) MOZ_OVERRIDE; michael@0: virtual nsFrameSelection* GetOwnedFrameSelection() MOZ_OVERRIDE; michael@0: michael@0: 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: //==== END NSITEXTCONTROLFRAME michael@0: michael@0: //==== NSISTATEFULFRAME michael@0: michael@0: NS_IMETHOD SaveState(nsPresState** aState) MOZ_OVERRIDE; michael@0: NS_IMETHOD RestoreState(nsPresState* aState) MOZ_OVERRIDE; michael@0: michael@0: //=== END NSISTATEFULFRAME michael@0: michael@0: //==== OVERLOAD of nsIFrame michael@0: virtual nsIAtom* GetType() const MOZ_OVERRIDE; michael@0: michael@0: /** handler for attribute changes to mContent */ michael@0: virtual nsresult AttributeChanged(int32_t aNameSpaceID, michael@0: nsIAtom* aAttribute, michael@0: int32_t aModType) MOZ_OVERRIDE; michael@0: michael@0: nsresult GetText(nsString& aText); michael@0: michael@0: virtual nsresult PeekOffset(nsPeekOffsetStruct *aPos) MOZ_OVERRIDE; michael@0: michael@0: NS_DECL_QUERYFRAME michael@0: michael@0: // Temp reference to scriptrunner michael@0: // We could make these auto-Revoking via the "delete" entry for safety michael@0: NS_DECLARE_FRAME_PROPERTY(TextControlInitializer, nullptr) michael@0: michael@0: protected: michael@0: /** michael@0: * Launch the reflow on the child frames - see nsTextControlFrame::Reflow() michael@0: */ michael@0: void ReflowTextControlChild(nsIFrame* aFrame, michael@0: nsPresContext* aPresContext, michael@0: const nsHTMLReflowState& aReflowState, michael@0: nsReflowStatus& aStatus, michael@0: nsHTMLReflowMetrics& aParentDesiredSize); michael@0: michael@0: public: //for methods who access nsTextControlFrame directly michael@0: void SetValueChanged(bool aValueChanged); michael@0: michael@0: // called by the focus listener michael@0: nsresult MaybeBeginSecureKeyboardInput(); michael@0: void MaybeEndSecureKeyboardInput(); michael@0: michael@0: #define DEFINE_TEXTCTRL_FORWARDER(type, name) \ michael@0: type name() { \ michael@0: nsCOMPtr txtCtrl = do_QueryInterface(GetContent()); \ michael@0: NS_ASSERTION(txtCtrl, "Content not a text control element"); \ michael@0: return txtCtrl->name(); \ michael@0: } michael@0: #define DEFINE_TEXTCTRL_CONST_FORWARDER(type, name) \ michael@0: type name() const { \ michael@0: nsCOMPtr txtCtrl = do_QueryInterface(GetContent()); \ michael@0: NS_ASSERTION(txtCtrl, "Content not a text control element"); \ michael@0: return txtCtrl->name(); \ michael@0: } michael@0: michael@0: DEFINE_TEXTCTRL_CONST_FORWARDER(bool, IsSingleLineTextControl) michael@0: DEFINE_TEXTCTRL_CONST_FORWARDER(bool, IsTextArea) michael@0: DEFINE_TEXTCTRL_CONST_FORWARDER(bool, IsPlainTextControl) michael@0: DEFINE_TEXTCTRL_CONST_FORWARDER(bool, IsPasswordTextControl) michael@0: DEFINE_TEXTCTRL_FORWARDER(int32_t, GetCols) michael@0: DEFINE_TEXTCTRL_FORWARDER(int32_t, GetWrapCols) michael@0: DEFINE_TEXTCTRL_FORWARDER(int32_t, GetRows) michael@0: michael@0: #undef DEFINE_TEXTCTRL_CONST_FORWARDER michael@0: #undef DEFINE_TEXTCTRL_FORWARDER michael@0: michael@0: protected: michael@0: class EditorInitializer; michael@0: friend class EditorInitializer; michael@0: friend class nsTextEditorState; // needs access to UpdateValueDisplay michael@0: michael@0: class EditorInitializer : public nsRunnable { michael@0: public: michael@0: EditorInitializer(nsTextControlFrame* aFrame) : michael@0: mFrame(aFrame) {} michael@0: michael@0: NS_IMETHOD Run() MOZ_OVERRIDE; michael@0: michael@0: // avoids use of nsWeakFrame michael@0: void Revoke() { michael@0: mFrame = nullptr; michael@0: } michael@0: michael@0: private: michael@0: nsTextControlFrame* mFrame; michael@0: }; michael@0: michael@0: class ScrollOnFocusEvent; michael@0: friend class ScrollOnFocusEvent; michael@0: michael@0: class ScrollOnFocusEvent : public nsRunnable { michael@0: public: michael@0: ScrollOnFocusEvent(nsTextControlFrame* aFrame) : michael@0: mFrame(aFrame) {} michael@0: michael@0: NS_DECL_NSIRUNNABLE michael@0: michael@0: void Revoke() { michael@0: mFrame = nullptr; michael@0: } michael@0: michael@0: private: michael@0: nsTextControlFrame* mFrame; michael@0: }; michael@0: michael@0: nsresult OffsetToDOMPoint(int32_t aOffset, nsIDOMNode** aResult, int32_t* aPosition); michael@0: michael@0: /** michael@0: * Update the textnode under our anonymous div to show the new michael@0: * value. This should only be called when we have no editor yet. michael@0: * @throws NS_ERROR_UNEXPECTED if the div has no text content michael@0: */ michael@0: nsresult UpdateValueDisplay(bool aNotify, michael@0: bool aBeforeEditorInit = false, michael@0: const nsAString *aValue = nullptr); michael@0: michael@0: /** michael@0: * Get the maxlength attribute michael@0: * @param aMaxLength the value of the max length attr michael@0: * @returns false if attr not defined michael@0: */ michael@0: bool GetMaxLength(int32_t* aMaxLength); michael@0: michael@0: /** michael@0: * Find out whether an attribute exists on the content or not. michael@0: * @param aAtt the attribute to determine the existence of michael@0: * @returns false if it does not exist michael@0: */ michael@0: bool AttributeExists(nsIAtom *aAtt) const michael@0: { return mContent && mContent->HasAttr(kNameSpaceID_None, aAtt); } michael@0: michael@0: /** michael@0: * We call this when we are being destroyed or removed from the PFM. michael@0: * @param aPresContext the current pres context michael@0: */ michael@0: void PreDestroy(); michael@0: michael@0: // Compute our intrinsic size. This does not include any borders, paddings, michael@0: // etc. Just the size of our actual area for the text (and the scrollbars, michael@0: // for