diff --git a/content/html/style/public/nsCSSAtomList.h b/content/html/style/public/nsCSSAtomList.h index df983156370..8afa5d0ac31 100644 --- a/content/html/style/public/nsCSSAtomList.h +++ b/content/html/style/public/nsCSSAtomList.h @@ -40,6 +40,8 @@ CSS_ATOM(afterPseudo, ":after") CSS_ATOM(beforePseudo, ":before") +CSS_ATOM(buttonLabelPseudo, ":-moz-buttonlabel") + CSS_ATOM(checkedPseudo, ":checked") CSS_ATOM(disabledPseudo, ":disabled") diff --git a/content/shared/public/nsCSSAtomList.h b/content/shared/public/nsCSSAtomList.h index df983156370..8afa5d0ac31 100644 --- a/content/shared/public/nsCSSAtomList.h +++ b/content/shared/public/nsCSSAtomList.h @@ -40,6 +40,8 @@ CSS_ATOM(afterPseudo, ":after") CSS_ATOM(beforePseudo, ":before") +CSS_ATOM(buttonLabelPseudo, ":-moz-buttonlabel") + CSS_ATOM(checkedPseudo, ":checked") CSS_ATOM(disabledPseudo, ":disabled") diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 8029e78d9cf..165aa3c72cd 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -2458,6 +2458,40 @@ nsCSSFrameConstructor::ConstructCheckboxControlFrame(nsIPresContext* aPres return rv; } +nsresult +nsCSSFrameConstructor::ConstructButtonLabelFrame(nsIPresContext *aPresContext, + nsIContent *aContent, + nsIFrame *&aFrame, + nsFrameConstructorState& aState, + nsFrameItems& aFrameItems) +{ + // Construct a button label using generated content specified + // through style. A style rule of following form must be + // present in ua.css or other style sheet + // input[type=button][value]:-moz-buttonlabel { + // content:attr(value); + // } + // The default for the label is specified with a rule similar to + // the following: + // input[type=reset]:-moz-buttonlabel { + // content:"Reset"; + // } + nsresult rv = NS_OK; + nsIStyleContext* styleContext = nsnull; + nsIFrame* generatedFrame = nsnull; + + // Probe for generated content before + aFrame->GetStyleContext(&styleContext); + if (CreateGeneratedContentFrame(aPresContext, aState, aFrame, aContent, + styleContext, nsCSSAtoms::buttonLabelPseudo, + PR_FALSE, PR_FALSE, &generatedFrame)) { + // Add the generated frame to the child list + aFrameItems.AddChild(generatedFrame); + } + return rv; +} + + nsresult nsCSSFrameConstructor::ConstructButtonControlFrame(nsIPresContext* aPresContext, nsIFrame*& aNewFrame) @@ -2814,6 +2848,10 @@ nsCSSFrameConstructor::ConstructFrameByTag(nsIPresContext* aPresContext PR_TRUE, childItems); } + if (nsHTMLAtoms::input == aTag) { + // Construct button label frame using generated content + ConstructButtonLabelFrame(aPresContext, aContent, newFrame, aState, childItems); + } // if there are any anonymous children create frames for them CreateAnonymousFrames(aPresContext, aTag, aState, aContent, newFrame, diff --git a/layout/base/nsCSSFrameConstructor.h b/layout/base/nsCSSFrameConstructor.h index 213ae3ff12e..a90ab2c3150 100644 --- a/layout/base/nsCSSFrameConstructor.h +++ b/layout/base/nsCSSFrameConstructor.h @@ -417,6 +417,12 @@ protected: nsresult ConstructCheckboxControlFrame(nsIPresContext* aPresContext, nsIFrame*& aNewFrame); + nsresult ConstructButtonLabelFrame(nsIPresContext *aPresContext, + nsIContent *aContent, + nsIFrame *&aFrame, + nsFrameConstructorState& aState, + nsFrameItems& aFrameItems); + nsresult ConstructButtonControlFrame(nsIPresContext* aPresContext, nsIFrame*& aNewFrame); diff --git a/layout/forms/nsGfxButtonControlFrame.cpp b/layout/forms/nsGfxButtonControlFrame.cpp index 233477f9146..39366f148d9 100644 --- a/layout/forms/nsGfxButtonControlFrame.cpp +++ b/layout/forms/nsGfxButtonControlFrame.cpp @@ -17,16 +17,71 @@ */ #include "nsGfxButtonControlFrame.h" -#include "nsHTMLAtoms.h" -#include "nsFormFrame.h" -#include "nsIFormControl.h" -#include "nsIContent.h" #include "nsIButton.h" -#include "nsINameSpaceManager.h" - +#include "nsWidgetsCID.h" +static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); static NS_DEFINE_IID(kIButtonIID, NS_IBUTTON_IID); +const nscoord kSuggestedNotSet = -1; + +nsGfxButtonControlFrame::nsGfxButtonControlFrame() +{ + mRenderer.SetNameSpace(kNameSpaceID_None); + mSuggestedWidth = kSuggestedNotSet; + mSuggestedHeight = kSuggestedNotSet; +} + +PRBool +nsGfxButtonControlFrame::IsSuccessful(nsIFormControlFrame* aSubmitter) +{ + PRInt32 type; + GetType(&type); + if ((NS_FORM_INPUT_HIDDEN == type) || (this == aSubmitter)) { + return nsHTMLButtonControlFrame::IsSuccessful(aSubmitter); + } else { + return PR_FALSE; + } +} + +PRInt32 +nsGfxButtonControlFrame::GetMaxNumValues() +{ + PRInt32 type; + GetType(&type); + if ((NS_FORM_INPUT_SUBMIT == type) || (NS_FORM_INPUT_HIDDEN == type)) { + return 1; + } else { + return 0; + } +} + +PRBool +nsGfxButtonControlFrame::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames) +{ + nsAutoString name; + nsresult result = GetName(&name); + if ((aMaxNumValues <= 0) || (NS_CONTENT_ATTR_HAS_VALUE != result)) { + return PR_FALSE; + } + + PRInt32 type; + GetType(&type); + + if (NS_FORM_INPUT_RESET == type) { + aNumValues = 0; + return PR_FALSE; + } else { + nsAutoString value; + GetValue(&value); + aValues[0] = value; + aNames[0] = name; + aNumValues = 1; + return PR_TRUE; + } +} + nsresult NS_NewGfxButtonControlFrame(nsIFrame** aNewFrame) { @@ -41,193 +96,128 @@ NS_NewGfxButtonControlFrame(nsIFrame** aNewFrame) *aNewFrame = it; return NS_OK; } - - -nsGfxButtonControlFrame::nsGfxButtonControlFrame() + +void +nsGfxButtonControlFrame::MouseClicked(nsIPresContext* aPresContext) { - mRenderer.SetNameSpace(kNameSpaceID_None); -} + PRInt32 type; + GetType(&type); -NS_IMETHODIMP -nsGfxButtonControlFrame::Init(nsIPresContext& aPresContext, - nsIContent* aContent, - nsIFrame* aParent, - nsIStyleContext* aContext, - nsIFrame* aPrevInFlow) -{ - nsresult rv = Inherited::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); - mRenderer.SetFrame(this,aPresContext); - return rv; -} + if ((nsnull != mFormFrame) && !nsFormFrame::GetDisabled(this)) { + nsEventStatus status = nsEventStatus_eIgnore; + nsEvent event; + event.eventStructType = NS_EVENT; + nsIContent *formContent = nsnull; + mFormFrame->GetContent(&formContent); - -// -// ReResolveStyleContext -// -// When the style context changes, make sure that all of our styles are still up to date. -// -NS_IMETHODIMP -nsGfxButtonControlFrame::ReResolveStyleContext ( nsIPresContext* aPresContext, nsIStyleContext* aParentContext, - PRInt32 aParentChange, - nsStyleChangeList* aChangeList, PRInt32* aLocalChange) -{ - // this re-resolves |mStyleContext|, so it may change - nsresult rv = Inherited::ReResolveStyleContext(aPresContext, aParentContext, - aParentChange, aChangeList, aLocalChange); - if (NS_FAILED(rv)) { - return rv; - } - - if (NS_COMFALSE != rv) { // frame style changed - if (aLocalChange) { - aParentChange = *aLocalChange; // tell children about or change + switch(type) { + case NS_FORM_INPUT_RESET: + event.message = NS_FORM_RESET; + if (nsnull != formContent) { + formContent->HandleDOMEvent(*aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, status); + } + if (nsEventStatus_eConsumeNoDefault != status) { + mFormFrame->OnReset(); + } + break; + case NS_FORM_INPUT_SUBMIT: + event.message = NS_FORM_SUBMIT; + if (nsnull != formContent) { + formContent->HandleDOMEvent(*aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, status); + } + if (nsEventStatus_eConsumeNoDefault != status) { + mFormFrame->OnSubmit(aPresContext, this); + } } - } - mRenderer.ReResolveStyles(*aPresContext, aParentChange, aChangeList, aLocalChange); - - return rv; - -} // ReResolveStyleContext + NS_IF_RELEASE(formContent); + } +} - - - -NS_METHOD -nsGfxButtonControlFrame::Paint(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer) +const nsIID& +nsGfxButtonControlFrame::GetIID() { - const nsStyleDisplay* disp = (const nsStyleDisplay*) - mStyleContext->GetStyleData(eStyleStruct_Display); - if (!disp->mVisible) - return NS_OK; - - nsRect rect(0, 0, mRect.width, mRect.height); - mRenderer.PaintButton(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, rect); - - if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { - nsString label; - nsresult result = GetValue(&label); - - if (NS_CONTENT_ATTR_HAS_VALUE != result) { - GetDefaultLabel(label); - } + static NS_DEFINE_IID(kButtonIID, NS_IBUTTON_IID); + return kButtonIID; +} - nsRect content; - mRenderer.GetButtonContentRect(rect,content); - - // paint the title - const nsStyleFont* fontStyle = (const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font); - const nsStyleColor* colorStyle = (const nsStyleColor*)mStyleContext->GetStyleData(eStyleStruct_Color); - - aRenderingContext.SetFont(fontStyle->mFont); - - PRBool clipState; - aRenderingContext.PushState(); - aRenderingContext.SetClipRect(rect, nsClipCombine_kIntersect, clipState); - // if disabled paint - if (PR_TRUE == mRenderer.isDisabled()) - { - float p2t; - aPresContext.GetScaledPixelsToTwips(&p2t); - nscoord pixel = NSIntPixelsToTwips(1, p2t); - - aRenderingContext.SetColor(NS_RGB(255,255,255)); - aRenderingContext.DrawString(label, content.x + pixel, content.y+ pixel); - } - - aRenderingContext.SetColor(colorStyle->mColor); - aRenderingContext.DrawString(label, content.x, content.y); - aRenderingContext.PopState(clipState); - } - - return NS_OK; +const nsIID& +nsGfxButtonControlFrame::GetCID() +{ + static NS_DEFINE_IID(kButtonCID, NS_BUTTON_CID); + return kButtonCID; } NS_IMETHODIMP -nsGfxButtonControlFrame::AttributeChanged(nsIPresContext* aPresContext, - nsIContent* aChild, - nsIAtom* aAttribute, - PRInt32 aHint) +nsGfxButtonControlFrame::GetFrameName(nsString& aResult) const { - if (nsHTMLAtoms::value == aAttribute) { - // redraw button with the changed value - Invalidate(mRect, PR_FALSE); - } - return NS_OK; + return MakeFrameName("ButtonControl", aResult); } -NS_METHOD -nsGfxButtonControlFrame::Reflow(nsIPresContext& aPresContext, + + +NS_IMETHODIMP +nsGfxButtonControlFrame::Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, + const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { - - // add ourself as an nsIFormControlFrame if (!mFormFrame && (eReflowReason_Initial == aReflowState.reason)) { - nsFormFrame::AddFormControlFrame(aPresContext, *this); + nsFormFrame::AddFormControlFrame(aPresContext, *this); } - if ((NS_FORMSIZE_NOTSET != mSuggestedWidth) && ( - NS_FORMSIZE_NOTSET != mSuggestedHeight)) - { - aDesiredSize.width = mSuggestedWidth; - aDesiredSize.height = mSuggestedHeight; - aDesiredSize.ascent = mSuggestedHeight; - aDesiredSize.descent = 0; - if (aDesiredSize.maxElementSize) { - aDesiredSize.maxElementSize->width = mSuggestedWidth; - aDesiredSize.maxElementSize->height = mSuggestedWidth; - } + if ((kSuggestedNotSet != mSuggestedWidth) || + (kSuggestedNotSet != mSuggestedHeight)) + { + nsHTMLReflowState suggestedReflowState(aReflowState); + + // Honor the suggested width and/or height. + if (kSuggestedNotSet != mSuggestedWidth) { + suggestedReflowState.mComputedWidth = mSuggestedWidth; + } - if (nsnull != aDesiredSize.maxElementSize) { - aDesiredSize.maxElementSize->width = aDesiredSize.width; - aDesiredSize.maxElementSize->height = aDesiredSize.height; - } + if (kSuggestedNotSet != mSuggestedHeight) { + suggestedReflowState.mComputedHeight = mSuggestedHeight; + } - aStatus = NS_FRAME_COMPLETE; - return NS_OK; + return nsHTMLButtonControlFrame::Reflow(aPresContext, aDesiredSize, suggestedReflowState, aStatus); - } - - nsSize ignore; - GetDesiredSize(&aPresContext, aReflowState, aDesiredSize, ignore); - - // if our size is intrinsic. Then we need to return the size we really need - // so include our inner borders we use for focus. - nsMargin added = mRenderer.GetAddedButtonBorderAndPadding(); - if (aReflowState.mComputedWidth == NS_INTRINSICSIZE) - aDesiredSize.width += added.left + added.right; - - if (aReflowState.mComputedHeight == NS_INTRINSICSIZE) - aDesiredSize.height += added.top + added.bottom; - - nsMargin bp(0,0,0,0); - AddBordersAndPadding(&aPresContext, aReflowState, aDesiredSize, bp); - - - if (nsnull != aDesiredSize.maxElementSize) { - aDesiredSize.AddBorderPaddingToMaxElementSize(bp); - aDesiredSize.maxElementSize->width += added.left + added.right; - aDesiredSize.maxElementSize->height += added.top + added.bottom; - - } - aStatus = NS_FRAME_COMPLETE; - return NS_OK; + } else { + // Normal reflow. + return nsHTMLButtonControlFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); + } } +NS_IMETHODIMP +nsGfxButtonControlFrame::SetSuggestedSize(nscoord aWidth, nscoord aHeight) +{ + mSuggestedWidth = aWidth; + mSuggestedHeight = aHeight; + return NS_OK; +} NS_IMETHODIMP nsGfxButtonControlFrame::HandleEvent(nsIPresContext& aPresContext, - nsGUIEvent* aEvent, - nsEventStatus& aEventStatus) + nsGUIEvent* aEvent, + nsEventStatus& aEventStatus) { + // Override the HandleEvent to prevent the nsFrame::HandleEvent + // from being called. The nsFrame::HandleEvent causes the button label + // to be selected (Drawn with an XOR rectangle over the label) + // if disabled do nothing if (mRenderer.isDisabled()) { return NS_OK; } - return Inherited::HandleEvent(aPresContext, aEvent, aEventStatus); + // lets see if the button was clicked + switch (aEvent->message) { + case NS_MOUSE_LEFT_CLICK: + MouseClicked(&aPresContext); + break; + } + + return NS_OK; + } + + diff --git a/layout/forms/nsGfxButtonControlFrame.h b/layout/forms/nsGfxButtonControlFrame.h index 1021430ebd9..658cec1612a 100644 --- a/layout/forms/nsGfxButtonControlFrame.h +++ b/layout/forms/nsGfxButtonControlFrame.h @@ -19,52 +19,46 @@ #ifndef nsGfxButtonControlFrame_h___ #define nsGfxButtonControlFrame_h___ -#include "nsNativeFormControlFrame.h" -#include "nsButtonControlFrame.h" -#include "nsButtonFrameRenderer.h" +#include "nsFormControlFrame.h" +#include "nsHTMLButtonControlFrame.h" -class nsGfxButtonControlFrame : public nsButtonControlFrame { -private: - typedef nsButtonControlFrame Inherited; +// Class which implements the input[type=button, reset, submit] and +// browse button for input[type=file]. +// The label for button is specified through generated content +// in the ua.css file. +class nsGfxButtonControlFrame : public nsHTMLButtonControlFrame { public: - nsGfxButtonControlFrame(); - NS_IMETHOD Init(nsIPresContext& aPresContext, - nsIContent* aContent, - nsIFrame* aParent, - nsIStyleContext* aContext, - nsIFrame* asPrevInFlow); - - NS_IMETHOD ReResolveStyleContext ( nsIPresContext* aPresContext, - nsIStyleContext* aParentContext, - PRInt32 aParentChange, - nsStyleChangeList* aChangeList, - PRInt32* aLocalChange) ; - - NS_IMETHOD Paint(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer); - - NS_IMETHOD Reflow(nsIPresContext& aPresContext, + //nsIFrame + NS_IMETHOD Reflow(nsIPresContext& aCX, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); + virtual const nsIID& GetCID(); + virtual const nsIID& GetIID(); - NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext, - nsIContent* aChild, - nsIAtom* aAttribute, - PRInt32 aHint); - - NS_IMETHOD HandleEvent(nsIPresContext& aPresContext, + NS_IMETHOD HandleEvent(nsIPresContext& aPresContext, nsGUIEvent* aEvent, nsEventStatus& aEventStatus); -protected: - //GFX-rendered state variables - nsButtonFrameRenderer mRenderer; + + // nsFormControlFrame + NS_IMETHOD SetSuggestedSize(nscoord aWidth, nscoord aHeight); + NS_IMETHOD GetFrameName(nsString& aResult) const; + PRBool IsSuccessful(nsIFormControlFrame* aSubmitter); + virtual PRInt32 GetMaxNumValues(); + virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames); + virtual void MouseClicked(nsIPresContext* aPresContext); + +private: + NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; } + NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; } + + nscoord mSuggestedWidth; + nscoord mSuggestedHeight; }; diff --git a/layout/html/document/src/ua.css b/layout/html/document/src/ua.css index 3fe675f38b1..aa7e242dab4 100644 --- a/layout/html/document/src/ua.css +++ b/layout/html/document/src/ua.css @@ -421,6 +421,49 @@ form { display: block; margin: 1em 0; } + + +/* button */ +input[type=button]:-moz-buttonlabel { + content:" "; + font-family: sans-serif; + font-size: small; + background-color:inherit; +} + +input[type=button][value]:-moz-buttonlabel { + content:attr(value); + font-family: sans-serif; + font-size: small; + background-color:inherit; +} + +/* submit */ +input[type=submit]:-moz-buttonlabel { + content:"submit"; + font-family: sans-serif; + font-size: small; +} + +input[type=submit][value]:-moz-buttonlabel { + content:attr(value); + font-family: sans-serif; + font-size: small; +} + +/* reset */ +input[type=reset]:-moz-buttonlabel { + content:"reset"; + font-family: sans-serif; + font-size: small; +} + +input[type=reset][value]:-moz-buttonlabel { + content:attr(value); + font-family: sans-serif; + font-size: small; +} + input { vertical-align: bottom; border: 2px inset rgb(204, 204, 204); @@ -443,6 +486,12 @@ input[type=file] input[type=button] { height:inherit; } +input[type=file] input[type=button]:-moz-buttonlabel { + content:"Browse..."; + font-family: sans-serif; +} + + input[type=radio] { /* these margins are for NavQuirks, we need a Standard ua.css */ margin-left: 3px; @@ -606,13 +655,11 @@ input[type="button"] { border: 2px outset rgb(156, 154, 156); background-color: rgb(206, 207, 206); color:black; - padding: 1px; } input[type="button"]:active { border-style: inset; - padding-left: 2px; padding-right: 0px; padding-top: 2px; @@ -648,7 +695,6 @@ input[type="button"]:focus:-moz-focus-inner { padding-right : 1px; padding-top : 0px; padding-bottom: 0px; - margin: 0px; border : 1px dotted black; } @@ -873,6 +919,7 @@ optgroup:before { content:attr(label); } + textarea { vertical-align: bottom; border: 2px inset #c0c0c0; diff --git a/layout/html/forms/src/nsGfxButtonControlFrame.cpp b/layout/html/forms/src/nsGfxButtonControlFrame.cpp index 233477f9146..39366f148d9 100644 --- a/layout/html/forms/src/nsGfxButtonControlFrame.cpp +++ b/layout/html/forms/src/nsGfxButtonControlFrame.cpp @@ -17,16 +17,71 @@ */ #include "nsGfxButtonControlFrame.h" -#include "nsHTMLAtoms.h" -#include "nsFormFrame.h" -#include "nsIFormControl.h" -#include "nsIContent.h" #include "nsIButton.h" -#include "nsINameSpaceManager.h" - +#include "nsWidgetsCID.h" +static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); static NS_DEFINE_IID(kIButtonIID, NS_IBUTTON_IID); +const nscoord kSuggestedNotSet = -1; + +nsGfxButtonControlFrame::nsGfxButtonControlFrame() +{ + mRenderer.SetNameSpace(kNameSpaceID_None); + mSuggestedWidth = kSuggestedNotSet; + mSuggestedHeight = kSuggestedNotSet; +} + +PRBool +nsGfxButtonControlFrame::IsSuccessful(nsIFormControlFrame* aSubmitter) +{ + PRInt32 type; + GetType(&type); + if ((NS_FORM_INPUT_HIDDEN == type) || (this == aSubmitter)) { + return nsHTMLButtonControlFrame::IsSuccessful(aSubmitter); + } else { + return PR_FALSE; + } +} + +PRInt32 +nsGfxButtonControlFrame::GetMaxNumValues() +{ + PRInt32 type; + GetType(&type); + if ((NS_FORM_INPUT_SUBMIT == type) || (NS_FORM_INPUT_HIDDEN == type)) { + return 1; + } else { + return 0; + } +} + +PRBool +nsGfxButtonControlFrame::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames) +{ + nsAutoString name; + nsresult result = GetName(&name); + if ((aMaxNumValues <= 0) || (NS_CONTENT_ATTR_HAS_VALUE != result)) { + return PR_FALSE; + } + + PRInt32 type; + GetType(&type); + + if (NS_FORM_INPUT_RESET == type) { + aNumValues = 0; + return PR_FALSE; + } else { + nsAutoString value; + GetValue(&value); + aValues[0] = value; + aNames[0] = name; + aNumValues = 1; + return PR_TRUE; + } +} + nsresult NS_NewGfxButtonControlFrame(nsIFrame** aNewFrame) { @@ -41,193 +96,128 @@ NS_NewGfxButtonControlFrame(nsIFrame** aNewFrame) *aNewFrame = it; return NS_OK; } - - -nsGfxButtonControlFrame::nsGfxButtonControlFrame() + +void +nsGfxButtonControlFrame::MouseClicked(nsIPresContext* aPresContext) { - mRenderer.SetNameSpace(kNameSpaceID_None); -} + PRInt32 type; + GetType(&type); -NS_IMETHODIMP -nsGfxButtonControlFrame::Init(nsIPresContext& aPresContext, - nsIContent* aContent, - nsIFrame* aParent, - nsIStyleContext* aContext, - nsIFrame* aPrevInFlow) -{ - nsresult rv = Inherited::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); - mRenderer.SetFrame(this,aPresContext); - return rv; -} + if ((nsnull != mFormFrame) && !nsFormFrame::GetDisabled(this)) { + nsEventStatus status = nsEventStatus_eIgnore; + nsEvent event; + event.eventStructType = NS_EVENT; + nsIContent *formContent = nsnull; + mFormFrame->GetContent(&formContent); - -// -// ReResolveStyleContext -// -// When the style context changes, make sure that all of our styles are still up to date. -// -NS_IMETHODIMP -nsGfxButtonControlFrame::ReResolveStyleContext ( nsIPresContext* aPresContext, nsIStyleContext* aParentContext, - PRInt32 aParentChange, - nsStyleChangeList* aChangeList, PRInt32* aLocalChange) -{ - // this re-resolves |mStyleContext|, so it may change - nsresult rv = Inherited::ReResolveStyleContext(aPresContext, aParentContext, - aParentChange, aChangeList, aLocalChange); - if (NS_FAILED(rv)) { - return rv; - } - - if (NS_COMFALSE != rv) { // frame style changed - if (aLocalChange) { - aParentChange = *aLocalChange; // tell children about or change + switch(type) { + case NS_FORM_INPUT_RESET: + event.message = NS_FORM_RESET; + if (nsnull != formContent) { + formContent->HandleDOMEvent(*aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, status); + } + if (nsEventStatus_eConsumeNoDefault != status) { + mFormFrame->OnReset(); + } + break; + case NS_FORM_INPUT_SUBMIT: + event.message = NS_FORM_SUBMIT; + if (nsnull != formContent) { + formContent->HandleDOMEvent(*aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, status); + } + if (nsEventStatus_eConsumeNoDefault != status) { + mFormFrame->OnSubmit(aPresContext, this); + } } - } - mRenderer.ReResolveStyles(*aPresContext, aParentChange, aChangeList, aLocalChange); - - return rv; - -} // ReResolveStyleContext + NS_IF_RELEASE(formContent); + } +} - - - -NS_METHOD -nsGfxButtonControlFrame::Paint(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer) +const nsIID& +nsGfxButtonControlFrame::GetIID() { - const nsStyleDisplay* disp = (const nsStyleDisplay*) - mStyleContext->GetStyleData(eStyleStruct_Display); - if (!disp->mVisible) - return NS_OK; - - nsRect rect(0, 0, mRect.width, mRect.height); - mRenderer.PaintButton(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer, rect); - - if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { - nsString label; - nsresult result = GetValue(&label); - - if (NS_CONTENT_ATTR_HAS_VALUE != result) { - GetDefaultLabel(label); - } + static NS_DEFINE_IID(kButtonIID, NS_IBUTTON_IID); + return kButtonIID; +} - nsRect content; - mRenderer.GetButtonContentRect(rect,content); - - // paint the title - const nsStyleFont* fontStyle = (const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font); - const nsStyleColor* colorStyle = (const nsStyleColor*)mStyleContext->GetStyleData(eStyleStruct_Color); - - aRenderingContext.SetFont(fontStyle->mFont); - - PRBool clipState; - aRenderingContext.PushState(); - aRenderingContext.SetClipRect(rect, nsClipCombine_kIntersect, clipState); - // if disabled paint - if (PR_TRUE == mRenderer.isDisabled()) - { - float p2t; - aPresContext.GetScaledPixelsToTwips(&p2t); - nscoord pixel = NSIntPixelsToTwips(1, p2t); - - aRenderingContext.SetColor(NS_RGB(255,255,255)); - aRenderingContext.DrawString(label, content.x + pixel, content.y+ pixel); - } - - aRenderingContext.SetColor(colorStyle->mColor); - aRenderingContext.DrawString(label, content.x, content.y); - aRenderingContext.PopState(clipState); - } - - return NS_OK; +const nsIID& +nsGfxButtonControlFrame::GetCID() +{ + static NS_DEFINE_IID(kButtonCID, NS_BUTTON_CID); + return kButtonCID; } NS_IMETHODIMP -nsGfxButtonControlFrame::AttributeChanged(nsIPresContext* aPresContext, - nsIContent* aChild, - nsIAtom* aAttribute, - PRInt32 aHint) +nsGfxButtonControlFrame::GetFrameName(nsString& aResult) const { - if (nsHTMLAtoms::value == aAttribute) { - // redraw button with the changed value - Invalidate(mRect, PR_FALSE); - } - return NS_OK; + return MakeFrameName("ButtonControl", aResult); } -NS_METHOD -nsGfxButtonControlFrame::Reflow(nsIPresContext& aPresContext, + + +NS_IMETHODIMP +nsGfxButtonControlFrame::Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, + const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { - - // add ourself as an nsIFormControlFrame if (!mFormFrame && (eReflowReason_Initial == aReflowState.reason)) { - nsFormFrame::AddFormControlFrame(aPresContext, *this); + nsFormFrame::AddFormControlFrame(aPresContext, *this); } - if ((NS_FORMSIZE_NOTSET != mSuggestedWidth) && ( - NS_FORMSIZE_NOTSET != mSuggestedHeight)) - { - aDesiredSize.width = mSuggestedWidth; - aDesiredSize.height = mSuggestedHeight; - aDesiredSize.ascent = mSuggestedHeight; - aDesiredSize.descent = 0; - if (aDesiredSize.maxElementSize) { - aDesiredSize.maxElementSize->width = mSuggestedWidth; - aDesiredSize.maxElementSize->height = mSuggestedWidth; - } + if ((kSuggestedNotSet != mSuggestedWidth) || + (kSuggestedNotSet != mSuggestedHeight)) + { + nsHTMLReflowState suggestedReflowState(aReflowState); + + // Honor the suggested width and/or height. + if (kSuggestedNotSet != mSuggestedWidth) { + suggestedReflowState.mComputedWidth = mSuggestedWidth; + } - if (nsnull != aDesiredSize.maxElementSize) { - aDesiredSize.maxElementSize->width = aDesiredSize.width; - aDesiredSize.maxElementSize->height = aDesiredSize.height; - } + if (kSuggestedNotSet != mSuggestedHeight) { + suggestedReflowState.mComputedHeight = mSuggestedHeight; + } - aStatus = NS_FRAME_COMPLETE; - return NS_OK; + return nsHTMLButtonControlFrame::Reflow(aPresContext, aDesiredSize, suggestedReflowState, aStatus); - } - - nsSize ignore; - GetDesiredSize(&aPresContext, aReflowState, aDesiredSize, ignore); - - // if our size is intrinsic. Then we need to return the size we really need - // so include our inner borders we use for focus. - nsMargin added = mRenderer.GetAddedButtonBorderAndPadding(); - if (aReflowState.mComputedWidth == NS_INTRINSICSIZE) - aDesiredSize.width += added.left + added.right; - - if (aReflowState.mComputedHeight == NS_INTRINSICSIZE) - aDesiredSize.height += added.top + added.bottom; - - nsMargin bp(0,0,0,0); - AddBordersAndPadding(&aPresContext, aReflowState, aDesiredSize, bp); - - - if (nsnull != aDesiredSize.maxElementSize) { - aDesiredSize.AddBorderPaddingToMaxElementSize(bp); - aDesiredSize.maxElementSize->width += added.left + added.right; - aDesiredSize.maxElementSize->height += added.top + added.bottom; - - } - aStatus = NS_FRAME_COMPLETE; - return NS_OK; + } else { + // Normal reflow. + return nsHTMLButtonControlFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); + } } +NS_IMETHODIMP +nsGfxButtonControlFrame::SetSuggestedSize(nscoord aWidth, nscoord aHeight) +{ + mSuggestedWidth = aWidth; + mSuggestedHeight = aHeight; + return NS_OK; +} NS_IMETHODIMP nsGfxButtonControlFrame::HandleEvent(nsIPresContext& aPresContext, - nsGUIEvent* aEvent, - nsEventStatus& aEventStatus) + nsGUIEvent* aEvent, + nsEventStatus& aEventStatus) { + // Override the HandleEvent to prevent the nsFrame::HandleEvent + // from being called. The nsFrame::HandleEvent causes the button label + // to be selected (Drawn with an XOR rectangle over the label) + // if disabled do nothing if (mRenderer.isDisabled()) { return NS_OK; } - return Inherited::HandleEvent(aPresContext, aEvent, aEventStatus); + // lets see if the button was clicked + switch (aEvent->message) { + case NS_MOUSE_LEFT_CLICK: + MouseClicked(&aPresContext); + break; + } + + return NS_OK; + } + + diff --git a/layout/html/forms/src/nsGfxButtonControlFrame.h b/layout/html/forms/src/nsGfxButtonControlFrame.h index 1021430ebd9..658cec1612a 100644 --- a/layout/html/forms/src/nsGfxButtonControlFrame.h +++ b/layout/html/forms/src/nsGfxButtonControlFrame.h @@ -19,52 +19,46 @@ #ifndef nsGfxButtonControlFrame_h___ #define nsGfxButtonControlFrame_h___ -#include "nsNativeFormControlFrame.h" -#include "nsButtonControlFrame.h" -#include "nsButtonFrameRenderer.h" +#include "nsFormControlFrame.h" +#include "nsHTMLButtonControlFrame.h" -class nsGfxButtonControlFrame : public nsButtonControlFrame { -private: - typedef nsButtonControlFrame Inherited; +// Class which implements the input[type=button, reset, submit] and +// browse button for input[type=file]. +// The label for button is specified through generated content +// in the ua.css file. +class nsGfxButtonControlFrame : public nsHTMLButtonControlFrame { public: - nsGfxButtonControlFrame(); - NS_IMETHOD Init(nsIPresContext& aPresContext, - nsIContent* aContent, - nsIFrame* aParent, - nsIStyleContext* aContext, - nsIFrame* asPrevInFlow); - - NS_IMETHOD ReResolveStyleContext ( nsIPresContext* aPresContext, - nsIStyleContext* aParentContext, - PRInt32 aParentChange, - nsStyleChangeList* aChangeList, - PRInt32* aLocalChange) ; - - NS_IMETHOD Paint(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer); - - NS_IMETHOD Reflow(nsIPresContext& aPresContext, + //nsIFrame + NS_IMETHOD Reflow(nsIPresContext& aCX, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); + virtual const nsIID& GetCID(); + virtual const nsIID& GetIID(); - NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext, - nsIContent* aChild, - nsIAtom* aAttribute, - PRInt32 aHint); - - NS_IMETHOD HandleEvent(nsIPresContext& aPresContext, + NS_IMETHOD HandleEvent(nsIPresContext& aPresContext, nsGUIEvent* aEvent, nsEventStatus& aEventStatus); -protected: - //GFX-rendered state variables - nsButtonFrameRenderer mRenderer; + + // nsFormControlFrame + NS_IMETHOD SetSuggestedSize(nscoord aWidth, nscoord aHeight); + NS_IMETHOD GetFrameName(nsString& aResult) const; + PRBool IsSuccessful(nsIFormControlFrame* aSubmitter); + virtual PRInt32 GetMaxNumValues(); + virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames); + virtual void MouseClicked(nsIPresContext* aPresContext); + +private: + NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; } + NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; } + + nscoord mSuggestedWidth; + nscoord mSuggestedHeight; }; diff --git a/layout/html/style/public/nsCSSAtomList.h b/layout/html/style/public/nsCSSAtomList.h index df983156370..8afa5d0ac31 100644 --- a/layout/html/style/public/nsCSSAtomList.h +++ b/layout/html/style/public/nsCSSAtomList.h @@ -40,6 +40,8 @@ CSS_ATOM(afterPseudo, ":after") CSS_ATOM(beforePseudo, ":before") +CSS_ATOM(buttonLabelPseudo, ":-moz-buttonlabel") + CSS_ATOM(checkedPseudo, ":checked") CSS_ATOM(disabledPseudo, ":disabled") diff --git a/layout/html/style/src/nsCSSFrameConstructor.cpp b/layout/html/style/src/nsCSSFrameConstructor.cpp index 8029e78d9cf..165aa3c72cd 100644 --- a/layout/html/style/src/nsCSSFrameConstructor.cpp +++ b/layout/html/style/src/nsCSSFrameConstructor.cpp @@ -2458,6 +2458,40 @@ nsCSSFrameConstructor::ConstructCheckboxControlFrame(nsIPresContext* aPres return rv; } +nsresult +nsCSSFrameConstructor::ConstructButtonLabelFrame(nsIPresContext *aPresContext, + nsIContent *aContent, + nsIFrame *&aFrame, + nsFrameConstructorState& aState, + nsFrameItems& aFrameItems) +{ + // Construct a button label using generated content specified + // through style. A style rule of following form must be + // present in ua.css or other style sheet + // input[type=button][value]:-moz-buttonlabel { + // content:attr(value); + // } + // The default for the label is specified with a rule similar to + // the following: + // input[type=reset]:-moz-buttonlabel { + // content:"Reset"; + // } + nsresult rv = NS_OK; + nsIStyleContext* styleContext = nsnull; + nsIFrame* generatedFrame = nsnull; + + // Probe for generated content before + aFrame->GetStyleContext(&styleContext); + if (CreateGeneratedContentFrame(aPresContext, aState, aFrame, aContent, + styleContext, nsCSSAtoms::buttonLabelPseudo, + PR_FALSE, PR_FALSE, &generatedFrame)) { + // Add the generated frame to the child list + aFrameItems.AddChild(generatedFrame); + } + return rv; +} + + nsresult nsCSSFrameConstructor::ConstructButtonControlFrame(nsIPresContext* aPresContext, nsIFrame*& aNewFrame) @@ -2814,6 +2848,10 @@ nsCSSFrameConstructor::ConstructFrameByTag(nsIPresContext* aPresContext PR_TRUE, childItems); } + if (nsHTMLAtoms::input == aTag) { + // Construct button label frame using generated content + ConstructButtonLabelFrame(aPresContext, aContent, newFrame, aState, childItems); + } // if there are any anonymous children create frames for them CreateAnonymousFrames(aPresContext, aTag, aState, aContent, newFrame, diff --git a/layout/html/style/src/nsCSSFrameConstructor.h b/layout/html/style/src/nsCSSFrameConstructor.h index 213ae3ff12e..a90ab2c3150 100644 --- a/layout/html/style/src/nsCSSFrameConstructor.h +++ b/layout/html/style/src/nsCSSFrameConstructor.h @@ -417,6 +417,12 @@ protected: nsresult ConstructCheckboxControlFrame(nsIPresContext* aPresContext, nsIFrame*& aNewFrame); + nsresult ConstructButtonLabelFrame(nsIPresContext *aPresContext, + nsIContent *aContent, + nsIFrame *&aFrame, + nsFrameConstructorState& aState, + nsFrameItems& aFrameItems); + nsresult ConstructButtonControlFrame(nsIPresContext* aPresContext, nsIFrame*& aNewFrame); diff --git a/layout/style/ua.css b/layout/style/ua.css index 3fe675f38b1..aa7e242dab4 100644 --- a/layout/style/ua.css +++ b/layout/style/ua.css @@ -421,6 +421,49 @@ form { display: block; margin: 1em 0; } + + +/* button */ +input[type=button]:-moz-buttonlabel { + content:" "; + font-family: sans-serif; + font-size: small; + background-color:inherit; +} + +input[type=button][value]:-moz-buttonlabel { + content:attr(value); + font-family: sans-serif; + font-size: small; + background-color:inherit; +} + +/* submit */ +input[type=submit]:-moz-buttonlabel { + content:"submit"; + font-family: sans-serif; + font-size: small; +} + +input[type=submit][value]:-moz-buttonlabel { + content:attr(value); + font-family: sans-serif; + font-size: small; +} + +/* reset */ +input[type=reset]:-moz-buttonlabel { + content:"reset"; + font-family: sans-serif; + font-size: small; +} + +input[type=reset][value]:-moz-buttonlabel { + content:attr(value); + font-family: sans-serif; + font-size: small; +} + input { vertical-align: bottom; border: 2px inset rgb(204, 204, 204); @@ -443,6 +486,12 @@ input[type=file] input[type=button] { height:inherit; } +input[type=file] input[type=button]:-moz-buttonlabel { + content:"Browse..."; + font-family: sans-serif; +} + + input[type=radio] { /* these margins are for NavQuirks, we need a Standard ua.css */ margin-left: 3px; @@ -606,13 +655,11 @@ input[type="button"] { border: 2px outset rgb(156, 154, 156); background-color: rgb(206, 207, 206); color:black; - padding: 1px; } input[type="button"]:active { border-style: inset; - padding-left: 2px; padding-right: 0px; padding-top: 2px; @@ -648,7 +695,6 @@ input[type="button"]:focus:-moz-focus-inner { padding-right : 1px; padding-top : 0px; padding-bottom: 0px; - margin: 0px; border : 1px dotted black; } @@ -873,6 +919,7 @@ optgroup:before { content:attr(label); } + textarea { vertical-align: bottom; border: 2px inset #c0c0c0;