Move checkbox state to content (bug 108307). r=rods, sr=jst

This commit is contained in:
jkeiser%netscape.com 2002-01-24 19:04:55 +00:00
Родитель 84ad1383ae
Коммит 57b832743d
10 изменённых файлов: 231 добавлений и 883 удалений

Просмотреть файл

@ -311,9 +311,6 @@ HTML_ATOM(wrappedFramePseudo, ":wrapped-frame")
HTML_ATOM(zindex, "zindex") HTML_ATOM(zindex, "zindex")
HTML_ATOM(z_index, "z-index") HTML_ATOM(z_index, "z-index")
HTML_ATOM(moz_tristate, "moz-tristate")
HTML_ATOM(moz_tristatevalue, "moz-tristatevalue")
#ifdef DEBUG #ifdef DEBUG
HTML_ATOM(iform, "IForm") HTML_ATOM(iform, "IForm")
HTML_ATOM(form_control_list, "FormControlList") HTML_ATOM(form_control_list, "FormControlList")

Просмотреть файл

@ -167,6 +167,10 @@ public:
|| mType == NS_FORM_INPUT_HIDDEN)) { || mType == NS_FORM_INPUT_HIDDEN)) {
Reset(); Reset();
} }
if (aName == nsHTMLAtoms::checked && !mCheckedChanged
&& (mType == NS_FORM_INPUT_CHECKBOX || mType == NS_FORM_INPUT_RADIO)) {
Reset();
}
return rv; return rv;
} }
NS_IMETHOD SetAttr(nsINodeInfo* aNodeInfo, const nsAReadableString& aValue, NS_IMETHOD SetAttr(nsINodeInfo* aNodeInfo, const nsAReadableString& aValue,
@ -180,7 +184,10 @@ public:
nsresult rv = nsGenericHTMLLeafElement::UnsetAttr(aNameSpaceID, nsresult rv = nsGenericHTMLLeafElement::UnsetAttr(aNameSpaceID,
aAttribute, aAttribute,
aNotify); aNotify);
if (aAttribute == nsHTMLAtoms::value) { if (aAttribute == nsHTMLAtoms::value && !mValueChanged) {
Reset();
}
if (aAttribute == nsHTMLAtoms::checked && !mCheckedChanged) {
Reset(); Reset();
} }
return rv; return rv;
@ -216,12 +223,16 @@ protected:
return tmp.EqualsIgnoreCase("image"); return tmp.EqualsIgnoreCase("image");
} }
void FireOnChange();
nsCOMPtr<nsIControllers> mControllers; nsCOMPtr<nsIControllers> mControllers;
PRInt8 mType; PRInt8 mType;
PRPackedBool mSkipFocusEvent; PRPackedBool mSkipFocusEvent;
PRPackedBool mHandlingClick; PRPackedBool mHandlingClick;
PRPackedBool mValueChanged; PRPackedBool mValueChanged;
PRPackedBool mCheckedChanged;
PRPackedBool mChecked;
char* mValue; char* mValue;
}; };
@ -261,6 +272,8 @@ nsHTMLInputElement::nsHTMLInputElement()
mHandlingClick = PR_FALSE; mHandlingClick = PR_FALSE;
mValueChanged = PR_FALSE; mValueChanged = PR_FALSE;
mValue = nsnull; mValue = nsnull;
mCheckedChanged = PR_FALSE;
mChecked = PR_FALSE;
} }
nsHTMLInputElement::~nsHTMLInputElement() nsHTMLInputElement::~nsHTMLInputElement()
@ -355,20 +368,15 @@ nsHTMLInputElement::GetDefaultChecked(PRBool* aDefaultChecked)
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLInputElement::SetDefaultChecked(PRBool aDefaultChecked) nsHTMLInputElement::SetDefaultChecked(PRBool aDefaultChecked)
{ {
nsresult rv = NS_OK; nsresult rv;
nsHTMLValue empty(eHTMLUnit_Empty);
if (aDefaultChecked) { if (aDefaultChecked) {
rv = SetHTMLAttribute(nsHTMLAtoms::checked, empty, PR_TRUE); rv = SetAttr(kNameSpaceID_HTML, nsHTMLAtoms::checked,
NS_LITERAL_STRING(""), PR_TRUE);
} else { } else {
rv = UnsetAttr(kNameSpaceID_HTML, nsHTMLAtoms::checked, PR_TRUE); 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; return rv;
} }
@ -560,32 +568,42 @@ nsHTMLInputElement::SetValueChanged(PRBool aValueChanged)
} }
NS_IMETHODIMP 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 // No need to flush here, if there's no frame created for this input
// yet, we know our own checked state. // yet, we know our own checked state.
nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_FALSE); nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_FALSE);
if (formControlFrame) { if (formControlFrame) {
formControlFrame->GetProperty(nsHTMLAtoms::checked, value); formControlFrame->GetProperty(nsHTMLAtoms::checked, value);
}
else {
// Retrieve the presentation state instead.
nsCOMPtr<nsIPresState> presState;
GetPrimaryPresState(this, getter_AddRefs(presState));
// Obtain the value property from the presentation state.
if (presState) {
presState->GetStateProperty(NS_LITERAL_STRING("checked"), value);
} }
} else {
// Retrieve the presentation state instead.
nsCOMPtr<nsIPresState> presState;
GetPrimaryPresState(this, getter_AddRefs(presState));
if (value.Equals(NS_LITERAL_STRING("1"))) { // Obtain the value property from the presentation state.
*aValue = PR_TRUE; if (presState) {
presState->GetStateProperty(NS_LITERAL_STRING("checked"), value);
}
}
if (value.Equals(NS_LITERAL_STRING("1"))) {
*aChecked = PR_TRUE;
} else {
*aChecked = PR_FALSE;
}
} else { } else {
*aValue = PR_FALSE; if (!mCheckedChanged) {
GetDefaultChecked(aChecked);
} else {
*aChecked = mChecked;
}
} }
return NS_OK; return NS_OK;
@ -608,71 +626,78 @@ nsHTMLInputElement::SetPresStateChecked(nsIHTMLContent * aHTMLContent,
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLInputElement::SetChecked(PRBool aValue) nsHTMLInputElement::SetChecked(PRBool aValue)
{ {
// First check to see if the new value is the same as our current value. mCheckedChanged = PR_TRUE;
// If so, then return.
PRBool checked = PR_TRUE;
GetChecked(&checked);
if (checked == aValue) {
return NS_OK;
}
// Since the value is changing, send out an onchange event (bug 23571) //
nsCOMPtr<nsIPresContext> presContext; // Set the value
GetPresContext(this, getter_AddRefs(presContext)); //
mChecked = aValue;
//
// Notify the frame
//
// No need to flush here since if there's no frame for this input at // 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 // this point we don't care about creating one, once it's created
// the frame will do the right thing. // the frame will do the right thing.
PRInt32 type;
GetType(&type);
nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_FALSE); nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_FALSE);
if (formControlFrame) { if (formControlFrame) {
// the value is being toggled nsCOMPtr<nsIPresContext> presContext;
nsAutoString val; val.AssignWithConversion(aValue ? "1" : "0"); 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); SetPresStateChecked(this, aValue);
PRInt32 type; nsAutoString name;
GetType(&type); GetName(name);
if (type == NS_FORM_INPUT_RADIO) {
nsAutoString name;
GetName(name);
nsCOMPtr<nsIDOMHTMLFormElement> formElement; nsCOMPtr<nsIDOMHTMLFormElement> formElement;
if (NS_SUCCEEDED(GetForm(getter_AddRefs(formElement))) && formElement) { if (NS_SUCCEEDED(GetForm(getter_AddRefs(formElement))) && formElement) {
nsCOMPtr<nsIDOMHTMLCollection> controls; nsCOMPtr<nsIDOMHTMLCollection> controls;
nsresult rv = formElement->GetElements(getter_AddRefs(controls)); nsresult rv = formElement->GetElements(getter_AddRefs(controls));
if (controls) { if (controls) {
PRUint32 numControls; PRUint32 numControls;
controls->GetLength(&numControls); controls->GetLength(&numControls);
for (PRUint32 i = 0; i < numControls; i++) { for (PRUint32 i = 0; i < numControls; i++) {
nsCOMPtr<nsIDOMNode> elementNode; nsCOMPtr<nsIDOMNode> elementNode;
controls->Item(i, getter_AddRefs(elementNode)); controls->Item(i, getter_AddRefs(elementNode));
if (elementNode) { if (elementNode) {
nsCOMPtr<nsIDOMHTMLInputElement> nsCOMPtr<nsIDOMHTMLInputElement>
inputElement(do_QueryInterface(elementNode)); inputElement(do_QueryInterface(elementNode));
if (inputElement && inputElement.get() != if (inputElement && inputElement.get() !=
NS_STATIC_CAST(nsIDOMHTMLInputElement *, this)) { NS_STATIC_CAST(nsIDOMHTMLInputElement *, this)) {
nsAutoString childName; nsAutoString childName;
rv = inputElement->GetName(childName); rv = inputElement->GetName(childName);
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
if (name == childName) { if (name == childName) {
nsCOMPtr<nsIHTMLContent> nsCOMPtr<nsIHTMLContent>
htmlContent(do_QueryInterface(inputElement)); 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<nsIPresContext> presContext;
GetPresContext(this, getter_AddRefs(presContext));
nsEventStatus status = nsEventStatus_eIgnore; nsEventStatus status = nsEventStatus_eIgnore;
nsEvent event; nsEvent event;
event.eventStructType = NS_EVENT; event.eventStructType = NS_EVENT;
event.message = NS_FORM_CHANGE; event.message = NS_FORM_CHANGE;
HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status); HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -1094,6 +1128,7 @@ nsHTMLInputElement::HandleDOMEvent(nsIPresContext* aPresContext,
PRBool checked; PRBool checked;
GetChecked(&checked); GetChecked(&checked);
SetChecked(!checked); SetChecked(!checked);
FireOnChange();
// Fire an event to notify accessibility // Fire an event to notify accessibility
#ifdef ACCESSIBILITY #ifdef ACCESSIBILITY
FireEventForAccessibility( aPresContext, NS_LITERAL_STRING("CheckboxStateChange")); FireEventForAccessibility( aPresContext, NS_LITERAL_STRING("CheckboxStateChange"));
@ -1115,6 +1150,7 @@ nsHTMLInputElement::HandleDOMEvent(nsIPresContext* aPresContext,
} }
} }
SetChecked(PR_TRUE); SetChecked(PR_TRUE);
FireOnChange();
// Fire an event to notify accessibility // Fire an event to notify accessibility
#ifdef ACCESSIBILITY #ifdef ACCESSIBILITY
if ( selectedRadiobtn != this ) { if ( selectedRadiobtn != this ) {
@ -1743,7 +1779,6 @@ nsHTMLInputElement::Reset()
nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_FALSE); nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_FALSE);
// Seems like a dumb idea to reset image.
switch (type) { switch (type) {
case NS_FORM_INPUT_CHECKBOX: case NS_FORM_INPUT_CHECKBOX:
case NS_FORM_INPUT_RADIO: case NS_FORM_INPUT_RADIO:
@ -1751,6 +1786,7 @@ nsHTMLInputElement::Reset()
PRBool resetVal; PRBool resetVal;
GetDefaultChecked(&resetVal); GetDefaultChecked(&resetVal);
rv = SetChecked(resetVal); rv = SetChecked(resetVal);
mCheckedChanged = PR_FALSE;
break; break;
} }
case NS_FORM_INPUT_HIDDEN: case NS_FORM_INPUT_HIDDEN:

Просмотреть файл

@ -311,9 +311,6 @@ HTML_ATOM(wrappedFramePseudo, ":wrapped-frame")
HTML_ATOM(zindex, "zindex") HTML_ATOM(zindex, "zindex")
HTML_ATOM(z_index, "z-index") HTML_ATOM(z_index, "z-index")
HTML_ATOM(moz_tristate, "moz-tristate")
HTML_ATOM(moz_tristatevalue, "moz-tristatevalue")
#ifdef DEBUG #ifdef DEBUG
HTML_ATOM(iform, "IForm") HTML_ATOM(iform, "IForm")
HTML_ATOM(form_control_list, "FormControlList") HTML_ATOM(form_control_list, "FormControlList")

Просмотреть файл

@ -76,8 +76,7 @@ NS_NewGfxCheckboxControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
//------------------------------------------------------------ //------------------------------------------------------------
// Initialize GFX-rendered state // Initialize GFX-rendered state
nsGfxCheckboxControlFrame::nsGfxCheckboxControlFrame() nsGfxCheckboxControlFrame::nsGfxCheckboxControlFrame()
: mChecked(eOff), : mCheckButtonFaceStyle(nsnull)
mCheckButtonFaceStyle(nsnull)
{ {
} }
@ -131,35 +130,6 @@ nsGfxCheckboxControlFrame::SetCheckboxFaceStyleContext(nsIStyleContext *aCheckbo
return NS_OK; 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 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 NS_IMETHODIMP
nsGfxCheckboxControlFrame::AttributeChanged(nsIPresContext* aPresContext, nsGfxCheckboxControlFrame::OnChecked(nsIPresContext* aPresContext,
nsIContent* aChild, PRBool aChecked)
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType,
PRInt32 aHint)
{ {
if ( aAttribute == GetTristateAtom() ) { nsFormControlHelper::ForceDrawFrame(aPresContext, this);
nsAutoString value; return aChecked;
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;
} }
//------------------------------------------------------------
//
// 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<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
if (!presShell) return;
nsCOMPtr<nsIDocument> doc;
presShell->GetDocument(getter_AddRefs(doc));
if (!doc) return;
nsCOMPtr<nsIPresShell> 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 void
@ -336,33 +205,9 @@ nsGfxCheckboxControlFrame::PaintCheckBox(nsIPresContext* aPresContext,
mStyleContext->GetStyleData(eStyleStruct_Color); mStyleContext->GetStyleData(eStyleStruct_Color);
aRenderingContext.SetColor(color->mColor); aRenderingContext.SetColor(color->mColor);
if ( IsTristateCheckbox() ) { // Get current checked state through content model.
// Get current checked state through content model. if ( GetCheckboxState() ) {
// XXX this won't work under printing. does that matter??? nsFormControlHelper::PaintCheckMark(aRenderingContext, p2t, checkRect);
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);
}
} }
PRBool clip; 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 NS_METHOD
nsGfxCheckboxControlFrame::Paint(nsIPresContext* aPresContext, nsGfxCheckboxControlFrame::Paint(nsIPresContext* aPresContext,
@ -433,7 +233,7 @@ nsGfxCheckboxControlFrame::Paint(nsIPresContext* aPresContext,
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) {
PRBool doDefaultPainting = PR_TRUE; PRBool doDefaultPainting = PR_TRUE;
// Paint the checkmark // Paint the checkmark
if (nsnull != mCheckButtonFaceStyle && GetCheckboxState() == eOn) { if (!mCheckButtonFaceStyle && GetCheckboxState()) {
const nsStyleBackground* myColor = (const nsStyleBackground*) const nsStyleBackground* myColor = (const nsStyleBackground*)
mCheckButtonFaceStyle->GetStyleData(eStyleStruct_Background); mCheckButtonFaceStyle->GetStyleData(eStyleStruct_Background);
@ -466,61 +266,43 @@ nsGfxCheckboxControlFrame::Paint(nsIPresContext* aPresContext,
} }
//------------------------------------------------------------ //------------------------------------------------------------
nsGfxCheckboxControlFrame::CheckState PRBool
nsGfxCheckboxControlFrame::GetCheckboxState ( ) nsGfxCheckboxControlFrame::GetCheckboxState ( )
{ {
return mChecked; nsCOMPtr<nsIDOMHTMLInputElement> elem(do_QueryInterface(mContent));
PRBool retval = PR_FALSE;
elem->GetChecked(&retval);
return retval;
} }
//------------------------------------------------------------ //------------------------------------------------------------
void void
nsGfxCheckboxControlFrame::SetCheckboxState (nsIPresContext* aPresContext, nsGfxCheckboxControlFrame::SetCheckboxState (nsIPresContext* aPresContext,
nsGfxCheckboxControlFrame::CheckState aValue ) PRBool aValue )
{ {
mChecked = aValue; nsCOMPtr<nsIDOMHTMLInputElement> elem(do_QueryInterface(mContent));
nsFormControlHelper::ForceDrawFrame(aPresContext, this); elem->SetChecked(aValue);
} }
//------------------------------------------------------------ //------------------------------------------------------------
void nsGfxCheckboxControlFrame::GetCheckboxControlFrameState(nsAWritableString& aValue) void
nsGfxCheckboxControlFrame::GetCheckboxControlFrameState (
nsAWritableString& aValue )
{ {
CheckStateToString(GetCheckboxState(), aValue); CheckStateToString(GetCheckboxState(), aValue);
} }
//------------------------------------------------------------ //------------------------------------------------------------
void nsGfxCheckboxControlFrame::SetCheckboxControlFrameState(nsIPresContext* aPresContext, void
const nsAReadableString& aValue) nsGfxCheckboxControlFrame::SetCheckboxControlFrameState (
nsIPresContext* aPresContext,
const nsAReadableString& aValue )
{ {
CheckState state = StringToCheckState(aValue); PRBool state = StringToCheckState(aValue);
SetCheckboxState(aPresContext, state); 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 // Converts from a CheckState to a string
// //
void void
nsGfxCheckboxControlFrame::CheckStateToString ( CheckState inState, nsAWritableString& outStateAsString ) nsGfxCheckboxControlFrame::CheckStateToString (
PRBool inState,
nsAWritableString& outStateAsString )
{ {
switch ( inState ) { if (inState) {
case eOn: outStateAsString.Assign(NS_STRING_TRUE);
outStateAsString.Assign(NS_STRING_TRUE); } else {
break; outStateAsString.Assign(NS_STRING_FALSE);
case eOff:
outStateAsString.Assign(NS_STRING_FALSE);
break;
case eMixed:
outStateAsString.Assign(NS_LITERAL_STRING("2"));
break;
} }
} // CheckStateToString } // CheckStateToString
@ -553,55 +329,13 @@ nsGfxCheckboxControlFrame::CheckStateToString ( CheckState inState, nsAWritableS
// //
// Converts from a string to a CheckState enum // Converts from a string to a CheckState enum
// //
nsGfxCheckboxControlFrame::CheckState PRBool
nsGfxCheckboxControlFrame::StringToCheckState ( const nsAReadableString & aStateAsString ) nsGfxCheckboxControlFrame::StringToCheckState ( const nsAReadableString & aStateAsString )
{ {
if ( aStateAsString.Equals(NS_STRING_TRUE) ) return 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;
} // StringToCheckState } // 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 // nsIStatefulFrame
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -615,15 +349,14 @@ NS_IMETHODIMP nsGfxCheckboxControlFrame::SaveState(nsIPresContext* aPresContext,
return NS_OK; return NS_OK;
} }
CheckState stateCheck = GetCheckboxState(); PRBool stateCheck = GetCheckboxState();
PRBool defaultStateBool = PR_FALSE; PRBool defaultStateBool = PR_FALSE;
nsresult res = GetDefaultCheckState(&defaultStateBool); nsresult res = GetDefaultCheckState(&defaultStateBool);
// Compare to default value, and only save if needed (Bug 62713) // 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 && if (!(NS_CONTENT_ATTR_HAS_VALUE == res &&
((eOn == stateCheck && defaultStateBool) || ((stateCheck && defaultStateBool) ||
(eOff == stateCheck && !defaultStateBool)))) { (!stateCheck && !defaultStateBool)))) {
// Get the value string // Get the value string
nsAutoString stateString; nsAutoString stateString;

Просмотреть файл

@ -66,21 +66,6 @@ public:
return MakeFrameName(NS_LITERAL_STRING("CheckboxControl"), aResult); return MakeFrameName(NS_LITERAL_STRING("CheckboxControl"), aResult);
} }
#endif #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, NS_IMETHOD Paint(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext, nsIRenderingContext& aRenderingContext,
@ -93,10 +78,9 @@ public:
#endif #endif
//nsICheckboxControlFrame methods //nsICheckboxControlFrame methods
NS_IMETHOD SetCheckboxFaceStyleContext(nsIStyleContext *aCheckboxFaceStyleContext); NS_IMETHOD SetCheckboxFaceStyleContext(nsIStyleContext *aCheckboxFaceStyleContext);
NS_IMETHOD OnChecked(nsIPresContext* aPresContext, PRBool aChecked);
void InitializeControl(nsIPresContext* aPresContext);
NS_IMETHOD GetAdditionalStyleContext(PRInt32 aIndex, NS_IMETHOD GetAdditionalStyleContext(PRInt32 aIndex,
nsIStyleContext** aStyleContext) const; nsIStyleContext** aStyleContext) const;
@ -104,8 +88,6 @@ public:
nsIStyleContext* aStyleContext); nsIStyleContext* aStyleContext);
// nsIFormControlFrame // nsIFormControlFrame
NS_IMETHOD SetProperty(nsIPresContext* aPresContext, nsIAtom* aName, const nsAReadableString& aValue);
NS_IMETHOD GetProperty(nsIAtom* aName, nsAWritableString& aValue);
NS_IMETHOD OnContentReset(); NS_IMETHOD OnContentReset();
// nsIStatefulFrame // nsIStatefulFrame
@ -121,14 +103,18 @@ public:
nsReflowStatus& aStatus); nsReflowStatus& aStatus);
#endif #endif
NS_IMETHOD GetChecked(PRBool* aIsChecked) { *aIsChecked = (GetCheckboxState() == eOn); return NS_OK; } NS_IMETHOD GetChecked(PRBool* aIsChecked) {
NS_IMETHOD SetChecked(nsIPresContext* aPresContext, PRBool aIsChecked) { SetCheckboxState(aPresContext, aIsChecked ? eOn : eOff); return NS_OK; } *aIsChecked = GetCheckboxState(); return NS_OK;
}
NS_IMETHOD SetChecked(nsIPresContext* aPresContext, PRBool aIsChecked) {
SetCheckboxState(aPresContext, aIsChecked); return NS_OK;
}
protected: protected:
// native/gfx implementations need to implement needs. // native/gfx implementations need to implement needs.
CheckState GetCheckboxState(); PRBool GetCheckboxState();
void SetCheckboxState(nsIPresContext* aPresContext, CheckState aValue); void SetCheckboxState(nsIPresContext* aPresContext, PRBool aValue);
// Utility methods for implementing SetProperty/GetProperty // Utility methods for implementing SetProperty/GetProperty
void SetCheckboxControlFrameState(nsIPresContext* aPresContext, void SetCheckboxControlFrameState(nsIPresContext* aPresContext,
@ -136,22 +122,8 @@ protected:
void GetCheckboxControlFrameState(nsAWritableString& aValue); void GetCheckboxControlFrameState(nsAWritableString& aValue);
// utility routine for converting from DOM values to internal enum // utility routine for converting from DOM values to internal enum
void CheckStateToString ( CheckState inState, nsAWritableString& outStateAsString ) ; void CheckStateToString(PRBool inState, nsAWritableString& outStateAsString) ;
CheckState StringToCheckState ( const nsAReadableString & aStateAsString ) ; PRBool 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() ;
protected: protected:
@ -159,12 +131,9 @@ protected:
nsIRenderingContext& aRenderingContext, nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect, const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer); nsFramePaintLayer aWhichLayer);
virtual void PaintMixedMark(nsIRenderingContext& aRenderingContext,
float aPixelsToTwips, const nsRect& aRect) ;
//GFX-rendered state variables //GFX-rendered state variables
PRBool mInClickEvent; PRBool mInClickEvent;
CheckState mChecked;
nsIStyleContext* mCheckButtonFaceStyle; nsIStyleContext* mCheckButtonFaceStyle;
private: private:

Просмотреть файл

@ -40,6 +40,7 @@
#include "nsISupports.h" #include "nsISupports.h"
class nsIStyleContext; class nsIStyleContext;
class nsIPresContext;
// IID for the nsICheckControlFrame class // IID for the nsICheckControlFrame class
// {401347ED-0101-11d4-9706-0060B0FB9956} // {401347ED-0101-11d4-9706-0060B0FB9956}
@ -58,10 +59,14 @@ public:
/** /**
* Sets the Pseudo Style Contexts for the Check button * 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 #endif

Просмотреть файл

@ -40,6 +40,7 @@
#include "nsISupports.h" #include "nsISupports.h"
class nsIStyleContext; class nsIStyleContext;
class nsIPresContext;
// IID for the nsICheckControlFrame class // IID for the nsICheckControlFrame class
// {401347ED-0101-11d4-9706-0060B0FB9956} // {401347ED-0101-11d4-9706-0060B0FB9956}
@ -58,10 +59,14 @@ public:
/** /**
* Sets the Pseudo Style Contexts for the Check button * 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 #endif

Просмотреть файл

@ -76,8 +76,7 @@ NS_NewGfxCheckboxControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
//------------------------------------------------------------ //------------------------------------------------------------
// Initialize GFX-rendered state // Initialize GFX-rendered state
nsGfxCheckboxControlFrame::nsGfxCheckboxControlFrame() nsGfxCheckboxControlFrame::nsGfxCheckboxControlFrame()
: mChecked(eOff), : mCheckButtonFaceStyle(nsnull)
mCheckButtonFaceStyle(nsnull)
{ {
} }
@ -131,35 +130,6 @@ nsGfxCheckboxControlFrame::SetCheckboxFaceStyleContext(nsIStyleContext *aCheckbo
return NS_OK; 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 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 NS_IMETHODIMP
nsGfxCheckboxControlFrame::AttributeChanged(nsIPresContext* aPresContext, nsGfxCheckboxControlFrame::OnChecked(nsIPresContext* aPresContext,
nsIContent* aChild, PRBool aChecked)
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType,
PRInt32 aHint)
{ {
if ( aAttribute == GetTristateAtom() ) { nsFormControlHelper::ForceDrawFrame(aPresContext, this);
nsAutoString value; return aChecked;
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;
} }
//------------------------------------------------------------
//
// 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<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
if (!presShell) return;
nsCOMPtr<nsIDocument> doc;
presShell->GetDocument(getter_AddRefs(doc));
if (!doc) return;
nsCOMPtr<nsIPresShell> 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 void
@ -336,33 +205,9 @@ nsGfxCheckboxControlFrame::PaintCheckBox(nsIPresContext* aPresContext,
mStyleContext->GetStyleData(eStyleStruct_Color); mStyleContext->GetStyleData(eStyleStruct_Color);
aRenderingContext.SetColor(color->mColor); aRenderingContext.SetColor(color->mColor);
if ( IsTristateCheckbox() ) { // Get current checked state through content model.
// Get current checked state through content model. if ( GetCheckboxState() ) {
// XXX this won't work under printing. does that matter??? nsFormControlHelper::PaintCheckMark(aRenderingContext, p2t, checkRect);
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);
}
} }
PRBool clip; 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 NS_METHOD
nsGfxCheckboxControlFrame::Paint(nsIPresContext* aPresContext, nsGfxCheckboxControlFrame::Paint(nsIPresContext* aPresContext,
@ -433,7 +233,7 @@ nsGfxCheckboxControlFrame::Paint(nsIPresContext* aPresContext,
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) {
PRBool doDefaultPainting = PR_TRUE; PRBool doDefaultPainting = PR_TRUE;
// Paint the checkmark // Paint the checkmark
if (nsnull != mCheckButtonFaceStyle && GetCheckboxState() == eOn) { if (!mCheckButtonFaceStyle && GetCheckboxState()) {
const nsStyleBackground* myColor = (const nsStyleBackground*) const nsStyleBackground* myColor = (const nsStyleBackground*)
mCheckButtonFaceStyle->GetStyleData(eStyleStruct_Background); mCheckButtonFaceStyle->GetStyleData(eStyleStruct_Background);
@ -466,61 +266,43 @@ nsGfxCheckboxControlFrame::Paint(nsIPresContext* aPresContext,
} }
//------------------------------------------------------------ //------------------------------------------------------------
nsGfxCheckboxControlFrame::CheckState PRBool
nsGfxCheckboxControlFrame::GetCheckboxState ( ) nsGfxCheckboxControlFrame::GetCheckboxState ( )
{ {
return mChecked; nsCOMPtr<nsIDOMHTMLInputElement> elem(do_QueryInterface(mContent));
PRBool retval = PR_FALSE;
elem->GetChecked(&retval);
return retval;
} }
//------------------------------------------------------------ //------------------------------------------------------------
void void
nsGfxCheckboxControlFrame::SetCheckboxState (nsIPresContext* aPresContext, nsGfxCheckboxControlFrame::SetCheckboxState (nsIPresContext* aPresContext,
nsGfxCheckboxControlFrame::CheckState aValue ) PRBool aValue )
{ {
mChecked = aValue; nsCOMPtr<nsIDOMHTMLInputElement> elem(do_QueryInterface(mContent));
nsFormControlHelper::ForceDrawFrame(aPresContext, this); elem->SetChecked(aValue);
} }
//------------------------------------------------------------ //------------------------------------------------------------
void nsGfxCheckboxControlFrame::GetCheckboxControlFrameState(nsAWritableString& aValue) void
nsGfxCheckboxControlFrame::GetCheckboxControlFrameState (
nsAWritableString& aValue )
{ {
CheckStateToString(GetCheckboxState(), aValue); CheckStateToString(GetCheckboxState(), aValue);
} }
//------------------------------------------------------------ //------------------------------------------------------------
void nsGfxCheckboxControlFrame::SetCheckboxControlFrameState(nsIPresContext* aPresContext, void
const nsAReadableString& aValue) nsGfxCheckboxControlFrame::SetCheckboxControlFrameState (
nsIPresContext* aPresContext,
const nsAReadableString& aValue )
{ {
CheckState state = StringToCheckState(aValue); PRBool state = StringToCheckState(aValue);
SetCheckboxState(aPresContext, state); 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 // Converts from a CheckState to a string
// //
void void
nsGfxCheckboxControlFrame::CheckStateToString ( CheckState inState, nsAWritableString& outStateAsString ) nsGfxCheckboxControlFrame::CheckStateToString (
PRBool inState,
nsAWritableString& outStateAsString )
{ {
switch ( inState ) { if (inState) {
case eOn: outStateAsString.Assign(NS_STRING_TRUE);
outStateAsString.Assign(NS_STRING_TRUE); } else {
break; outStateAsString.Assign(NS_STRING_FALSE);
case eOff:
outStateAsString.Assign(NS_STRING_FALSE);
break;
case eMixed:
outStateAsString.Assign(NS_LITERAL_STRING("2"));
break;
} }
} // CheckStateToString } // CheckStateToString
@ -553,55 +329,13 @@ nsGfxCheckboxControlFrame::CheckStateToString ( CheckState inState, nsAWritableS
// //
// Converts from a string to a CheckState enum // Converts from a string to a CheckState enum
// //
nsGfxCheckboxControlFrame::CheckState PRBool
nsGfxCheckboxControlFrame::StringToCheckState ( const nsAReadableString & aStateAsString ) nsGfxCheckboxControlFrame::StringToCheckState ( const nsAReadableString & aStateAsString )
{ {
if ( aStateAsString.Equals(NS_STRING_TRUE) ) return 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;
} // StringToCheckState } // 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 // nsIStatefulFrame
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -615,15 +349,14 @@ NS_IMETHODIMP nsGfxCheckboxControlFrame::SaveState(nsIPresContext* aPresContext,
return NS_OK; return NS_OK;
} }
CheckState stateCheck = GetCheckboxState(); PRBool stateCheck = GetCheckboxState();
PRBool defaultStateBool = PR_FALSE; PRBool defaultStateBool = PR_FALSE;
nsresult res = GetDefaultCheckState(&defaultStateBool); nsresult res = GetDefaultCheckState(&defaultStateBool);
// Compare to default value, and only save if needed (Bug 62713) // 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 && if (!(NS_CONTENT_ATTR_HAS_VALUE == res &&
((eOn == stateCheck && defaultStateBool) || ((stateCheck && defaultStateBool) ||
(eOff == stateCheck && !defaultStateBool)))) { (!stateCheck && !defaultStateBool)))) {
// Get the value string // Get the value string
nsAutoString stateString; nsAutoString stateString;

Просмотреть файл

@ -66,21 +66,6 @@ public:
return MakeFrameName(NS_LITERAL_STRING("CheckboxControl"), aResult); return MakeFrameName(NS_LITERAL_STRING("CheckboxControl"), aResult);
} }
#endif #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, NS_IMETHOD Paint(nsIPresContext* aPresContext,
nsIRenderingContext& aRenderingContext, nsIRenderingContext& aRenderingContext,
@ -93,10 +78,9 @@ public:
#endif #endif
//nsICheckboxControlFrame methods //nsICheckboxControlFrame methods
NS_IMETHOD SetCheckboxFaceStyleContext(nsIStyleContext *aCheckboxFaceStyleContext); NS_IMETHOD SetCheckboxFaceStyleContext(nsIStyleContext *aCheckboxFaceStyleContext);
NS_IMETHOD OnChecked(nsIPresContext* aPresContext, PRBool aChecked);
void InitializeControl(nsIPresContext* aPresContext);
NS_IMETHOD GetAdditionalStyleContext(PRInt32 aIndex, NS_IMETHOD GetAdditionalStyleContext(PRInt32 aIndex,
nsIStyleContext** aStyleContext) const; nsIStyleContext** aStyleContext) const;
@ -104,8 +88,6 @@ public:
nsIStyleContext* aStyleContext); nsIStyleContext* aStyleContext);
// nsIFormControlFrame // nsIFormControlFrame
NS_IMETHOD SetProperty(nsIPresContext* aPresContext, nsIAtom* aName, const nsAReadableString& aValue);
NS_IMETHOD GetProperty(nsIAtom* aName, nsAWritableString& aValue);
NS_IMETHOD OnContentReset(); NS_IMETHOD OnContentReset();
// nsIStatefulFrame // nsIStatefulFrame
@ -121,14 +103,18 @@ public:
nsReflowStatus& aStatus); nsReflowStatus& aStatus);
#endif #endif
NS_IMETHOD GetChecked(PRBool* aIsChecked) { *aIsChecked = (GetCheckboxState() == eOn); return NS_OK; } NS_IMETHOD GetChecked(PRBool* aIsChecked) {
NS_IMETHOD SetChecked(nsIPresContext* aPresContext, PRBool aIsChecked) { SetCheckboxState(aPresContext, aIsChecked ? eOn : eOff); return NS_OK; } *aIsChecked = GetCheckboxState(); return NS_OK;
}
NS_IMETHOD SetChecked(nsIPresContext* aPresContext, PRBool aIsChecked) {
SetCheckboxState(aPresContext, aIsChecked); return NS_OK;
}
protected: protected:
// native/gfx implementations need to implement needs. // native/gfx implementations need to implement needs.
CheckState GetCheckboxState(); PRBool GetCheckboxState();
void SetCheckboxState(nsIPresContext* aPresContext, CheckState aValue); void SetCheckboxState(nsIPresContext* aPresContext, PRBool aValue);
// Utility methods for implementing SetProperty/GetProperty // Utility methods for implementing SetProperty/GetProperty
void SetCheckboxControlFrameState(nsIPresContext* aPresContext, void SetCheckboxControlFrameState(nsIPresContext* aPresContext,
@ -136,22 +122,8 @@ protected:
void GetCheckboxControlFrameState(nsAWritableString& aValue); void GetCheckboxControlFrameState(nsAWritableString& aValue);
// utility routine for converting from DOM values to internal enum // utility routine for converting from DOM values to internal enum
void CheckStateToString ( CheckState inState, nsAWritableString& outStateAsString ) ; void CheckStateToString(PRBool inState, nsAWritableString& outStateAsString) ;
CheckState StringToCheckState ( const nsAReadableString & aStateAsString ) ; PRBool 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() ;
protected: protected:
@ -159,12 +131,9 @@ protected:
nsIRenderingContext& aRenderingContext, nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect, const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer); nsFramePaintLayer aWhichLayer);
virtual void PaintMixedMark(nsIRenderingContext& aRenderingContext,
float aPixelsToTwips, const nsRect& aRect) ;
//GFX-rendered state variables //GFX-rendered state variables
PRBool mInClickEvent; PRBool mInClickEvent;
CheckState mChecked;
nsIStyleContext* mCheckButtonFaceStyle; nsIStyleContext* mCheckButtonFaceStyle;
private: private:

Просмотреть файл

@ -1,96 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://navigator/skin/navigator.css" type="text/css"?>
<?xml-stylesheet href="chrome://communicator/skin/bookmarks/bookmarks.css" type="text/css"?>
<!DOCTYPE window>
<window style="overflow: auto" xmlns:html="http://www.w3.org/1999/xhtml"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" orient="vertical"
onload="">
<html:h1>TriStateCheckbox Test 1</html:h1>
<html:script>
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;
}
</html:script>
<html:h3>
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.
</html:h3>
<html:div>
<html:hr/>
</html:div>
<html:label>
<html:input type="checkbox" id="normal"/>Button One (Normal)
</html:label>
<html:label>
<html:input type="checkbox" moz-tristate="1" id="tristate"/>Button Two (Tristate)
</html:label>
<html:label>
<html:input type="checkbox" style="moz-tristate: 1;" id="foop"/>Button Three (Tristate set by css)
</html:label>
<html:button onclick="MakeOneTriState()">Change Mode On Button One</html:button>
<html:button onclick="MakeTwoNormal()">Change Mode On Button Two</html:button>
<html:div>
<html:hr/>
</html:div>
<html:button onclick="setTwoToMixed()">Set Two To Mixed</html:button>
<html:button onclick="dumpOneValue()">Dump Value of Button One</html:button>
<html:button onclick="dumpTwoValue()">Dump Value of Button Two</html:button>
<html:div>
<html:hr/>
</html:div>
<html:button onclick="disableTwo()">Disable Button Two</html:button>
<html:button onclick="enableTwo()">Enable Button Two</html:button>
</window>