Add an nsIContent api for getting the intrinsic state of the content; this can

be used to implement more pseudo-classes (eg CSS3 UI ones for XForms).  Bug
296309, r+sr=dbaron, a=chofmann
This commit is contained in:
bzbarsky%mit.edu 2005-06-03 02:02:45 +00:00
Родитель c65178a702
Коммит 8fc3ac9a30
8 изменённых файлов: 60 добавлений и 32 удалений

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

@ -60,8 +60,8 @@ class nsIURI;
// IID for the nsIContent interface
#define NS_ICONTENT_IID \
{ 0x10caf6a4, 0x8891, 0x46c9, \
{ 0x9b, 0x6c, 0x6d, 0xc8, 0xdf, 0x01, 0x2d, 0x29 } }
{ 0x3fecc374, 0x2839, 0x4db3, \
{ 0x8d, 0xe8, 0x6b, 0x76, 0xd1, 0xd8, 0xe6, 0xf6 } }
/**
* A node of content in a document's content model. This interface
@ -651,6 +651,20 @@ public:
return PR_TRUE;
}
/**
* Method to get the _intrinsic_ content state of this content node. This is
* the state that is independent of the node's presentation. To get the full
* content state, use nsIEventStateManager. Also see nsIEventStateManager
* for the possible bits that could be set here.
*/
// XXXbz this is PRInt32 because all the ESM content state APIs use
// PRInt32. We should really use PRUint32 instead.
virtual PRInt32 IntrinsicState() const
{
return 0;
}
/* Methods for manipulating content node properties. For documentation on
* properties, see nsPropertyTable.h.
*/

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

@ -132,7 +132,6 @@ public:
NS_IMETHOD ShiftFocus(PRBool aDirection, nsIContent* aStart)=0;
};
#define NS_EVENT_STATE_UNSPECIFIED 0x0000
#define NS_EVENT_STATE_ACTIVE 0x0001 // mouse is down on content
#define NS_EVENT_STATE_FOCUS 0x0002 // content has focus
#define NS_EVENT_STATE_HOVER 0x0004 // mouse is hovering over content

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

@ -3625,7 +3625,7 @@ nsEventStateManager::GetEventRelatedContent(nsIContent** aContent)
NS_IMETHODIMP
nsEventStateManager::GetContentState(nsIContent *aContent, PRInt32& aState)
{
aState = NS_EVENT_STATE_UNSPECIFIED;
aState = aContent->IntrinsicState();
// Hierchical active: Check the ancestor chain of mActiveContent to see
// if we are on it.

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

@ -225,6 +225,8 @@ public:
virtual void DoneCreatingElement();
virtual PRInt32 IntrinsicState() const;
// nsITextControlElement
NS_IMETHOD TakeTextFrameValue(const nsAString& aValue);
NS_IMETHOD SetValueChanged(PRBool aValueChanged);
@ -2461,6 +2463,18 @@ nsHTMLInputElement::DoneCreatingElement()
SET_BOOLBIT(mBitField, BF_SHOULD_INIT_CHECKED, PR_FALSE);
}
PRInt32
nsHTMLInputElement::IntrinsicState() const
{
PRInt32 state = nsGenericHTMLFormElement::IntrinsicState();
if (GET_BOOLBIT(mBitField, BF_CHECKED) &&
(mType == NS_FORM_INPUT_CHECKBOX ||
mType == NS_FORM_INPUT_RADIO)) {
state |= NS_EVENT_STATE_CHECKED;
}
return state;
}
PRBool
nsHTMLInputElement::RestoreState(nsPresState* aState)
{

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

@ -122,6 +122,7 @@ public:
PRBool aNotify);
virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify);
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
virtual PRInt32 IntrinsicState() const;
protected:
/**
@ -493,6 +494,20 @@ nsHTMLOptionElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
return rv;
}
PRInt32
nsHTMLOptionElement::IntrinsicState() const
{
PRInt32 state = nsGenericHTMLElement::IntrinsicState();
// Nasty hack because we need to call an interface method, and one that
// toggles some of our hidden internal state at that! Would that we could
// use |mutable|.
PRBool selected;
NS_CONST_CAST(nsHTMLOptionElement*, this)->GetSelected(&selected);
if (selected) {
state |= NS_EVENT_STATE_CHECKED;
}
return state;
}
// Options don't have frames - get the select content node
// then call nsGenericHTMLElement::GetFormControlFrameFor()

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

@ -233,7 +233,7 @@ inDOMUtils::SetContentState(nsIDOMElement *aElement, PRInt32 aState)
NS_IMETHODIMP
inDOMUtils::GetContentState(nsIDOMElement *aElement, PRInt32* aState)
{
*aState = NS_EVENT_STATE_UNSPECIFIED;
*aState = 0;
if (!aElement)
return NS_ERROR_NULL_POINTER;

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

@ -2655,9 +2655,8 @@ RuleProcessorData::RuleProcessorData(nsPresContext* aPresContext,
mIsHTMLContent = PR_FALSE;
mIsHTMLLink = PR_FALSE;
mIsSimpleXLink = PR_FALSE;
mIsChecked = PR_FALSE;
mLinkState = eLinkState_Unknown;
mEventState = NS_EVENT_STATE_UNSPECIFIED;
mEventState = 0;
mNameSpaceID = kNameSpaceID_Unknown;
mPreviousSiblingData = nsnull;
mParentData = nsnull;
@ -2721,18 +2720,6 @@ RuleProcessorData::RuleProcessorData(nsPresContext* aPresContext,
nsStyleUtil::IsSimpleXlink(aContent, mPresContext, &mLinkState)) {
mIsSimpleXLink = PR_TRUE;
}
if (mIsHTMLContent) {
PRBool isChecked = PR_FALSE;
if (mContentTag == nsHTMLAtoms::option) {
nsCOMPtr<nsIDOMHTMLOptionElement> optEl = do_QueryInterface(mContent);
optEl->GetSelected(&isChecked);
} else if (mContentTag == nsHTMLAtoms::input) {
nsCOMPtr<nsIDOMHTMLInputElement> inputEl = do_QueryInterface(mContent);
inputEl->GetChecked(&isChecked);
}
mIsChecked = isChecked;
}
}
}
@ -2900,6 +2887,10 @@ static PRBool AttrMatchesValue(const nsAttrSelector* aAttrSelector,
}
}
#define STATE_CHECK(_state) \
((aStateMask & (_state)) || \
(localTrue == (0 != (data.mEventState & (_state)))))
// NOTE: The |aStateMask| code isn't going to work correctly anymore if
// we start batching style changes, because if multiple states change in
// separate notifications then we might determine the style is not
@ -3095,24 +3086,19 @@ static PRBool SelectorMatches(RuleProcessorData &data,
result = localFalse;
} else {
if (nsCSSPseudoClasses::active == pseudoClass->mAtom) {
result = (aStateMask & NS_EVENT_STATE_ACTIVE) ||
(localTrue == (0 != (data.mEventState & NS_EVENT_STATE_ACTIVE)));
result = STATE_CHECK(NS_EVENT_STATE_ACTIVE);
}
else if (nsCSSPseudoClasses::focus == pseudoClass->mAtom) {
result = (aStateMask & NS_EVENT_STATE_FOCUS) ||
(localTrue == (0 != (data.mEventState & NS_EVENT_STATE_FOCUS)));
result = STATE_CHECK(NS_EVENT_STATE_FOCUS);
}
else if (nsCSSPseudoClasses::hover == pseudoClass->mAtom) {
result = (aStateMask & NS_EVENT_STATE_HOVER) ||
(localTrue == (0 != (data.mEventState & NS_EVENT_STATE_HOVER)));
result = STATE_CHECK(NS_EVENT_STATE_HOVER);
}
else if (nsCSSPseudoClasses::mozDragOver == pseudoClass->mAtom) {
result = (aStateMask & NS_EVENT_STATE_DRAGOVER) ||
(localTrue == (0 != (data.mEventState & NS_EVENT_STATE_DRAGOVER)));
result = STATE_CHECK(NS_EVENT_STATE_DRAGOVER);
}
else if (nsCSSPseudoClasses::target == pseudoClass->mAtom) {
result = (aStateMask & NS_EVENT_STATE_URLTARGET) ||
(localTrue == (0 != (data.mEventState & NS_EVENT_STATE_URLTARGET)));
result = STATE_CHECK(NS_EVENT_STATE_URLTARGET);
}
}
}
@ -3137,8 +3123,7 @@ static PRBool SelectorMatches(RuleProcessorData &data,
// <option>
// <input type=checkbox>
// <input type=radio>
if (!(aStateMask & NS_EVENT_STATE_CHECKED))
result = data.mIsChecked ? localTrue : localFalse;
result = STATE_CHECK(NS_EVENT_STATE_CHECKED);
}
else {
NS_ERROR("CSS parser parsed a pseudo-class that we do not handle");
@ -3295,6 +3280,8 @@ static PRBool SelectorMatches(RuleProcessorData &data,
return result;
}
#undef STATE_CHECK
// Right now, there are four operators:
// PRUnichar(0), the descendent combinator, is greedy
// '~', the indirect adjacent sibling combinator, is greedy

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

@ -90,7 +90,6 @@ struct RuleProcessorData {
PRPackedBool mIsSimpleXLink; // if content, calls nsStyleUtil::IsSimpleXLink
nsCompatibility mCompatMode; // Possibly remove use of this in SelectorMatches?
PRPackedBool mHasAttributes; // if content, content->GetAttrCount() > 0
PRPackedBool mIsChecked; // checked/selected attribute for option and select elements
nsLinkState mLinkState; // if a link, this is the state, otherwise unknown
PRInt32 mEventState; // if content, eventStateMgr->GetContentState()
PRInt32 mNameSpaceID; // if content, content->GetNameSapce()