diff --git a/mozilla/content/html/content/public/nsIFormControl.h b/mozilla/content/html/content/public/nsIFormControl.h index 7249c803174..d46896ebab8 100644 --- a/mozilla/content/html/content/public/nsIFormControl.h +++ b/mozilla/content/html/content/public/nsIFormControl.h @@ -23,23 +23,25 @@ class nsIDOMHTMLFormElement; class nsIWidget; #define NS_FORM_BROWSE 0 -#define NS_FORM_BUTTON 1 -#define NS_FORM_FIELDSET 2 -#define NS_FORM_INPUT_BUTTON 3 -#define NS_FORM_INPUT_CHECKBOX 4 -#define NS_FORM_INPUT_FILE 5 -#define NS_FORM_INPUT_HIDDEN 6 -#define NS_FORM_INPUT_RESET 7 -#define NS_FORM_INPUT_IMAGE 8 -#define NS_FORM_INPUT_PASSWORD 9 -#define NS_FORM_INPUT_RADIO 10 -#define NS_FORM_INPUT_SUBMIT 11 -#define NS_FORM_INPUT_TEXT 12 -#define NS_FORM_OPTION 13 -#define NS_FORM_OPTGROUP 14 -#define NS_FORM_LEGEND 15 -#define NS_FORM_SELECT 16 -#define NS_FORM_TEXTAREA 17 +#define NS_FORM_BUTTON_BUTTON 1 +#define NS_FORM_BUTTON_RESET 2 +#define NS_FORM_BUTTON_SUBMIT 3 +#define NS_FORM_FIELDSET 4 +#define NS_FORM_INPUT_BUTTON 5 +#define NS_FORM_INPUT_CHECKBOX 6 +#define NS_FORM_INPUT_FILE 7 +#define NS_FORM_INPUT_HIDDEN 8 +#define NS_FORM_INPUT_RESET 9 +#define NS_FORM_INPUT_IMAGE 10 +#define NS_FORM_INPUT_PASSWORD 11 +#define NS_FORM_INPUT_RADIO 12 +#define NS_FORM_INPUT_SUBMIT 13 +#define NS_FORM_INPUT_TEXT 14 +#define NS_FORM_OPTION 15 +#define NS_FORM_OPTGROUP 16 +#define NS_FORM_LEGEND 17 +#define NS_FORM_SELECT 18 +#define NS_FORM_TEXTAREA 19 #define NS_FORM_NOTOK 0xFFFFFFF7 #define NS_FORM_NOTSET 0xFFFFFFF7 diff --git a/mozilla/content/html/content/src/nsHTMLAtoms.cpp b/mozilla/content/html/content/src/nsHTMLAtoms.cpp index 664697ff836..d15ad429828 100644 --- a/mozilla/content/html/content/src/nsHTMLAtoms.cpp +++ b/mozilla/content/html/content/src/nsHTMLAtoms.cpp @@ -44,6 +44,7 @@ nsIAtom* nsHTMLAtoms::bordercolor; nsIAtom* nsHTMLAtoms::bottompadding; nsIAtom* nsHTMLAtoms::br; nsIAtom* nsHTMLAtoms::bulletPseudo; +nsIAtom* nsHTMLAtoms::button; nsIAtom* nsHTMLAtoms::caption; nsIAtom* nsHTMLAtoms::cellpadding; nsIAtom* nsHTMLAtoms::cellspacing; @@ -259,6 +260,7 @@ void nsHTMLAtoms::AddrefAtoms() bottompadding = NS_NewAtom("BOTTOMPADDING"); br = NS_NewAtom("BR"); bulletPseudo = NS_NewAtom(":BULLET"); + button = NS_NewAtom("BUTTON"); caption = NS_NewAtom("CAPTION"); cellpadding = NS_NewAtom("CELLPADDING"); cellspacing = NS_NewAtom("CELLSPACING"); @@ -471,6 +473,7 @@ void nsHTMLAtoms::ReleaseAtoms() NS_RELEASE(bottompadding); NS_RELEASE(br); NS_RELEASE(bulletPseudo); + NS_RELEASE(button); NS_RELEASE(caption); NS_RELEASE(cellpadding); NS_RELEASE(cellspacing); diff --git a/mozilla/content/html/content/src/nsHTMLAtoms.h b/mozilla/content/html/content/src/nsHTMLAtoms.h index fe866cddc06..645146ccb68 100644 --- a/mozilla/content/html/content/src/nsHTMLAtoms.h +++ b/mozilla/content/html/content/src/nsHTMLAtoms.h @@ -64,6 +64,7 @@ public: static nsIAtom* bottompadding; static nsIAtom* br; static nsIAtom* bulletPseudo; + static nsIAtom* button; static nsIAtom* caption; static nsIAtom* cellpadding; diff --git a/mozilla/content/html/content/src/nsHTMLButtonElement.cpp b/mozilla/content/html/content/src/nsHTMLButtonElement.cpp index d33736e4a70..1b52ac7531c 100644 --- a/mozilla/content/html/content/src/nsHTMLButtonElement.cpp +++ b/mozilla/content/html/content/src/nsHTMLButtonElement.cpp @@ -17,6 +17,7 @@ * Netscape Communications Corporation. All Rights Reserved. */ #include "nsIDOMHTMLButtonElement.h" +#include "nsIDOMHTMLFormElement.h" #include "nsIScriptObjectOwner.h" #include "nsIDOMEventReceiver.h" #include "nsIHTMLContent.h" @@ -26,6 +27,8 @@ #include "nsIStyleContext.h" #include "nsStyleConsts.h" #include "nsIPresContext.h" +#include "nsIFormControl.h" +#include "nsIForm.h" #include "nsIEventStateManager.h" #include "nsDOMEvent.h" @@ -35,7 +38,8 @@ static NS_DEFINE_IID(kIDOMHTMLButtonElementIID, NS_IDOMHTMLBUTTONELEMENT_IID); class nsHTMLButtonElement : public nsIDOMHTMLButtonElement, public nsIScriptObjectOwner, public nsIDOMEventReceiver, - public nsIHTMLContent + public nsIHTMLContent, + public nsIFormControl { public: nsHTMLButtonElement(nsIAtom* aTag); @@ -81,10 +85,23 @@ public: // nsIHTMLContent NS_IMPL_IHTMLCONTENT_USING_GENERIC(mInner) + // nsIFormControl + NS_IMETHOD GetType(PRInt32* aType); + NS_IMETHOD SetWidget(nsIWidget* aWidget) { return NS_OK; }; + NS_IMETHOD Init() { return NS_OK; } + protected: nsGenericHTMLContainerElement mInner; + nsIForm* mForm; + PRInt32 mType; }; +static NS_DEFINE_IID(kIDOMHTMLFormElementIID, NS_IDOMHTMLFORMELEMENT_IID); +static NS_DEFINE_IID(kIFormIID, NS_IFORM_IID); +static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); + +// Construction, destruction + nsresult NS_NewHTMLButtonElement(nsIHTMLContent** aInstancePtrResult, nsIAtom* aTag) { @@ -103,29 +120,64 @@ nsHTMLButtonElement::nsHTMLButtonElement(nsIAtom* aTag) { NS_INIT_REFCNT(); mInner.Init(this, aTag); + mForm = nsnull; + mType = NS_FORM_BUTTON_BUTTON; // default } nsHTMLButtonElement::~nsHTMLButtonElement() { + if (nsnull != mForm) { + // prevent mForm from decrementing its ref count on us + mForm->RemoveElement(this, PR_FALSE); + NS_RELEASE(mForm); + } } -NS_IMPL_ADDREF(nsHTMLButtonElement) +// nsISupports -NS_IMPL_RELEASE(nsHTMLButtonElement) +NS_IMETHODIMP_(nsrefcnt) +nsHTMLButtonElement::AddRef(void) +{ + PRInt32 refCnt = mRefCnt; // debugging + return ++mRefCnt; +} nsresult nsHTMLButtonElement::QueryInterface(REFNSIID aIID, void** aInstancePtr) { NS_IMPL_HTML_CONTENT_QUERY_INTERFACE(aIID, aInstancePtr, this) if (aIID.Equals(kIDOMHTMLButtonElementIID)) { - nsIDOMHTMLButtonElement* tmp = this; - *aInstancePtr = (void*) tmp; + *aInstancePtr = (void*)(nsIDOMHTMLButtonElement*)this; mRefCnt++; return NS_OK; } + else if (aIID.Equals(kIFormControlIID)) { + *aInstancePtr = (void*)(nsIFormControl*) this; + NS_ADDREF_THIS(); + return NS_OK; + } return NS_NOINTERFACE; } +NS_IMETHODIMP_(nsrefcnt) +nsHTMLButtonElement::Release() +{ + --mRefCnt; + if (mRefCnt <= 0) { + delete this; + return 0; + } else if ((1 == mRefCnt) && mForm) { + mRefCnt = 0; + delete this; + return 0; + } else { + return mRefCnt; + } +} + + +// nsIDOMHTMLButtonElement + nsresult nsHTMLButtonElement::CloneNode(nsIDOMNode** aReturn) { @@ -137,17 +189,43 @@ nsHTMLButtonElement::CloneNode(nsIDOMNode** aReturn) return it->QueryInterface(kIDOMNodeIID, (void**) aReturn); } -NS_IMETHODIMP -nsHTMLButtonElement::GetForm(nsIDOMHTMLFormElement** aForm) -{ - *aForm = nsnull;/* XXX */ - return NS_OK; -} - +// An important assumption is that if aForm is null, the previous mForm will not be released +// This allows nsHTMLFormElement to deal with circular references. NS_IMETHODIMP nsHTMLButtonElement::SetForm(nsIDOMHTMLFormElement* aForm) { - return NS_OK; + nsresult result = NS_OK; + if (nsnull == aForm) { + mForm = nsnull; + return NS_OK; + } else { + NS_IF_RELEASE(mForm); + nsIFormControl* formControl = nsnull; + result = QueryInterface(kIFormControlIID, (void**)&formControl); + if ((NS_OK == result) && formControl) { + result = aForm->QueryInterface(kIFormIID, (void**)&mForm); // keep the ref + if ((NS_OK == result) && mForm) { + mForm->AddElement(formControl); + } + NS_RELEASE(formControl); + } + } + return result; +} + +NS_IMETHODIMP +nsHTMLButtonElement::GetForm(nsIDOMHTMLFormElement** aForm) +{ + nsresult result = NS_OK; + *aForm = nsnull; + if (nsnull != mForm) { + nsIDOMHTMLFormElement* formElem = nsnull; + result = mForm->QueryInterface(kIDOMHTMLFormElementIID, (void**)&formElem); + if (NS_OK == result) { + *aForm = formElem; + } + } + return result; } NS_IMPL_STRING_ATTR(nsHTMLButtonElement, AccessKey, accesskey, eSetAttrNotify_None) @@ -157,6 +235,13 @@ NS_IMPL_STRING_ATTR(nsHTMLButtonElement, Type, type, eSetAttrNotify_Restart) NS_IMPL_INT_ATTR(nsHTMLButtonElement, TabIndex, tabindex, eSetAttrNotify_None) NS_IMPL_STRING_ATTR(nsHTMLButtonElement, Value, value, eSetAttrNotify_Render) +static nsGenericHTMLElement::EnumTable kButtonTypeTable[] = { + { "button", NS_FORM_BUTTON_BUTTON }, + { "reset", NS_FORM_BUTTON_RESET }, + { "submit", NS_FORM_BUTTON_SUBMIT }, + { 0 } +}; + NS_IMETHODIMP nsHTMLButtonElement::StringToAttribute(nsIAtom* aAttribute, const nsString& aValue, @@ -167,6 +252,21 @@ nsHTMLButtonElement::StringToAttribute(nsIAtom* aAttribute, eHTMLUnit_Integer); return NS_CONTENT_ATTR_HAS_VALUE; } + if (aAttribute == nsHTMLAtoms::type) { + nsGenericHTMLElement::EnumTable *table = kButtonTypeTable; + while (nsnull != table->tag) { + if (aValue.EqualsIgnoreCase(table->tag)) { + aResult.SetIntValue(table->value, eHTMLUnit_Enumerated); + mType = table->value; + return NS_CONTENT_ATTR_HAS_VALUE; + } + table++; + } + } + else if (aAttribute == nsHTMLAtoms::disabled) { + aResult.SetEmptyValue(); + return NS_CONTENT_ATTR_HAS_VALUE; + } return NS_CONTENT_ATTR_NOT_THERE; } @@ -175,6 +275,12 @@ nsHTMLButtonElement::AttributeToString(nsIAtom* aAttribute, nsHTMLValue& aValue, nsString& aResult) const { + if (aAttribute == nsHTMLAtoms::type) { + if (eHTMLUnit_Enumerated == aValue.GetUnit()) { + nsGenericHTMLElement::EnumValueToString(aValue, kButtonTypeTable, aResult); + return NS_CONTENT_ATTR_HAS_VALUE; + } + } return mInner.AttributeToString(aAttribute, aValue, aResult); } @@ -282,3 +388,14 @@ nsHTMLButtonElement::HandleDOMEvent(nsIPresContext& aPresContext, } return ret; } + +NS_IMETHODIMP +nsHTMLButtonElement::GetType(PRInt32* aType) +{ + if (aType) { + *aType = mType; + return NS_OK; + } else { + return NS_FORM_NOTOK; + } +} diff --git a/mozilla/content/html/content/src/nsHTMLInputElement.cpp b/mozilla/content/html/content/src/nsHTMLInputElement.cpp index f3362732f99..861b9ac089d 100644 --- a/mozilla/content/html/content/src/nsHTMLInputElement.cpp +++ b/mozilla/content/html/content/src/nsHTMLInputElement.cpp @@ -352,6 +352,14 @@ nsHTMLInputElement::StringToAttribute(nsIAtom* aAttribute, aResult.SetEmptyValue(); return NS_CONTENT_ATTR_HAS_VALUE; } + else if (aAttribute == nsHTMLAtoms::disabled) { + aResult.SetEmptyValue(); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::readonly) { + aResult.SetEmptyValue(); + return NS_CONTENT_ATTR_HAS_VALUE; + } else if (aAttribute == nsHTMLAtoms::width) { nsGenericHTMLElement::ParseValueOrPercent(aValue, aResult, eHTMLUnit_Pixel); diff --git a/mozilla/content/html/content/src/nsHTMLSelectElement.cpp b/mozilla/content/html/content/src/nsHTMLSelectElement.cpp index a0011688e08..e496bdf5bbc 100644 --- a/mozilla/content/html/content/src/nsHTMLSelectElement.cpp +++ b/mozilla/content/html/content/src/nsHTMLSelectElement.cpp @@ -317,7 +317,7 @@ NS_IMPL_INT_ATTR(nsHTMLSelectElement, SelectedIndex, selectedindex, eSetAttrNoti NS_IMPL_STRING_ATTR(nsHTMLSelectElement, Value, value, eSetAttrNotify_Render) NS_IMPL_INT_ATTR(nsHTMLSelectElement, Length, length, eSetAttrNotify_Restart) NS_IMPL_BOOL_ATTR(nsHTMLSelectElement, Disabled, disabled, eSetAttrNotify_Render) -NS_IMPL_INT_ATTR(nsHTMLSelectElement, Multiple, multiple, eSetAttrNotify_Restart) +NS_IMPL_BOOL_ATTR(nsHTMLSelectElement, Multiple, multiple, eSetAttrNotify_Restart) NS_IMPL_STRING_ATTR(nsHTMLSelectElement, Name, name, eSetAttrNotify_Restart) NS_IMPL_INT_ATTR(nsHTMLSelectElement, Size, size, eSetAttrNotify_Render) NS_IMPL_INT_ATTR(nsHTMLSelectElement, TabIndex, tabindex, eSetAttrNotify_Render) diff --git a/mozilla/content/html/document/src/nsHTMLContentSink.cpp b/mozilla/content/html/document/src/nsHTMLContentSink.cpp index 964b940cf61..92c1ec40667 100644 --- a/mozilla/content/html/document/src/nsHTMLContentSink.cpp +++ b/mozilla/content/html/document/src/nsHTMLContentSink.cpp @@ -501,6 +501,10 @@ MakeContentObject(nsHTMLTag aNodeType, case eHTMLTag_br: rv = NS_NewHTMLBRElement(aResult, aAtom); break; + case eHTMLTag_button: + rv = NS_NewHTMLButtonElement(aResult, aAtom); + SetForm(*aResult, aForm); + break; case eHTMLTag_caption: rv = NS_NewHTMLTableCaptionElement(aResult, aAtom); break; diff --git a/mozilla/content/html/style/src/nsHTMLStyleSheet.cpp b/mozilla/content/html/style/src/nsHTMLStyleSheet.cpp index 4b7623917aa..e510cb3f7bf 100644 --- a/mozilla/content/html/style/src/nsHTMLStyleSheet.cpp +++ b/mozilla/content/html/style/src/nsHTMLStyleSheet.cpp @@ -1239,6 +1239,10 @@ HTMLStyleSheetImpl::ConstructFrameByTag(nsIPresContext* aPresContext, else if (nsHTMLAtoms::spacer == aTag) { rv = NS_NewSpacerFrame(aContent, aParentFrame, aNewFrame); } + else if (nsHTMLAtoms::button == aTag) { + rv = NS_NewHTMLButtonControlFrame(aContent, aParentFrame, aNewFrame); + processChildren = PR_TRUE; + } // If we succeeded in creating a frame then set its style context, // process its children (if requested), and initialize the frame diff --git a/mozilla/content/shared/public/nsHTMLAtoms.h b/mozilla/content/shared/public/nsHTMLAtoms.h index fe866cddc06..645146ccb68 100644 --- a/mozilla/content/shared/public/nsHTMLAtoms.h +++ b/mozilla/content/shared/public/nsHTMLAtoms.h @@ -64,6 +64,7 @@ public: static nsIAtom* bottompadding; static nsIAtom* br; static nsIAtom* bulletPseudo; + static nsIAtom* button; static nsIAtom* caption; static nsIAtom* cellpadding; diff --git a/mozilla/content/shared/src/nsHTMLAtoms.cpp b/mozilla/content/shared/src/nsHTMLAtoms.cpp index 664697ff836..d15ad429828 100644 --- a/mozilla/content/shared/src/nsHTMLAtoms.cpp +++ b/mozilla/content/shared/src/nsHTMLAtoms.cpp @@ -44,6 +44,7 @@ nsIAtom* nsHTMLAtoms::bordercolor; nsIAtom* nsHTMLAtoms::bottompadding; nsIAtom* nsHTMLAtoms::br; nsIAtom* nsHTMLAtoms::bulletPseudo; +nsIAtom* nsHTMLAtoms::button; nsIAtom* nsHTMLAtoms::caption; nsIAtom* nsHTMLAtoms::cellpadding; nsIAtom* nsHTMLAtoms::cellspacing; @@ -259,6 +260,7 @@ void nsHTMLAtoms::AddrefAtoms() bottompadding = NS_NewAtom("BOTTOMPADDING"); br = NS_NewAtom("BR"); bulletPseudo = NS_NewAtom(":BULLET"); + button = NS_NewAtom("BUTTON"); caption = NS_NewAtom("CAPTION"); cellpadding = NS_NewAtom("CELLPADDING"); cellspacing = NS_NewAtom("CELLSPACING"); @@ -471,6 +473,7 @@ void nsHTMLAtoms::ReleaseAtoms() NS_RELEASE(bottompadding); NS_RELEASE(br); NS_RELEASE(bulletPseudo); + NS_RELEASE(button); NS_RELEASE(caption); NS_RELEASE(cellpadding); NS_RELEASE(cellspacing); diff --git a/mozilla/layout/forms/nsFileControlFrame.cpp b/mozilla/layout/forms/nsFileControlFrame.cpp index 9e73c4fcc62..c1b1e6e540d 100644 --- a/mozilla/layout/forms/nsFileControlFrame.cpp +++ b/mozilla/layout/forms/nsFileControlFrame.cpp @@ -17,6 +17,7 @@ */ #include "nsFileControlFrame.h" +#include "nsFormFrame.h" #include "nsButtonControlFrame.h" #include "nsTextControlFrame.h" #include "nsIContent.h" @@ -194,10 +195,14 @@ NS_IMETHODIMP nsFileControlFrame::Reflow(nsIPresContext& aPresContext, if (0 == numChildren) { // XXX This code should move to Init(), someday when the frame construction // changes are all done and Init() is always getting called... + PRBool disabled = nsFormFrame::GetDisabled(this); nsIHTMLContent* text = nsnull; nsIAtom* tag = NS_NewAtom("text"); NS_NewHTMLInputElement(&text, tag); text->SetAttribute("type", "text", PR_FALSE); + if (disabled) { + text->SetAttribute("disabled", "1", PR_FALSE); + } NS_NewTextControlFrame(text, this, childFrame); childFrame->SetStyleContext(&aPresContext, mStyleContext); mTextFrame = (nsTextControlFrame*)childFrame; @@ -207,6 +212,9 @@ NS_IMETHODIMP nsFileControlFrame::Reflow(nsIPresContext& aPresContext, tag = NS_NewAtom("browse"); NS_NewHTMLInputElement(&browse, tag); browse->SetAttribute("type", "browse", PR_FALSE); + if (disabled) { + browse->SetAttribute("disabled", "1", PR_FALSE); + } NS_NewButtonControlFrame(browse, this, childFrame); ((nsButtonControlFrame*)childFrame)->SetFileControlFrame(this); mBrowseFrame = (nsButtonControlFrame*)childFrame; diff --git a/mozilla/layout/forms/nsFormControlFrame.cpp b/mozilla/layout/forms/nsFormControlFrame.cpp index a05ab7f2d8e..c23690bc49d 100644 --- a/mozilla/layout/forms/nsFormControlFrame.cpp +++ b/mozilla/layout/forms/nsFormControlFrame.cpp @@ -341,6 +341,7 @@ nsFormControlFrame::GetWidget(nsIWidget** aWidget) if (mWidget) { NS_ADDREF(mWidget); *aWidget = mWidget; + mWidget->Enable(!nsFormFrame::GetDisabled(this)); return NS_OK; } else { *aWidget = nsnull; diff --git a/mozilla/layout/forms/nsHTMLButtonControlFrame.cpp b/mozilla/layout/forms/nsHTMLButtonControlFrame.cpp new file mode 100644 index 00000000000..08c3238709a --- /dev/null +++ b/mozilla/layout/forms/nsHTMLButtonControlFrame.cpp @@ -0,0 +1,481 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +#include "nsHTMLContainerFrame.h" +#include "nsIFormControlFrame.h" +#include "nsHTMLParts.h" +#include "nsIFormControl.h" +#include "nsFormFrame.h" + +#include "nsIRenderingContext.h" +#include "nsIPresContext.h" +#include "nsIPresShell.h" +#include "nsIStyleContext.h" +#include "nsLeafFrame.h" +#include "nsCSSRendering.h" +#include "nsHTMLIIDs.h" +#include "nsISupports.h" +#include "nsHTMLAtoms.h" +#include "nsIImage.h" +#include "nsHTMLImage.h" +#include "nsStyleUtil.h" +#include "nsDOMEvent.h" +#include "nsStyleConsts.h" +#include "nsIHTMLAttributes.h" +#include "nsGenericHTMLElement.h" +#include "nsIWidget.h" +#include "nsRepository.h" +#include "nsIView.h" +#include "nsIViewManager.h" +#include "nsViewsCID.h" + +//Enumeration of possible mouse states used to detect mouse clicks +enum nsMouseState { + eMouseNone, + eMouseEnter, + eMouseDown, + eMouseUp +}; + +static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); +static NS_DEFINE_IID(kIFormControlFrameIID, NS_IFORMCONTROLFRAME_IID); +static NS_DEFINE_IID(kViewCID, NS_VIEW_CID); +static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID); + +class nsHTMLButtonControlFrame : public nsHTMLContainerFrame, + public nsIFormControlFrame +{ +public: + nsHTMLButtonControlFrame(nsIContent* aContent, nsIFrame* aParentFrame); + + NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + + NS_IMETHOD Paint(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect); + + NS_IMETHOD Reflow(nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus); + + NS_IMETHOD HandleEvent(nsIPresContext& aPresContext, + nsGUIEvent* aEvent, + nsEventStatus& aEventStatus); + + NS_IMETHOD Init(nsIPresContext& aPresContext, nsIFrame* aChildList); + + virtual PRBool IsSuccessful(); + NS_IMETHOD GetType(PRInt32* aType) const; + NS_IMETHOD GetName(nsString* aName); + NS_IMETHOD GetValue(nsString* aName); + virtual PRInt32 GetMaxNumValues(); + virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames); + virtual void MouseClicked(nsIPresContext* aPresContext); + virtual void Reset() {}; + virtual void SetFormFrame(nsFormFrame* aFormFrame) { mFormFrame = aFormFrame; } + + void GetDefaultLabel(nsString& aLabel); + +protected: + virtual ~nsHTMLButtonControlFrame(); + NS_IMETHOD_(nsrefcnt) AddRef(void); + NS_IMETHOD_(nsrefcnt) Release(void); + + PRIntn GetSkipSides() const; + PRBool mInline; + nsFormFrame* mFormFrame; + nsMouseState mLastMouseState; + PRBool mGrabbingTheMouse; +}; + +nsresult +NS_NewHTMLButtonControlFrame(nsIContent* aContent, + nsIFrame* aParent, + nsIFrame*& aResult) +{ + aResult = new nsHTMLButtonControlFrame(aContent, aParent); + if (nsnull == aResult) { + return NS_ERROR_OUT_OF_MEMORY; + } + return NS_OK; +} + +nsHTMLButtonControlFrame::nsHTMLButtonControlFrame(nsIContent* aContent, + nsIFrame* aParentFrame) + : nsHTMLContainerFrame(aContent, aParentFrame) +{ + mInline = PR_TRUE; + mLastMouseState = eMouseNone; + mGrabbingTheMouse = PR_FALSE; +} + +nsHTMLButtonControlFrame::~nsHTMLButtonControlFrame() +{ +} + +nsrefcnt nsHTMLButtonControlFrame::AddRef(void) +{ + NS_WARNING("not supported"); + return 1; +} + +nsrefcnt nsHTMLButtonControlFrame::Release(void) +{ + NS_WARNING("not supported"); + return 1; +} + +nsresult +nsHTMLButtonControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) +{ + NS_PRECONDITION(0 != aInstancePtr, "null ptr"); + if (NULL == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + if (aIID.Equals(kIFormControlFrameIID)) { + *aInstancePtr = (void*) ((nsIFormControlFrame*) this); + return NS_OK; + } + return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtr); +} + +void +nsHTMLButtonControlFrame::GetDefaultLabel(nsString& aString) +{ + PRInt32 type; + GetType(&type); + if (NS_FORM_BUTTON_BUTTON == type) { + aString = "Button"; + } + else if (NS_FORM_BUTTON_RESET == type) { + aString = "Reset"; + } + else if (NS_FORM_BUTTON_SUBMIT == type) { + aString = "Submit"; + } +} + + +PRInt32 +nsHTMLButtonControlFrame::GetMaxNumValues() +{ + return 1; +} + + +PRBool +nsHTMLButtonControlFrame::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); + nsAutoString value; + nsresult valResult = GetValue(&value); + + if (NS_CONTENT_ATTR_HAS_VALUE == valResult) { + aValues[0] = value; + aNames[0] = name; + aNumValues = 1; + return PR_TRUE; + } else { + aNumValues = 0; + return PR_FALSE; + } +} + + +NS_IMETHODIMP +nsHTMLButtonControlFrame::GetType(PRInt32* aType) const +{ + nsresult result = NS_FORM_NOTOK; + if (mContent) { + nsIFormControl* formControl = nsnull; + result = mContent->QueryInterface(kIFormControlIID, (void**)&formControl); + if ((NS_OK == result) && formControl) { + result = formControl->GetType(aType); + NS_RELEASE(formControl); + } + } + return result; +} + +NS_IMETHODIMP +nsHTMLButtonControlFrame::GetName(nsString* aResult) +{ + nsresult result = NS_FORM_NOTOK; + if (mContent) { + nsIHTMLContent* formControl = nsnull; + result = mContent->QueryInterface(kIHTMLContentIID, (void**)&formControl); + if ((NS_OK == result) && formControl) { + nsHTMLValue value; + result = formControl->GetAttribute(nsHTMLAtoms::name, value); + if (NS_CONTENT_ATTR_HAS_VALUE == result) { + if (eHTMLUnit_String == value.GetUnit()) { + value.GetStringValue(*aResult); + } + } + NS_RELEASE(formControl); + } + } + return result; +} + +NS_IMETHODIMP +nsHTMLButtonControlFrame::GetValue(nsString* aResult) +{ + nsresult result = NS_FORM_NOTOK; + if (mContent) { + nsIHTMLContent* formControl = nsnull; + result = mContent->QueryInterface(kIHTMLContentIID, (void**)&formControl); + if ((NS_OK == result) && formControl) { + nsHTMLValue value; + result = formControl->GetAttribute(nsHTMLAtoms::value, value); + if (NS_CONTENT_ATTR_HAS_VALUE == result) { + if (eHTMLUnit_String == value.GetUnit()) { + value.GetStringValue(*aResult); + } + } + NS_RELEASE(formControl); + } + } + return result; +} + +PRBool +nsHTMLButtonControlFrame::IsSuccessful() +{ + nsAutoString name; + return (NS_CONTENT_ATTR_HAS_VALUE == GetName(&name)); +} + + + +void +nsHTMLButtonControlFrame::MouseClicked(nsIPresContext* aPresContext) +{ + if (!mFormFrame) { + return; + } + + PRInt32 type; + GetType(&type); + if (nsnull != mFormFrame) { + if (NS_FORM_BUTTON_RESET == type) { + //Send DOM event + nsEventStatus mStatus; + nsEvent mEvent; + mEvent.eventStructType = NS_EVENT; + mEvent.message = NS_FORM_RESET; + mContent->HandleDOMEvent(*aPresContext, &mEvent, nsnull, DOM_EVENT_INIT, mStatus); + + mFormFrame->OnReset(); + } + else if (NS_FORM_BUTTON_SUBMIT == type) { + //Send DOM event + nsEventStatus mStatus; + nsEvent mEvent; + mEvent.eventStructType = NS_EVENT; + mEvent.message = NS_FORM_SUBMIT; + mContent->HandleDOMEvent(*aPresContext, &mEvent, nsnull, DOM_EVENT_INIT, mStatus); + + mFormFrame->OnSubmit(aPresContext, this); + } + } +} + +NS_METHOD +nsHTMLButtonControlFrame::HandleEvent(nsIPresContext& aPresContext, + nsGUIEvent* aEvent, + nsEventStatus& aEventStatus) +{ + nsIWidget* window; + nsIView* view; + nsIViewManager* viewMan; + PRBool ignore; + + switch (aEvent->message) { + case NS_MOUSE_ENTER: // not implemented yet on frames + mLastMouseState = eMouseEnter; + break; + case NS_MOUSE_LEFT_BUTTON_DOWN: + mLastMouseState = eMouseDown; + //mLastMouseState = (eMouseEnter == mLastMouseState) ? eMouseDown : eMouseNone; + break; + case NS_MOUSE_MOVE: + GetWindow(window); + if (window) { + window->SetCursor(eCursor_arrow_west_plus); // XXX don't do this every time + NS_RELEASE(window); + } + if (!mGrabbingTheMouse) { + GetView(view); + if (view) { + view->GetViewManager(viewMan); + if (viewMan) { + viewMan->GrabMouseEvents(view, ignore); + NS_RELEASE(viewMan); + mGrabbingTheMouse = PR_TRUE; + } + } + } + break; + case NS_MOUSE_LEFT_BUTTON_UP: + if (eMouseDown == mLastMouseState) { + nsEventStatus status = nsEventStatus_eIgnore; + nsMouseEvent event; + event.eventStructType = NS_MOUSE_EVENT; + event.message = NS_MOUSE_LEFT_CLICK; + mContent->HandleDOMEvent(aPresContext, &event, nsnull, DOM_EVENT_INIT, status); + + if (nsEventStatus_eConsumeNoDefault != status) { + MouseClicked(&aPresContext); + } + } + mLastMouseState = eMouseEnter; + break; + case NS_MOUSE_EXIT: + GetWindow(window); + if (window) { + window->SetCursor(eCursor_standard); + NS_RELEASE(window); + } + GetView(view); + if (view) { + view->GetViewManager(viewMan); + if (viewMan) { + viewMan->GrabMouseEvents(nsnull, ignore); + NS_RELEASE(viewMan); + mGrabbingTheMouse = PR_FALSE; + } + } + mLastMouseState = eMouseNone; + break; + } + aEventStatus = nsEventStatus_eConsumeNoDefault; + return NS_OK; +} + +NS_IMETHODIMP +nsHTMLButtonControlFrame::Init(nsIPresContext& aPresContext, nsIFrame* aChildList) +{ + // cache our display type + const nsStyleDisplay* styleDisplay; + GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) styleDisplay); + mInline = (NS_STYLE_DISPLAY_BLOCK != styleDisplay->mDisplay); + + PRUint8 flags = (mInline) ? NS_BODY_SHRINK_WRAP : 0; + NS_NewBodyFrame(mContent, this, mFirstChild, flags); + + // Resolve style and set the style context + nsIStyleContext* styleContext = + aPresContext.ResolveStyleContextFor(mContent, this); + mFirstChild->SetStyleContext(&aPresContext, styleContext); + NS_RELEASE(styleContext); + + // Set the geometric and content parent for each of the child frames + for (nsIFrame* frame = aChildList; nsnull != frame; frame->GetNextSibling(frame)) { + frame->SetGeometricParent(mFirstChild); + frame->SetContentParent(mFirstChild); + } + + // Queue up the frames for the inline frame + return mFirstChild->Init(aPresContext, aChildList); +} + +NS_IMETHODIMP +nsHTMLButtonControlFrame::Paint(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect) +{ + return nsHTMLContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect); +} + +NS_IMETHODIMP +nsHTMLButtonControlFrame::Reflow(nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) +{ + nsSize availSize(aReflowState.maxSize); + + // reflow the child + nsHTMLReflowState reflowState(aPresContext, mFirstChild, aReflowState, availSize); + ReflowChild(mFirstChild, aPresContext, aDesiredSize, reflowState, aStatus); + + // get border and padding + const nsStyleSpacing* spacing = + (const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing); + nsMargin borderPadding; + spacing->CalcBorderPaddingFor(this, borderPadding); + + // Place the child + nsRect rect = nsRect(borderPadding.left, borderPadding.top, aDesiredSize.width, aDesiredSize.height); + mFirstChild->SetRect(rect); + + // add in our border and padding to the size of the child + aDesiredSize.width += borderPadding.left + borderPadding.right; + aDesiredSize.height += borderPadding.top + borderPadding.bottom; + + // adjust our max element size, if necessary + if (aDesiredSize.maxElementSize) { + aDesiredSize.maxElementSize->width += borderPadding.left + borderPadding.right; + aDesiredSize.maxElementSize->height += borderPadding.top + borderPadding.bottom; + } + aDesiredSize.ascent = aDesiredSize.height; + aDesiredSize.descent = 0; + + // create our view, we need a view to grab the mouse away from children frames + nsIView* view; + GetView(view); + if (!view) { + nsresult result = nsRepository::CreateInstance(kViewCID, nsnull, kIViewIID, + (void **)&view); + nsIPresShell *presShell = aPresContext.GetShell(); + nsIViewManager *viewMan = presShell->GetViewManager(); + NS_RELEASE(presShell); + + nsIFrame* parWithView; + nsIView *parView; + GetParentWithView(parWithView); + parWithView->GetView(parView); + nsRect boundBox(0, 0, aDesiredSize.width, aDesiredSize.height); + result = view->Init(viewMan, boundBox, parView, nsnull); + viewMan->InsertChild(parView, view, 0); + SetView(view); + NS_RELEASE(viewMan); + } + + aStatus = NS_FRAME_COMPLETE; + return NS_OK; +} + +PRIntn +nsHTMLButtonControlFrame::GetSkipSides() const +{ + return 0; +} + + diff --git a/mozilla/layout/forms/nsTextControlFrame.cpp b/mozilla/layout/forms/nsTextControlFrame.cpp index 250e46bc026..4312a2d7cb5 100644 --- a/mozilla/layout/forms/nsTextControlFrame.cpp +++ b/mozilla/layout/forms/nsTextControlFrame.cpp @@ -253,14 +253,14 @@ nsTextControlFrame::GetText(nsString* aText) GetType(&type); if (NS_FORM_INPUT_TEXT == type) { nsIDOMHTMLInputElement* textElem = nsnull; - nsresult result = mContent->QueryInterface(kIDOMHTMLInputElementIID, (void**)&textElem); + result = mContent->QueryInterface(kIDOMHTMLInputElementIID, (void**)&textElem); if ((NS_OK == result) && textElem) { result = textElem->GetValue(*aText); NS_RELEASE(textElem); } } else { nsIDOMHTMLTextAreaElement* textArea = nsnull; - nsresult result = mContent->QueryInterface(kIDOMHTMLTextAreaElementIID, (void**)&textArea); + result = mContent->QueryInterface(kIDOMHTMLTextAreaElementIID, (void**)&textArea); if ((NS_OK == result) && textArea) { result = textArea->GetDefaultValue(*aText); NS_RELEASE(textArea); @@ -303,6 +303,7 @@ nsTextControlFrame::PostCreateWidget(nsIPresContext* aPresContext) textArea->SetText(value, ignore); NS_RELEASE(textArea); } + mWidget->Enable(!nsFormFrame::GetDisabled(this)); } PRInt32 diff --git a/mozilla/layout/generic/nsHTMLParts.h b/mozilla/layout/generic/nsHTMLParts.h index c41b9f00bc8..581bbbc6c21 100644 --- a/mozilla/layout/generic/nsHTMLParts.h +++ b/mozilla/layout/generic/nsHTMLParts.h @@ -316,6 +316,10 @@ extern nsresult NS_NewButtonControlFrame(nsIContent* aContent, nsIFrame* aParentFrame, nsIFrame*& aResult); +extern nsresult +NS_NewHTMLButtonControlFrame(nsIContent* aContent, nsIFrame* aParentFrame, + nsIFrame*& aResult); + extern nsresult NS_NewCheckboxControlFrame(nsIContent* aContent, nsIFrame* aParentFrame, nsIFrame*& aResult); diff --git a/mozilla/layout/html/base/src/nsHTMLAtoms.cpp b/mozilla/layout/html/base/src/nsHTMLAtoms.cpp index 664697ff836..d15ad429828 100644 --- a/mozilla/layout/html/base/src/nsHTMLAtoms.cpp +++ b/mozilla/layout/html/base/src/nsHTMLAtoms.cpp @@ -44,6 +44,7 @@ nsIAtom* nsHTMLAtoms::bordercolor; nsIAtom* nsHTMLAtoms::bottompadding; nsIAtom* nsHTMLAtoms::br; nsIAtom* nsHTMLAtoms::bulletPseudo; +nsIAtom* nsHTMLAtoms::button; nsIAtom* nsHTMLAtoms::caption; nsIAtom* nsHTMLAtoms::cellpadding; nsIAtom* nsHTMLAtoms::cellspacing; @@ -259,6 +260,7 @@ void nsHTMLAtoms::AddrefAtoms() bottompadding = NS_NewAtom("BOTTOMPADDING"); br = NS_NewAtom("BR"); bulletPseudo = NS_NewAtom(":BULLET"); + button = NS_NewAtom("BUTTON"); caption = NS_NewAtom("CAPTION"); cellpadding = NS_NewAtom("CELLPADDING"); cellspacing = NS_NewAtom("CELLSPACING"); @@ -471,6 +473,7 @@ void nsHTMLAtoms::ReleaseAtoms() NS_RELEASE(bottompadding); NS_RELEASE(br); NS_RELEASE(bulletPseudo); + NS_RELEASE(button); NS_RELEASE(caption); NS_RELEASE(cellpadding); NS_RELEASE(cellspacing); diff --git a/mozilla/layout/html/base/src/nsHTMLAtoms.h b/mozilla/layout/html/base/src/nsHTMLAtoms.h index fe866cddc06..645146ccb68 100644 --- a/mozilla/layout/html/base/src/nsHTMLAtoms.h +++ b/mozilla/layout/html/base/src/nsHTMLAtoms.h @@ -64,6 +64,7 @@ public: static nsIAtom* bottompadding; static nsIAtom* br; static nsIAtom* bulletPseudo; + static nsIAtom* button; static nsIAtom* caption; static nsIAtom* cellpadding; diff --git a/mozilla/layout/html/base/src/nsHTMLParts.h b/mozilla/layout/html/base/src/nsHTMLParts.h index c41b9f00bc8..581bbbc6c21 100644 --- a/mozilla/layout/html/base/src/nsHTMLParts.h +++ b/mozilla/layout/html/base/src/nsHTMLParts.h @@ -316,6 +316,10 @@ extern nsresult NS_NewButtonControlFrame(nsIContent* aContent, nsIFrame* aParentFrame, nsIFrame*& aResult); +extern nsresult +NS_NewHTMLButtonControlFrame(nsIContent* aContent, nsIFrame* aParentFrame, + nsIFrame*& aResult); + extern nsresult NS_NewCheckboxControlFrame(nsIContent* aContent, nsIFrame* aParentFrame, nsIFrame*& aResult); diff --git a/mozilla/layout/html/content/public/nsIFormControl.h b/mozilla/layout/html/content/public/nsIFormControl.h index 7249c803174..d46896ebab8 100644 --- a/mozilla/layout/html/content/public/nsIFormControl.h +++ b/mozilla/layout/html/content/public/nsIFormControl.h @@ -23,23 +23,25 @@ class nsIDOMHTMLFormElement; class nsIWidget; #define NS_FORM_BROWSE 0 -#define NS_FORM_BUTTON 1 -#define NS_FORM_FIELDSET 2 -#define NS_FORM_INPUT_BUTTON 3 -#define NS_FORM_INPUT_CHECKBOX 4 -#define NS_FORM_INPUT_FILE 5 -#define NS_FORM_INPUT_HIDDEN 6 -#define NS_FORM_INPUT_RESET 7 -#define NS_FORM_INPUT_IMAGE 8 -#define NS_FORM_INPUT_PASSWORD 9 -#define NS_FORM_INPUT_RADIO 10 -#define NS_FORM_INPUT_SUBMIT 11 -#define NS_FORM_INPUT_TEXT 12 -#define NS_FORM_OPTION 13 -#define NS_FORM_OPTGROUP 14 -#define NS_FORM_LEGEND 15 -#define NS_FORM_SELECT 16 -#define NS_FORM_TEXTAREA 17 +#define NS_FORM_BUTTON_BUTTON 1 +#define NS_FORM_BUTTON_RESET 2 +#define NS_FORM_BUTTON_SUBMIT 3 +#define NS_FORM_FIELDSET 4 +#define NS_FORM_INPUT_BUTTON 5 +#define NS_FORM_INPUT_CHECKBOX 6 +#define NS_FORM_INPUT_FILE 7 +#define NS_FORM_INPUT_HIDDEN 8 +#define NS_FORM_INPUT_RESET 9 +#define NS_FORM_INPUT_IMAGE 10 +#define NS_FORM_INPUT_PASSWORD 11 +#define NS_FORM_INPUT_RADIO 12 +#define NS_FORM_INPUT_SUBMIT 13 +#define NS_FORM_INPUT_TEXT 14 +#define NS_FORM_OPTION 15 +#define NS_FORM_OPTGROUP 16 +#define NS_FORM_LEGEND 17 +#define NS_FORM_SELECT 18 +#define NS_FORM_TEXTAREA 19 #define NS_FORM_NOTOK 0xFFFFFFF7 #define NS_FORM_NOTSET 0xFFFFFFF7 diff --git a/mozilla/layout/html/content/src/nsHTMLButtonElement.cpp b/mozilla/layout/html/content/src/nsHTMLButtonElement.cpp index d33736e4a70..1b52ac7531c 100644 --- a/mozilla/layout/html/content/src/nsHTMLButtonElement.cpp +++ b/mozilla/layout/html/content/src/nsHTMLButtonElement.cpp @@ -17,6 +17,7 @@ * Netscape Communications Corporation. All Rights Reserved. */ #include "nsIDOMHTMLButtonElement.h" +#include "nsIDOMHTMLFormElement.h" #include "nsIScriptObjectOwner.h" #include "nsIDOMEventReceiver.h" #include "nsIHTMLContent.h" @@ -26,6 +27,8 @@ #include "nsIStyleContext.h" #include "nsStyleConsts.h" #include "nsIPresContext.h" +#include "nsIFormControl.h" +#include "nsIForm.h" #include "nsIEventStateManager.h" #include "nsDOMEvent.h" @@ -35,7 +38,8 @@ static NS_DEFINE_IID(kIDOMHTMLButtonElementIID, NS_IDOMHTMLBUTTONELEMENT_IID); class nsHTMLButtonElement : public nsIDOMHTMLButtonElement, public nsIScriptObjectOwner, public nsIDOMEventReceiver, - public nsIHTMLContent + public nsIHTMLContent, + public nsIFormControl { public: nsHTMLButtonElement(nsIAtom* aTag); @@ -81,10 +85,23 @@ public: // nsIHTMLContent NS_IMPL_IHTMLCONTENT_USING_GENERIC(mInner) + // nsIFormControl + NS_IMETHOD GetType(PRInt32* aType); + NS_IMETHOD SetWidget(nsIWidget* aWidget) { return NS_OK; }; + NS_IMETHOD Init() { return NS_OK; } + protected: nsGenericHTMLContainerElement mInner; + nsIForm* mForm; + PRInt32 mType; }; +static NS_DEFINE_IID(kIDOMHTMLFormElementIID, NS_IDOMHTMLFORMELEMENT_IID); +static NS_DEFINE_IID(kIFormIID, NS_IFORM_IID); +static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); + +// Construction, destruction + nsresult NS_NewHTMLButtonElement(nsIHTMLContent** aInstancePtrResult, nsIAtom* aTag) { @@ -103,29 +120,64 @@ nsHTMLButtonElement::nsHTMLButtonElement(nsIAtom* aTag) { NS_INIT_REFCNT(); mInner.Init(this, aTag); + mForm = nsnull; + mType = NS_FORM_BUTTON_BUTTON; // default } nsHTMLButtonElement::~nsHTMLButtonElement() { + if (nsnull != mForm) { + // prevent mForm from decrementing its ref count on us + mForm->RemoveElement(this, PR_FALSE); + NS_RELEASE(mForm); + } } -NS_IMPL_ADDREF(nsHTMLButtonElement) +// nsISupports -NS_IMPL_RELEASE(nsHTMLButtonElement) +NS_IMETHODIMP_(nsrefcnt) +nsHTMLButtonElement::AddRef(void) +{ + PRInt32 refCnt = mRefCnt; // debugging + return ++mRefCnt; +} nsresult nsHTMLButtonElement::QueryInterface(REFNSIID aIID, void** aInstancePtr) { NS_IMPL_HTML_CONTENT_QUERY_INTERFACE(aIID, aInstancePtr, this) if (aIID.Equals(kIDOMHTMLButtonElementIID)) { - nsIDOMHTMLButtonElement* tmp = this; - *aInstancePtr = (void*) tmp; + *aInstancePtr = (void*)(nsIDOMHTMLButtonElement*)this; mRefCnt++; return NS_OK; } + else if (aIID.Equals(kIFormControlIID)) { + *aInstancePtr = (void*)(nsIFormControl*) this; + NS_ADDREF_THIS(); + return NS_OK; + } return NS_NOINTERFACE; } +NS_IMETHODIMP_(nsrefcnt) +nsHTMLButtonElement::Release() +{ + --mRefCnt; + if (mRefCnt <= 0) { + delete this; + return 0; + } else if ((1 == mRefCnt) && mForm) { + mRefCnt = 0; + delete this; + return 0; + } else { + return mRefCnt; + } +} + + +// nsIDOMHTMLButtonElement + nsresult nsHTMLButtonElement::CloneNode(nsIDOMNode** aReturn) { @@ -137,17 +189,43 @@ nsHTMLButtonElement::CloneNode(nsIDOMNode** aReturn) return it->QueryInterface(kIDOMNodeIID, (void**) aReturn); } -NS_IMETHODIMP -nsHTMLButtonElement::GetForm(nsIDOMHTMLFormElement** aForm) -{ - *aForm = nsnull;/* XXX */ - return NS_OK; -} - +// An important assumption is that if aForm is null, the previous mForm will not be released +// This allows nsHTMLFormElement to deal with circular references. NS_IMETHODIMP nsHTMLButtonElement::SetForm(nsIDOMHTMLFormElement* aForm) { - return NS_OK; + nsresult result = NS_OK; + if (nsnull == aForm) { + mForm = nsnull; + return NS_OK; + } else { + NS_IF_RELEASE(mForm); + nsIFormControl* formControl = nsnull; + result = QueryInterface(kIFormControlIID, (void**)&formControl); + if ((NS_OK == result) && formControl) { + result = aForm->QueryInterface(kIFormIID, (void**)&mForm); // keep the ref + if ((NS_OK == result) && mForm) { + mForm->AddElement(formControl); + } + NS_RELEASE(formControl); + } + } + return result; +} + +NS_IMETHODIMP +nsHTMLButtonElement::GetForm(nsIDOMHTMLFormElement** aForm) +{ + nsresult result = NS_OK; + *aForm = nsnull; + if (nsnull != mForm) { + nsIDOMHTMLFormElement* formElem = nsnull; + result = mForm->QueryInterface(kIDOMHTMLFormElementIID, (void**)&formElem); + if (NS_OK == result) { + *aForm = formElem; + } + } + return result; } NS_IMPL_STRING_ATTR(nsHTMLButtonElement, AccessKey, accesskey, eSetAttrNotify_None) @@ -157,6 +235,13 @@ NS_IMPL_STRING_ATTR(nsHTMLButtonElement, Type, type, eSetAttrNotify_Restart) NS_IMPL_INT_ATTR(nsHTMLButtonElement, TabIndex, tabindex, eSetAttrNotify_None) NS_IMPL_STRING_ATTR(nsHTMLButtonElement, Value, value, eSetAttrNotify_Render) +static nsGenericHTMLElement::EnumTable kButtonTypeTable[] = { + { "button", NS_FORM_BUTTON_BUTTON }, + { "reset", NS_FORM_BUTTON_RESET }, + { "submit", NS_FORM_BUTTON_SUBMIT }, + { 0 } +}; + NS_IMETHODIMP nsHTMLButtonElement::StringToAttribute(nsIAtom* aAttribute, const nsString& aValue, @@ -167,6 +252,21 @@ nsHTMLButtonElement::StringToAttribute(nsIAtom* aAttribute, eHTMLUnit_Integer); return NS_CONTENT_ATTR_HAS_VALUE; } + if (aAttribute == nsHTMLAtoms::type) { + nsGenericHTMLElement::EnumTable *table = kButtonTypeTable; + while (nsnull != table->tag) { + if (aValue.EqualsIgnoreCase(table->tag)) { + aResult.SetIntValue(table->value, eHTMLUnit_Enumerated); + mType = table->value; + return NS_CONTENT_ATTR_HAS_VALUE; + } + table++; + } + } + else if (aAttribute == nsHTMLAtoms::disabled) { + aResult.SetEmptyValue(); + return NS_CONTENT_ATTR_HAS_VALUE; + } return NS_CONTENT_ATTR_NOT_THERE; } @@ -175,6 +275,12 @@ nsHTMLButtonElement::AttributeToString(nsIAtom* aAttribute, nsHTMLValue& aValue, nsString& aResult) const { + if (aAttribute == nsHTMLAtoms::type) { + if (eHTMLUnit_Enumerated == aValue.GetUnit()) { + nsGenericHTMLElement::EnumValueToString(aValue, kButtonTypeTable, aResult); + return NS_CONTENT_ATTR_HAS_VALUE; + } + } return mInner.AttributeToString(aAttribute, aValue, aResult); } @@ -282,3 +388,14 @@ nsHTMLButtonElement::HandleDOMEvent(nsIPresContext& aPresContext, } return ret; } + +NS_IMETHODIMP +nsHTMLButtonElement::GetType(PRInt32* aType) +{ + if (aType) { + *aType = mType; + return NS_OK; + } else { + return NS_FORM_NOTOK; + } +} diff --git a/mozilla/layout/html/content/src/nsHTMLInputElement.cpp b/mozilla/layout/html/content/src/nsHTMLInputElement.cpp index f3362732f99..861b9ac089d 100644 --- a/mozilla/layout/html/content/src/nsHTMLInputElement.cpp +++ b/mozilla/layout/html/content/src/nsHTMLInputElement.cpp @@ -352,6 +352,14 @@ nsHTMLInputElement::StringToAttribute(nsIAtom* aAttribute, aResult.SetEmptyValue(); return NS_CONTENT_ATTR_HAS_VALUE; } + else if (aAttribute == nsHTMLAtoms::disabled) { + aResult.SetEmptyValue(); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::readonly) { + aResult.SetEmptyValue(); + return NS_CONTENT_ATTR_HAS_VALUE; + } else if (aAttribute == nsHTMLAtoms::width) { nsGenericHTMLElement::ParseValueOrPercent(aValue, aResult, eHTMLUnit_Pixel); diff --git a/mozilla/layout/html/content/src/nsHTMLSelectElement.cpp b/mozilla/layout/html/content/src/nsHTMLSelectElement.cpp index a0011688e08..e496bdf5bbc 100644 --- a/mozilla/layout/html/content/src/nsHTMLSelectElement.cpp +++ b/mozilla/layout/html/content/src/nsHTMLSelectElement.cpp @@ -317,7 +317,7 @@ NS_IMPL_INT_ATTR(nsHTMLSelectElement, SelectedIndex, selectedindex, eSetAttrNoti NS_IMPL_STRING_ATTR(nsHTMLSelectElement, Value, value, eSetAttrNotify_Render) NS_IMPL_INT_ATTR(nsHTMLSelectElement, Length, length, eSetAttrNotify_Restart) NS_IMPL_BOOL_ATTR(nsHTMLSelectElement, Disabled, disabled, eSetAttrNotify_Render) -NS_IMPL_INT_ATTR(nsHTMLSelectElement, Multiple, multiple, eSetAttrNotify_Restart) +NS_IMPL_BOOL_ATTR(nsHTMLSelectElement, Multiple, multiple, eSetAttrNotify_Restart) NS_IMPL_STRING_ATTR(nsHTMLSelectElement, Name, name, eSetAttrNotify_Restart) NS_IMPL_INT_ATTR(nsHTMLSelectElement, Size, size, eSetAttrNotify_Render) NS_IMPL_INT_ATTR(nsHTMLSelectElement, TabIndex, tabindex, eSetAttrNotify_Render) diff --git a/mozilla/layout/html/document/src/nsHTMLContentSink.cpp b/mozilla/layout/html/document/src/nsHTMLContentSink.cpp index 964b940cf61..92c1ec40667 100644 --- a/mozilla/layout/html/document/src/nsHTMLContentSink.cpp +++ b/mozilla/layout/html/document/src/nsHTMLContentSink.cpp @@ -501,6 +501,10 @@ MakeContentObject(nsHTMLTag aNodeType, case eHTMLTag_br: rv = NS_NewHTMLBRElement(aResult, aAtom); break; + case eHTMLTag_button: + rv = NS_NewHTMLButtonElement(aResult, aAtom); + SetForm(*aResult, aForm); + break; case eHTMLTag_caption: rv = NS_NewHTMLTableCaptionElement(aResult, aAtom); break; diff --git a/mozilla/layout/html/forms/src/Makefile b/mozilla/layout/html/forms/src/Makefile index 6e2e038ad5e..505bcbc05c6 100644 --- a/mozilla/layout/html/forms/src/Makefile +++ b/mozilla/layout/html/forms/src/Makefile @@ -35,6 +35,7 @@ CPPSRCS = \ nsSelectControlFrame.cpp \ nsFieldSetFrame.cpp \ nsLegendFrame.cpp \ + nsHTMLButtonControlFrame.cpp \ $(NULL) MODULE = raptor diff --git a/mozilla/layout/html/forms/src/makefile.win b/mozilla/layout/html/forms/src/makefile.win index ed65a4c178d..bbb87ecb540 100644 --- a/mozilla/layout/html/forms/src/makefile.win +++ b/mozilla/layout/html/forms/src/makefile.win @@ -25,13 +25,14 @@ REQUIRES=xpcom raptor js CPPSRCS=nsFormFrame.cpp nsFormControlFrame.cpp nsButtonControlFrame.cpp nsCheckboxControlFrame.cpp \ nsFileControlFrame.cpp nsRadioControlFrame.cpp nsTextControlFrame.cpp nsSelectControlFrame.cpp \ - nsFieldSetFrame.cpp nsLegendFrame.cpp + nsFieldSetFrame.cpp nsLegendFrame.cpp nsHTMLButtonControlFrame.cpp CPP_OBJS=.\$(OBJDIR)\nsFormFrame.obj .\$(OBJDIR)\nsFormControlFrame.obj \ .\$(OBJDIR)\nsButtonControlFrame.obj .\$(OBJDIR)\nsCheckboxControlFrame.obj \ .\$(OBJDIR)\nsFileControlFrame.obj .\$(OBJDIR)\nsRadioControlFrame.obj \ .\$(OBJDIR)\nsTextControlFrame.obj .\$(OBJDIR)\nsSelectControlFrame.obj \ - .\$(OBJDIR)\nsFieldSetFrame.obj .\$(OBJDIR)\nsLegendFrame.obj + .\$(OBJDIR)\nsFieldSetFrame.obj .\$(OBJDIR)\nsLegendFrame.obj \ + .\$(OBJDIR)\nsHTMLButtonControlFrame.obj LINCS=-I$(PUBLIC)\xpcom -I$(PUBLIC)\raptor -I$(PUBLIC)\js \ -I$(PUBLIC)\dom -I$(PUBLIC)\netlib \ diff --git a/mozilla/layout/html/forms/src/nsButtonControlFrame.cpp b/mozilla/layout/html/forms/src/nsButtonControlFrame.cpp index be0b1a80566..cf4468ce0ca 100644 --- a/mozilla/layout/html/forms/src/nsButtonControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsButtonControlFrame.cpp @@ -255,7 +255,8 @@ nsButtonControlFrame::MouseClicked(nsIPresContext* aPresContext) mFormFrame->OnReset(); } - else if ((NS_FORM_INPUT_SUBMIT == type) || (NS_FORM_INPUT_IMAGE == type)) { + else if ((NS_FORM_INPUT_SUBMIT == type) || + ((NS_FORM_INPUT_IMAGE == type) && !nsFormFrame::GetDisabled(this))) { //Send DOM event nsEventStatus mStatus; nsEvent mEvent; @@ -373,6 +374,7 @@ nsButtonControlFrame::PostCreateWidget(nsIPresContext* aPresContext) button->SetLabel(label); } } + mWidget->Enable(!nsFormFrame::GetDisabled(this)); NS_RELEASE(button); } } diff --git a/mozilla/layout/html/forms/src/nsCheckboxControlFrame.cpp b/mozilla/layout/html/forms/src/nsCheckboxControlFrame.cpp index 8d4a8d17416..06fe8704694 100644 --- a/mozilla/layout/html/forms/src/nsCheckboxControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsCheckboxControlFrame.cpp @@ -18,6 +18,7 @@ #include "nsICheckButton.h" #include "nsFormControlFrame.h" +#include "nsFormFrame.h" #include "nsIContent.h" #include "prtypes.h" #include "nsIFrame.h" @@ -143,17 +144,22 @@ nsCheckboxControlFrame::GetChecked(PRBool* aResult) void nsCheckboxControlFrame::PostCreateWidget(nsIPresContext* aPresContext) { - PRBool checked; - nsresult result = GetChecked(&checked); - if (NS_CONTENT_ATTR_HAS_VALUE == result) { - // set the widget to the initial state - nsICheckButton* checkbox = nsnull; - - if (mWidget && (NS_OK == mWidget->QueryInterface(GetIID(),(void**)&checkbox))) { + if (!mWidget) { + return; + } + + SetColors(*aPresContext); + mWidget->Enable(!nsFormFrame::GetDisabled(this)); + + // set the widget to the initial state + nsICheckButton* checkbox = nsnull; + if (NS_OK == mWidget->QueryInterface(GetIID(),(void**)&checkbox)) { + PRBool checked; + nsresult result = GetChecked(&checked); + if (NS_CONTENT_ATTR_HAS_VALUE == result) { checkbox->SetState(checked); - SetColors(*aPresContext); - NS_IF_RELEASE(checkbox); } + NS_RELEASE(checkbox); } } diff --git a/mozilla/layout/html/forms/src/nsFileControlFrame.cpp b/mozilla/layout/html/forms/src/nsFileControlFrame.cpp index 9e73c4fcc62..c1b1e6e540d 100644 --- a/mozilla/layout/html/forms/src/nsFileControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsFileControlFrame.cpp @@ -17,6 +17,7 @@ */ #include "nsFileControlFrame.h" +#include "nsFormFrame.h" #include "nsButtonControlFrame.h" #include "nsTextControlFrame.h" #include "nsIContent.h" @@ -194,10 +195,14 @@ NS_IMETHODIMP nsFileControlFrame::Reflow(nsIPresContext& aPresContext, if (0 == numChildren) { // XXX This code should move to Init(), someday when the frame construction // changes are all done and Init() is always getting called... + PRBool disabled = nsFormFrame::GetDisabled(this); nsIHTMLContent* text = nsnull; nsIAtom* tag = NS_NewAtom("text"); NS_NewHTMLInputElement(&text, tag); text->SetAttribute("type", "text", PR_FALSE); + if (disabled) { + text->SetAttribute("disabled", "1", PR_FALSE); + } NS_NewTextControlFrame(text, this, childFrame); childFrame->SetStyleContext(&aPresContext, mStyleContext); mTextFrame = (nsTextControlFrame*)childFrame; @@ -207,6 +212,9 @@ NS_IMETHODIMP nsFileControlFrame::Reflow(nsIPresContext& aPresContext, tag = NS_NewAtom("browse"); NS_NewHTMLInputElement(&browse, tag); browse->SetAttribute("type", "browse", PR_FALSE); + if (disabled) { + browse->SetAttribute("disabled", "1", PR_FALSE); + } NS_NewButtonControlFrame(browse, this, childFrame); ((nsButtonControlFrame*)childFrame)->SetFileControlFrame(this); mBrowseFrame = (nsButtonControlFrame*)childFrame; diff --git a/mozilla/layout/html/forms/src/nsFormControlFrame.cpp b/mozilla/layout/html/forms/src/nsFormControlFrame.cpp index a05ab7f2d8e..c23690bc49d 100644 --- a/mozilla/layout/html/forms/src/nsFormControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsFormControlFrame.cpp @@ -341,6 +341,7 @@ nsFormControlFrame::GetWidget(nsIWidget** aWidget) if (mWidget) { NS_ADDREF(mWidget); *aWidget = mWidget; + mWidget->Enable(!nsFormFrame::GetDisabled(this)); return NS_OK; } else { *aWidget = nsnull; diff --git a/mozilla/layout/html/forms/src/nsFormFrame.cpp b/mozilla/layout/html/forms/src/nsFormFrame.cpp index 6f0882ab909..4d73a0db77e 100644 --- a/mozilla/layout/html/forms/src/nsFormFrame.cpp +++ b/mozilla/layout/html/forms/src/nsFormFrame.cpp @@ -1016,3 +1016,31 @@ char* nsFormFrame::Temp_GenerateTempFileName(PRInt32 aMaxSize, char* file_buf) } + +// static helper functions for nsIFormControls + +PRBool +nsFormFrame::GetDisabled(nsIFrame* aChildFrame, nsIContent* aContent) +{ + PRBool result = PR_FALSE; + + nsIContent* content = aContent; + if (nsnull == content) { + aChildFrame->GetContent(content); + } + if (nsnull != content) { + nsIHTMLContent* htmlContent = nsnull; + content->QueryInterface(kIHTMLContentIID, (void**)&htmlContent); + if (nsnull != htmlContent) { + nsHTMLValue value; + if (NS_CONTENT_ATTR_HAS_VALUE == htmlContent->GetAttribute(nsHTMLAtoms::disabled, value)) { + result = PR_TRUE; + } + NS_RELEASE(htmlContent); + } + if (nsnull == aContent) { + NS_RELEASE(content); + } + } + return result; +} diff --git a/mozilla/layout/html/forms/src/nsFormFrame.h b/mozilla/layout/html/forms/src/nsFormFrame.h index 0a26da97e66..f6a40a114b6 100644 --- a/mozilla/layout/html/forms/src/nsFormFrame.h +++ b/mozilla/layout/html/forms/src/nsFormFrame.h @@ -64,6 +64,9 @@ public: NS_IMETHOD GetTarget(nsString* aTarget); NS_IMETHOD GetAction(nsString* aAction); + // static helper functions for nsIFormControls + + static PRBool GetDisabled(nsIFrame* aChildFrame, nsIContent* aContent = 0); protected: NS_IMETHOD_(nsrefcnt) AddRef(void); diff --git a/mozilla/layout/html/forms/src/nsHTMLButtonControlFrame.cpp b/mozilla/layout/html/forms/src/nsHTMLButtonControlFrame.cpp new file mode 100644 index 00000000000..08c3238709a --- /dev/null +++ b/mozilla/layout/html/forms/src/nsHTMLButtonControlFrame.cpp @@ -0,0 +1,481 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +#include "nsHTMLContainerFrame.h" +#include "nsIFormControlFrame.h" +#include "nsHTMLParts.h" +#include "nsIFormControl.h" +#include "nsFormFrame.h" + +#include "nsIRenderingContext.h" +#include "nsIPresContext.h" +#include "nsIPresShell.h" +#include "nsIStyleContext.h" +#include "nsLeafFrame.h" +#include "nsCSSRendering.h" +#include "nsHTMLIIDs.h" +#include "nsISupports.h" +#include "nsHTMLAtoms.h" +#include "nsIImage.h" +#include "nsHTMLImage.h" +#include "nsStyleUtil.h" +#include "nsDOMEvent.h" +#include "nsStyleConsts.h" +#include "nsIHTMLAttributes.h" +#include "nsGenericHTMLElement.h" +#include "nsIWidget.h" +#include "nsRepository.h" +#include "nsIView.h" +#include "nsIViewManager.h" +#include "nsViewsCID.h" + +//Enumeration of possible mouse states used to detect mouse clicks +enum nsMouseState { + eMouseNone, + eMouseEnter, + eMouseDown, + eMouseUp +}; + +static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); +static NS_DEFINE_IID(kIFormControlFrameIID, NS_IFORMCONTROLFRAME_IID); +static NS_DEFINE_IID(kViewCID, NS_VIEW_CID); +static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID); + +class nsHTMLButtonControlFrame : public nsHTMLContainerFrame, + public nsIFormControlFrame +{ +public: + nsHTMLButtonControlFrame(nsIContent* aContent, nsIFrame* aParentFrame); + + NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + + NS_IMETHOD Paint(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect); + + NS_IMETHOD Reflow(nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus); + + NS_IMETHOD HandleEvent(nsIPresContext& aPresContext, + nsGUIEvent* aEvent, + nsEventStatus& aEventStatus); + + NS_IMETHOD Init(nsIPresContext& aPresContext, nsIFrame* aChildList); + + virtual PRBool IsSuccessful(); + NS_IMETHOD GetType(PRInt32* aType) const; + NS_IMETHOD GetName(nsString* aName); + NS_IMETHOD GetValue(nsString* aName); + virtual PRInt32 GetMaxNumValues(); + virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames); + virtual void MouseClicked(nsIPresContext* aPresContext); + virtual void Reset() {}; + virtual void SetFormFrame(nsFormFrame* aFormFrame) { mFormFrame = aFormFrame; } + + void GetDefaultLabel(nsString& aLabel); + +protected: + virtual ~nsHTMLButtonControlFrame(); + NS_IMETHOD_(nsrefcnt) AddRef(void); + NS_IMETHOD_(nsrefcnt) Release(void); + + PRIntn GetSkipSides() const; + PRBool mInline; + nsFormFrame* mFormFrame; + nsMouseState mLastMouseState; + PRBool mGrabbingTheMouse; +}; + +nsresult +NS_NewHTMLButtonControlFrame(nsIContent* aContent, + nsIFrame* aParent, + nsIFrame*& aResult) +{ + aResult = new nsHTMLButtonControlFrame(aContent, aParent); + if (nsnull == aResult) { + return NS_ERROR_OUT_OF_MEMORY; + } + return NS_OK; +} + +nsHTMLButtonControlFrame::nsHTMLButtonControlFrame(nsIContent* aContent, + nsIFrame* aParentFrame) + : nsHTMLContainerFrame(aContent, aParentFrame) +{ + mInline = PR_TRUE; + mLastMouseState = eMouseNone; + mGrabbingTheMouse = PR_FALSE; +} + +nsHTMLButtonControlFrame::~nsHTMLButtonControlFrame() +{ +} + +nsrefcnt nsHTMLButtonControlFrame::AddRef(void) +{ + NS_WARNING("not supported"); + return 1; +} + +nsrefcnt nsHTMLButtonControlFrame::Release(void) +{ + NS_WARNING("not supported"); + return 1; +} + +nsresult +nsHTMLButtonControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) +{ + NS_PRECONDITION(0 != aInstancePtr, "null ptr"); + if (NULL == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + if (aIID.Equals(kIFormControlFrameIID)) { + *aInstancePtr = (void*) ((nsIFormControlFrame*) this); + return NS_OK; + } + return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtr); +} + +void +nsHTMLButtonControlFrame::GetDefaultLabel(nsString& aString) +{ + PRInt32 type; + GetType(&type); + if (NS_FORM_BUTTON_BUTTON == type) { + aString = "Button"; + } + else if (NS_FORM_BUTTON_RESET == type) { + aString = "Reset"; + } + else if (NS_FORM_BUTTON_SUBMIT == type) { + aString = "Submit"; + } +} + + +PRInt32 +nsHTMLButtonControlFrame::GetMaxNumValues() +{ + return 1; +} + + +PRBool +nsHTMLButtonControlFrame::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); + nsAutoString value; + nsresult valResult = GetValue(&value); + + if (NS_CONTENT_ATTR_HAS_VALUE == valResult) { + aValues[0] = value; + aNames[0] = name; + aNumValues = 1; + return PR_TRUE; + } else { + aNumValues = 0; + return PR_FALSE; + } +} + + +NS_IMETHODIMP +nsHTMLButtonControlFrame::GetType(PRInt32* aType) const +{ + nsresult result = NS_FORM_NOTOK; + if (mContent) { + nsIFormControl* formControl = nsnull; + result = mContent->QueryInterface(kIFormControlIID, (void**)&formControl); + if ((NS_OK == result) && formControl) { + result = formControl->GetType(aType); + NS_RELEASE(formControl); + } + } + return result; +} + +NS_IMETHODIMP +nsHTMLButtonControlFrame::GetName(nsString* aResult) +{ + nsresult result = NS_FORM_NOTOK; + if (mContent) { + nsIHTMLContent* formControl = nsnull; + result = mContent->QueryInterface(kIHTMLContentIID, (void**)&formControl); + if ((NS_OK == result) && formControl) { + nsHTMLValue value; + result = formControl->GetAttribute(nsHTMLAtoms::name, value); + if (NS_CONTENT_ATTR_HAS_VALUE == result) { + if (eHTMLUnit_String == value.GetUnit()) { + value.GetStringValue(*aResult); + } + } + NS_RELEASE(formControl); + } + } + return result; +} + +NS_IMETHODIMP +nsHTMLButtonControlFrame::GetValue(nsString* aResult) +{ + nsresult result = NS_FORM_NOTOK; + if (mContent) { + nsIHTMLContent* formControl = nsnull; + result = mContent->QueryInterface(kIHTMLContentIID, (void**)&formControl); + if ((NS_OK == result) && formControl) { + nsHTMLValue value; + result = formControl->GetAttribute(nsHTMLAtoms::value, value); + if (NS_CONTENT_ATTR_HAS_VALUE == result) { + if (eHTMLUnit_String == value.GetUnit()) { + value.GetStringValue(*aResult); + } + } + NS_RELEASE(formControl); + } + } + return result; +} + +PRBool +nsHTMLButtonControlFrame::IsSuccessful() +{ + nsAutoString name; + return (NS_CONTENT_ATTR_HAS_VALUE == GetName(&name)); +} + + + +void +nsHTMLButtonControlFrame::MouseClicked(nsIPresContext* aPresContext) +{ + if (!mFormFrame) { + return; + } + + PRInt32 type; + GetType(&type); + if (nsnull != mFormFrame) { + if (NS_FORM_BUTTON_RESET == type) { + //Send DOM event + nsEventStatus mStatus; + nsEvent mEvent; + mEvent.eventStructType = NS_EVENT; + mEvent.message = NS_FORM_RESET; + mContent->HandleDOMEvent(*aPresContext, &mEvent, nsnull, DOM_EVENT_INIT, mStatus); + + mFormFrame->OnReset(); + } + else if (NS_FORM_BUTTON_SUBMIT == type) { + //Send DOM event + nsEventStatus mStatus; + nsEvent mEvent; + mEvent.eventStructType = NS_EVENT; + mEvent.message = NS_FORM_SUBMIT; + mContent->HandleDOMEvent(*aPresContext, &mEvent, nsnull, DOM_EVENT_INIT, mStatus); + + mFormFrame->OnSubmit(aPresContext, this); + } + } +} + +NS_METHOD +nsHTMLButtonControlFrame::HandleEvent(nsIPresContext& aPresContext, + nsGUIEvent* aEvent, + nsEventStatus& aEventStatus) +{ + nsIWidget* window; + nsIView* view; + nsIViewManager* viewMan; + PRBool ignore; + + switch (aEvent->message) { + case NS_MOUSE_ENTER: // not implemented yet on frames + mLastMouseState = eMouseEnter; + break; + case NS_MOUSE_LEFT_BUTTON_DOWN: + mLastMouseState = eMouseDown; + //mLastMouseState = (eMouseEnter == mLastMouseState) ? eMouseDown : eMouseNone; + break; + case NS_MOUSE_MOVE: + GetWindow(window); + if (window) { + window->SetCursor(eCursor_arrow_west_plus); // XXX don't do this every time + NS_RELEASE(window); + } + if (!mGrabbingTheMouse) { + GetView(view); + if (view) { + view->GetViewManager(viewMan); + if (viewMan) { + viewMan->GrabMouseEvents(view, ignore); + NS_RELEASE(viewMan); + mGrabbingTheMouse = PR_TRUE; + } + } + } + break; + case NS_MOUSE_LEFT_BUTTON_UP: + if (eMouseDown == mLastMouseState) { + nsEventStatus status = nsEventStatus_eIgnore; + nsMouseEvent event; + event.eventStructType = NS_MOUSE_EVENT; + event.message = NS_MOUSE_LEFT_CLICK; + mContent->HandleDOMEvent(aPresContext, &event, nsnull, DOM_EVENT_INIT, status); + + if (nsEventStatus_eConsumeNoDefault != status) { + MouseClicked(&aPresContext); + } + } + mLastMouseState = eMouseEnter; + break; + case NS_MOUSE_EXIT: + GetWindow(window); + if (window) { + window->SetCursor(eCursor_standard); + NS_RELEASE(window); + } + GetView(view); + if (view) { + view->GetViewManager(viewMan); + if (viewMan) { + viewMan->GrabMouseEvents(nsnull, ignore); + NS_RELEASE(viewMan); + mGrabbingTheMouse = PR_FALSE; + } + } + mLastMouseState = eMouseNone; + break; + } + aEventStatus = nsEventStatus_eConsumeNoDefault; + return NS_OK; +} + +NS_IMETHODIMP +nsHTMLButtonControlFrame::Init(nsIPresContext& aPresContext, nsIFrame* aChildList) +{ + // cache our display type + const nsStyleDisplay* styleDisplay; + GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) styleDisplay); + mInline = (NS_STYLE_DISPLAY_BLOCK != styleDisplay->mDisplay); + + PRUint8 flags = (mInline) ? NS_BODY_SHRINK_WRAP : 0; + NS_NewBodyFrame(mContent, this, mFirstChild, flags); + + // Resolve style and set the style context + nsIStyleContext* styleContext = + aPresContext.ResolveStyleContextFor(mContent, this); + mFirstChild->SetStyleContext(&aPresContext, styleContext); + NS_RELEASE(styleContext); + + // Set the geometric and content parent for each of the child frames + for (nsIFrame* frame = aChildList; nsnull != frame; frame->GetNextSibling(frame)) { + frame->SetGeometricParent(mFirstChild); + frame->SetContentParent(mFirstChild); + } + + // Queue up the frames for the inline frame + return mFirstChild->Init(aPresContext, aChildList); +} + +NS_IMETHODIMP +nsHTMLButtonControlFrame::Paint(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect) +{ + return nsHTMLContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect); +} + +NS_IMETHODIMP +nsHTMLButtonControlFrame::Reflow(nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) +{ + nsSize availSize(aReflowState.maxSize); + + // reflow the child + nsHTMLReflowState reflowState(aPresContext, mFirstChild, aReflowState, availSize); + ReflowChild(mFirstChild, aPresContext, aDesiredSize, reflowState, aStatus); + + // get border and padding + const nsStyleSpacing* spacing = + (const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing); + nsMargin borderPadding; + spacing->CalcBorderPaddingFor(this, borderPadding); + + // Place the child + nsRect rect = nsRect(borderPadding.left, borderPadding.top, aDesiredSize.width, aDesiredSize.height); + mFirstChild->SetRect(rect); + + // add in our border and padding to the size of the child + aDesiredSize.width += borderPadding.left + borderPadding.right; + aDesiredSize.height += borderPadding.top + borderPadding.bottom; + + // adjust our max element size, if necessary + if (aDesiredSize.maxElementSize) { + aDesiredSize.maxElementSize->width += borderPadding.left + borderPadding.right; + aDesiredSize.maxElementSize->height += borderPadding.top + borderPadding.bottom; + } + aDesiredSize.ascent = aDesiredSize.height; + aDesiredSize.descent = 0; + + // create our view, we need a view to grab the mouse away from children frames + nsIView* view; + GetView(view); + if (!view) { + nsresult result = nsRepository::CreateInstance(kViewCID, nsnull, kIViewIID, + (void **)&view); + nsIPresShell *presShell = aPresContext.GetShell(); + nsIViewManager *viewMan = presShell->GetViewManager(); + NS_RELEASE(presShell); + + nsIFrame* parWithView; + nsIView *parView; + GetParentWithView(parWithView); + parWithView->GetView(parView); + nsRect boundBox(0, 0, aDesiredSize.width, aDesiredSize.height); + result = view->Init(viewMan, boundBox, parView, nsnull); + viewMan->InsertChild(parView, view, 0); + SetView(view); + NS_RELEASE(viewMan); + } + + aStatus = NS_FRAME_COMPLETE; + return NS_OK; +} + +PRIntn +nsHTMLButtonControlFrame::GetSkipSides() const +{ + return 0; +} + + diff --git a/mozilla/layout/html/forms/src/nsRadioControlFrame.cpp b/mozilla/layout/html/forms/src/nsRadioControlFrame.cpp index 0e683ab342c..fad3dd31716 100644 --- a/mozilla/layout/html/forms/src/nsRadioControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsRadioControlFrame.cpp @@ -112,6 +112,7 @@ nsRadioControlFrame::PostCreateWidget(nsIPresContext* aPresContext) mWidget->SetBackgroundColor(NS_RGB(0xFF, 0xFF, 0xFF)); } NS_RELEASE(radio); + mWidget->Enable(!nsFormFrame::GetDisabled(this)); } } diff --git a/mozilla/layout/html/forms/src/nsSelectControlFrame.cpp b/mozilla/layout/html/forms/src/nsSelectControlFrame.cpp index c222c973fea..3103192e534 100644 --- a/mozilla/layout/html/forms/src/nsSelectControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsSelectControlFrame.cpp @@ -19,6 +19,7 @@ // YY need to pass isMultiple before create called #include "nsFormControlFrame.h" +#include "nsFormFrame.h" #include "nsIDOMNode.h" #include "nsIDOMHTMLSelectElement.h" #include "nsIDOMHTMLOptionElement.h" @@ -353,6 +354,7 @@ nsSelectControlFrame::PostCreateWidget(nsIPresContext* aPresContext) return; } + mWidget->Enable(!nsFormFrame::GetDisabled(this)); nsFont font(aPresContext->GetDefaultFixedFont()); GetFont(aPresContext, font); mWidget->SetFont(font); diff --git a/mozilla/layout/html/forms/src/nsTextControlFrame.cpp b/mozilla/layout/html/forms/src/nsTextControlFrame.cpp index 250e46bc026..4312a2d7cb5 100644 --- a/mozilla/layout/html/forms/src/nsTextControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsTextControlFrame.cpp @@ -253,14 +253,14 @@ nsTextControlFrame::GetText(nsString* aText) GetType(&type); if (NS_FORM_INPUT_TEXT == type) { nsIDOMHTMLInputElement* textElem = nsnull; - nsresult result = mContent->QueryInterface(kIDOMHTMLInputElementIID, (void**)&textElem); + result = mContent->QueryInterface(kIDOMHTMLInputElementIID, (void**)&textElem); if ((NS_OK == result) && textElem) { result = textElem->GetValue(*aText); NS_RELEASE(textElem); } } else { nsIDOMHTMLTextAreaElement* textArea = nsnull; - nsresult result = mContent->QueryInterface(kIDOMHTMLTextAreaElementIID, (void**)&textArea); + result = mContent->QueryInterface(kIDOMHTMLTextAreaElementIID, (void**)&textArea); if ((NS_OK == result) && textArea) { result = textArea->GetDefaultValue(*aText); NS_RELEASE(textArea); @@ -303,6 +303,7 @@ nsTextControlFrame::PostCreateWidget(nsIPresContext* aPresContext) textArea->SetText(value, ignore); NS_RELEASE(textArea); } + mWidget->Enable(!nsFormFrame::GetDisabled(this)); } PRInt32 diff --git a/mozilla/layout/html/style/src/nsHTMLStyleSheet.cpp b/mozilla/layout/html/style/src/nsHTMLStyleSheet.cpp index 4b7623917aa..e510cb3f7bf 100644 --- a/mozilla/layout/html/style/src/nsHTMLStyleSheet.cpp +++ b/mozilla/layout/html/style/src/nsHTMLStyleSheet.cpp @@ -1239,6 +1239,10 @@ HTMLStyleSheetImpl::ConstructFrameByTag(nsIPresContext* aPresContext, else if (nsHTMLAtoms::spacer == aTag) { rv = NS_NewSpacerFrame(aContent, aParentFrame, aNewFrame); } + else if (nsHTMLAtoms::button == aTag) { + rv = NS_NewHTMLButtonControlFrame(aContent, aParentFrame, aNewFrame); + processChildren = PR_TRUE; + } // If we succeeded in creating a frame then set its style context, // process its children (if requested), and initialize the frame diff --git a/mozilla/layout/style/nsHTMLStyleSheet.cpp b/mozilla/layout/style/nsHTMLStyleSheet.cpp index 4b7623917aa..e510cb3f7bf 100644 --- a/mozilla/layout/style/nsHTMLStyleSheet.cpp +++ b/mozilla/layout/style/nsHTMLStyleSheet.cpp @@ -1239,6 +1239,10 @@ HTMLStyleSheetImpl::ConstructFrameByTag(nsIPresContext* aPresContext, else if (nsHTMLAtoms::spacer == aTag) { rv = NS_NewSpacerFrame(aContent, aParentFrame, aNewFrame); } + else if (nsHTMLAtoms::button == aTag) { + rv = NS_NewHTMLButtonControlFrame(aContent, aParentFrame, aNewFrame); + processChildren = PR_TRUE; + } // If we succeeded in creating a frame then set its style context, // process its children (if requested), and initialize the frame diff --git a/mozilla/webshell/tests/viewer/samples/test8.html b/mozilla/webshell/tests/viewer/samples/test8.html index 3dfaa772526..d4d5d408f83 100644 --- a/mozilla/webshell/tests/viewer/samples/test8.html +++ b/mozilla/webshell/tests/viewer/samples/test8.html @@ -26,7 +26,7 @@ SELECT#select1 {