Move radio buttons to content (bug 108308). r=rods@netscape.com, sr=jst@netscape.com, a=asa@mozilla.org

This commit is contained in:
jkeiser%netscape.com 2002-03-07 20:53:40 +00:00
parent 9d2234ac01
commit 0ffd29f281
26 changed files with 1122 additions and 1237 deletions

View File

@ -6,5 +6,7 @@ nsIFormControl.h
nsIFormSubmission.h
nsILink.h
nsIOptionElement.h
nsIRadioControlElement.h
nsIRadioVisitor.h
nsIScriptElement.h
nsITextControlElement.h

View File

@ -38,6 +38,9 @@ EXPORTS = \
nsIForm.h \
nsILink.h \
nsIOptionElement.h \
nsIRadioControlElement.h \
nsIRadioVisitor.h \
nsIScriptElement.h \
nsITextControlElement.h \
nsIScriptElement.h \
nsIFormSubmission.h \

View File

@ -30,6 +30,8 @@ EXPORTS= \
nsIForm.h \
nsILink.h \
nsIOptionElement.h \
nsIRadioControlElement.h \
nsIRadioVisitor.h \
nsIScriptElement.h \
nsITextControlElement.h \
nsIFormSubmission.h \

View File

@ -43,6 +43,8 @@
class nsIFormControl;
class nsISizeOfHandler;
class nsIDOMHTMLInputElement;
class nsIRadioVisitor;
#define NS_FORM_METHOD_GET 0
@ -69,91 +71,129 @@ public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IFORM_IID)
/**
* Add an element to end of this form's list of elements
* @param aElement the element to add
* @return NS_OK if the element was successfully added
*/
* Add an element to end of this form's list of elements
*
* @param aElement the element to add
* @return NS_OK if the element was successfully added
*/
NS_IMETHOD AddElement(nsIFormControl* aElement) = 0;
/**
* Add an element to the lookup table mainted by the form.
* We can't fold this method into AddElement() because when
* AddElement() is called, the form control has no
* attributes. The name or id attributes of the form control
* are used as a key into the table.
*/
* Add an element to the lookup table mainted by the form.
*
* We can't fold this method into AddElement() because when
* AddElement() is called, the form control has no
* attributes. The name or id attributes of the form control
* are used as a key into the table.
*/
NS_IMETHOD AddElementToTable(nsIFormControl* aElement,
const nsAReadableString& aName) = 0;
/**
* Get the element at a specified index position
* @param aIndex the index
* @param aElement the element at that index
* @return NS_OK if there was an element at that position, -1 otherwise
*/
* Get the element at a specified index position
*
* @param aIndex the index
* @param aElement the element at that index
* @return NS_OK if there was an element at that position, -1 otherwise
*/
NS_IMETHOD GetElementAt(PRInt32 aIndex, nsIFormControl** aElement) const = 0;
/**
* Get the number of elements in this form
* @param aCount the number of elements
* @return NS_OK if there was an element at that position, -1 otherwise
*/
* Get the number of elements in this form
*
* @param aCount the number of elements
* @return NS_OK if there was an element at that position, -1 otherwise
*/
NS_IMETHOD GetElementCount(PRUint32* aCount) const = 0;
/**
* Remove an element from this form's list of elements
* @param aElement the element to remove
* @return NS_OK if the element was successfully removed.
*/
* Remove an element from this form's list of elements
*
* @param aElement the element to remove
* @return NS_OK if the element was successfully removed.
*/
NS_IMETHOD RemoveElement(nsIFormControl* aElement) = 0;
/**
* Remove an element from the lookup table mainted by the form.
* We can't fold this method into RemoveElement() because when
* RemoveElement() is called it doesn't know if the element is
* removed because the id attribute has changed, or bacause the
* name attribute has changed.
*
* @param aElement the element to remove
* @param aName the name or id of the element to remove
* @return NS_OK if the element was successfully removed.
*/
* Remove an element from the lookup table mainted by the form.
* We can't fold this method into RemoveElement() because when
* RemoveElement() is called it doesn't know if the element is
* removed because the id attribute has changed, or bacause the
* name attribute has changed.
*
* @param aElement the element to remove
* @param aName the name or id of the element to remove
* @return NS_OK if the element was successfully removed.
*/
NS_IMETHOD RemoveElementFromTable(nsIFormControl* aElement,
const nsAReadableString& aName) = 0;
/**
* Resolve a name in the scope of the form object, this means find
* form controls in this form with the correct value in the name
* attribute.
*
* @param aElement the element to remove
* @param aName the name or id of the element to remove
* @return NS_OK if the element was successfully removed.
*/
* Resolve a name in the scope of the form object, this means find
* form controls in this form with the correct value in the name
* attribute.
*
* @param aElement the element to remove
* @param aName the name or id of the element to remove
* @return NS_OK if the element was successfully removed.
*/
NS_IMETHOD ResolveName(const nsAReadableString& aName,
nsISupports **aResult) = 0;
/**
* Get the index of the given control within this form.
*/
* Get the index of the given control within this form.
*/
NS_IMETHOD IndexOfControl(nsIFormControl* aControl, PRInt32* aIndex) = 0;
/**
* This is a flag set on the form by nsHTMLContentSink::DemoteForm()
* to let form controls know that children of the form are being moved
* around needlessly (which is what DemoteForm() does).
*
* Form controls query this so that they can avoid changing their form when
* the inevitable SetParent() occurs. This prevents problems with indexing
* in DemoteForm() itself as well as other problems that arise from form
* controls setting their form to null, even temporarily.
*/
* This is a flag set on the form by nsHTMLContentSink::DemoteForm()
* to let form controls know that children of the form are being moved
* around needlessly (which is what DemoteForm() does).
*
* Form controls query this so that they can avoid changing their form when
* the inevitable SetParent() occurs. This prevents problems with indexing
* in DemoteForm() itself as well as other problems that arise from form
* controls setting their form to null, even temporarily.
*
* @param aDemotingForm whether the current form is being demoted.
*/
NS_IMETHOD SetDemotingForm(PRBool aDemotingForm) = 0;
/**
* Test whether this form is currently being demoted
*/
* Test whether this form is currently being demoted
*
* @param aDemotingForm a boolean to hold whether the current form is being
* demoted.
*/
NS_IMETHOD IsDemotingForm(PRBool* aDemotingForm) = 0;
/**
* Set the currently selected radio button in a group
*
* @param aName the radio group to set the button in
* @param aRadio the radio button to be returned
*/
NS_IMETHOD SetCurrentRadioButton(const nsAString& aName,
nsIDOMHTMLInputElement* aRadio) = 0;
/**
* Get the currently selected radio button in a group
*
* @param aName the radio group to get the radio button in
* @param aRadio the radio button to be returned
*/
NS_IMETHOD GetCurrentRadioButton(const nsAString& aName,
nsIDOMHTMLInputElement** aRadio) = 0;
/**
* Walk over the radios in a group and call Visit() on the visitor.
*
* @param aName the radio group to walk
* @param aVisitor the visitor to call Visit() on
*/
NS_IMETHOD WalkRadioGroup(const nsAString& aName,
nsIRadioVisitor* aVisitor) = 0;
};
#endif /* nsIForm_h___ */

View File

@ -0,0 +1,113 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* John B. Keiser
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsIRadioControlElement_h___
#define nsIRadioControlElement_h___
#include "nsISupports.h"
class nsAString;
class nsIForm;
// IID for the nsIRadioControl interface
#define NS_IRADIOCONTROLELEMENT_IID \
{ 0x647dff84, 0x1dd2, 0x11b2, \
{ 0x95, 0xcf, 0xe5, 0x01, 0xa8, 0x54, 0xa6, 0x40 } }
/**
* This interface is used for the text control frame to store its value away
* into the content.
*/
class nsIRadioControlElement : public nsISupports {
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IRADIOCONTROLELEMENT_IID)
/**
* Set the radio button checked, but don't do any extra checks and don't
* trigger "value changed". This is for experts only. Do not try this
* at home. Well, OK, try it at home, but not late at night.
*/
NS_IMETHOD RadioSetChecked() = 0;
/**
* Let this radio button know that the radio group's "checked" property has
* been changed by JavaScript or by the user
*
* @param aCheckedChanged whether the checked property has been changed.
* @param aOnlyOnThisRadioButton set to TRUE to only set the property only on
* the radio button in question; otherwise it will set the property on
* all other radio buttons in its group just to be sure they are
* consistent.
*/
NS_IMETHOD SetCheckedChangedInternal(PRBool aCheckedChanged) = 0;
/**
* Let an entire radio group know that it's "checked" property has been
* changed by JS or by the user (calls SetCheckedChangedInternal multiple
* times via a visitor)
*
* @param aCheckedChanged whether the checked property has been changed.
*/
NS_IMETHOD SetCheckedChanged(PRBool aCheckedChanged) = 0;
/**
* Find out whether this radio group's "checked" property has been changed by
* JavaScript or by the user
*
* @param aCheckedChanged out param, whether the checked property has been
* changed.
*/
NS_IMETHOD GetCheckedChanged(PRBool* aCheckedChanged) = 0;
/**
* Let this radio button know that state has been changed such that it has
* been added to a group.
*/
NS_IMETHOD AddedToRadioGroup() = 0;
/**
* Let this radio button know that state has been changed such that it has
* been *removed* from a group (and tell it which group).
* @param aForm the form it was removed from
* @param aName the name of the group it was removed from (nsnull to detect
* using GetName())
*/
NS_IMETHOD RemovedFromRadioGroup(nsIForm* aForm, nsAString* aName) = 0;
};
#endif // nsIRadioControlElement_h___

View File

@ -0,0 +1,96 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* John B. Keiser
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsIRadioVisitor_h___
#define nsIRadioVisitor_h___
#include "nsISupports.h"
class nsIFormControl;
// IID for the nsIRadioControl interface
#define NS_IRADIOVISITOR_IID \
{ 0xd3494bd2, 0x1dd1, 0x11b2, \
{ 0xbe, 0x86, 0xb5, 0x08, 0xc8, 0x71, 0xd7, 0xc5 } }
/**
* This interface is used for the text control frame to store its value away
* into the content.
*/
class nsIRadioVisitor : public nsISupports {
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IRADIOVISITOR_IID)
/**
* Visit a node in the tree. This is meant to be called on all radios in a
* group, sequentially. (Each radio group implementor may define
* sequentially in their own way, it just has to be the same every time.)
* Currently all radio groups are ordered in the order they appear in the
* document. Radio group implementors should honor the aStop parameter and
* stop iterating over form controls when Visit() returns true there.
*
* @param aRadio the radio button in question (must be nsnull and QI'able to
* nsIRadioControlElement)
* @param aStop whether or not to stop iterating (out-param)
*/
NS_IMETHOD Visit(nsIFormControl* aRadio, PRBool* aStop) = 0;
};
/**
* This visitor sets CheckedChanged on all elements it finds.
*
* @param aVisitor the visitor (out param)
* @param aCheckedChanged the value of CheckedChanged to set on all elements
*/
extern NS_METHOD NS_GetRadioSetCheckedChangedVisitor(PRBool aCheckedChanged,
nsIRadioVisitor** aVisitor);
/**
* This visitor will take the boolean you're pointing at and put
* aCheckedChanged into it. If the visitor is never called, aCheckedChanged
* will of course not change.
*
* @param aVisitor the visitor (out param)
* @param aCheckedChanged the boolean to put CheckedChanged into
* @param aExcludeElement the element
*/
extern NS_METHOD NS_GetRadioGetCheckedChangedVisitor(PRBool* aCheckedChanged,
nsIFormControl* aExcludeElement,
nsIRadioVisitor** aVisitor);
#endif // nsIRadioVisitor_h___

View File

@ -4081,12 +4081,6 @@ nsGenericHTMLContainerFormElement::SetForm(nsIDOMHTMLFormElement* aForm,
return NS_OK;
}
NS_IMETHODIMP
nsGenericHTMLContainerFormElement::Init()
{
return NS_OK;
}
NS_IMETHODIMP
nsGenericHTMLContainerFormElement::GetForm(nsIDOMHTMLFormElement** aForm)
{
@ -4329,12 +4323,6 @@ nsGenericHTMLLeafFormElement::SetForm(nsIDOMHTMLFormElement* aForm,
return NS_OK;
}
NS_IMETHODIMP
nsGenericHTMLLeafFormElement::Init()
{
return NS_OK;
}
NS_IMETHODIMP
nsGenericHTMLLeafFormElement::GetForm(nsIDOMHTMLFormElement** aForm)
{
@ -4731,6 +4719,8 @@ nsGenericHTMLElement::GetHostnameFromHrefString(const nsAReadableString& aHref,
if (NS_FAILED(rv))
return rv;
CopyASCIItoUCS2(host, aHostname);
aHostname.Assign(NS_ConvertUTF8toUCS2(host));
return NS_OK;
}

View File

@ -589,7 +589,6 @@ public:
NS_IMETHOD GetForm(nsIDOMHTMLFormElement** aForm);
NS_IMETHOD SetForm(nsIDOMHTMLFormElement* aForm,
PRBool aRemoveFromForm = PR_TRUE);
NS_IMETHOD Init();
NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState)
{
return NS_OK;
@ -639,7 +638,6 @@ public:
NS_IMETHOD GetForm(nsIDOMHTMLFormElement** aForm);
NS_IMETHOD SetForm(nsIDOMHTMLFormElement* aForm,
PRBool aRemoveFromForm = PR_TRUE);
NS_IMETHOD Init();
NS_IMETHOD SaveState(nsIPresContext* aPresContext, nsIPresState** aState)
{
return NS_OK;

View File

@ -61,6 +61,7 @@
#include "nsDOMError.h"
#include "nsContentUtils.h"
#include "nsHashtable.h"
#include "nsDoubleHashtable.h"
#include "nsContentList.h"
#include "nsGUIEvent.h"
@ -75,6 +76,10 @@
#include "nsIScriptSecurityManager.h"
#include "nsNetUtil.h"
// radio buttons
#include "nsIDOMHTMLInputElement.h"
#include "nsIRadioControlElement.h"
#include "nsIRadioVisitor.h"
static const int NS_FORM_CONTROL_LIST_HASHTABLE_SIZE = 16;
@ -88,9 +93,15 @@ class nsHTMLFormElement : public nsGenericHTMLContainerElement,
public nsIForm
{
public:
nsHTMLFormElement();
nsHTMLFormElement() :
mGeneratingSubmit(PR_FALSE),
mGeneratingReset(PR_FALSE),
mDemotingForm(PR_FALSE) { };
virtual ~nsHTMLFormElement();
virtual nsresult Init(nsINodeInfo* aNodeInfo);
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
@ -119,10 +130,15 @@ public:
NS_IMETHOD RemoveElementFromTable(nsIFormControl* aElement,
const nsAReadableString& aName);
NS_IMETHOD ResolveName(const nsAReadableString& aName,
nsISupports **aReturn);
nsISupports** aReturn);
NS_IMETHOD IndexOfControl(nsIFormControl* aControl, PRInt32* aIndex);
NS_IMETHOD SetDemotingForm(PRBool aDemotingForm);
NS_IMETHOD IsDemotingForm(PRBool* aDemotingForm);
NS_IMETHOD SetCurrentRadioButton(const nsAString& aName,
nsIDOMHTMLInputElement* aRadio);
NS_IMETHOD GetCurrentRadioButton(const nsAString& aName,
nsIDOMHTMLInputElement** aRadio);
NS_IMETHOD WalkRadioGroup(const nsAString& aName, nsIRadioVisitor* aVisitor);
#ifdef DEBUG
NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const;
@ -138,6 +154,7 @@ public:
NS_IMETHOD HandleDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent,
nsIDOMEvent** aDOMEvent, PRUint32 aFlags,
nsEventStatus* aEventStatus);
protected:
nsresult DoSubmitOrReset(nsIPresContext* aPresContext,
nsEvent* aEvent,
@ -196,6 +213,7 @@ protected:
// Data members
//
nsFormControlList *mControls;
nsDoubleHashtableStringSupports mSelectedRadioButtons;
PRPackedBool mGeneratingSubmit;
PRPackedBool mGeneratingReset;
PRPackedBool mDemotingForm;
@ -335,14 +353,22 @@ NS_NewHTMLFormElement(nsIHTMLContent** aInstancePtrResult,
}
nsHTMLFormElement::nsHTMLFormElement():
mGeneratingSubmit(PR_FALSE),
mGeneratingReset(PR_FALSE),
mDemotingForm(PR_FALSE)
nsresult
nsHTMLFormElement::Init(nsINodeInfo *aNodeInfo)
{
mControls = new nsFormControlList(this);
nsresult rv = nsGenericHTMLElement::Init(aNodeInfo);
NS_ENSURE_SUCCESS(rv, rv);
NS_IF_ADDREF(mControls);
mControls = new nsFormControlList(this);
if (!mControls) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(mControls);
rv = mSelectedRadioButtons.Init();
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
nsHTMLFormElement::~nsHTMLFormElement()
@ -990,6 +1016,17 @@ nsHTMLFormElement::AddElement(nsIFormControl* aChild)
}
}
//
// Notify the radio button it's been added to a group
//
PRInt32 type;
aChild->GetType(&type);
if (type == NS_FORM_INPUT_RADIO) {
nsCOMPtr<nsIRadioControlElement> radio = do_QueryInterface(aChild);
nsresult rv = radio->AddedToRadioGroup();
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
@ -1016,6 +1053,17 @@ nsHTMLFormElement::RemoveElement(nsIFormControl* aChild)
mControls->mNotInElements->Remove(&key);
}
//
// Remove it from the radio group if it's a radio button
//
PRInt32 type;
aChild->GetType(&type);
if (type == NS_FORM_INPUT_RADIO) {
nsCOMPtr<nsIRadioControlElement> radio = do_QueryInterface(aChild);
nsresult rv = radio->RemovedFromRadioGroup(this, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
@ -1083,8 +1131,111 @@ nsHTMLFormElement::IsDemotingForm(PRBool* aDemotingForm)
return NS_OK;
}
//----------------------------------------------------------------------
NS_IMETHODIMP
nsHTMLFormElement::SetCurrentRadioButton(const nsAString& aName,
nsIDOMHTMLInputElement* aRadio)
{
return mSelectedRadioButtons.Put(aName, (nsISupports*)aRadio);
}
NS_IMETHODIMP
nsHTMLFormElement::GetCurrentRadioButton(const nsAString& aName,
nsIDOMHTMLInputElement** aRadio)
{
*aRadio = (nsIDOMHTMLInputElement*)mSelectedRadioButtons.Get(aName).get();
return NS_OK;
}
NS_IMETHODIMP
nsHTMLFormElement::WalkRadioGroup(const nsAString& aName,
nsIRadioVisitor* aVisitor)
{
nsresult rv = NS_OK;
PRBool stopIterating = PR_FALSE;
if (aName.IsEmpty()) {
//
// XXX If the name is empty, it's not stored in the control list. There
// *must* be a more efficient way to do this.
//
nsCOMPtr<nsIFormControl> control;
PRUint32 len = 0;
GetElementCount(&len);
for (PRUint32 i=0; i<len; i++) {
GetElementAt(i, getter_AddRefs(control));
PRInt32 type;
control->GetType(&type);
if (type == NS_FORM_INPUT_RADIO) {
nsCOMPtr<nsIDOMHTMLInputElement> elem(do_QueryInterface(control));
if (elem) {
//
// XXX This is a particularly frivolous string copy just to determine
// if the string is empty or not
//
nsAutoString name;
elem->GetName(name);
if (name.IsEmpty()) {
aVisitor->Visit(control, &stopIterating);
if (stopIterating) {
break;
}
}
}
}
}
} else {
//
// Get the control / list of controls from the form using form["name"]
//
nsCOMPtr<nsISupports> item;
rv = ResolveName(aName, getter_AddRefs(item));
if (item) {
//
// If it's just a lone radio button, then select it.
//
nsCOMPtr<nsIFormControl> formControl(do_QueryInterface(item));
if (formControl) {
PRInt32 type;
formControl->GetType(&type);
if (type == NS_FORM_INPUT_RADIO) {
aVisitor->Visit(formControl, &stopIterating);
}
} else {
//
// If it's a list, we have to find the first non-disabled one and
// select it.
//
nsCOMPtr<nsIDOMNodeList> nodeList(do_QueryInterface(item));
if (nodeList) {
PRUint32 length = 0;
nodeList->GetLength(&length);
for (PRUint32 i=0; i<length; i++) {
nsCOMPtr<nsIDOMNode> node;
nodeList->Item(i, getter_AddRefs(node));
nsCOMPtr<nsIFormControl> formControl(do_QueryInterface(node));
if (formControl) {
PRInt32 type;
formControl->GetType(&type);
if (type == NS_FORM_INPUT_RADIO) {
aVisitor->Visit(formControl, &stopIterating);
if (stopIterating) {
break;
}
}
}
}
}
}
}
}
return rv;
}
//----------------------------------------------------------------------
// nsFormControlList implementation, this could go away if there were
// a lightweight collection implementation somewhere

View File

@ -40,6 +40,9 @@
#include "nsIDOMHTMLInputElement.h"
#include "nsIDOMNSHTMLInputElement.h"
#include "nsITextControlElement.h"
#include "nsIRadioControlElement.h"
#include "nsIRadioVisitor.h"
#include "nsIControllers.h"
#include "nsIEditorController.h"
#include "nsIFocusController.h"
@ -61,6 +64,7 @@
#include "nsIForm.h"
#include "nsIFormSubmission.h"
#include "nsIGfxTextControlFrame.h"
#include "nsIRadioControlFrame.h"
#include "nsIDocument.h"
#include "nsIPresShell.h"
#include "nsIFormControlFrame.h"
@ -80,7 +84,6 @@
#include "nsIDOMNodeList.h"
#include "nsIDOMHTMLCollection.h"
#include "nsICheckboxControlFrame.h"
#include "nsIRadioControlFrame.h"
#include "nsIFormManager.h"
#include "nsIImageControlFrame.h"
#include "nsLinebreakConverter.h" //to strip out carriage returns
@ -125,7 +128,8 @@ typedef nsIGfxTextControlFrame2 textControlPlace;
class nsHTMLInputElement : public nsGenericHTMLLeafFormElement,
public nsIDOMHTMLInputElement,
public nsIDOMNSHTMLInputElement,
public nsITextControlElement
public nsITextControlElement,
public nsIRadioControlElement
{
public:
nsHTMLInputElement();
@ -150,6 +154,8 @@ public:
NS_DECL_NSIDOMNSHTMLINPUTELEMENT
// Overriden nsIFormControl methods
NS_IMETHOD SetForm(nsIDOMHTMLFormElement* aForm,
PRBool aRemoveFromForm = PR_TRUE);
NS_IMETHOD GetType(PRInt32* aType);
NS_IMETHOD Reset();
NS_IMETHOD SubmitNamesValues(nsIFormSubmission* aFormSubmission,
@ -179,21 +185,12 @@ public:
NS_IMETHOD SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAReadableString& aValue, PRBool aNotify) {
BeforeSetAttr(aNameSpaceID, aName, &aValue, aNotify);
nsresult rv = nsGenericHTMLLeafFormElement::SetAttr(aNameSpaceID, aName,
aValue, aNotify);
if (aName == nsHTMLAtoms::value
&& !GET_BOOLBIT(mBitField, BF_VALUE_CHANGED)
&& (mType == NS_FORM_INPUT_TEXT
|| mType == NS_FORM_INPUT_PASSWORD
|| mType == NS_FORM_INPUT_FILE
|| mType == NS_FORM_INPUT_HIDDEN)) {
Reset();
}
if (aName == nsHTMLAtoms::checked
&& !GET_BOOLBIT(mBitField, BF_CHECKED_CHANGED)
&& (mType == NS_FORM_INPUT_CHECKBOX || mType == NS_FORM_INPUT_RADIO)) {
Reset();
}
AfterSetAttr(aNameSpaceID, aName, &aValue, aNotify);
return rv;
}
NS_IMETHOD SetAttr(nsINodeInfo* aNodeInfo, const nsAReadableString& aValue,
@ -204,17 +201,13 @@ public:
NS_IMETHOD UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
PRBool aNotify) {
BeforeSetAttr(aNameSpaceID, aAttribute, nsnull, aNotify);
nsresult rv = nsGenericHTMLLeafElement::UnsetAttr(aNameSpaceID,
aAttribute,
aNotify);
if (aAttribute == nsHTMLAtoms::value
&& !GET_BOOLBIT(mBitField, BF_VALUE_CHANGED)) {
Reset();
}
if (aAttribute == nsHTMLAtoms::checked
&& !GET_BOOLBIT(mBitField, BF_CHECKED_CHANGED)) {
Reset();
}
AfterSetAttr(aNameSpaceID, aAttribute, nsnull, aNotify);
return rv;
}
@ -222,6 +215,14 @@ public:
NS_IMETHOD SetValueGuaranteed(const nsAString& aValue, nsIGfxTextControlFrame2* aFrame);
NS_IMETHOD SetValueChanged(PRBool aValueChanged);
// nsIRadioControlElement
NS_IMETHOD RadioSetChecked();
NS_IMETHOD SetCheckedChanged(PRBool aCheckedChanged);
NS_IMETHOD SetCheckedChangedInternal(PRBool aCheckedChanged);
NS_IMETHOD GetCheckedChanged(PRBool* aCheckedChanged);
NS_IMETHOD AddedToRadioGroup();
NS_IMETHOD RemovedFromRadioGroup(nsIForm* aForm, nsAString* aName);
protected:
// Helper method
void SetPresStateChecked(nsIHTMLContent * aHTMLContent, PRBool aValue);
@ -237,6 +238,17 @@ protected:
const nsAReadableString& aEventType);
#endif
/**
* Called when an attribute is about to be changed
*/
void BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAReadableString* aValue, PRBool aNotify);
/**
* Called when an attribute has just been changed
*/
void AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAReadableString* aValue, PRBool aNotify);
void SelectAll(nsIPresContext* aPresContext);
PRBool IsImage() const
{
@ -249,6 +261,10 @@ protected:
void FireOnChange();
nsresult VisitGroup(nsIRadioVisitor* aVisitor);
nsresult SetCheckedInternal(PRBool aValue);
static nsresult GetContentType(const char* aPathName, char** aContentType);
nsCOMPtr<nsIControllers> mControllers;
@ -259,6 +275,34 @@ protected:
char* mValue;
};
//
// Visitor declarations
//
/**
* This visitor sets CheckedChanged on all elements it finds.
*
* @param aCheckedChanged the value of CheckedChanged to set on all elements
* @param aVisitor the visitor (out param)
*/
NS_METHOD NS_GetRadioSetCheckedChangedVisitor(PRBool aCheckedChanged,
nsIRadioVisitor** aVisitor);
/**
* This visitor will take the boolean you're pointing at and put
* aCheckedChanged into it. If the visitor is never called, aCheckedChanged
* will of course not change.
*
* @param aCheckedChanged the boolean to put CheckedChanged into
* @param aExcludeElement an element to exclude--i.e. don't get checked changed
* on this element
* @param aVisitor the visitor (out param)
*/
NS_METHOD NS_GetRadioGetCheckedChangedVisitor(PRBool* aCheckedChanged,
nsIFormControl* aExcludeElement,
nsIRadioVisitor** aVisitor);
//
// construction, destruction
//
@ -320,6 +364,7 @@ NS_HTML_CONTENT_INTERFACE_MAP_BEGIN(nsHTMLInputElement,
NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLInputElement)
NS_INTERFACE_MAP_ENTRY(nsIDOMNSHTMLInputElement)
NS_INTERFACE_MAP_ENTRY(nsITextControlElement)
NS_INTERFACE_MAP_ENTRY(nsIRadioControlElement)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(HTMLInputElement)
NS_HTML_CONTENT_INTERFACE_MAP_END
@ -355,6 +400,57 @@ nsHTMLInputElement::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
}
void
nsHTMLInputElement::BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAReadableString* aValue,
PRBool aNotify)
{
if (aName == nsHTMLAtoms::name &&
mType == NS_FORM_INPUT_RADIO) {
// XXX Because we are not doing anything that assumes the radio button has
// actually had its name changed at this point, we can get away with
// calling this before the name has changed (and gain in performance by not
// grabbing the old name every time the name is changed).
RemovedFromRadioGroup(mForm, nsnull);
}
}
void
nsHTMLInputElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAReadableString* aValue,
PRBool aNotify)
{
//
// When name changes, radio moves to a different group
// (type changes are handled in the form itself currently)
//
if (aName == nsHTMLAtoms::name &&
mType == NS_FORM_INPUT_RADIO) {
AddedToRadioGroup();
}
//
// Some elements have to change their value when the value and checked
// attributes change (but they only do so when ValueChanged() and
// CheckedChanged() are false--i.e. the value has not been changed by the
// user or by JS)
//
if (aName == nsHTMLAtoms::value &&
!GET_BOOLBIT(mBitField, BF_VALUE_CHANGED) &&
(mType == NS_FORM_INPUT_TEXT ||
mType == NS_FORM_INPUT_PASSWORD ||
mType == NS_FORM_INPUT_FILE ||
mType == NS_FORM_INPUT_HIDDEN)) {
Reset();
}
if (aName == nsHTMLAtoms::checked &&
!GET_BOOLBIT(mBitField, BF_CHECKED_CHANGED) &&
(mType == NS_FORM_INPUT_CHECKBOX ||
mType == NS_FORM_INPUT_RADIO)) {
Reset();
}
}
NS_IMETHODIMP
nsHTMLInputElement::GetForm(nsIDOMHTMLFormElement** aForm)
{
@ -377,7 +473,7 @@ nsHTMLInputElement::SetDefaultValue(const nsAReadableString& aDefaultValue)
NS_IMETHODIMP
nsHTMLInputElement::GetDefaultChecked(PRBool* aDefaultChecked)
{
nsHTMLValue val;
nsHTMLValue val;
nsresult rv;
rv = GetHTMLAttribute(nsHTMLAtoms::checked, val);
@ -591,42 +687,7 @@ nsHTMLInputElement::SetValueChanged(PRBool aValueChanged)
NS_IMETHODIMP
nsHTMLInputElement::GetChecked(PRBool* aChecked)
{
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);
if (formControlFrame) {
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);
}
}
if (value.Equals(NS_LITERAL_STRING("1"))) {
*aChecked = PR_TRUE;
} else {
*aChecked = PR_FALSE;
}
} else {
if (!GET_BOOLBIT(mBitField, BF_CHECKED_CHANGED)) {
GetDefaultChecked(aChecked);
} else {
*aChecked = GET_BOOLBIT(mBitField, BF_CHECKED);
}
}
*aChecked = GET_BOOLBIT(mBitField, BF_CHECKED);
return NS_OK;
}
@ -644,15 +705,143 @@ nsHTMLInputElement::SetPresStateChecked(nsIHTMLContent * aHTMLContent,
}
}
NS_IMETHODIMP
nsHTMLInputElement::SetChecked(PRBool aValue)
NS_IMETHODIMP
nsHTMLInputElement::SetCheckedChanged(PRBool aCheckedChanged)
{
SET_BOOLBIT(mBitField, BF_CHECKED_CHANGED, PR_TRUE);
if (mType == NS_FORM_INPUT_RADIO) {
if (GET_BOOLBIT(mBitField, BF_CHECKED_CHANGED) != aCheckedChanged) {
nsCOMPtr<nsIRadioVisitor> visitor;
NS_GetRadioSetCheckedChangedVisitor(aCheckedChanged,
getter_AddRefs(visitor));
VisitGroup(visitor);
}
} else {
SetCheckedChangedInternal(aCheckedChanged);
}
return NS_OK;
}
NS_IMETHODIMP
nsHTMLInputElement::SetCheckedChangedInternal(PRBool aCheckedChanged)
{
SET_BOOLBIT(mBitField, BF_CHECKED_CHANGED, aCheckedChanged);
return NS_OK;
}
NS_IMETHODIMP
nsHTMLInputElement::GetCheckedChanged(PRBool* aCheckedChanged)
{
*aCheckedChanged = GET_BOOLBIT(mBitField, BF_CHECKED_CHANGED);
return NS_OK;
}
NS_IMETHODIMP
nsHTMLInputElement::SetChecked(PRBool aChecked)
{
nsresult rv = NS_OK;
//
// If the user or JS attempts to set checked, whether it actually changes the
// value or not, we say the value was changed so that defaultValue don't
// affect it no more.
//
SetCheckedChanged(PR_TRUE);
//
// Don't do anything if we're not changing whether it's checked (it would
// screw up state actually, especially when you are setting radio button to
// false)
//
PRBool checked = PR_FALSE;
GetChecked(&checked);
if (checked == aChecked) {
return NS_OK;
}
//
// Set checked
//
PRInt32 type;
GetType(&type);
if (type == NS_FORM_INPUT_RADIO) {
//
// For radio button, we need to do some extra fun stuff
//
if (aChecked) {
rv = RadioSetChecked();
} else {
rv = SetCheckedInternal(PR_FALSE);
if (mForm) {
nsAutoString name;
GetName(name);
mForm->SetCurrentRadioButton(name, nsnull);
}
}
} else {
rv = SetCheckedInternal(aChecked);
}
return rv;
}
NS_IMETHODIMP
nsHTMLInputElement::RadioSetChecked()
{
nsresult rv = NS_OK;
//
// Find the selected radio button so we can deselect it
//
nsCOMPtr<nsIDOMHTMLInputElement> currentlySelected;
nsAutoString name;
if (mForm) {
// This is only initialized in if (mForm) for use in later if (mForm)s
GetName(name);
mForm->GetCurrentRadioButton(name, getter_AddRefs(currentlySelected));
}
//
// Deselect the currently selected radio button
//
if (currentlySelected) {
rv = NS_STATIC_CAST(nsHTMLInputElement*,
NS_STATIC_CAST(nsIDOMHTMLInputElement*, currentlySelected)
)->SetCheckedInternal(PR_FALSE);
}
//
// Actually select this one
//
if (NS_SUCCEEDED(rv)) {
rv = SetCheckedInternal(PR_TRUE);
}
//
// Let the form know that we are now the One True Radio Button
//
if (mForm && NS_SUCCEEDED(rv)) {
rv = mForm->SetCurrentRadioButton(name, NS_STATIC_CAST(nsIDOMHTMLInputElement*, this));
}
return rv;
}
NS_IMETHODIMP
nsHTMLInputElement::SetForm(nsIDOMHTMLFormElement* aForm,
PRBool aRemoveFromForm)
{
return nsGenericHTMLLeafFormElement::SetForm(aForm, aRemoveFromForm);
}
nsresult
nsHTMLInputElement::SetCheckedInternal(PRBool aChecked)
{
//
// Set the value
//
SET_BOOLBIT(mBitField, BF_CHECKED, aValue);
SET_BOOLBIT(mBitField, BF_CHECKED, aChecked);
//
// Notify the frame
@ -660,10 +849,11 @@ nsHTMLInputElement::SetChecked(PRBool aValue)
// 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);
nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_FALSE);
if (formControlFrame) {
nsCOMPtr<nsIPresContext> presContext;
GetPresContext(this, getter_AddRefs(presContext));
@ -672,63 +862,21 @@ nsHTMLInputElement::SetChecked(PRBool aValue)
nsICheckboxControlFrame* checkboxFrame = nsnull;
CallQueryInterface(formControlFrame, &checkboxFrame);
if (checkboxFrame) {
checkboxFrame->OnChecked(presContext, aValue);
checkboxFrame->OnChecked(presContext, aChecked);
}
// These are frames. You don't refcount frames. Silly wabbit.
} 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 if (type == NS_FORM_INPUT_RADIO) {
SetPresStateChecked(this, aValue);
nsAutoString name;
GetName(name);
nsCOMPtr<nsIDOMHTMLFormElement> formElement;
if (NS_SUCCEEDED(GetForm(getter_AddRefs(formElement))) && formElement) {
nsCOMPtr<nsIDOMHTMLCollection> controls;
nsresult rv = formElement->GetElements(getter_AddRefs(controls));
if (controls) {
PRUint32 numControls;
controls->GetLength(&numControls);
for (PRUint32 i = 0; i < numControls; i++) {
nsCOMPtr<nsIDOMNode> elementNode;
controls->Item(i, getter_AddRefs(elementNode));
if (elementNode) {
nsCOMPtr<nsIDOMHTMLInputElement>
inputElement(do_QueryInterface(elementNode));
if (inputElement && inputElement.get() !=
NS_STATIC_CAST(nsIDOMHTMLInputElement *, this)) {
nsAutoString childName;
rv = inputElement->GetName(childName);
if (NS_SUCCEEDED(rv)) {
if (name == childName) {
nsCOMPtr<nsIHTMLContent>
htmlContent(do_QueryInterface(inputElement));
SetPresStateChecked(htmlContent, PR_FALSE);
}
}
}
}
}
nsIRadioControlFrame* radioFrame = nsnull;
CallQueryInterface(formControlFrame, &radioFrame);
if (radioFrame) {
radioFrame->OnChecked(presContext, aChecked);
}
// You don't refcount frames.
}
}
// special attr for XBL form controls
else if (type == NS_FORM_INPUT_CHECKBOX) {
if (GET_BOOLBIT(mBitField, BF_CHECKED))
if (aChecked)
SetAttr(kNameSpaceID_None, nsHTMLAtoms::inputCheckedPseudo,
NS_LITERAL_STRING(""), PR_TRUE);
else
@ -1152,12 +1300,15 @@ nsHTMLInputElement::HandleDOMEvent(nsIPresContext* aPresContext,
// Start by remember the original value and for radio buttons we
// must get the currently selected radiobtn. So we go get the
// content instead of the frame
PRBool orginalCheckedValue = PR_FALSE;
//
PRBool originalCheckedValue = PR_FALSE;
PRBool checkWasSet = PR_FALSE;
nsCOMPtr<nsIContent> selectedRadiobtn;
nsCOMPtr<nsIDOMHTMLInputElement> selectedRadioButton;
if (!(aFlags & NS_EVENT_FLAG_CAPTURE) &&
aEvent->message == NS_MOUSE_LEFT_CLICK) {
GetChecked(&orginalCheckedValue);
GetChecked(&originalCheckedValue);
checkWasSet = PR_TRUE;
switch(type) {
case NS_FORM_INPUT_CHECKBOX:
@ -1168,30 +1319,32 @@ nsHTMLInputElement::HandleDOMEvent(nsIPresContext* aPresContext,
FireOnChange();
// Fire an event to notify accessibility
#ifdef ACCESSIBILITY
FireEventForAccessibility( aPresContext, NS_LITERAL_STRING("CheckboxStateChange"));
FireEventForAccessibility(aPresContext,
NS_LITERAL_STRING("CheckboxStateChange"));
#endif
}
break;
case NS_FORM_INPUT_RADIO:
{
// Get the currently selected button from the radio group
// we get access to that via the nsIRadioControlFrame interface
// because the current grouping is kept in the frame.
if (formControlFrame) {
nsIRadioControlFrame * rb = nsnull;
CallQueryInterface(formControlFrame, &rb);
if (rb) {
rb->GetRadioGroupSelectedContent(getter_AddRefs(selectedRadiobtn));
}
if (mForm) {
nsAutoString name;
GetName(name);
mForm->GetCurrentRadioButton(name,
getter_AddRefs(selectedRadioButton));
}
PRBool checked;
GetChecked(&checked);
if (!checked) {
SetChecked(PR_TRUE);
FireOnChange();
}
SetChecked(PR_TRUE);
FireOnChange();
// Fire an event to notify accessibility
#ifdef ACCESSIBILITY
if ( selectedRadiobtn != this ) {
FireEventForAccessibility( aPresContext, NS_LITERAL_STRING("RadioStateChange"));
if (selectedRadioButton != this) {
FireEventForAccessibility(aPresContext,
NS_LITERAL_STRING("RadioStateChange"));
}
#endif
}
@ -1228,13 +1381,10 @@ nsHTMLInputElement::HandleDOMEvent(nsIPresContext* aPresContext,
// if it was cancelled and a radio button, then set the old
// selected btn to TRUE. if it is a checkbox then set it to its
// original value
if (selectedRadiobtn) {
nsCOMPtr<nsIDOMHTMLInputElement> inputElement(do_QueryInterface(selectedRadiobtn));
if (inputElement) {
inputElement->SetChecked(PR_TRUE);
}
} else {
SetChecked(orginalCheckedValue);
if (selectedRadioButton) {
selectedRadioButton->SetChecked(PR_TRUE);
} else if (type == NS_FORM_INPUT_CHECKBOX) {
SetChecked(originalCheckedValue);
}
}
@ -1600,12 +1750,9 @@ nsHTMLInputElement::GetAttributeMappingFunction(nsMapRuleToAttributesFunc& aMapR
NS_IMETHODIMP
nsHTMLInputElement::GetType(PRInt32* aType)
{
if (aType) {
*aType = mType;
return NS_OK;
} else {
return NS_FORM_NOTOK;
}
NS_ASSERTION(aType, "aType must not be null!");
*aType = mType;
return NS_OK;
}
#ifdef DEBUG
@ -1828,7 +1975,7 @@ nsHTMLInputElement::Reset()
PRBool resetVal;
GetDefaultChecked(&resetVal);
rv = SetChecked(resetVal);
SET_BOOLBIT(mBitField, BF_CHECKED_CHANGED, PR_FALSE);
SetCheckedChanged(PR_FALSE);
break;
}
case NS_FORM_INPUT_HIDDEN:
@ -2082,26 +2229,47 @@ nsHTMLInputElement::SaveState(nsIPresContext* aPresContext,
GetType(&type);
switch (type) {
case NS_FORM_INPUT_CHECKBOX:
case NS_FORM_INPUT_RADIO:
{
PRBool checked = PR_FALSE;
GetChecked(&checked);
rv = GetPrimaryPresState(this, aState);
if (*aState) {
if (checked) {
rv = (*aState)->SetStateProperty(NS_LITERAL_STRING("checked"),
NS_LITERAL_STRING("t"));
} else {
rv = (*aState)->SetStateProperty(NS_LITERAL_STRING("checked"),
NS_LITERAL_STRING("f"));
}
NS_ASSERTION(NS_SUCCEEDED(rv), "checked save failed!");
}
break;
}
// Never save passwords in session history
case NS_FORM_INPUT_PASSWORD:
break;
case NS_FORM_INPUT_TEXT:
case NS_FORM_INPUT_FILE:
nsresult rv = GetPrimaryPresState(this, aState);
if (*aState) {
nsString value;
GetValue(value);
// XXX Should use nsAutoString above but ConvertStringLineBreaks
// requires mOwnsBuffer!
rv = nsLinebreakConverter::ConvertStringLineBreaks(
value,
nsLinebreakConverter::eLinebreakPlatform,
nsLinebreakConverter::eLinebreakContent);
NS_ASSERTION(NS_SUCCEEDED(rv), "Converting linebreaks failed!");
rv = (*aState)->SetStateProperty(NS_LITERAL_STRING("value"), value);
NS_ASSERTION(NS_SUCCEEDED(rv), "value save failed!");
{
nsresult rv = GetPrimaryPresState(this, aState);
if (*aState) {
nsString value;
GetValue(value);
// XXX Should use nsAutoString above but ConvertStringLineBreaks
// requires mOwnsBuffer!
rv = nsLinebreakConverter::ConvertStringLineBreaks(
value,
nsLinebreakConverter::eLinebreakPlatform,
nsLinebreakConverter::eLinebreakContent);
NS_ASSERTION(NS_SUCCEEDED(rv), "Converting linebreaks failed!");
rv = (*aState)->SetStateProperty(NS_LITERAL_STRING("value"), value);
NS_ASSERTION(NS_SUCCEEDED(rv), "value save failed!");
}
break;
}
break;
}
return rv;
@ -2117,17 +2285,271 @@ nsHTMLInputElement::RestoreState(nsIPresContext* aPresContext,
GetType(&type);
switch (type) {
case NS_FORM_INPUT_CHECKBOX:
case NS_FORM_INPUT_RADIO:
{
nsAutoString checked;
rv = aState->GetStateProperty(NS_LITERAL_STRING("checked"), checked);
// We assume that we are the only ones who saved the state. Thus we
// know the exact value that would have been saved.
if (checked.Equals(NS_LITERAL_STRING("t"))) {
SetChecked(PR_TRUE);
} else {
SetChecked(PR_FALSE);
}
break;
}
// Never save passwords in session history
case NS_FORM_INPUT_PASSWORD:
break;
case NS_FORM_INPUT_TEXT:
case NS_FORM_INPUT_FILE:
nsAutoString value;
rv = aState->GetStateProperty(NS_LITERAL_STRING("value"), value);
NS_ASSERTION(NS_SUCCEEDED(rv), "value restore failed!");
SetValue(value);
break;
{
nsAutoString value;
rv = aState->GetStateProperty(NS_LITERAL_STRING("value"), value);
NS_ASSERTION(NS_SUCCEEDED(rv), "value restore failed!");
SetValue(value);
break;
}
}
return rv;
}
/*
* Radio group stuff
*/
NS_IMETHODIMP
nsHTMLInputElement::AddedToRadioGroup()
{
//
// Currently the only time radio groups really happen is in forms
//
if (!mForm) {
return NS_OK;
}
//
// If the input element is checked, and we add it to the group, it will
// deselect whatever is currently selected in that group
//
PRBool checked;
GetChecked(&checked);
if (checked) {
//
// If it is checked, call "RadioSetChecked" to perform the selection/
// deselection ritual. This has the side effect of repainting the
// radio button, but as adding a checked radio button into the group
// should not be that common an occurrence, I think we can live with
// that.
//
RadioSetChecked();
}
//
// For integrity purposes, we have to ensure that "checkedChanged" is
// the same for this new element as for all the others in the group
//
PRBool checkedChanged = PR_FALSE;
nsCOMPtr<nsIRadioVisitor> visitor;
nsresult rv = NS_GetRadioGetCheckedChangedVisitor(&checkedChanged, this,
getter_AddRefs(visitor));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString name;
GetName(name);
rv = mForm->WalkRadioGroup(name, visitor);
SetCheckedChangedInternal(checkedChanged);
return NS_OK;
}
NS_IMETHODIMP
nsHTMLInputElement::RemovedFromRadioGroup(nsIForm* aForm, nsAString* aName)
{
//
// Currently radio groups only happen in forms
//
if (!aForm) {
return NS_OK;
}
//
// If this button was checked, we need to notify the group that there is no
// longer a selected radio button
//
PRBool checked = PR_FALSE;
GetChecked(&checked);
if (checked) {
if (aName) {
aForm->SetCurrentRadioButton(*aName, (nsIDOMHTMLInputElement*)nsnull);
} else {
nsAutoString name;
GetName(name);
aForm->SetCurrentRadioButton(name, (nsIDOMHTMLInputElement*)nsnull);
}
}
return NS_OK;
}
nsresult
nsHTMLInputElement::VisitGroup(nsIRadioVisitor* aVisitor)
{
nsresult rv;
if (mForm) {
nsAutoString name;
GetName(name);
rv = mForm->WalkRadioGroup(name, aVisitor);
} else {
PRBool stop = PR_FALSE;
rv = aVisitor->Visit(this, &stop);
}
return rv;
}
//
// Visitor classes
//
//
// CLASS nsRadioVisitor
//
// (this is the superclass of the others)
//
class nsRadioVisitor : public nsIRadioVisitor {
public:
nsRadioVisitor() { NS_INIT_ISUPPORTS(); }
virtual ~nsRadioVisitor() { };
NS_DECL_ISUPPORTS
NS_IMETHOD Visit(nsIFormControl* aRadio, PRBool* aStop) = 0;
};
NS_IMPL_ADDREF(nsRadioVisitor)
NS_IMPL_RELEASE(nsRadioVisitor)
NS_INTERFACE_MAP_BEGIN(nsRadioVisitor)
NS_INTERFACE_MAP_ENTRY(nsIRadioVisitor)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
//
// CLASS nsRadioSetCheckedChangedVisitor
//
class nsRadioSetCheckedChangedVisitor : public nsRadioVisitor {
public:
nsRadioSetCheckedChangedVisitor(PRBool aCheckedChanged) :
nsRadioVisitor(), mCheckedChanged(aCheckedChanged)
{ }
virtual ~nsRadioSetCheckedChangedVisitor() { }
NS_IMETHOD Visit(nsIFormControl* aRadio, PRBool* aStop)
{
nsCOMPtr<nsIRadioControlElement> radio(do_QueryInterface(aRadio));
NS_ASSERTION(radio, "Visit() passed a null button (or non-radio)!");
radio->SetCheckedChangedInternal(mCheckedChanged);
*aStop = PR_TRUE;
return NS_OK;
}
protected:
PRPackedBool mCheckedChanged;
};
//
// CLASS nsRadioGetCheckedChangedVisitor
//
class nsRadioGetCheckedChangedVisitor : public nsRadioVisitor {
public:
nsRadioGetCheckedChangedVisitor(PRBool* aCheckedChanged,
nsIFormControl* aExcludeElement) :
nsRadioVisitor(),
mCheckedChanged(aCheckedChanged),
mExcludeElement(aExcludeElement)
{ }
virtual ~nsRadioGetCheckedChangedVisitor() { }
NS_IMETHOD Visit(nsIFormControl* aRadio, PRBool* aStop)
{
if (aRadio == mExcludeElement) {
return NS_OK;
}
nsCOMPtr<nsIRadioControlElement> radio(do_QueryInterface(aRadio));
NS_ASSERTION(radio, "Visit() passed a null button (or non-radio)!");
radio->GetCheckedChanged(mCheckedChanged);
*aStop = PR_TRUE;
return NS_OK;
}
protected:
PRBool* mCheckedChanged;
nsIFormControl* mExcludeElement;
};
NS_METHOD
NS_GetRadioSetCheckedChangedVisitor(PRBool aCheckedChanged,
nsIRadioVisitor** aVisitor)
{
//
// These are static so that we don't have to keep creating new visitors for
// such an ordinary process all the time. There are only two possibilities
// for this visitor: set to true, and set to false.
//
static nsIRadioVisitor* visitorTrue = nsnull;
static nsIRadioVisitor* visitorFalse = nsnull;
//
// Get the visitor that sets them to true
//
if (aCheckedChanged) {
if (!visitorTrue) {
visitorTrue = new nsRadioSetCheckedChangedVisitor(PR_TRUE);
if (!visitorTrue) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(visitorTrue);
}
*aVisitor = visitorTrue;
}
//
// Get the visitor that sets them to false
//
if (!aCheckedChanged) {
if (!visitorFalse) {
visitorFalse = new nsRadioSetCheckedChangedVisitor(PR_FALSE);
if (!visitorFalse) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(visitorFalse);
}
*aVisitor = visitorFalse;
}
NS_ADDREF(*aVisitor);
return NS_OK;
}
NS_METHOD
NS_GetRadioGetCheckedChangedVisitor(PRBool* aCheckedChanged,
nsIFormControl* aExcludeElement,
nsIRadioVisitor** aVisitor)
{
*aVisitor = new nsRadioGetCheckedChangedVisitor(aCheckedChanged,
aExcludeElement);
if (!*aVisitor) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(*aVisitor);
return NS_OK;
}

View File

@ -129,8 +129,6 @@ nsFormControlFrame::~nsFormControlFrame()
{
if (mFormFrame) {
mFormFrame->RemoveFormControlFrame(*this);
// This method only removes from radio lists if we are a radio input
mFormFrame->RemoveRadioControlFrame(this);
mFormFrame = nsnull;
}
}
@ -857,11 +855,11 @@ nsFormControlFrame::GetFont(nsIPresContext* aPresContext,
nsresult
nsFormControlFrame::GetDefaultCheckState(PRBool *aState)
{ nsresult res = NS_OK;
nsIDOMHTMLInputElement* inputElement;
if (NS_OK == mContent->QueryInterface(NS_GET_IID(nsIDOMHTMLInputElement), (void**)&inputElement)) {
{
nsresult res = NS_OK;
nsCOMPtr<nsIDOMHTMLInputElement> inputElement = do_QueryInterface(mContent);
if (inputElement) {
res = inputElement->GetDefaultChecked(aState);
NS_RELEASE(inputElement);
}
return res;
}
@ -870,10 +868,9 @@ nsresult
nsFormControlFrame::SetDefaultCheckState(PRBool aState)
{
nsresult res = NS_OK;
nsIDOMHTMLInputElement* inputElement;
if (NS_OK == mContent->QueryInterface(NS_GET_IID(nsIDOMHTMLInputElement), (void**)&inputElement)) {
nsCOMPtr<nsIDOMHTMLInputElement> inputElement = do_QueryInterface(mContent);
if (inputElement) {
res = inputElement->SetDefaultChecked(aState);
NS_RELEASE(inputElement);
}
return res;
}
@ -882,10 +879,9 @@ nsresult
nsFormControlFrame::GetCurrentCheckState(PRBool *aState)
{
nsresult res = NS_OK;
nsIDOMHTMLInputElement* inputElement;
if (NS_OK == mContent->QueryInterface(NS_GET_IID(nsIDOMHTMLInputElement), (void**)&inputElement)) {
nsCOMPtr<nsIDOMHTMLInputElement> inputElement = do_QueryInterface(mContent);
if (inputElement) {
res = inputElement->GetChecked(aState);
NS_RELEASE(inputElement);
}
return res;
}
@ -894,10 +890,9 @@ nsresult
nsFormControlFrame::SetCurrentCheckState(PRBool aState)
{
nsresult res = NS_OK;
nsIDOMHTMLInputElement* inputElement;
if (NS_OK == mContent->QueryInterface(NS_GET_IID(nsIDOMHTMLInputElement), (void**)&inputElement)) {
nsCOMPtr<nsIDOMHTMLInputElement> inputElement = do_QueryInterface(mContent);
if (inputElement) {
inputElement->SetChecked(aState);
NS_RELEASE(inputElement);
}
return res;
}

View File

@ -275,127 +275,26 @@ nsGfxCheckboxControlFrame::GetCheckboxState ( )
return retval;
}
//------------------------------------------------------------
void
nsGfxCheckboxControlFrame::SetCheckboxState (nsIPresContext* aPresContext,
PRBool aValue )
{
nsCOMPtr<nsIDOMHTMLInputElement> elem(do_QueryInterface(mContent));
elem->SetChecked(aValue);
}
//------------------------------------------------------------
void
nsGfxCheckboxControlFrame::GetCheckboxControlFrameState (
nsAWritableString& aValue )
{
CheckStateToString(GetCheckboxState(), aValue);
}
//------------------------------------------------------------
void
nsGfxCheckboxControlFrame::SetCheckboxControlFrameState (
nsIPresContext* aPresContext,
const nsAReadableString& aValue )
{
PRBool state = StringToCheckState(aValue);
SetCheckboxState(aPresContext, state);
}
//------------------------------------------------------------
//
// CheckStateToString
//
// Converts from a CheckState to a string
//
void
nsGfxCheckboxControlFrame::CheckStateToString (
PRBool inState,
nsAWritableString& outStateAsString )
{
if (inState) {
outStateAsString.Assign(NS_STRING_TRUE);
} else {
outStateAsString.Assign(NS_STRING_FALSE);
}
} // CheckStateToString
//------------------------------------------------------------
//
// StringToCheckState
//
// Converts from a string to a CheckState enum
//
PRBool
nsGfxCheckboxControlFrame::StringToCheckState ( const nsAReadableString & aStateAsString )
{
return aStateAsString.Equals(NS_STRING_TRUE);
} // StringToCheckState
//----------------------------------------------------------------------
// nsIStatefulFrame
//----------------------------------------------------------------------
NS_IMETHODIMP nsGfxCheckboxControlFrame::SaveState(nsIPresContext* aPresContext,
nsIPresState** aState)
{
NS_ENSURE_ARG_POINTER(aState);
// Don't save state before we are initialized
if (!mDidInit) {
return NS_OK;
}
PRBool stateCheck = GetCheckboxState();
PRBool defaultStateBool = PR_FALSE;
nsresult res = GetDefaultCheckState(&defaultStateBool);
// Compare to default value, and only save if needed (Bug 62713)
if (!(NS_CONTENT_ATTR_HAS_VALUE == res &&
((stateCheck && defaultStateBool) ||
(!stateCheck && !defaultStateBool)))) {
// Get the value string
nsAutoString stateString;
CheckStateToString(stateCheck, stateString);
// Construct a pres state and store value in it.
res = NS_NewPresState(aState);
NS_ENSURE_SUCCESS(res, res);
res = (*aState)->SetStateProperty(NS_LITERAL_STRING("checked"), stateString);
}
return res;
return nsFormControlHelper::SaveContentState(this, aPresContext, aState);
}
NS_IMETHODIMP nsGfxCheckboxControlFrame::RestoreState(nsIPresContext* aPresContext,
nsIPresState* aState)
{
NS_ENSURE_ARG_POINTER(aState);
if (!mDidInit) {
mPresContext = aPresContext;
InitializeControl(aPresContext);
mDidInit = PR_TRUE;
}
// Set the value to the stored state.
nsAutoString stateString;
nsresult res = aState->GetStateProperty(NS_LITERAL_STRING("checked"), stateString);
NS_ENSURE_SUCCESS(res, res);
SetCheckboxControlFrameState(aPresContext, stateString);
return NS_OK;
return nsFormControlHelper::RestoreContentState(this, aPresContext, aState);
}
//------------------------------------------------------------
// Extra Debug Methods
//------------------------------------------------------------
#ifdef DEBUG_rodsXXX
NS_IMETHODIMP
NS_IMETHODIMP
nsGfxCheckboxControlFrame::Reflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,

View File

@ -103,27 +103,9 @@ public:
nsReflowStatus& aStatus);
#endif
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.
PRBool GetCheckboxState();
void SetCheckboxState(nsIPresContext* aPresContext, PRBool aValue);
// Utility methods for implementing SetProperty/GetProperty
void SetCheckboxControlFrameState(nsIPresContext* aPresContext,
const nsAReadableString& aValue);
void GetCheckboxControlFrameState(nsAWritableString& aValue);
// utility routine for converting from DOM values to internal enum
void CheckStateToString(PRBool inState, nsAWritableString& outStateAsString) ;
PRBool StringToCheckState(const nsAReadableString & aStateAsString) ;
protected:

View File

@ -74,7 +74,6 @@ NS_NewGfxRadioControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
nsGfxRadioControlFrame::nsGfxRadioControlFrame()
{
// Initialize GFX-rendered state
mChecked = PR_FALSE;
mRadioButtonFaceStyle = nsnull;
}
@ -155,79 +154,6 @@ nsGfxRadioControlFrame::SetAdditionalStyleContext(PRInt32 aIndex,
return NS_OK;
}
//--------------------------------------------------------------
NS_IMETHODIMP nsGfxRadioControlFrame::SetProperty(nsIPresContext* aPresContext, nsIAtom* aName, const nsAReadableString& aValue)
{
if (nsHTMLAtoms::checked == aName) {
PRBool state = (aValue.Equals(NS_STRING_TRUE)) ? PR_TRUE : PR_FALSE;
// if there is no form than the radiobtn is an orphan
if (mFormFrame) {
// if this failed then it didn't have a named radio group
if (NS_FAILED(mFormFrame->OnRadioChecked(aPresContext, *this, state))) {
// The line below is commented out to duplicate NavQuirks behavior
//SetRadioState(aPresContext, state);
}
} else {
SetRadioState(aPresContext, state);
}
}
else {
return nsFormControlFrame::SetProperty(aPresContext, aName, aValue);
}
return NS_OK;
}
//--------------------------------------------------------------
NS_IMETHODIMP nsGfxRadioControlFrame::GetProperty(nsIAtom* aName, nsAWritableString& aValue)
{
// Return the value of the property from the widget it is not null.
// If is null, assume the widget is GFX-rendered and return a member variable instead.
if (nsHTMLAtoms::checked == aName) {
nsFormControlHelper::GetBoolString(GetRadioState(), aValue);
} else {
return nsFormControlFrame::GetProperty(aName, aValue);
}
return NS_OK;
}
//--------------------------------------------------------------
PRBool
nsGfxRadioControlFrame::GetChecked()
{
PRBool checked = PR_FALSE;
GetCurrentCheckState(&checked);
return(checked);
}
//--------------------------------------------------------------
PRBool
nsGfxRadioControlFrame::GetDefaultChecked()
{
PRBool checked = PR_FALSE;
GetDefaultCheckState(&checked);
return(checked);
}
//--------------------------------------------------------------
void
nsGfxRadioControlFrame::SetChecked(nsIPresContext* aPresContext, PRBool aValue, PRBool aSetInitialValue)
{
if (aSetInitialValue) {
if (aValue) {
mContent->SetAttr(kNameSpaceID_HTML, nsHTMLAtoms::checked, NS_LITERAL_STRING("1"), PR_FALSE); // XXX should be "empty" value
} else {
mContent->SetAttr(kNameSpaceID_HTML, nsHTMLAtoms::checked, NS_LITERAL_STRING("0"), PR_FALSE);
}
}
SetRadioState(aPresContext, aValue);
}
//--------------------------------------------------------------
NS_IMETHODIMP
nsGfxRadioControlFrame::SetRadioButtonFaceStyleContext(nsIStyleContext *aRadioButtonFaceStyleContext)
@ -238,15 +164,6 @@ nsGfxRadioControlFrame::SetRadioButtonFaceStyleContext(nsIStyleContext *aRadioBu
}
//--------------------------------------------------------------
NS_IMETHODIMP
nsGfxRadioControlFrame::GetRadioGroupSelectedContent(nsIContent ** aRadioBtn)
{
NS_ENSURE_ARG_POINTER(aRadioBtn);
nsFormFrame::GetRadioGroupSelectedContent(this, aRadioBtn);
return NS_OK;
}
NS_IMETHODIMP
nsGfxRadioControlFrame::HandleEvent(nsIPresContext* aPresContext,
nsGUIEvent* aEvent,
@ -271,8 +188,8 @@ nsGfxRadioControlFrame::PaintRadioButton(nsIPresContext* aPresContext,
PRBool checked = PR_TRUE;
GetCurrentCheckState(&checked); // Get check state from the content model
if (PR_TRUE == checked) {
// Paint the button for the radio button using CSS background rendering code
if (checked) {
// Paint the button for the radio button using CSS background rendering code
if (nsnull != mRadioButtonFaceStyle) {
const nsStyleBackground* myColor = (const nsStyleBackground*)
mRadioButtonFaceStyle->GetStyleData(eStyleStruct_Background);
@ -332,80 +249,22 @@ nsGfxRadioControlFrame::Paint(nsIPresContext* aPresContext,
//--------------------------------------------------------------
PRBool nsGfxRadioControlFrame::GetRadioState()
NS_IMETHODIMP
nsGfxRadioControlFrame::OnChecked(nsIPresContext* aPresContext,
PRBool aChecked)
{
return mChecked;
}
//--------------------------------------------------------------
void nsGfxRadioControlFrame::SetRadioState(nsIPresContext* aPresContext, PRBool aValue)
{
mChecked = aValue;
nsFormControlHelper::ForceDrawFrame(aPresContext, this);
}
void
nsGfxRadioControlFrame::InitializeControl(nsIPresContext* aPresContext)
{
nsFormControlFrame::InitializeControl(aPresContext);
// Only reset on init if this is the primary shell
// Temporary workaround until radio 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()) {
// set the widget to the initial state
// XXX We can't use reset because radio buttons fire onChange
// from content (much to our dismay)
PRBool checked = PR_FALSE;
nsresult rv = GetDefaultCheckState(&checked);
if (NS_CONTENT_ATTR_HAS_VALUE == rv) {
SetRadioState(aPresContext, checked);
}
}
return NS_OK;
}
//----------------------------------------------------------------------
// nsIStatefulFrame
//----------------------------------------------------------------------
NS_IMETHODIMP
nsGfxRadioControlFrame::SaveState(nsIPresContext* aPresContext, nsIPresState** aState)
nsGfxRadioControlFrame::SaveState(nsIPresContext* aPresContext,
nsIPresState** aState)
{
NS_ENSURE_ARG_POINTER(aState);
// Don't save state before we are initialized
if (!mDidInit) {
return NS_OK;
}
nsresult res = NS_OK;
PRBool stateBool = GetRadioState();
PRBool defaultStateBool = GetDefaultChecked();
// Compare to default value, and only save if needed (Bug 62713)
if (stateBool != defaultStateBool) {
// Get the value string
nsAutoString stateString;
nsFormControlHelper::GetBoolString(stateBool, stateString);
// Construct a pres state and store value in it.
res = NS_NewPresState(aState);
NS_ENSURE_SUCCESS(res, res);
res = (*aState)->SetStateProperty(NS_LITERAL_STRING("checked"), stateString);
}
return res;
return nsFormControlHelper::SaveContentState(this, aPresContext, aState);
}
@ -414,25 +273,7 @@ nsGfxRadioControlFrame::SaveState(nsIPresContext* aPresContext, nsIPresState** a
NS_IMETHODIMP
nsGfxRadioControlFrame::RestoreState(nsIPresContext* aPresContext, nsIPresState* aState)
{
NS_ENSURE_ARG_POINTER(aState);
if (!mDidInit) {
mPresContext = aPresContext;
InitializeControl(aPresContext);
mDidInit = PR_TRUE;
}
mIsRestored = PR_TRUE;
nsAutoString stateString;
nsresult res = aState->GetStateProperty(NS_LITERAL_STRING("checked"), stateString);
NS_ENSURE_SUCCESS(res, res);
res = SetProperty(aPresContext, nsHTMLAtoms::checked, stateString);
NS_ENSURE_SUCCESS(res, res);
mRestoredChecked = mChecked;
return NS_OK;
return nsFormControlHelper::RestoreContentState(this, aPresContext, aState);
}

View File

@ -65,19 +65,10 @@ public:
//nsIRadioControlFrame methods
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
NS_IMETHOD SetRadioButtonFaceStyleContext(nsIStyleContext *aRadioButtonFaceStyleContext);
NS_IMETHOD GetRadioGroupSelectedContent(nsIContent ** aRadioBtn);
#ifdef ACCESSIBILITY
NS_IMETHOD GetAccessible(nsIAccessible** aAccessible);
#endif
virtual PRBool GetChecked();
virtual PRBool GetDefaultChecked();
virtual PRBool GetRestoredChecked() { return mRestoredChecked;}
virtual PRBool IsRestored() { return mIsRestored;}
virtual void SetChecked(nsIPresContext* aPresContext, PRBool aValue, PRBool aSetInitialValue);
void InitializeControl(nsIPresContext* aPresContext);
NS_IMETHOD OnChecked(nsIPresContext* aPresContext, PRBool aChecked);
NS_IMETHOD GetAdditionalStyleContext(PRInt32 aIndex,
nsIStyleContext** aStyleContext) const;
@ -103,9 +94,7 @@ public:
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect);
// nsIFormControlFrame
NS_IMETHOD SetProperty(nsIPresContext* aPresContext, nsIAtom* aName, const nsAReadableString& aValue);
NS_IMETHOD GetProperty(nsIAtom* aName, nsAWritableString& aValue);
// nsIFormControlFrame
NS_IMETHOD OnContentReset();
//nsIStatefulFrame
@ -122,14 +111,8 @@ public:
protected:
virtual PRBool GetRadioState();
virtual void SetRadioState(nsIPresContext* aPresContext, PRBool aValue);
//GFX-rendered state variables
PRBool mChecked;
nsIStyleContext* mRadioButtonFaceStyle;
PRBool mRestoredChecked;
PRBool mIsRestored;
private:
NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; }

View File

@ -50,7 +50,7 @@ class nsIStyleContext;
/**
* nsIRadioControlFrame is the common interface radio buttons.
* @see nsFromControlFrame and its base classes for more info
* @see nsFormControlFrame and its base classes for more info
*/
class nsIRadioControlFrame : public nsISupports {
@ -59,30 +59,14 @@ public:
/**
* Sets the Pseudo Style Contexts for the Radio button
*
*/
NS_IMETHOD SetRadioButtonFaceStyleContext(nsIStyleContext *aRadioButtonFaceStyleContext) = 0;
/**
* When a user clicks on a radiobutton the value needs to be set after the onmouseup
* and before the onclick event is processed via script. The EVM always lets script
* get first crack at the processing, and script can cancel further processing of
* the event by return null.
*
* This means the radiobutton needs to have it's new value set before it goes to script
* to process the onclick and then if script cancels the event it needs to be set back.
* In Nav and IE there is a flash of it being set and then unset
*
* We have added this extra method to the radiobutton so nsHTMLInputElement can get
* the content of the currently selected radiobutton for that radio group
*
* That way if it is cancelled then the original radiobutton can be set back
*/
NS_IMETHOD GetRadioGroupSelectedContent(nsIContent ** aRadioBtn) = 0;
/**
* Called by content when the radio button's state changes
*/
NS_IMETHOD OnChecked(nsIPresContext* aPresContext, PRBool aChecked) = 0;
};
#endif

View File

@ -50,7 +50,7 @@ class nsIStyleContext;
/**
* nsIRadioControlFrame is the common interface radio buttons.
* @see nsFromControlFrame and its base classes for more info
* @see nsFormControlFrame and its base classes for more info
*/
class nsIRadioControlFrame : public nsISupports {
@ -59,30 +59,14 @@ public:
/**
* Sets the Pseudo Style Contexts for the Radio button
*
*/
NS_IMETHOD SetRadioButtonFaceStyleContext(nsIStyleContext *aRadioButtonFaceStyleContext) = 0;
/**
* When a user clicks on a radiobutton the value needs to be set after the onmouseup
* and before the onclick event is processed via script. The EVM always lets script
* get first crack at the processing, and script can cancel further processing of
* the event by return null.
*
* This means the radiobutton needs to have it's new value set before it goes to script
* to process the onclick and then if script cancels the event it needs to be set back.
* In Nav and IE there is a flash of it being set and then unset
*
* We have added this extra method to the radiobutton so nsHTMLInputElement can get
* the content of the currently selected radiobutton for that radio group
*
* That way if it is cancelled then the original radiobutton can be set back
*/
NS_IMETHOD GetRadioGroupSelectedContent(nsIContent ** aRadioBtn) = 0;
/**
* Called by content when the radio button's state changes
*/
NS_IMETHOD OnChecked(nsIPresContext* aPresContext, PRBool aChecked) = 0;
};
#endif

View File

@ -72,7 +72,6 @@ CPPSRCS = \
nsLabelFrame.cpp \
nsLegendFrame.cpp \
nsListControlFrame.cpp \
nsRadioControlGroup.cpp \
nsIsIndexFrame.cpp \
$(NULL)

View File

@ -68,8 +68,7 @@ CPP_OBJS= \
.\$(OBJDIR)\nsGfxButtonControlFrame.obj \
.\$(OBJDIR)\nsGfxCheckboxControlFrame.obj \
.\$(OBJDIR)\nsGfxRadioControlFrame.obj \
.\$(OBJDIR)\nsIsIndexFrame.obj \
.\$(OBJDIR)\nsRadioControlGroup.obj
.\$(OBJDIR)\nsIsIndexFrame.obj
LINCS= -I..\..\base\src \

View File

@ -129,8 +129,6 @@ nsFormControlFrame::~nsFormControlFrame()
{
if (mFormFrame) {
mFormFrame->RemoveFormControlFrame(*this);
// This method only removes from radio lists if we are a radio input
mFormFrame->RemoveRadioControlFrame(this);
mFormFrame = nsnull;
}
}
@ -857,11 +855,11 @@ nsFormControlFrame::GetFont(nsIPresContext* aPresContext,
nsresult
nsFormControlFrame::GetDefaultCheckState(PRBool *aState)
{ nsresult res = NS_OK;
nsIDOMHTMLInputElement* inputElement;
if (NS_OK == mContent->QueryInterface(NS_GET_IID(nsIDOMHTMLInputElement), (void**)&inputElement)) {
{
nsresult res = NS_OK;
nsCOMPtr<nsIDOMHTMLInputElement> inputElement = do_QueryInterface(mContent);
if (inputElement) {
res = inputElement->GetDefaultChecked(aState);
NS_RELEASE(inputElement);
}
return res;
}
@ -870,10 +868,9 @@ nsresult
nsFormControlFrame::SetDefaultCheckState(PRBool aState)
{
nsresult res = NS_OK;
nsIDOMHTMLInputElement* inputElement;
if (NS_OK == mContent->QueryInterface(NS_GET_IID(nsIDOMHTMLInputElement), (void**)&inputElement)) {
nsCOMPtr<nsIDOMHTMLInputElement> inputElement = do_QueryInterface(mContent);
if (inputElement) {
res = inputElement->SetDefaultChecked(aState);
NS_RELEASE(inputElement);
}
return res;
}
@ -882,10 +879,9 @@ nsresult
nsFormControlFrame::GetCurrentCheckState(PRBool *aState)
{
nsresult res = NS_OK;
nsIDOMHTMLInputElement* inputElement;
if (NS_OK == mContent->QueryInterface(NS_GET_IID(nsIDOMHTMLInputElement), (void**)&inputElement)) {
nsCOMPtr<nsIDOMHTMLInputElement> inputElement = do_QueryInterface(mContent);
if (inputElement) {
res = inputElement->GetChecked(aState);
NS_RELEASE(inputElement);
}
return res;
}
@ -894,10 +890,9 @@ nsresult
nsFormControlFrame::SetCurrentCheckState(PRBool aState)
{
nsresult res = NS_OK;
nsIDOMHTMLInputElement* inputElement;
if (NS_OK == mContent->QueryInterface(NS_GET_IID(nsIDOMHTMLInputElement), (void**)&inputElement)) {
nsCOMPtr<nsIDOMHTMLInputElement> inputElement = do_QueryInterface(mContent);
if (inputElement) {
inputElement->SetChecked(aState);
NS_RELEASE(inputElement);
}
return res;
}

View File

@ -54,7 +54,6 @@
#include "nsIFormControlFrame.h"
#include "nsFormControlFrame.h"
#include "nsFileControlFrame.h"
#include "nsRadioControlGroup.h"
#include "nsIForm.h"
#include "nsIFormControl.h"
@ -78,7 +77,6 @@
#include "nsIDocument.h"
#include "nsILinkHandler.h"
#include "nsGfxRadioControlFrame.h"
#include "nsIDOMHTMLFormElement.h"
#include "nsIDOMNSHTMLFormElement.h"
#include "nsDOMError.h"
@ -125,7 +123,6 @@ nsFormFrame::nsFormFrame()
nsFormFrame::~nsFormFrame()
{
RemoveRadioGroups();
PRInt32 numControls = mFormControls.Count();
PRInt32 i;
@ -135,16 +132,6 @@ nsFormFrame::~nsFormFrame()
}
}
void nsFormFrame::RemoveRadioGroups()
{
int numRadioGroups = mRadioGroups.Count();
for (int i = 0; i < numRadioGroups; i++) {
nsRadioControlGroup* radioGroup = (nsRadioControlGroup *) mRadioGroups.ElementAt(i);
delete radioGroup;
}
mRadioGroups.Clear();
}
void nsFormFrame::AddFormControlFrame(nsIPresContext* aPresContext, nsIFrame& aFrame)
{
// Make sure we have a form control
@ -190,132 +177,6 @@ void nsFormFrame::RemoveFormControlFrame(nsIFormControlFrame& aFrame)
mFormControls.RemoveElement(&aFrame);
}
NS_IMETHODIMP
nsFormFrame::RemoveFrame(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aOldFrame)
{
nsIFormControlFrame* fcFrame = nsnull;
nsresult result = aOldFrame->QueryInterface(NS_GET_IID(nsIFormControlFrame), (void**)&fcFrame);
if ((NS_OK == result) || (nsnull != fcFrame)) {
PRInt32 type;
fcFrame->GetType(&type);
if (NS_FORM_INPUT_RADIO == type) {
nsRadioControlGroup * group;
nsAutoString name;
nsresult rv = GetRadioInfo(fcFrame, name, group);
if (NS_SUCCEEDED(rv) && nsnull != group) {
DoDefaultSelection(aPresContext, group, (nsGfxRadioControlFrame*)fcFrame);
}
}
}
return nsBlockFrame::RemoveFrame(aPresContext, aPresShell, aListName, aOldFrame);
}
nsresult nsFormFrame::GetRadioInfo(nsIFormControlFrame* aFrame,
nsString& aName,
nsRadioControlGroup *& aGroup)
{
aGroup = nsnull;
aName.SetLength(0);
aFrame->GetName(&aName);
PRBool hasName = aName.Length() > 0;
// radio group processing
if (hasName) {
int numGroups = mRadioGroups.Count();
nsRadioControlGroup* group;
for (int j = 0; j < numGroups; j++) {
group = (nsRadioControlGroup *) mRadioGroups.ElementAt(j);
nsString groupName;
group->GetName(groupName);
if (groupName.Equals(aName)) {
aGroup = group;
return NS_OK;
}
}
}
return NS_ERROR_FAILURE;
}
void nsFormFrame::DoDefaultSelection(nsIPresContext* aPresContext,
nsRadioControlGroup * aGroup,
nsGfxRadioControlFrame * aRadioToIgnore)
{
#if 0
// We do not want to do the default selection when printing
// The code below ends up calling into the content, which then sets
// the state on the "primary" frame the frame being displayed
// this causes it to be "reset" to the default selection,
// then when we go to get the current state of the UI it has been reset back
// and then the printed state has the wrong value also
nsCOMPtr<nsIPrintContext> printContext = do_QueryInterface(aPresContext);
if (printContext) {
return;
}
// If in standard mode, then a radio group MUST default
// to the first item in the group (it must be selected)
nsCompatibility mode;
nsFormControlHelper::GetFormCompatibilityMode(aPresContext, mode);
if (eCompatibility_Standard == mode) {
// first find out if any have a default selection
PRInt32 i;
PRInt32 numItems = aGroup->GetNumRadios();
PRBool oneIsDefSelected = PR_FALSE;
for (i=0;i<numItems;i++) {
nsGfxRadioControlFrame * radioBtn = (nsGfxRadioControlFrame*) aGroup->GetRadioAt(i);
nsCOMPtr<nsIContent> content;
radioBtn->GetContent(getter_AddRefs(content));
if (content) {
nsCOMPtr<nsIDOMHTMLInputElement> input(do_QueryInterface(content));
if (input) {
PRBool initiallyChecked = PR_FALSE;
if (radioBtn->IsRestored()) {
initiallyChecked = radioBtn->GetRestoredChecked();
} else {
initiallyChecked = radioBtn->GetDefaultChecked();
}
PRBool currentValue = radioBtn->GetChecked();
if (currentValue != initiallyChecked ) {
input->SetChecked(initiallyChecked);
//radioBtn->SetChecked(aPresContext, initSelected, PR_FALSE);
}
if (initiallyChecked) {
oneIsDefSelected = PR_TRUE;
}
}
}
}
// if there isn't a default selcted radio then
// select the firdst one in the group.
// if aRadioToIgnore is not null then it is being deleted
// so don't select that item, select the next one if there is one.
if (!oneIsDefSelected && numItems > 0) {
nsGfxRadioControlFrame * radioBtn = (nsGfxRadioControlFrame*) aGroup->GetRadioAt(0);
if (aRadioToIgnore != nsnull && aRadioToIgnore == radioBtn) {
if (numItems == 1) {
return;
}
radioBtn = (nsGfxRadioControlFrame*) aGroup->GetRadioAt(1);
}
nsCOMPtr<nsIContent> content;
radioBtn->GetContent(getter_AddRefs(content));
if (content) {
nsCOMPtr<nsIDOMHTMLInputElement> input(do_QueryInterface(content));
if (input) {
input->SetChecked(PR_TRUE);
}
}
}
}
#endif
}
void nsFormFrame::AddFormControlFrame(nsIPresContext* aPresContext, nsIFormControlFrame& aFrame)
{
PRInt32 type;
@ -360,145 +221,9 @@ void nsFormFrame::AddFormControlFrame(nsIPresContext* aPresContext, nsIFormContr
}
}
mFormControls.InsertElementAt(&aFrame, i);
// determine which radio buttons belong to which radio groups, unnamed radio
// buttons don't go into any group since they can't be submitted. Determine
// which controls are capable of form submission.
if (NS_FORM_INPUT_RADIO == type) {
nsGfxRadioControlFrame* radioFrame = (nsGfxRadioControlFrame*)&aFrame;
// gets the name of the radio group and the group
nsRadioControlGroup * group;
nsAutoString name;
rv = GetRadioInfo(&aFrame, name, group);
if (NS_SUCCEEDED(rv) && nsnull != group) {
group->AddRadio(radioFrame);
} else {
group = new nsRadioControlGroup(name);
mRadioGroups.AppendElement(group);
group->AddRadio(radioFrame);
}
// allow only one checked radio button
PRBool initiallyChecked = PR_FALSE;
if (radioFrame->IsRestored()) {
initiallyChecked = radioFrame->GetRestoredChecked();
} else {
initiallyChecked = radioFrame->GetDefaultChecked();
}
if (initiallyChecked) {
if (nsnull == group->GetCheckedRadio()) {
group->SetCheckedRadio(radioFrame);
} else {
radioFrame->SetChecked(aPresContext, PR_FALSE, PR_FALSE);
}
}
DoDefaultSelection(aPresContext, group);
}
}
void nsFormFrame::RemoveRadioControlFrame(nsIFormControlFrame * aFrame)
{
PRInt32 type;
aFrame->GetType(&type);
// radio group processing
if (NS_FORM_INPUT_RADIO == type) {
nsGfxRadioControlFrame* radioFrame = (nsGfxRadioControlFrame*)aFrame;
// gets the name of the radio group and the group
nsRadioControlGroup * group;
nsAutoString name;
nsresult rv = GetRadioInfo(aFrame, name, group);
if (NS_SUCCEEDED(rv) && nsnull != group) {
group->RemoveRadio(radioFrame);
}
}
}
//--------------------------------------------------------
// Return the content of the currently selected item in
// the radio group of the incoming radiobutton.
//--------------------------------------------------------
nsresult
nsFormFrame::GetRadioGroupSelectedContent(nsGfxRadioControlFrame* aControl,
nsIContent ** aRadiobtn)
{
NS_ASSERTION(aControl, "nsGfxRadioControlFrame can't be null");
// first get correct interface
nsIFormControlFrame* fcFrame = nsnull;
nsresult result = aControl->QueryInterface(NS_GET_IID(nsIFormControlFrame), (void**)&fcFrame);
if (NS_SUCCEEDED(result)) {
// get the form frame for the radio btn
nsFormFrame * formFrame = ((nsFormControlFrame *)aControl)->GetFormFrame();
if (formFrame != nsnull) {
// now get the radio group by name
nsAutoString groupName;
nsRadioControlGroup * group = nsnull;
result = formFrame->GetRadioInfo(fcFrame, groupName, group);
if (NS_SUCCEEDED(result) && nsnull != group) {
// get the currently checked radio button
nsGfxRadioControlFrame* currentCheckBtn = group->GetCheckedRadio();
if (currentCheckBtn != nsnull) {
currentCheckBtn->GetContent(aRadiobtn);
}
}
}
}
return NS_OK;
}
//--------------------------------------------------------
// returns NS_ERROR_FAILURE if the radiobtn doesn't have a group
// returns NS_OK is it did have a radio group
//--------------------------------------------------------
nsresult
nsFormFrame::OnRadioChecked(nsIPresContext* aPresContext,
nsGfxRadioControlFrame& aControl,
PRBool aNewCheckedVal)
{
// first get correct interface
nsIFormControlFrame* fcFrame = nsnull;
nsresult result = aControl.QueryInterface(NS_GET_IID(nsIFormControlFrame), (void**)&fcFrame);
if (NS_SUCCEEDED(result)) {
// now get the radio group by name
nsAutoString groupName;
nsRadioControlGroup * group = nsnull;
result = GetRadioInfo(fcFrame, groupName, group);
if (NS_SUCCEEDED(result) && nsnull != group) {
// get the currently checked radio button
nsGfxRadioControlFrame* currentCheckBtn = group->GetCheckedRadio();
// is the new checked btn different than the current button?
if (&aControl != currentCheckBtn) {
// if the new button is being set to false
// then don't do anything
if (aNewCheckedVal) {
// the current btn could be null
if (currentCheckBtn != nsnull) {
currentCheckBtn->SetChecked(aPresContext, !aNewCheckedVal, PR_FALSE);
}
aControl.SetChecked(aPresContext, aNewCheckedVal, PR_FALSE);
group->SetCheckedRadio(&aControl);
}
} else {
// here we are setting the same radio button
// as the one that is currently checked
//
if (currentCheckBtn != nsnull) {
currentCheckBtn->SetChecked(aPresContext, aNewCheckedVal, PR_FALSE);
// So if we are setting the current btn to be 0 or off
// then we must set a default selction
if (!aNewCheckedVal) {
DoDefaultSelection(aPresContext, group, currentCheckBtn);
}
}
}
}
}
return NS_OK;
}
nsresult
NS_NewFormFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRUint32 aFlags)
{

View File

@ -48,14 +48,12 @@ class nsIFrame;
class nsIPresContext;
struct nsHTMLReflowState;
class nsFormControlFrame;
class nsGfxRadioControlFrame;
class nsIFormControlFrame;
class nsIDOMHTMLFormElement;
class nsIDocument;
class nsIPresContext;
class nsFormFrame;
class nsIUnicodeEncoder;
class nsRadioControlGroup;
class nsFormFrame : public nsBlockFrame
{
@ -65,24 +63,11 @@ public:
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
NS_IMETHOD RemoveFrame(nsIPresContext* aPresContext,
nsIPresShell& aPresShell,
nsIAtom* aListName,
nsIFrame* aOldFrame);
// other methods
//--------------------------------------------------------
// returns NS_ERROR_FAILURE if the radiobtn doesn't have a group
// returns NS_OK is it did have a radio group
//--------------------------------------------------------
nsresult OnRadioChecked(nsIPresContext* aPresContext, nsGfxRadioControlFrame& aRadio, PRBool aChecked = PR_TRUE);
void AddFormControlFrame(nsIPresContext* aPresContext, nsIFormControlFrame& aFrame);
static void AddFormControlFrame(nsIPresContext* aPresContext, nsIFrame& aFrame);
void RemoveFormControlFrame(nsIFormControlFrame& aFrame);
void RemoveRadioControlFrame(nsIFormControlFrame * aFrame);
nsresult GetRadioInfo(nsIFormControlFrame* aFrame, nsString& aName, nsRadioControlGroup *& aGroup);
// static helper functions for nsIFormControls
@ -96,8 +81,6 @@ public:
nsIContent* aContent = 0);
static void StyleChangeReflow(nsIPresContext* aPresContext,
nsIFrame* aFrame);
static nsresult GetRadioGroupSelectedContent(nsGfxRadioControlFrame* aControl,
nsIContent ** aRadiobtn);
void SetFlags(PRUint32 aFlags) {
mState &= ~NS_BLOCK_FLAGS_MASK;
mState |= aFlags;
@ -109,14 +92,8 @@ public:
protected:
NS_IMETHOD_(nsrefcnt) AddRef(void);
NS_IMETHOD_(nsrefcnt) Release(void);
void RemoveRadioGroups();
void DoDefaultSelection(nsIPresContext* aPresContext,
nsRadioControlGroup * aGroup,
nsGfxRadioControlFrame * aRadioToIgnore = nsnull);
nsVoidArray mFormControls;
nsVoidArray mRadioGroups;
static PRBool gInitPasswordManager;
};

View File

@ -275,127 +275,26 @@ nsGfxCheckboxControlFrame::GetCheckboxState ( )
return retval;
}
//------------------------------------------------------------
void
nsGfxCheckboxControlFrame::SetCheckboxState (nsIPresContext* aPresContext,
PRBool aValue )
{
nsCOMPtr<nsIDOMHTMLInputElement> elem(do_QueryInterface(mContent));
elem->SetChecked(aValue);
}
//------------------------------------------------------------
void
nsGfxCheckboxControlFrame::GetCheckboxControlFrameState (
nsAWritableString& aValue )
{
CheckStateToString(GetCheckboxState(), aValue);
}
//------------------------------------------------------------
void
nsGfxCheckboxControlFrame::SetCheckboxControlFrameState (
nsIPresContext* aPresContext,
const nsAReadableString& aValue )
{
PRBool state = StringToCheckState(aValue);
SetCheckboxState(aPresContext, state);
}
//------------------------------------------------------------
//
// CheckStateToString
//
// Converts from a CheckState to a string
//
void
nsGfxCheckboxControlFrame::CheckStateToString (
PRBool inState,
nsAWritableString& outStateAsString )
{
if (inState) {
outStateAsString.Assign(NS_STRING_TRUE);
} else {
outStateAsString.Assign(NS_STRING_FALSE);
}
} // CheckStateToString
//------------------------------------------------------------
//
// StringToCheckState
//
// Converts from a string to a CheckState enum
//
PRBool
nsGfxCheckboxControlFrame::StringToCheckState ( const nsAReadableString & aStateAsString )
{
return aStateAsString.Equals(NS_STRING_TRUE);
} // StringToCheckState
//----------------------------------------------------------------------
// nsIStatefulFrame
//----------------------------------------------------------------------
NS_IMETHODIMP nsGfxCheckboxControlFrame::SaveState(nsIPresContext* aPresContext,
nsIPresState** aState)
{
NS_ENSURE_ARG_POINTER(aState);
// Don't save state before we are initialized
if (!mDidInit) {
return NS_OK;
}
PRBool stateCheck = GetCheckboxState();
PRBool defaultStateBool = PR_FALSE;
nsresult res = GetDefaultCheckState(&defaultStateBool);
// Compare to default value, and only save if needed (Bug 62713)
if (!(NS_CONTENT_ATTR_HAS_VALUE == res &&
((stateCheck && defaultStateBool) ||
(!stateCheck && !defaultStateBool)))) {
// Get the value string
nsAutoString stateString;
CheckStateToString(stateCheck, stateString);
// Construct a pres state and store value in it.
res = NS_NewPresState(aState);
NS_ENSURE_SUCCESS(res, res);
res = (*aState)->SetStateProperty(NS_LITERAL_STRING("checked"), stateString);
}
return res;
return nsFormControlHelper::SaveContentState(this, aPresContext, aState);
}
NS_IMETHODIMP nsGfxCheckboxControlFrame::RestoreState(nsIPresContext* aPresContext,
nsIPresState* aState)
{
NS_ENSURE_ARG_POINTER(aState);
if (!mDidInit) {
mPresContext = aPresContext;
InitializeControl(aPresContext);
mDidInit = PR_TRUE;
}
// Set the value to the stored state.
nsAutoString stateString;
nsresult res = aState->GetStateProperty(NS_LITERAL_STRING("checked"), stateString);
NS_ENSURE_SUCCESS(res, res);
SetCheckboxControlFrameState(aPresContext, stateString);
return NS_OK;
return nsFormControlHelper::RestoreContentState(this, aPresContext, aState);
}
//------------------------------------------------------------
// Extra Debug Methods
//------------------------------------------------------------
#ifdef DEBUG_rodsXXX
NS_IMETHODIMP
NS_IMETHODIMP
nsGfxCheckboxControlFrame::Reflow(nsIPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,

View File

@ -103,27 +103,9 @@ public:
nsReflowStatus& aStatus);
#endif
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.
PRBool GetCheckboxState();
void SetCheckboxState(nsIPresContext* aPresContext, PRBool aValue);
// Utility methods for implementing SetProperty/GetProperty
void SetCheckboxControlFrameState(nsIPresContext* aPresContext,
const nsAReadableString& aValue);
void GetCheckboxControlFrameState(nsAWritableString& aValue);
// utility routine for converting from DOM values to internal enum
void CheckStateToString(PRBool inState, nsAWritableString& outStateAsString) ;
PRBool StringToCheckState(const nsAReadableString & aStateAsString) ;
protected:

View File

@ -74,7 +74,6 @@ NS_NewGfxRadioControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
nsGfxRadioControlFrame::nsGfxRadioControlFrame()
{
// Initialize GFX-rendered state
mChecked = PR_FALSE;
mRadioButtonFaceStyle = nsnull;
}
@ -155,79 +154,6 @@ nsGfxRadioControlFrame::SetAdditionalStyleContext(PRInt32 aIndex,
return NS_OK;
}
//--------------------------------------------------------------
NS_IMETHODIMP nsGfxRadioControlFrame::SetProperty(nsIPresContext* aPresContext, nsIAtom* aName, const nsAReadableString& aValue)
{
if (nsHTMLAtoms::checked == aName) {
PRBool state = (aValue.Equals(NS_STRING_TRUE)) ? PR_TRUE : PR_FALSE;
// if there is no form than the radiobtn is an orphan
if (mFormFrame) {
// if this failed then it didn't have a named radio group
if (NS_FAILED(mFormFrame->OnRadioChecked(aPresContext, *this, state))) {
// The line below is commented out to duplicate NavQuirks behavior
//SetRadioState(aPresContext, state);
}
} else {
SetRadioState(aPresContext, state);
}
}
else {
return nsFormControlFrame::SetProperty(aPresContext, aName, aValue);
}
return NS_OK;
}
//--------------------------------------------------------------
NS_IMETHODIMP nsGfxRadioControlFrame::GetProperty(nsIAtom* aName, nsAWritableString& aValue)
{
// Return the value of the property from the widget it is not null.
// If is null, assume the widget is GFX-rendered and return a member variable instead.
if (nsHTMLAtoms::checked == aName) {
nsFormControlHelper::GetBoolString(GetRadioState(), aValue);
} else {
return nsFormControlFrame::GetProperty(aName, aValue);
}
return NS_OK;
}
//--------------------------------------------------------------
PRBool
nsGfxRadioControlFrame::GetChecked()
{
PRBool checked = PR_FALSE;
GetCurrentCheckState(&checked);
return(checked);
}
//--------------------------------------------------------------
PRBool
nsGfxRadioControlFrame::GetDefaultChecked()
{
PRBool checked = PR_FALSE;
GetDefaultCheckState(&checked);
return(checked);
}
//--------------------------------------------------------------
void
nsGfxRadioControlFrame::SetChecked(nsIPresContext* aPresContext, PRBool aValue, PRBool aSetInitialValue)
{
if (aSetInitialValue) {
if (aValue) {
mContent->SetAttr(kNameSpaceID_HTML, nsHTMLAtoms::checked, NS_LITERAL_STRING("1"), PR_FALSE); // XXX should be "empty" value
} else {
mContent->SetAttr(kNameSpaceID_HTML, nsHTMLAtoms::checked, NS_LITERAL_STRING("0"), PR_FALSE);
}
}
SetRadioState(aPresContext, aValue);
}
//--------------------------------------------------------------
NS_IMETHODIMP
nsGfxRadioControlFrame::SetRadioButtonFaceStyleContext(nsIStyleContext *aRadioButtonFaceStyleContext)
@ -238,15 +164,6 @@ nsGfxRadioControlFrame::SetRadioButtonFaceStyleContext(nsIStyleContext *aRadioBu
}
//--------------------------------------------------------------
NS_IMETHODIMP
nsGfxRadioControlFrame::GetRadioGroupSelectedContent(nsIContent ** aRadioBtn)
{
NS_ENSURE_ARG_POINTER(aRadioBtn);
nsFormFrame::GetRadioGroupSelectedContent(this, aRadioBtn);
return NS_OK;
}
NS_IMETHODIMP
nsGfxRadioControlFrame::HandleEvent(nsIPresContext* aPresContext,
nsGUIEvent* aEvent,
@ -271,8 +188,8 @@ nsGfxRadioControlFrame::PaintRadioButton(nsIPresContext* aPresContext,
PRBool checked = PR_TRUE;
GetCurrentCheckState(&checked); // Get check state from the content model
if (PR_TRUE == checked) {
// Paint the button for the radio button using CSS background rendering code
if (checked) {
// Paint the button for the radio button using CSS background rendering code
if (nsnull != mRadioButtonFaceStyle) {
const nsStyleBackground* myColor = (const nsStyleBackground*)
mRadioButtonFaceStyle->GetStyleData(eStyleStruct_Background);
@ -332,80 +249,22 @@ nsGfxRadioControlFrame::Paint(nsIPresContext* aPresContext,
//--------------------------------------------------------------
PRBool nsGfxRadioControlFrame::GetRadioState()
NS_IMETHODIMP
nsGfxRadioControlFrame::OnChecked(nsIPresContext* aPresContext,
PRBool aChecked)
{
return mChecked;
}
//--------------------------------------------------------------
void nsGfxRadioControlFrame::SetRadioState(nsIPresContext* aPresContext, PRBool aValue)
{
mChecked = aValue;
nsFormControlHelper::ForceDrawFrame(aPresContext, this);
}
void
nsGfxRadioControlFrame::InitializeControl(nsIPresContext* aPresContext)
{
nsFormControlFrame::InitializeControl(aPresContext);
// Only reset on init if this is the primary shell
// Temporary workaround until radio 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()) {
// set the widget to the initial state
// XXX We can't use reset because radio buttons fire onChange
// from content (much to our dismay)
PRBool checked = PR_FALSE;
nsresult rv = GetDefaultCheckState(&checked);
if (NS_CONTENT_ATTR_HAS_VALUE == rv) {
SetRadioState(aPresContext, checked);
}
}
return NS_OK;
}
//----------------------------------------------------------------------
// nsIStatefulFrame
//----------------------------------------------------------------------
NS_IMETHODIMP
nsGfxRadioControlFrame::SaveState(nsIPresContext* aPresContext, nsIPresState** aState)
nsGfxRadioControlFrame::SaveState(nsIPresContext* aPresContext,
nsIPresState** aState)
{
NS_ENSURE_ARG_POINTER(aState);
// Don't save state before we are initialized
if (!mDidInit) {
return NS_OK;
}
nsresult res = NS_OK;
PRBool stateBool = GetRadioState();
PRBool defaultStateBool = GetDefaultChecked();
// Compare to default value, and only save if needed (Bug 62713)
if (stateBool != defaultStateBool) {
// Get the value string
nsAutoString stateString;
nsFormControlHelper::GetBoolString(stateBool, stateString);
// Construct a pres state and store value in it.
res = NS_NewPresState(aState);
NS_ENSURE_SUCCESS(res, res);
res = (*aState)->SetStateProperty(NS_LITERAL_STRING("checked"), stateString);
}
return res;
return nsFormControlHelper::SaveContentState(this, aPresContext, aState);
}
@ -414,25 +273,7 @@ nsGfxRadioControlFrame::SaveState(nsIPresContext* aPresContext, nsIPresState** a
NS_IMETHODIMP
nsGfxRadioControlFrame::RestoreState(nsIPresContext* aPresContext, nsIPresState* aState)
{
NS_ENSURE_ARG_POINTER(aState);
if (!mDidInit) {
mPresContext = aPresContext;
InitializeControl(aPresContext);
mDidInit = PR_TRUE;
}
mIsRestored = PR_TRUE;
nsAutoString stateString;
nsresult res = aState->GetStateProperty(NS_LITERAL_STRING("checked"), stateString);
NS_ENSURE_SUCCESS(res, res);
res = SetProperty(aPresContext, nsHTMLAtoms::checked, stateString);
NS_ENSURE_SUCCESS(res, res);
mRestoredChecked = mChecked;
return NS_OK;
return nsFormControlHelper::RestoreContentState(this, aPresContext, aState);
}

View File

@ -65,19 +65,10 @@ public:
//nsIRadioControlFrame methods
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
NS_IMETHOD SetRadioButtonFaceStyleContext(nsIStyleContext *aRadioButtonFaceStyleContext);
NS_IMETHOD GetRadioGroupSelectedContent(nsIContent ** aRadioBtn);
#ifdef ACCESSIBILITY
NS_IMETHOD GetAccessible(nsIAccessible** aAccessible);
#endif
virtual PRBool GetChecked();
virtual PRBool GetDefaultChecked();
virtual PRBool GetRestoredChecked() { return mRestoredChecked;}
virtual PRBool IsRestored() { return mIsRestored;}
virtual void SetChecked(nsIPresContext* aPresContext, PRBool aValue, PRBool aSetInitialValue);
void InitializeControl(nsIPresContext* aPresContext);
NS_IMETHOD OnChecked(nsIPresContext* aPresContext, PRBool aChecked);
NS_IMETHOD GetAdditionalStyleContext(PRInt32 aIndex,
nsIStyleContext** aStyleContext) const;
@ -103,9 +94,7 @@ public:
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect);
// nsIFormControlFrame
NS_IMETHOD SetProperty(nsIPresContext* aPresContext, nsIAtom* aName, const nsAReadableString& aValue);
NS_IMETHOD GetProperty(nsIAtom* aName, nsAWritableString& aValue);
// nsIFormControlFrame
NS_IMETHOD OnContentReset();
//nsIStatefulFrame
@ -122,14 +111,8 @@ public:
protected:
virtual PRBool GetRadioState();
virtual void SetRadioState(nsIPresContext* aPresContext, PRBool aValue);
//GFX-rendered state variables
PRBool mChecked;
nsIStyleContext* mRadioButtonFaceStyle;
PRBool mRestoredChecked;
PRBool mIsRestored;
private:
NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; }