From 57b832743d8d7798e7d895f055fc11cd28e86ce9 Mon Sep 17 00:00:00 2001 From: "jkeiser%netscape.com" Date: Thu, 24 Jan 2002 19:04:55 +0000 Subject: [PATCH] Move checkbox state to content (bug 108307). r=rods, sr=jst --- content/html/content/src/nsHTMLAtomList.h | 3 - .../html/content/src/nsHTMLInputElement.cpp | 194 ++++++---- content/shared/public/nsHTMLAtomList.h | 3 - layout/forms/nsGfxCheckboxControlFrame.cpp | 345 ++---------------- layout/forms/nsGfxCheckboxControlFrame.h | 55 +-- layout/forms/nsICheckboxControlFrame.h | 9 +- .../forms/public/nsICheckboxControlFrame.h | 9 +- .../forms/src/nsGfxCheckboxControlFrame.cpp | 345 ++---------------- .../forms/src/nsGfxCheckboxControlFrame.h | 55 +-- .../tests/viewer/samples/checkboxTest.xul | 96 ----- 10 files changed, 231 insertions(+), 883 deletions(-) diff --git a/content/html/content/src/nsHTMLAtomList.h b/content/html/content/src/nsHTMLAtomList.h index 73596283246..c2aafcead68 100644 --- a/content/html/content/src/nsHTMLAtomList.h +++ b/content/html/content/src/nsHTMLAtomList.h @@ -311,9 +311,6 @@ HTML_ATOM(wrappedFramePseudo, ":wrapped-frame") HTML_ATOM(zindex, "zindex") HTML_ATOM(z_index, "z-index") -HTML_ATOM(moz_tristate, "moz-tristate") -HTML_ATOM(moz_tristatevalue, "moz-tristatevalue") - #ifdef DEBUG HTML_ATOM(iform, "IForm") HTML_ATOM(form_control_list, "FormControlList") diff --git a/content/html/content/src/nsHTMLInputElement.cpp b/content/html/content/src/nsHTMLInputElement.cpp index 0dba727ecaf..4f8795d889a 100644 --- a/content/html/content/src/nsHTMLInputElement.cpp +++ b/content/html/content/src/nsHTMLInputElement.cpp @@ -167,6 +167,10 @@ public: || mType == NS_FORM_INPUT_HIDDEN)) { Reset(); } + if (aName == nsHTMLAtoms::checked && !mCheckedChanged + && (mType == NS_FORM_INPUT_CHECKBOX || mType == NS_FORM_INPUT_RADIO)) { + Reset(); + } return rv; } NS_IMETHOD SetAttr(nsINodeInfo* aNodeInfo, const nsAReadableString& aValue, @@ -180,7 +184,10 @@ public: nsresult rv = nsGenericHTMLLeafElement::UnsetAttr(aNameSpaceID, aAttribute, aNotify); - if (aAttribute == nsHTMLAtoms::value) { + if (aAttribute == nsHTMLAtoms::value && !mValueChanged) { + Reset(); + } + if (aAttribute == nsHTMLAtoms::checked && !mCheckedChanged) { Reset(); } return rv; @@ -216,12 +223,16 @@ protected: return tmp.EqualsIgnoreCase("image"); } + void FireOnChange(); + nsCOMPtr mControllers; PRInt8 mType; PRPackedBool mSkipFocusEvent; PRPackedBool mHandlingClick; PRPackedBool mValueChanged; + PRPackedBool mCheckedChanged; + PRPackedBool mChecked; char* mValue; }; @@ -261,6 +272,8 @@ nsHTMLInputElement::nsHTMLInputElement() mHandlingClick = PR_FALSE; mValueChanged = PR_FALSE; mValue = nsnull; + mCheckedChanged = PR_FALSE; + mChecked = PR_FALSE; } nsHTMLInputElement::~nsHTMLInputElement() @@ -355,20 +368,15 @@ nsHTMLInputElement::GetDefaultChecked(PRBool* aDefaultChecked) NS_IMETHODIMP nsHTMLInputElement::SetDefaultChecked(PRBool aDefaultChecked) { - nsresult rv = NS_OK; - nsHTMLValue empty(eHTMLUnit_Empty); + nsresult rv; - if (aDefaultChecked) { - rv = SetHTMLAttribute(nsHTMLAtoms::checked, empty, PR_TRUE); - } else { + if (aDefaultChecked) { + rv = SetAttr(kNameSpaceID_HTML, nsHTMLAtoms::checked, + NS_LITERAL_STRING(""), PR_TRUE); + } else { rv = UnsetAttr(kNameSpaceID_HTML, nsHTMLAtoms::checked, PR_TRUE); } - - if (NS_SUCCEEDED(rv)) { - //When setting DefaultChecked, we must also reset Checked (DOM Errata) - SetChecked(aDefaultChecked); - } - + return rv; } @@ -560,35 +568,45 @@ nsHTMLInputElement::SetValueChanged(PRBool aValueChanged) } NS_IMETHODIMP -nsHTMLInputElement::GetChecked(PRBool* aValue) +nsHTMLInputElement::GetChecked(PRBool* aChecked) { - nsAutoString value(NS_LITERAL_STRING("0")); + PRInt32 type; + GetType(&type); + if (type == NS_FORM_INPUT_RADIO) { + nsAutoString value(NS_LITERAL_STRING("0")); - // No need to flush here, if there's no frame created for this input - // yet, we know our own checked state. - nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_FALSE); + // No need to flush here, if there's no frame created for this input + // yet, we know our own checked state. + nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_FALSE); - if (formControlFrame) { - formControlFrame->GetProperty(nsHTMLAtoms::checked, value); - } - else { - // Retrieve the presentation state instead. - nsCOMPtr presState; - GetPrimaryPresState(this, getter_AddRefs(presState)); + if (formControlFrame) { + formControlFrame->GetProperty(nsHTMLAtoms::checked, value); + } + else { + // Retrieve the presentation state instead. + nsCOMPtr presState; + GetPrimaryPresState(this, getter_AddRefs(presState)); - // Obtain the value property from the presentation state. - if (presState) { - presState->GetStateProperty(NS_LITERAL_STRING("checked"), value); + // Obtain the value property from the presentation state. + if (presState) { + presState->GetStateProperty(NS_LITERAL_STRING("checked"), value); + } + } + + if (value.Equals(NS_LITERAL_STRING("1"))) { + *aChecked = PR_TRUE; + } else { + *aChecked = PR_FALSE; + } + } else { + if (!mCheckedChanged) { + GetDefaultChecked(aChecked); + } else { + *aChecked = mChecked; } } - - if (value.Equals(NS_LITERAL_STRING("1"))) { - *aValue = PR_TRUE; - } else { - *aValue = PR_FALSE; - } - return NS_OK; + return NS_OK; } void @@ -608,71 +626,78 @@ nsHTMLInputElement::SetPresStateChecked(nsIHTMLContent * aHTMLContent, NS_IMETHODIMP nsHTMLInputElement::SetChecked(PRBool aValue) { - // First check to see if the new value is the same as our current value. - // If so, then return. - PRBool checked = PR_TRUE; - GetChecked(&checked); - if (checked == aValue) { - return NS_OK; - } + mCheckedChanged = PR_TRUE; - // Since the value is changing, send out an onchange event (bug 23571) - nsCOMPtr presContext; - GetPresContext(this, getter_AddRefs(presContext)); + // + // Set the value + // + mChecked = aValue; + // + // Notify the frame + // // No need to flush here since if there's no frame for this input at // this point we don't care about creating one, once it's created // the frame will do the right thing. + PRInt32 type; + GetType(&type); nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_FALSE); if (formControlFrame) { - // the value is being toggled - nsAutoString val; val.AssignWithConversion(aValue ? "1" : "0"); + nsCOMPtr presContext; + GetPresContext(this, getter_AddRefs(presContext)); - formControlFrame->SetProperty(presContext, nsHTMLAtoms::checked, val); + if (type == NS_FORM_INPUT_CHECKBOX) { + nsICheckboxControlFrame* checkboxFrame = nsnull; + CallQueryInterface(formControlFrame, &checkboxFrame); + if (checkboxFrame) { + checkboxFrame->OnChecked(presContext, aValue); + } + } else if (type == NS_FORM_INPUT_RADIO) { + // the value is being toggled + nsAutoString val; val.AssignWithConversion(aValue ? "1" : "0"); + + formControlFrame->SetProperty(presContext, nsHTMLAtoms::checked, val); + } } - else { + else if (type == NS_FORM_INPUT_RADIO) { SetPresStateChecked(this, aValue); - PRInt32 type; - GetType(&type); - if (type == NS_FORM_INPUT_RADIO) { - nsAutoString name; - GetName(name); + nsAutoString name; + GetName(name); - nsCOMPtr formElement; - if (NS_SUCCEEDED(GetForm(getter_AddRefs(formElement))) && formElement) { - nsCOMPtr controls; + nsCOMPtr formElement; + if (NS_SUCCEEDED(GetForm(getter_AddRefs(formElement))) && formElement) { + nsCOMPtr controls; - nsresult rv = formElement->GetElements(getter_AddRefs(controls)); + nsresult rv = formElement->GetElements(getter_AddRefs(controls)); - if (controls) { - PRUint32 numControls; + if (controls) { + PRUint32 numControls; - controls->GetLength(&numControls); + controls->GetLength(&numControls); - for (PRUint32 i = 0; i < numControls; i++) { - nsCOMPtr elementNode; + for (PRUint32 i = 0; i < numControls; i++) { + nsCOMPtr elementNode; - controls->Item(i, getter_AddRefs(elementNode)); + controls->Item(i, getter_AddRefs(elementNode)); - if (elementNode) { - nsCOMPtr - inputElement(do_QueryInterface(elementNode)); + if (elementNode) { + nsCOMPtr + inputElement(do_QueryInterface(elementNode)); - if (inputElement && inputElement.get() != - NS_STATIC_CAST(nsIDOMHTMLInputElement *, this)) { - nsAutoString childName; + if (inputElement && inputElement.get() != + NS_STATIC_CAST(nsIDOMHTMLInputElement *, this)) { + nsAutoString childName; - rv = inputElement->GetName(childName); + rv = inputElement->GetName(childName); - if (NS_SUCCEEDED(rv)) { - if (name == childName) { - nsCOMPtr - htmlContent(do_QueryInterface(inputElement)); + if (NS_SUCCEEDED(rv)) { + if (name == childName) { + nsCOMPtr + htmlContent(do_QueryInterface(inputElement)); - SetPresStateChecked(htmlContent, PR_FALSE); - } + SetPresStateChecked(htmlContent, PR_FALSE); } } } @@ -682,13 +707,22 @@ nsHTMLInputElement::SetChecked(PRBool aValue) } } + return NS_OK; +} + +void +nsHTMLInputElement::FireOnChange() +{ + // + // Since the value is changing, send out an onchange event (bug 23571) + // + nsCOMPtr presContext; + GetPresContext(this, getter_AddRefs(presContext)); nsEventStatus status = nsEventStatus_eIgnore; nsEvent event; event.eventStructType = NS_EVENT; event.message = NS_FORM_CHANGE; HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); - - return NS_OK; } NS_IMETHODIMP @@ -1094,6 +1128,7 @@ nsHTMLInputElement::HandleDOMEvent(nsIPresContext* aPresContext, PRBool checked; GetChecked(&checked); SetChecked(!checked); + FireOnChange(); // Fire an event to notify accessibility #ifdef ACCESSIBILITY FireEventForAccessibility( aPresContext, NS_LITERAL_STRING("CheckboxStateChange")); @@ -1115,6 +1150,7 @@ nsHTMLInputElement::HandleDOMEvent(nsIPresContext* aPresContext, } } SetChecked(PR_TRUE); + FireOnChange(); // Fire an event to notify accessibility #ifdef ACCESSIBILITY if ( selectedRadiobtn != this ) { @@ -1743,7 +1779,6 @@ nsHTMLInputElement::Reset() nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_FALSE); - // Seems like a dumb idea to reset image. switch (type) { case NS_FORM_INPUT_CHECKBOX: case NS_FORM_INPUT_RADIO: @@ -1751,6 +1786,7 @@ nsHTMLInputElement::Reset() PRBool resetVal; GetDefaultChecked(&resetVal); rv = SetChecked(resetVal); + mCheckedChanged = PR_FALSE; break; } case NS_FORM_INPUT_HIDDEN: diff --git a/content/shared/public/nsHTMLAtomList.h b/content/shared/public/nsHTMLAtomList.h index 73596283246..c2aafcead68 100644 --- a/content/shared/public/nsHTMLAtomList.h +++ b/content/shared/public/nsHTMLAtomList.h @@ -311,9 +311,6 @@ HTML_ATOM(wrappedFramePseudo, ":wrapped-frame") HTML_ATOM(zindex, "zindex") HTML_ATOM(z_index, "z-index") -HTML_ATOM(moz_tristate, "moz-tristate") -HTML_ATOM(moz_tristatevalue, "moz-tristatevalue") - #ifdef DEBUG HTML_ATOM(iform, "IForm") HTML_ATOM(form_control_list, "FormControlList") diff --git a/layout/forms/nsGfxCheckboxControlFrame.cpp b/layout/forms/nsGfxCheckboxControlFrame.cpp index 217a4596454..65ef96ad97e 100644 --- a/layout/forms/nsGfxCheckboxControlFrame.cpp +++ b/layout/forms/nsGfxCheckboxControlFrame.cpp @@ -76,8 +76,7 @@ NS_NewGfxCheckboxControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) //------------------------------------------------------------ // Initialize GFX-rendered state nsGfxCheckboxControlFrame::nsGfxCheckboxControlFrame() -: mChecked(eOff), - mCheckButtonFaceStyle(nsnull) +: mCheckButtonFaceStyle(nsnull) { } @@ -131,35 +130,6 @@ nsGfxCheckboxControlFrame::SetCheckboxFaceStyleContext(nsIStyleContext *aCheckbo return NS_OK; } -//------------------------------------------------------------ -// -// Init -// -// We need to override this in order to see if we're a tristate checkbox. -// -NS_IMETHODIMP -nsGfxCheckboxControlFrame::Init(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParent, - nsIStyleContext* aContext, - nsIFrame* aPrevInFlow) -{ - nsFormControlFrame::Init ( aPresContext, aContent, aParent, aContext, aPrevInFlow ); - - // figure out if we're a tristate at the start. This may change later on once - // we've been running for a while, so more code is in AttributeChanged() to pick - // that up. Regardless, we need this check when initializing. - nsAutoString value; - nsresult res = mContent->GetAttr ( kNameSpaceID_None, GetTristateAtom(), value ); - if ( res == NS_CONTENT_ATTR_HAS_VALUE ) - mIsTristate = PR_TRUE; - - // give the attribute a default value so it's always present, if we're a tristate - if ( IsTristateCheckbox() ) - mContent->SetAttr ( kNameSpaceID_None, GetTristateValueAtom(), NS_LITERAL_STRING("0"), PR_FALSE ); - - return NS_OK; -} //-------------------------------------------------------------- NS_IMETHODIMP @@ -204,115 +174,14 @@ nsGfxCheckboxControlFrame::SetAdditionalStyleContext(PRInt32 aIndex, //------------------------------------------------------------ -// -// GetTristateAtom [static] -// -// Use a lazily instantiated static initialization scheme to create an atom that -// represents the attribute set when this should be a tri-state checkbox. -// -// Does NOT addref! -// -nsIAtom* -nsGfxCheckboxControlFrame :: GetTristateAtom ( ) -{ - return nsHTMLAtoms::moz_tristate; -} - -//------------------------------------------------------------ -// -// GetTristateValueAtom [static] -// -// Use a lazily instantiated static initialization scheme to create an atom that -// represents the attribute that holds the value when the button is a tri-state (since -// we can't use "checked"). -// -// Does NOT addref! -// -nsIAtom* -nsGfxCheckboxControlFrame :: GetTristateValueAtom ( ) -{ - return nsHTMLAtoms::moz_tristatevalue; -} - -//------------------------------------------------------------ -// -// AttributeChanged -// -// Override to check for the attribute that determines if we're a normal or a -// tristate checkbox. If we notice a switch from one to the other, we need -// to adjust the proper attributes in the content model accordingly. -// -// Also, since the value of a tri-state is kept in a separate attribute (we -// can't use "checked" because it's a boolean), we have to notice it changing -// here. -// NS_IMETHODIMP -nsGfxCheckboxControlFrame::AttributeChanged(nsIPresContext* aPresContext, - nsIContent* aChild, - PRInt32 aNameSpaceID, - nsIAtom* aAttribute, - PRInt32 aModType, - PRInt32 aHint) +nsGfxCheckboxControlFrame::OnChecked(nsIPresContext* aPresContext, + PRBool aChecked) { - if ( aAttribute == GetTristateAtom() ) { - nsAutoString value; - nsresult res = mContent->GetAttr ( kNameSpaceID_None, GetTristateAtom(), value ); - PRBool isNowTristate = (res == NS_CONTENT_ATTR_HAS_VALUE); - if ( isNowTristate != mIsTristate ) - SwitchModesWithEmergencyBrake(aPresContext, isNowTristate); - } - else if ( aAttribute == GetTristateValueAtom() ) { - // ignore this change if we're not a tri-state checkbox - if ( IsTristateCheckbox() ) { - nsAutoString value; - nsresult res = mContent->GetAttr ( kNameSpaceID_None, GetTristateValueAtom(), value ); - if ( res == NS_CONTENT_ATTR_HAS_VALUE ) - SetCheckboxControlFrameState(aPresContext, value); - } - } - else - return nsFormControlFrame::AttributeChanged(aPresContext, aChild, aNameSpaceID, aAttribute, aModType, aHint); - - return NS_OK; + nsFormControlHelper::ForceDrawFrame(aPresContext, this); + return aChecked; } -//------------------------------------------------------------ -// -// InitializeControl -// -// Set the default checked state of the checkbox. -// -void -nsGfxCheckboxControlFrame::InitializeControl(nsIPresContext* aPresContext) -{ - nsFormControlFrame::InitializeControl(aPresContext); - - // Only reset on init if this is the primary shell - // Temporary workaround until checkbox state is in content - nsCOMPtr presShell; - aPresContext->GetShell(getter_AddRefs(presShell)); - if (!presShell) return; - - nsCOMPtr doc; - presShell->GetDocument(getter_AddRefs(doc)); - if (!doc) return; - - nsCOMPtr primaryPresShell; - doc->GetShellAt(0, getter_AddRefs(primaryPresShell)); - if (!primaryPresShell) return; - - if (presShell.get() == primaryPresShell.get()) { - // Reset the value - // XXX We set the checkbox directly in the frame, because - // content fires onChange :( - PRBool checked = PR_FALSE; - nsresult rv = GetDefaultCheckState(&checked); - - if (NS_CONTENT_ATTR_HAS_VALUE == rv) { - SetCheckboxState (aPresContext, checked ? eOn : eOff ); - } - } -} //------------------------------------------------------------ void @@ -336,33 +205,9 @@ nsGfxCheckboxControlFrame::PaintCheckBox(nsIPresContext* aPresContext, mStyleContext->GetStyleData(eStyleStruct_Color); aRenderingContext.SetColor(color->mColor); - if ( IsTristateCheckbox() ) { - // Get current checked state through content model. - // XXX this won't work under printing. does that matter??? - CheckState checked = GetCheckboxState(); - switch ( checked ) { - case eOn: - nsFormControlHelper::PaintCheckMark(aRenderingContext, p2t, checkRect); - break; - - case eMixed: - PaintMixedMark(aRenderingContext, p2t, checkRect); - break; - - // no special drawing otherwise - default: - break; - } // case of value of checkbox - } else { - // Get current checked state through content model. - // XXX: This is very inefficient, but it is necessary in the case of printing. - // During printing the Paint is called but the actual state of the checkbox - // is in a frame in presentation shell 0. - PRBool checked = PR_FALSE; - GetCurrentCheckState(&checked); - if ( checked ) { - nsFormControlHelper::PaintCheckMark(aRenderingContext, p2t, checkRect); - } + // Get current checked state through content model. + if ( GetCheckboxState() ) { + nsFormControlHelper::PaintCheckMark(aRenderingContext, p2t, checkRect); } PRBool clip; @@ -370,51 +215,6 @@ nsGfxCheckboxControlFrame::PaintCheckBox(nsIPresContext* aPresContext, } -//------------------------------------------------------------ -// -// PaintMixedMark -// -// Like nsFormControlHelper::PaintCheckMark(), but paints the horizontal "mixed" -// bar inside the box. Only used for tri-state checkboxes. -// -void -nsGfxCheckboxControlFrame::PaintMixedMark ( nsIRenderingContext& aRenderingContext, - float aPixelsToTwips, const nsRect& aRect) -{ - const PRUint32 checkpoints = 4; - const PRUint32 checksize = 6; //This is value is determined by added 2 units to the end - //of the 7X& pixel rectangle below to provide some white space - //around the checkmark when it is rendered. - - // Points come from the coordinates on a 7X7 pixels - // box with 0,0 at the lower left. - nscoord checkedPolygonDef[] = { 1,2, 5,2, 5,4, 1,4 }; - // Location of the center point of the checkmark - const PRUint32 centerx = 3; - const PRUint32 centery = 3; - - nsPoint checkedPolygon[checkpoints]; - PRUint32 defIndex = 0; - PRUint32 polyIndex = 0; - - // Scale the checkmark based on the smallest dimension - PRUint32 size = aRect.width / checksize; - if (aRect.height < aRect.width) - size = aRect.height / checksize; - - // Center and offset each point in the polygon definition. - for (defIndex = 0; defIndex < (checkpoints * 2); defIndex++) { - checkedPolygon[polyIndex].x = nscoord((((checkedPolygonDef[defIndex]) - centerx) * (size)) + (aRect.width / 2) + aRect.x); - defIndex++; - checkedPolygon[polyIndex].y = nscoord((((checkedPolygonDef[defIndex]) - centery) * (size)) + (aRect.height / 2) + aRect.y); - polyIndex++; - } - - aRenderingContext.FillPolygon(checkedPolygon, checkpoints); - -} // PaintMixedMark - - //------------------------------------------------------------ NS_METHOD nsGfxCheckboxControlFrame::Paint(nsIPresContext* aPresContext, @@ -432,8 +232,8 @@ nsGfxCheckboxControlFrame::Paint(nsIPresContext* aPresContext, nsresult rv = nsFormControlFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { PRBool doDefaultPainting = PR_TRUE; - // Paint the checkmark - if (nsnull != mCheckButtonFaceStyle && GetCheckboxState() == eOn) { + // Paint the checkmark + if (!mCheckButtonFaceStyle && GetCheckboxState()) { const nsStyleBackground* myColor = (const nsStyleBackground*) mCheckButtonFaceStyle->GetStyleData(eStyleStruct_Background); @@ -466,61 +266,43 @@ nsGfxCheckboxControlFrame::Paint(nsIPresContext* aPresContext, } //------------------------------------------------------------ -nsGfxCheckboxControlFrame::CheckState +PRBool nsGfxCheckboxControlFrame::GetCheckboxState ( ) { - return mChecked; + nsCOMPtr elem(do_QueryInterface(mContent)); + PRBool retval = PR_FALSE; + elem->GetChecked(&retval); + return retval; } //------------------------------------------------------------ -void +void nsGfxCheckboxControlFrame::SetCheckboxState (nsIPresContext* aPresContext, - nsGfxCheckboxControlFrame::CheckState aValue ) + PRBool aValue ) { - mChecked = aValue; - nsFormControlHelper::ForceDrawFrame(aPresContext, this); + nsCOMPtr elem(do_QueryInterface(mContent)); + elem->SetChecked(aValue); } //------------------------------------------------------------ -void nsGfxCheckboxControlFrame::GetCheckboxControlFrameState(nsAWritableString& aValue) +void +nsGfxCheckboxControlFrame::GetCheckboxControlFrameState ( + nsAWritableString& aValue ) { CheckStateToString(GetCheckboxState(), aValue); } //------------------------------------------------------------ -void nsGfxCheckboxControlFrame::SetCheckboxControlFrameState(nsIPresContext* aPresContext, - const nsAReadableString& aValue) +void +nsGfxCheckboxControlFrame::SetCheckboxControlFrameState ( + nsIPresContext* aPresContext, + const nsAReadableString& aValue ) { - CheckState state = StringToCheckState(aValue); + PRBool state = StringToCheckState(aValue); SetCheckboxState(aPresContext, state); } -//------------------------------------------------------------ -NS_IMETHODIMP nsGfxCheckboxControlFrame::SetProperty(nsIPresContext* aPresContext, - nsIAtom* aName, - const nsAReadableString& aValue) -{ - if (nsHTMLAtoms::checked == aName) - SetCheckboxControlFrameState(aPresContext, aValue); - else - return nsFormControlFrame::SetProperty(aPresContext, aName, aValue); - - return NS_OK; -} - - -//------------------------------------------------------------ -NS_IMETHODIMP nsGfxCheckboxControlFrame::GetProperty(nsIAtom* aName, nsAWritableString& aValue) -{ - if (nsHTMLAtoms::checked == aName) - GetCheckboxControlFrameState(aValue); - else - return nsFormControlFrame::GetProperty(aName, aValue); - - return NS_OK; -} - //------------------------------------------------------------ // @@ -529,20 +311,14 @@ NS_IMETHODIMP nsGfxCheckboxControlFrame::GetProperty(nsIAtom* aName, nsAWritable // Converts from a CheckState to a string // void -nsGfxCheckboxControlFrame::CheckStateToString ( CheckState inState, nsAWritableString& outStateAsString ) +nsGfxCheckboxControlFrame::CheckStateToString ( + PRBool inState, + nsAWritableString& outStateAsString ) { - switch ( inState ) { - case eOn: - outStateAsString.Assign(NS_STRING_TRUE); - break; - - case eOff: - outStateAsString.Assign(NS_STRING_FALSE); - break; - - case eMixed: - outStateAsString.Assign(NS_LITERAL_STRING("2")); - break; + if (inState) { + outStateAsString.Assign(NS_STRING_TRUE); + } else { + outStateAsString.Assign(NS_STRING_FALSE); } } // CheckStateToString @@ -553,55 +329,13 @@ nsGfxCheckboxControlFrame::CheckStateToString ( CheckState inState, nsAWritableS // // Converts from a string to a CheckState enum // -nsGfxCheckboxControlFrame::CheckState +PRBool nsGfxCheckboxControlFrame::StringToCheckState ( const nsAReadableString & aStateAsString ) { - if ( aStateAsString.Equals(NS_STRING_TRUE) ) - return eOn; - else if ( aStateAsString.Equals(NS_STRING_FALSE) ) - return eOff; - - // not true and not false means mixed - return eMixed; - + return aStateAsString.Equals(NS_STRING_TRUE); } // StringToCheckState -//------------------------------------------------------------ -// -// SwitchModesWithEmergencyBrake -// -// Since we use an attribute to decide if we're a tristate box or not, this can change -// at any time. Since we have to use separate attributes to store the values depending -// on the mode, we have to convert from one to the other. -// -void -nsGfxCheckboxControlFrame::SwitchModesWithEmergencyBrake ( nsIPresContext* aPresContext, - PRBool inIsNowTristate ) -{ - if ( inIsNowTristate ) { - // we were a normal checkbox, and now we're a tristate. That means that the - // state of the checkbox was in "checked" and needs to be copied over into - // our parallel attribute. - nsAutoString value; - CheckStateToString ( GetCheckboxState(), value ); - mContent->SetAttr ( kNameSpaceID_None, GetTristateValueAtom(), value, PR_FALSE ); - } - else { - // we were a tri-state checkbox, and now we're a normal checkbox. The current - // state is already up to date (because it's always up to date). We just have - // to make sure it's not mixed. If it is, just set it to checked. Remove our - // parallel attribute so that we're nice and HTML4 compliant. - if ( GetCheckboxState() == eMixed ) - SetCheckboxState(aPresContext, eOn); - mContent->UnsetAttr ( kNameSpaceID_None, GetTristateValueAtom(), PR_FALSE ); - } - - // switch! - mIsTristate = inIsNowTristate; - -} // SwitchModesWithEmergencyBrake - //---------------------------------------------------------------------- // nsIStatefulFrame //---------------------------------------------------------------------- @@ -615,15 +349,14 @@ NS_IMETHODIMP nsGfxCheckboxControlFrame::SaveState(nsIPresContext* aPresContext, return NS_OK; } - CheckState stateCheck = GetCheckboxState(); + PRBool stateCheck = GetCheckboxState(); PRBool defaultStateBool = PR_FALSE; nsresult res = GetDefaultCheckState(&defaultStateBool); // Compare to default value, and only save if needed (Bug 62713) - // eOn/eOff comparisons used to handle 'mixed' state (alway save) if (!(NS_CONTENT_ATTR_HAS_VALUE == res && - ((eOn == stateCheck && defaultStateBool) || - (eOff == stateCheck && !defaultStateBool)))) { + ((stateCheck && defaultStateBool) || + (!stateCheck && !defaultStateBool)))) { // Get the value string nsAutoString stateString; diff --git a/layout/forms/nsGfxCheckboxControlFrame.h b/layout/forms/nsGfxCheckboxControlFrame.h index c9db5fc2d35..69bf5e41f69 100644 --- a/layout/forms/nsGfxCheckboxControlFrame.h +++ b/layout/forms/nsGfxCheckboxControlFrame.h @@ -66,21 +66,6 @@ public: return MakeFrameName(NS_LITERAL_STRING("CheckboxControl"), aResult); } #endif - // this should be protected, but VC6 is lame. - enum CheckState { eOff, eOn, eMixed } ; - - NS_IMETHOD Init(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParent, - nsIStyleContext* aContext, - nsIFrame* aPrevInFlow) ; - - NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext, - nsIContent* aChild, - PRInt32 aNameSpaceID, - nsIAtom* aAttribute, - PRInt32 aModType, - PRInt32 aHint) ; NS_IMETHOD Paint(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -93,10 +78,9 @@ public: #endif - //nsICheckboxControlFrame methods + //nsICheckboxControlFrame methods NS_IMETHOD SetCheckboxFaceStyleContext(nsIStyleContext *aCheckboxFaceStyleContext); - - void InitializeControl(nsIPresContext* aPresContext); + NS_IMETHOD OnChecked(nsIPresContext* aPresContext, PRBool aChecked); NS_IMETHOD GetAdditionalStyleContext(PRInt32 aIndex, nsIStyleContext** aStyleContext) const; @@ -104,8 +88,6 @@ public: nsIStyleContext* aStyleContext); // nsIFormControlFrame - NS_IMETHOD SetProperty(nsIPresContext* aPresContext, nsIAtom* aName, const nsAReadableString& aValue); - NS_IMETHOD GetProperty(nsIAtom* aName, nsAWritableString& aValue); NS_IMETHOD OnContentReset(); // nsIStatefulFrame @@ -121,14 +103,18 @@ public: nsReflowStatus& aStatus); #endif - NS_IMETHOD GetChecked(PRBool* aIsChecked) { *aIsChecked = (GetCheckboxState() == eOn); return NS_OK; } - NS_IMETHOD SetChecked(nsIPresContext* aPresContext, PRBool aIsChecked) { SetCheckboxState(aPresContext, aIsChecked ? eOn : eOff); return NS_OK; } + NS_IMETHOD GetChecked(PRBool* aIsChecked) { + *aIsChecked = GetCheckboxState(); return NS_OK; + } + NS_IMETHOD SetChecked(nsIPresContext* aPresContext, PRBool aIsChecked) { + SetCheckboxState(aPresContext, aIsChecked); return NS_OK; + } protected: // native/gfx implementations need to implement needs. - CheckState GetCheckboxState(); - void SetCheckboxState(nsIPresContext* aPresContext, CheckState aValue); + PRBool GetCheckboxState(); + void SetCheckboxState(nsIPresContext* aPresContext, PRBool aValue); // Utility methods for implementing SetProperty/GetProperty void SetCheckboxControlFrameState(nsIPresContext* aPresContext, @@ -136,22 +122,8 @@ protected: void GetCheckboxControlFrameState(nsAWritableString& aValue); // utility routine for converting from DOM values to internal enum - void CheckStateToString ( CheckState inState, nsAWritableString& outStateAsString ) ; - CheckState StringToCheckState ( const nsAReadableString & aStateAsString ) ; - - // figure out if we're a tri-state checkbox. - PRBool IsTristateCheckbox ( ) const { return mIsTristate; } - - // we just became a tri-state, or we just lost tri-state status. fix up - // the attributes for the new mode. - void SwitchModesWithEmergencyBrake ( nsIPresContext* aPresContext, - PRBool inIsNowTristate ) ; - - // for tri-state checkbox. meaningless for normal HTML - PRBool mIsTristate; - - static nsIAtom* GetTristateAtom() ; - static nsIAtom* GetTristateValueAtom() ; + void CheckStateToString(PRBool inState, nsAWritableString& outStateAsString) ; + PRBool StringToCheckState(const nsAReadableString & aStateAsString) ; protected: @@ -159,12 +131,9 @@ protected: nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer); - virtual void PaintMixedMark(nsIRenderingContext& aRenderingContext, - float aPixelsToTwips, const nsRect& aRect) ; //GFX-rendered state variables PRBool mInClickEvent; - CheckState mChecked; nsIStyleContext* mCheckButtonFaceStyle; private: diff --git a/layout/forms/nsICheckboxControlFrame.h b/layout/forms/nsICheckboxControlFrame.h index c69e8367a0a..e74b399816d 100644 --- a/layout/forms/nsICheckboxControlFrame.h +++ b/layout/forms/nsICheckboxControlFrame.h @@ -40,6 +40,7 @@ #include "nsISupports.h" class nsIStyleContext; +class nsIPresContext; // IID for the nsICheckControlFrame class // {401347ED-0101-11d4-9706-0060B0FB9956} @@ -58,10 +59,14 @@ public: /** * Sets the Pseudo Style Contexts for the Check button - * */ - NS_IMETHOD SetCheckboxFaceStyleContext(nsIStyleContext *aCheckboxFaceStyleContext) = 0; + NS_IMETHOD SetCheckboxFaceStyleContext( + nsIStyleContext* aCheckboxFaceStyleContext) = 0; + /** + * Called by content when checkbox "checked" changes + */ + NS_IMETHOD OnChecked(nsIPresContext* aPresContext, PRBool aChecked) = 0; }; #endif diff --git a/layout/html/forms/public/nsICheckboxControlFrame.h b/layout/html/forms/public/nsICheckboxControlFrame.h index c69e8367a0a..e74b399816d 100644 --- a/layout/html/forms/public/nsICheckboxControlFrame.h +++ b/layout/html/forms/public/nsICheckboxControlFrame.h @@ -40,6 +40,7 @@ #include "nsISupports.h" class nsIStyleContext; +class nsIPresContext; // IID for the nsICheckControlFrame class // {401347ED-0101-11d4-9706-0060B0FB9956} @@ -58,10 +59,14 @@ public: /** * Sets the Pseudo Style Contexts for the Check button - * */ - NS_IMETHOD SetCheckboxFaceStyleContext(nsIStyleContext *aCheckboxFaceStyleContext) = 0; + NS_IMETHOD SetCheckboxFaceStyleContext( + nsIStyleContext* aCheckboxFaceStyleContext) = 0; + /** + * Called by content when checkbox "checked" changes + */ + NS_IMETHOD OnChecked(nsIPresContext* aPresContext, PRBool aChecked) = 0; }; #endif diff --git a/layout/html/forms/src/nsGfxCheckboxControlFrame.cpp b/layout/html/forms/src/nsGfxCheckboxControlFrame.cpp index 217a4596454..65ef96ad97e 100644 --- a/layout/html/forms/src/nsGfxCheckboxControlFrame.cpp +++ b/layout/html/forms/src/nsGfxCheckboxControlFrame.cpp @@ -76,8 +76,7 @@ NS_NewGfxCheckboxControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) //------------------------------------------------------------ // Initialize GFX-rendered state nsGfxCheckboxControlFrame::nsGfxCheckboxControlFrame() -: mChecked(eOff), - mCheckButtonFaceStyle(nsnull) +: mCheckButtonFaceStyle(nsnull) { } @@ -131,35 +130,6 @@ nsGfxCheckboxControlFrame::SetCheckboxFaceStyleContext(nsIStyleContext *aCheckbo return NS_OK; } -//------------------------------------------------------------ -// -// Init -// -// We need to override this in order to see if we're a tristate checkbox. -// -NS_IMETHODIMP -nsGfxCheckboxControlFrame::Init(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParent, - nsIStyleContext* aContext, - nsIFrame* aPrevInFlow) -{ - nsFormControlFrame::Init ( aPresContext, aContent, aParent, aContext, aPrevInFlow ); - - // figure out if we're a tristate at the start. This may change later on once - // we've been running for a while, so more code is in AttributeChanged() to pick - // that up. Regardless, we need this check when initializing. - nsAutoString value; - nsresult res = mContent->GetAttr ( kNameSpaceID_None, GetTristateAtom(), value ); - if ( res == NS_CONTENT_ATTR_HAS_VALUE ) - mIsTristate = PR_TRUE; - - // give the attribute a default value so it's always present, if we're a tristate - if ( IsTristateCheckbox() ) - mContent->SetAttr ( kNameSpaceID_None, GetTristateValueAtom(), NS_LITERAL_STRING("0"), PR_FALSE ); - - return NS_OK; -} //-------------------------------------------------------------- NS_IMETHODIMP @@ -204,115 +174,14 @@ nsGfxCheckboxControlFrame::SetAdditionalStyleContext(PRInt32 aIndex, //------------------------------------------------------------ -// -// GetTristateAtom [static] -// -// Use a lazily instantiated static initialization scheme to create an atom that -// represents the attribute set when this should be a tri-state checkbox. -// -// Does NOT addref! -// -nsIAtom* -nsGfxCheckboxControlFrame :: GetTristateAtom ( ) -{ - return nsHTMLAtoms::moz_tristate; -} - -//------------------------------------------------------------ -// -// GetTristateValueAtom [static] -// -// Use a lazily instantiated static initialization scheme to create an atom that -// represents the attribute that holds the value when the button is a tri-state (since -// we can't use "checked"). -// -// Does NOT addref! -// -nsIAtom* -nsGfxCheckboxControlFrame :: GetTristateValueAtom ( ) -{ - return nsHTMLAtoms::moz_tristatevalue; -} - -//------------------------------------------------------------ -// -// AttributeChanged -// -// Override to check for the attribute that determines if we're a normal or a -// tristate checkbox. If we notice a switch from one to the other, we need -// to adjust the proper attributes in the content model accordingly. -// -// Also, since the value of a tri-state is kept in a separate attribute (we -// can't use "checked" because it's a boolean), we have to notice it changing -// here. -// NS_IMETHODIMP -nsGfxCheckboxControlFrame::AttributeChanged(nsIPresContext* aPresContext, - nsIContent* aChild, - PRInt32 aNameSpaceID, - nsIAtom* aAttribute, - PRInt32 aModType, - PRInt32 aHint) +nsGfxCheckboxControlFrame::OnChecked(nsIPresContext* aPresContext, + PRBool aChecked) { - if ( aAttribute == GetTristateAtom() ) { - nsAutoString value; - nsresult res = mContent->GetAttr ( kNameSpaceID_None, GetTristateAtom(), value ); - PRBool isNowTristate = (res == NS_CONTENT_ATTR_HAS_VALUE); - if ( isNowTristate != mIsTristate ) - SwitchModesWithEmergencyBrake(aPresContext, isNowTristate); - } - else if ( aAttribute == GetTristateValueAtom() ) { - // ignore this change if we're not a tri-state checkbox - if ( IsTristateCheckbox() ) { - nsAutoString value; - nsresult res = mContent->GetAttr ( kNameSpaceID_None, GetTristateValueAtom(), value ); - if ( res == NS_CONTENT_ATTR_HAS_VALUE ) - SetCheckboxControlFrameState(aPresContext, value); - } - } - else - return nsFormControlFrame::AttributeChanged(aPresContext, aChild, aNameSpaceID, aAttribute, aModType, aHint); - - return NS_OK; + nsFormControlHelper::ForceDrawFrame(aPresContext, this); + return aChecked; } -//------------------------------------------------------------ -// -// InitializeControl -// -// Set the default checked state of the checkbox. -// -void -nsGfxCheckboxControlFrame::InitializeControl(nsIPresContext* aPresContext) -{ - nsFormControlFrame::InitializeControl(aPresContext); - - // Only reset on init if this is the primary shell - // Temporary workaround until checkbox state is in content - nsCOMPtr presShell; - aPresContext->GetShell(getter_AddRefs(presShell)); - if (!presShell) return; - - nsCOMPtr doc; - presShell->GetDocument(getter_AddRefs(doc)); - if (!doc) return; - - nsCOMPtr primaryPresShell; - doc->GetShellAt(0, getter_AddRefs(primaryPresShell)); - if (!primaryPresShell) return; - - if (presShell.get() == primaryPresShell.get()) { - // Reset the value - // XXX We set the checkbox directly in the frame, because - // content fires onChange :( - PRBool checked = PR_FALSE; - nsresult rv = GetDefaultCheckState(&checked); - - if (NS_CONTENT_ATTR_HAS_VALUE == rv) { - SetCheckboxState (aPresContext, checked ? eOn : eOff ); - } - } -} //------------------------------------------------------------ void @@ -336,33 +205,9 @@ nsGfxCheckboxControlFrame::PaintCheckBox(nsIPresContext* aPresContext, mStyleContext->GetStyleData(eStyleStruct_Color); aRenderingContext.SetColor(color->mColor); - if ( IsTristateCheckbox() ) { - // Get current checked state through content model. - // XXX this won't work under printing. does that matter??? - CheckState checked = GetCheckboxState(); - switch ( checked ) { - case eOn: - nsFormControlHelper::PaintCheckMark(aRenderingContext, p2t, checkRect); - break; - - case eMixed: - PaintMixedMark(aRenderingContext, p2t, checkRect); - break; - - // no special drawing otherwise - default: - break; - } // case of value of checkbox - } else { - // Get current checked state through content model. - // XXX: This is very inefficient, but it is necessary in the case of printing. - // During printing the Paint is called but the actual state of the checkbox - // is in a frame in presentation shell 0. - PRBool checked = PR_FALSE; - GetCurrentCheckState(&checked); - if ( checked ) { - nsFormControlHelper::PaintCheckMark(aRenderingContext, p2t, checkRect); - } + // Get current checked state through content model. + if ( GetCheckboxState() ) { + nsFormControlHelper::PaintCheckMark(aRenderingContext, p2t, checkRect); } PRBool clip; @@ -370,51 +215,6 @@ nsGfxCheckboxControlFrame::PaintCheckBox(nsIPresContext* aPresContext, } -//------------------------------------------------------------ -// -// PaintMixedMark -// -// Like nsFormControlHelper::PaintCheckMark(), but paints the horizontal "mixed" -// bar inside the box. Only used for tri-state checkboxes. -// -void -nsGfxCheckboxControlFrame::PaintMixedMark ( nsIRenderingContext& aRenderingContext, - float aPixelsToTwips, const nsRect& aRect) -{ - const PRUint32 checkpoints = 4; - const PRUint32 checksize = 6; //This is value is determined by added 2 units to the end - //of the 7X& pixel rectangle below to provide some white space - //around the checkmark when it is rendered. - - // Points come from the coordinates on a 7X7 pixels - // box with 0,0 at the lower left. - nscoord checkedPolygonDef[] = { 1,2, 5,2, 5,4, 1,4 }; - // Location of the center point of the checkmark - const PRUint32 centerx = 3; - const PRUint32 centery = 3; - - nsPoint checkedPolygon[checkpoints]; - PRUint32 defIndex = 0; - PRUint32 polyIndex = 0; - - // Scale the checkmark based on the smallest dimension - PRUint32 size = aRect.width / checksize; - if (aRect.height < aRect.width) - size = aRect.height / checksize; - - // Center and offset each point in the polygon definition. - for (defIndex = 0; defIndex < (checkpoints * 2); defIndex++) { - checkedPolygon[polyIndex].x = nscoord((((checkedPolygonDef[defIndex]) - centerx) * (size)) + (aRect.width / 2) + aRect.x); - defIndex++; - checkedPolygon[polyIndex].y = nscoord((((checkedPolygonDef[defIndex]) - centery) * (size)) + (aRect.height / 2) + aRect.y); - polyIndex++; - } - - aRenderingContext.FillPolygon(checkedPolygon, checkpoints); - -} // PaintMixedMark - - //------------------------------------------------------------ NS_METHOD nsGfxCheckboxControlFrame::Paint(nsIPresContext* aPresContext, @@ -432,8 +232,8 @@ nsGfxCheckboxControlFrame::Paint(nsIPresContext* aPresContext, nsresult rv = nsFormControlFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { PRBool doDefaultPainting = PR_TRUE; - // Paint the checkmark - if (nsnull != mCheckButtonFaceStyle && GetCheckboxState() == eOn) { + // Paint the checkmark + if (!mCheckButtonFaceStyle && GetCheckboxState()) { const nsStyleBackground* myColor = (const nsStyleBackground*) mCheckButtonFaceStyle->GetStyleData(eStyleStruct_Background); @@ -466,61 +266,43 @@ nsGfxCheckboxControlFrame::Paint(nsIPresContext* aPresContext, } //------------------------------------------------------------ -nsGfxCheckboxControlFrame::CheckState +PRBool nsGfxCheckboxControlFrame::GetCheckboxState ( ) { - return mChecked; + nsCOMPtr elem(do_QueryInterface(mContent)); + PRBool retval = PR_FALSE; + elem->GetChecked(&retval); + return retval; } //------------------------------------------------------------ -void +void nsGfxCheckboxControlFrame::SetCheckboxState (nsIPresContext* aPresContext, - nsGfxCheckboxControlFrame::CheckState aValue ) + PRBool aValue ) { - mChecked = aValue; - nsFormControlHelper::ForceDrawFrame(aPresContext, this); + nsCOMPtr elem(do_QueryInterface(mContent)); + elem->SetChecked(aValue); } //------------------------------------------------------------ -void nsGfxCheckboxControlFrame::GetCheckboxControlFrameState(nsAWritableString& aValue) +void +nsGfxCheckboxControlFrame::GetCheckboxControlFrameState ( + nsAWritableString& aValue ) { CheckStateToString(GetCheckboxState(), aValue); } //------------------------------------------------------------ -void nsGfxCheckboxControlFrame::SetCheckboxControlFrameState(nsIPresContext* aPresContext, - const nsAReadableString& aValue) +void +nsGfxCheckboxControlFrame::SetCheckboxControlFrameState ( + nsIPresContext* aPresContext, + const nsAReadableString& aValue ) { - CheckState state = StringToCheckState(aValue); + PRBool state = StringToCheckState(aValue); SetCheckboxState(aPresContext, state); } -//------------------------------------------------------------ -NS_IMETHODIMP nsGfxCheckboxControlFrame::SetProperty(nsIPresContext* aPresContext, - nsIAtom* aName, - const nsAReadableString& aValue) -{ - if (nsHTMLAtoms::checked == aName) - SetCheckboxControlFrameState(aPresContext, aValue); - else - return nsFormControlFrame::SetProperty(aPresContext, aName, aValue); - - return NS_OK; -} - - -//------------------------------------------------------------ -NS_IMETHODIMP nsGfxCheckboxControlFrame::GetProperty(nsIAtom* aName, nsAWritableString& aValue) -{ - if (nsHTMLAtoms::checked == aName) - GetCheckboxControlFrameState(aValue); - else - return nsFormControlFrame::GetProperty(aName, aValue); - - return NS_OK; -} - //------------------------------------------------------------ // @@ -529,20 +311,14 @@ NS_IMETHODIMP nsGfxCheckboxControlFrame::GetProperty(nsIAtom* aName, nsAWritable // Converts from a CheckState to a string // void -nsGfxCheckboxControlFrame::CheckStateToString ( CheckState inState, nsAWritableString& outStateAsString ) +nsGfxCheckboxControlFrame::CheckStateToString ( + PRBool inState, + nsAWritableString& outStateAsString ) { - switch ( inState ) { - case eOn: - outStateAsString.Assign(NS_STRING_TRUE); - break; - - case eOff: - outStateAsString.Assign(NS_STRING_FALSE); - break; - - case eMixed: - outStateAsString.Assign(NS_LITERAL_STRING("2")); - break; + if (inState) { + outStateAsString.Assign(NS_STRING_TRUE); + } else { + outStateAsString.Assign(NS_STRING_FALSE); } } // CheckStateToString @@ -553,55 +329,13 @@ nsGfxCheckboxControlFrame::CheckStateToString ( CheckState inState, nsAWritableS // // Converts from a string to a CheckState enum // -nsGfxCheckboxControlFrame::CheckState +PRBool nsGfxCheckboxControlFrame::StringToCheckState ( const nsAReadableString & aStateAsString ) { - if ( aStateAsString.Equals(NS_STRING_TRUE) ) - return eOn; - else if ( aStateAsString.Equals(NS_STRING_FALSE) ) - return eOff; - - // not true and not false means mixed - return eMixed; - + return aStateAsString.Equals(NS_STRING_TRUE); } // StringToCheckState -//------------------------------------------------------------ -// -// SwitchModesWithEmergencyBrake -// -// Since we use an attribute to decide if we're a tristate box or not, this can change -// at any time. Since we have to use separate attributes to store the values depending -// on the mode, we have to convert from one to the other. -// -void -nsGfxCheckboxControlFrame::SwitchModesWithEmergencyBrake ( nsIPresContext* aPresContext, - PRBool inIsNowTristate ) -{ - if ( inIsNowTristate ) { - // we were a normal checkbox, and now we're a tristate. That means that the - // state of the checkbox was in "checked" and needs to be copied over into - // our parallel attribute. - nsAutoString value; - CheckStateToString ( GetCheckboxState(), value ); - mContent->SetAttr ( kNameSpaceID_None, GetTristateValueAtom(), value, PR_FALSE ); - } - else { - // we were a tri-state checkbox, and now we're a normal checkbox. The current - // state is already up to date (because it's always up to date). We just have - // to make sure it's not mixed. If it is, just set it to checked. Remove our - // parallel attribute so that we're nice and HTML4 compliant. - if ( GetCheckboxState() == eMixed ) - SetCheckboxState(aPresContext, eOn); - mContent->UnsetAttr ( kNameSpaceID_None, GetTristateValueAtom(), PR_FALSE ); - } - - // switch! - mIsTristate = inIsNowTristate; - -} // SwitchModesWithEmergencyBrake - //---------------------------------------------------------------------- // nsIStatefulFrame //---------------------------------------------------------------------- @@ -615,15 +349,14 @@ NS_IMETHODIMP nsGfxCheckboxControlFrame::SaveState(nsIPresContext* aPresContext, return NS_OK; } - CheckState stateCheck = GetCheckboxState(); + PRBool stateCheck = GetCheckboxState(); PRBool defaultStateBool = PR_FALSE; nsresult res = GetDefaultCheckState(&defaultStateBool); // Compare to default value, and only save if needed (Bug 62713) - // eOn/eOff comparisons used to handle 'mixed' state (alway save) if (!(NS_CONTENT_ATTR_HAS_VALUE == res && - ((eOn == stateCheck && defaultStateBool) || - (eOff == stateCheck && !defaultStateBool)))) { + ((stateCheck && defaultStateBool) || + (!stateCheck && !defaultStateBool)))) { // Get the value string nsAutoString stateString; diff --git a/layout/html/forms/src/nsGfxCheckboxControlFrame.h b/layout/html/forms/src/nsGfxCheckboxControlFrame.h index c9db5fc2d35..69bf5e41f69 100644 --- a/layout/html/forms/src/nsGfxCheckboxControlFrame.h +++ b/layout/html/forms/src/nsGfxCheckboxControlFrame.h @@ -66,21 +66,6 @@ public: return MakeFrameName(NS_LITERAL_STRING("CheckboxControl"), aResult); } #endif - // this should be protected, but VC6 is lame. - enum CheckState { eOff, eOn, eMixed } ; - - NS_IMETHOD Init(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParent, - nsIStyleContext* aContext, - nsIFrame* aPrevInFlow) ; - - NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext, - nsIContent* aChild, - PRInt32 aNameSpaceID, - nsIAtom* aAttribute, - PRInt32 aModType, - PRInt32 aHint) ; NS_IMETHOD Paint(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -93,10 +78,9 @@ public: #endif - //nsICheckboxControlFrame methods + //nsICheckboxControlFrame methods NS_IMETHOD SetCheckboxFaceStyleContext(nsIStyleContext *aCheckboxFaceStyleContext); - - void InitializeControl(nsIPresContext* aPresContext); + NS_IMETHOD OnChecked(nsIPresContext* aPresContext, PRBool aChecked); NS_IMETHOD GetAdditionalStyleContext(PRInt32 aIndex, nsIStyleContext** aStyleContext) const; @@ -104,8 +88,6 @@ public: nsIStyleContext* aStyleContext); // nsIFormControlFrame - NS_IMETHOD SetProperty(nsIPresContext* aPresContext, nsIAtom* aName, const nsAReadableString& aValue); - NS_IMETHOD GetProperty(nsIAtom* aName, nsAWritableString& aValue); NS_IMETHOD OnContentReset(); // nsIStatefulFrame @@ -121,14 +103,18 @@ public: nsReflowStatus& aStatus); #endif - NS_IMETHOD GetChecked(PRBool* aIsChecked) { *aIsChecked = (GetCheckboxState() == eOn); return NS_OK; } - NS_IMETHOD SetChecked(nsIPresContext* aPresContext, PRBool aIsChecked) { SetCheckboxState(aPresContext, aIsChecked ? eOn : eOff); return NS_OK; } + NS_IMETHOD GetChecked(PRBool* aIsChecked) { + *aIsChecked = GetCheckboxState(); return NS_OK; + } + NS_IMETHOD SetChecked(nsIPresContext* aPresContext, PRBool aIsChecked) { + SetCheckboxState(aPresContext, aIsChecked); return NS_OK; + } protected: // native/gfx implementations need to implement needs. - CheckState GetCheckboxState(); - void SetCheckboxState(nsIPresContext* aPresContext, CheckState aValue); + PRBool GetCheckboxState(); + void SetCheckboxState(nsIPresContext* aPresContext, PRBool aValue); // Utility methods for implementing SetProperty/GetProperty void SetCheckboxControlFrameState(nsIPresContext* aPresContext, @@ -136,22 +122,8 @@ protected: void GetCheckboxControlFrameState(nsAWritableString& aValue); // utility routine for converting from DOM values to internal enum - void CheckStateToString ( CheckState inState, nsAWritableString& outStateAsString ) ; - CheckState StringToCheckState ( const nsAReadableString & aStateAsString ) ; - - // figure out if we're a tri-state checkbox. - PRBool IsTristateCheckbox ( ) const { return mIsTristate; } - - // we just became a tri-state, or we just lost tri-state status. fix up - // the attributes for the new mode. - void SwitchModesWithEmergencyBrake ( nsIPresContext* aPresContext, - PRBool inIsNowTristate ) ; - - // for tri-state checkbox. meaningless for normal HTML - PRBool mIsTristate; - - static nsIAtom* GetTristateAtom() ; - static nsIAtom* GetTristateValueAtom() ; + void CheckStateToString(PRBool inState, nsAWritableString& outStateAsString) ; + PRBool StringToCheckState(const nsAReadableString & aStateAsString) ; protected: @@ -159,12 +131,9 @@ protected: nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer); - virtual void PaintMixedMark(nsIRenderingContext& aRenderingContext, - float aPixelsToTwips, const nsRect& aRect) ; //GFX-rendered state variables PRBool mInClickEvent; - CheckState mChecked; nsIStyleContext* mCheckButtonFaceStyle; private: diff --git a/webshell/tests/viewer/samples/checkboxTest.xul b/webshell/tests/viewer/samples/checkboxTest.xul index bb2dc31011c..e69de29bb2d 100644 --- a/webshell/tests/viewer/samples/checkboxTest.xul +++ b/webshell/tests/viewer/samples/checkboxTest.xul @@ -1,96 +0,0 @@ - - - - - - - - -TriStateCheckbox Test 1 - - - - -function MakeOneTriState() -{ - var tsbox = document.getElementById("normal"); - tsbox.setAttribute("moz-tristate", "1"); -} -function MakeTwoNormal() -{ - var tsbox = document.getElementById("tristate"); - tsbox.removeAttribute("moz-tristate"); -} - -function setTwoToMixed() -{ - var tsbox = document.getElementById("tristate"); - tsbox.setAttribute("moz-tristatevalue", "2"); -} - -function dumpTwoValue() -{ - var tsbox = document.getElementById("tristate"); - dump ( "value of button two is " + tsbox.getAttribute("moz-tristatevalue") + "\n" ); -} -function dumpOneValue() -{ - var tsbox = document.getElementById("normal"); - dump ( "value of button one is " + tsbox.getAttribute("moz-tristatevalue") + "\n" ); -} - -function disableTwo() -{ - var tsbox = document.getElementById("tristate"); - tsbox.disabled = true; -} -function enableTwo() -{ - var tsbox = document.getElementById("tristate"); - tsbox.disabled = false; -} - - - - -This is a tri-state checkbox test. The first checkbox should only act like a -normal two-state checkbox. The last one should behave like a tri-state. - - - - - - - -Button One (Normal) - - - -Button Two (Tristate) - - - -Button Three (Tristate set by css) - - -Change Mode On Button One -Change Mode On Button Two - - - - - -Set Two To Mixed -Dump Value of Button One -Dump Value of Button Two - - - - - -Disable Button Two -Enable Button Two - -