Correct documentation of initial/inherit values and of last boolean in CheckPropertyData. Note that document misses modifications to nsDOMCSSDeclaration and relevant interfaces. Massive formatting cleanup (especially <br> overuse), but not enough.
git-svn-id: svn://10.0.0.236/trunk@123565 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
438ada5443
commit
841cdced78
@ -4,68 +4,70 @@
|
||||
|
||||
<body>
|
||||
<h1>Adding a new style property</h1>
|
||||
<br>
|
||||
<blockquote>
|
||||
<h4>Document history:</h4>
|
||||
<ul>
|
||||
<li>03/21/2001: Marc Attinasi (attinasi@netscape.com) created document
|
||||
<li>03/21/2002: Marc Attinasi (attinasi@netscape.com) created document
|
||||
/ implementing -moz-force-broken-image-icon for bug <a href="http://bugzilla.mozilla.org/show_bug.cgi?id=58646">
|
||||
58646</a>
|
||||
<br>
|
||||
58646</a></li>
|
||||
<li>
|
||||
6/18/2002: David Baron (dbaron@fas.harvard.edu): corrected support
|
||||
for 'inherit' and '-moz-initial' (didn't test with code, though),
|
||||
and explained what the final boolean in CheckPropertyData is for.
|
||||
<li>NOTE: This document is still missing a few pieces. I need to
|
||||
add information on adding to <code>nsIDOM[NS]CSS2Properties</code>
|
||||
and <code>nsDOMCSSDeclaration</code>.
|
||||
</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<br>
|
||||
<h4> </h4>
|
||||
<h2>Overview</h2>
|
||||
When a new style property is needed there are many places in the code that
|
||||
need to be updated. This document outlines the proceedure used to add a new
|
||||
property, in this case the property is a proprietary one called '-moz-force-broken-image-icons'
|
||||
and is used as a way for a stylesheet to force broken image icons to be displayed.
|
||||
This is all being done in the context of <a href="http://bugzilla.mozilla.org/show_bug.cgi?id=58646">
|
||||
bug 58646</a>
|
||||
.<br>
|
||||
bug 58646</a>.
|
||||
|
||||
<h2>Analysis</h2>
|
||||
Up front you have to decide some things about the new property:<br>
|
||||
<br>
|
||||
<b>Questions:</b><br>
|
||||
<p>Up front you have to decide some things about the new property:</p>
|
||||
|
||||
<p><b>Questions:</b></p>
|
||||
<ol>
|
||||
<li>Is the property proprietary or specified by the CSS standard?<br>
|
||||
</li>
|
||||
<li>Is the property proprietary or specified by the CSS standard?</li>
|
||||
<li>Is the property inherited?</li>
|
||||
<li>What types of values can the property have?<br>
|
||||
</li>
|
||||
<li>What types of values can the property have?</li>
|
||||
<li>Does it logically fit with other existing properties?</li>
|
||||
<li>What is the impact to the layout of a page if that property changes?</li>
|
||||
<li>What do you want to name it?</li>
|
||||
</ol>
|
||||
<b>Answers:</b><br>
|
||||
<p><b>Answers:</b></p>
|
||||
<ol>
|
||||
<li>In our specific case, we want a property that is used internally,
|
||||
so it is a proprietary property. </li>
|
||||
so it is a proprietary property.</li>
|
||||
<li>The property is to be used for images, which are leaf elements, so
|
||||
there is no need to inherit it. </li>
|
||||
there is no need to inherit it.</li>
|
||||
<li>The property is used simply to force a broken image to be represented
|
||||
by an icon, so it only supports the values '0' and '1' as numerics. </li>
|
||||
<li>It is hard to see how this property fits logically in with other
|
||||
properties, but if we stretch our imaginations we could say that it is a
|
||||
sort of UI property. </li>
|
||||
sort of UI property.</li>
|
||||
<li>If this property changes, the image frame has to be recreated. This
|
||||
is because the decision about whether to display the icon or not will impact
|
||||
the decision to replace the image frame with an inline text frame for the
|
||||
ALT text, so if the ALT text inline is already made, there is no image frame
|
||||
left around to reflow or otherwise modify. </li>
|
||||
left around to reflow or otherwise modify.</li>
|
||||
<li>Finally, the name will be '-moz-force-broken-image-icons' - that
|
||||
should be pretty self-describing (by convention we start proprietary property
|
||||
names with '-moz-').</li>
|
||||
</ol>
|
||||
<h2>Implementation</h2>
|
||||
There are several places that need to be educated about a new style property.
|
||||
The are:<br>
|
||||
|
||||
<p>There are several places that need to be educated about a new style property.
|
||||
They are:
|
||||
</p>
|
||||
<ul>
|
||||
<li>CSS Property Names and Hint Tables: the new property name must be
|
||||
made formally know to the system<br>
|
||||
</li>
|
||||
made formally know to the system</li>
|
||||
<li>CSS Declaration: the declaration must be able to hold the property
|
||||
and its value(s)</li>
|
||||
<li>CSS Parser: the parser must be able to parse the property name, validate
|
||||
@ -80,20 +82,24 @@ and how it is shared by other elements.</li>
|
||||
words, the meaning of the property.</li>
|
||||
</ul>
|
||||
<h3>CSS Property Name / Constants / Hints</h3>
|
||||
|
||||
<p>
|
||||
First, add the new name to the property list in <a href="http://lxr.mozilla.org/seamonkey/source/content/shared/public/nsCSSPropList.h">
|
||||
nsCSSPropList.h</a>
|
||||
Insert the property in the list alphabetically, using the existing
|
||||
property names as a template. The format of the entry you will create is:
|
||||
</p>
|
||||
<pre>CSS_PROP(-moz-force-broken-image-iconst, force_broken_image_icons, FRAMECHANGE) // bug 58646</pre>
|
||||
The first value is the formal property name, in other words the property
|
||||
|
||||
<p>The first value is the formal property name, in other words the property
|
||||
name as it is seen by the CSS parser.<br>
|
||||
The second value is the name of the property as it will appear internally.<br>
|
||||
The last value indicates what must change when the value of the property
|
||||
changes. It should be one of (<a href="http://lxr.mozilla.org/seamonkey/source/layout/base/public/nsStyleConsts.h#46">
|
||||
VISUAL, AURAL, REFLOW, CONTENT, FRAMECHANGE</a>
|
||||
).<br>
|
||||
<br>
|
||||
If you need to introduce new constants for the values of the property, they
|
||||
).</p>
|
||||
|
||||
<p>If you need to introduce new constants for the values of the property, they
|
||||
must be added to <a href="http://lxr.mozilla.org/seamonkey/source/layout/base/public/nsStyleConsts.h">
|
||||
nsStyleConsts.h</a>
|
||||
and to the appropriate keyword tables in <a href="http://lxr.mozilla.org/seamonkey/source/content/shared/src/nsCSSProps.cpp">
|
||||
@ -122,13 +128,115 @@ to (or create a new section if you are creating a new style struct). For
|
||||
this example we will find the 'UserInterface' section and add our new property
|
||||
<a href="#AppendValueCase">there</a>
|
||||
.<br>
|
||||
<pre> // nsCSSUserInterface<br> case eCSSProperty_user_input:<br> case eCSSProperty_user_modify:<br> case eCSSProperty_user_select:<br> case eCSSProperty_key_equivalent:<br> case eCSSProperty_user_focus:<br> case eCSSProperty_resizer:<br> case eCSSProperty_cursor:<br> case eCSSProperty_force_broken_image_icons: {<br> CSS_ENSURE(UserInterface) {<br> switch (aProperty) {<br> case eCSSProperty_user_input: theUserInterface->mUserInput = aValue; break;<br> case eCSSProperty_user_modify: theUserInterface->mUserModify = aValue; break;<br> case eCSSProperty_user_select: theUserInterface->mUserSelect = aValue; break;<br> case eCSSProperty_key_equivalent: <br> CSS_ENSURE_DATA(theUserInterface->mKeyEquivalent, nsCSSValueList) {<br> theUserInterface->mKeyEquivalent->mValue = aValue;<br> CSS_IF_DELETE(theUserInterface->mKeyEquivalent->mNext);<br> }<br> break;<br> case eCSSProperty_user_focus: theUserInterface->mUserFocus = aValue; break;<br> case eCSSProperty_resizer: theUserInterface->mResizer = aValue; break;<br> case eCSSProperty_cursor:<br> CSS_ENSURE_DATA(theUserInterface->mCursor, nsCSSValueList) {<br> theUserInterface->mCursor->mValue = aValue;<br> CSS_IF_DELETE(theUserInterface->mCursor->mNext);<br> }<br> break;<br><b> <a name="AppendValueCase"></a>case eCSSProperty_force_broken_image_icons: theUserInterface->mForceBrokenImageIcon = aValue; break;<br></b><br> CSS_BOGUS_DEFAULT; // make compiler happy<br> }<br> }<br> break;<br> }<br><br></pre>
|
||||
<pre> // nsCSSUserInterface
|
||||
case eCSSProperty_user_input:
|
||||
case eCSSProperty_user_modify:
|
||||
case eCSSProperty_user_select:
|
||||
case eCSSProperty_key_equivalent:
|
||||
case eCSSProperty_user_focus:
|
||||
case eCSSProperty_resizer:
|
||||
case eCSSProperty_cursor:
|
||||
case eCSSProperty_force_broken_image_icons: {
|
||||
CSS_ENSURE(UserInterface) {
|
||||
switch (aProperty) {
|
||||
case eCSSProperty_user_input: theUserInterface->mUserInput = aValue; break;
|
||||
case eCSSProperty_user_modify: theUserInterface->mUserModify = aValue; break;
|
||||
case eCSSProperty_user_select: theUserInterface->mUserSelect = aValue; break;
|
||||
case eCSSProperty_key_equivalent:
|
||||
CSS_ENSURE_DATA(theUserInterface->mKeyEquivalent, nsCSSValueList) {
|
||||
theUserInterface->mKeyEquivalent->mValue = aValue;
|
||||
CSS_IF_DELETE(theUserInterface->mKeyEquivalent->mNext);
|
||||
}
|
||||
break;
|
||||
case eCSSProperty_user_focus: theUserInterface->mUserFocus = aValue; break;
|
||||
case eCSSProperty_resizer: theUserInterface->mResizer = aValue; break;
|
||||
case eCSSProperty_cursor:
|
||||
CSS_ENSURE_DATA(theUserInterface->mCursor, nsCSSValueList) {
|
||||
theUserInterface->mCursor->mValue = aValue;
|
||||
CSS_IF_DELETE(theUserInterface->mCursor->mNext);
|
||||
}
|
||||
break;
|
||||
<b> <a name="AppendValueCase"></a>case eCSSProperty_force_broken_image_icons: theUserInterface->mForceBrokenImageIcon = aValue; break;
|
||||
</b>
|
||||
CSS_BOGUS_DEFAULT; // make compiler happy
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
</pre>
|
||||
The GetValue method must be similarly <a href="#GetValueCase">modified</a>
|
||||
:<br>
|
||||
<pre> // nsCSSUserInterface<br> case eCSSProperty_user_input:<br> case eCSSProperty_user_modify:<br> case eCSSProperty_user_select:<br> case eCSSProperty_key_equivalent:<br> case eCSSProperty_user_focus:<br> case eCSSProperty_resizer:<br> case eCSSProperty_cursor:<br> case eCSSProperty_force_broken_image_icons: {<br> CSS_VARONSTACK_GET(UserInterface);<br> if (nsnull != theUserInterface) {<br> switch (aProperty) {<br> case eCSSProperty_user_input: aValue = theUserInterface->mUserInput; break;<br> case eCSSProperty_user_modify: aValue = theUserInterface->mUserModify; break;<br> case eCSSProperty_user_select: aValue = theUserInterface->mUserSelect; break;<br> case eCSSProperty_key_equivalent:<br> if (nsnull != theUserInterface->mKeyEquivalent) {<br> aValue = theUserInterface->mKeyEquivalent->mValue;<br> }<br> break;<br> case eCSSProperty_user_focus: aValue = theUserInterface->mUserFocus; break;<br> case eCSSProperty_resizer: aValue = theUserInterface->mResizer; break;<br> case eCSSProperty_cursor:<br> if (nsnull != theUserInterface->mCursor) {<br> aValue = theUserInterface->mCursor->mValue;<br> }<br> break;<br><b> <a name="GetValueCase"></a>case eCSSProperty_force_broken_image_icons: aValue = theUserInterface->mForceBrokenImageIcons; break;<br></b><br> CSS_BOGUS_DEFAULT; // make compiler happy<br> }<br> }<br> else {<br> aValue.Reset();<br> }<br> break;<br> }<br><br></pre>
|
||||
<pre> // nsCSSUserInterface
|
||||
case eCSSProperty_user_input:
|
||||
case eCSSProperty_user_modify:
|
||||
case eCSSProperty_user_select:
|
||||
case eCSSProperty_key_equivalent:
|
||||
case eCSSProperty_user_focus:
|
||||
case eCSSProperty_resizer:
|
||||
case eCSSProperty_cursor:
|
||||
case eCSSProperty_force_broken_image_icons: {
|
||||
CSS_VARONSTACK_GET(UserInterface);
|
||||
if (nsnull != theUserInterface) {
|
||||
switch (aProperty) {
|
||||
case eCSSProperty_user_input: aValue = theUserInterface->mUserInput; break;
|
||||
case eCSSProperty_user_modify: aValue = theUserInterface->mUserModify; break;
|
||||
case eCSSProperty_user_select: aValue = theUserInterface->mUserSelect; break;
|
||||
case eCSSProperty_key_equivalent:
|
||||
if (nsnull != theUserInterface->mKeyEquivalent) {
|
||||
aValue = theUserInterface->mKeyEquivalent->mValue;
|
||||
}
|
||||
break;
|
||||
case eCSSProperty_user_focus: aValue = theUserInterface->mUserFocus; break;
|
||||
case eCSSProperty_resizer: aValue = theUserInterface->mResizer; break;
|
||||
case eCSSProperty_cursor:
|
||||
if (nsnull != theUserInterface->mCursor) {
|
||||
aValue = theUserInterface->mCursor->mValue;
|
||||
}
|
||||
break;
|
||||
<b> <a name="GetValueCase"></a>case eCSSProperty_force_broken_image_icons: aValue = theUserInterface->mForceBrokenImageIcons; break;
|
||||
</b>
|
||||
CSS_BOGUS_DEFAULT; // make compiler happy
|
||||
}
|
||||
}
|
||||
else {
|
||||
aValue.Reset();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
</pre>
|
||||
Finally <a href="#ListCase">modify </a>
|
||||
the 'List' method to output the property value.<br>
|
||||
<pre>void nsCSSUserInterface::List(FILE* out, PRInt32 aIndent) const<br>{<br> for (PRInt32 index = aIndent; --index >= 0; ) fputs(" ", out);<br><br> nsAutoString buffer;<br><br> mUserInput.AppendToString(buffer, eCSSProperty_user_input);<br> mUserModify.AppendToString(buffer, eCSSProperty_user_modify);<br> mUserSelect.AppendToString(buffer, eCSSProperty_user_select);<br> nsCSSValueList* keyEquiv = mKeyEquivalent;<br> while (nsnull != keyEquiv) {<br> keyEquiv->mValue.AppendToString(buffer, eCSSProperty_key_equivalent);<br> keyEquiv= keyEquiv->mNext;<br> }<br> mUserFocus.AppendToString(buffer, eCSSProperty_user_focus);<br> mResizer.AppendToString(buffer, eCSSProperty_resizer);<br> <br> nsCSSValueList* cursor = mCursor;<br> while (nsnull != cursor) {<br> cursor->mValue.AppendToString(buffer, eCSSProperty_cursor);<br> cursor = cursor->mNext;<br> }<br><br> <b> <a name="ListCase"></a>mForceBrokenImageIcon.AppendToString(buffer,eCSSProperty_force_broken_image_icons);</b><br><br> fputs(NS_LossyConvertUCS2toASCII(buffer).get(), out);<br>}<br><br></pre>
|
||||
<pre>void nsCSSUserInterface::List(FILE* out, PRInt32 aIndent) const
|
||||
{
|
||||
for (PRInt32 index = aIndent; --index >= 0; ) fputs(" ", out);
|
||||
|
||||
nsAutoString buffer;
|
||||
|
||||
mUserInput.AppendToString(buffer, eCSSProperty_user_input);
|
||||
mUserModify.AppendToString(buffer, eCSSProperty_user_modify);
|
||||
mUserSelect.AppendToString(buffer, eCSSProperty_user_select);
|
||||
nsCSSValueList* keyEquiv = mKeyEquivalent;
|
||||
while (nsnull != keyEquiv) {
|
||||
keyEquiv->mValue.AppendToString(buffer, eCSSProperty_key_equivalent);
|
||||
keyEquiv= keyEquiv->mNext;
|
||||
}
|
||||
mUserFocus.AppendToString(buffer, eCSSProperty_user_focus);
|
||||
mResizer.AppendToString(buffer, eCSSProperty_resizer);
|
||||
|
||||
nsCSSValueList* cursor = mCursor;
|
||||
while (nsnull != cursor) {
|
||||
cursor->mValue.AppendToString(buffer, eCSSProperty_cursor);
|
||||
cursor = cursor->mNext;
|
||||
}
|
||||
|
||||
<b> <a name="ListCase"></a>mForceBrokenImageIcon.AppendToString(buffer,eCSSProperty_force_broken_image_icons);</b>
|
||||
|
||||
fputs(NS_LossyConvertUCS2toASCII(buffer).get(), out);
|
||||
}
|
||||
|
||||
</pre>
|
||||
|
||||
<h3>CSS Parser</h3>
|
||||
Next, the CSSParser must be educated about this new property so that it can
|
||||
@ -171,14 +279,54 @@ however there is also a class nsStyleUIReset that holds the non-inherited
|
||||
values, so we will use that one (remember, our property is not inherited).
|
||||
Add a <a href="#StyleContextMember">data member</a>
|
||||
to hold the value:
|
||||
<pre>struct nsStyleUIReset: public nsStyleStruct {<br> nsStyleUIReset(void);<br> nsStyleUIReset(const nsStyleUIReset& aOther);<br> ~nsStyleUIReset(void);<br><br> NS_DEFINE_STATIC_STYLESTRUCTID_ACCESSOR(eStyleStruct_UIReset)<br><br> void* operator new(size_t sz, nsIPresContext* aContext) {<br> void* result = nsnull;<br> aContext->AllocateFromShell(sz, &result);<br> return result;<br> }<br> void Destroy(nsIPresContext* aContext) {<br> this->~nsStyleUIReset();<br> aContext->FreeToShell(sizeof(nsStyleUIReset), this);<br> };<br><br> PRInt32 CalcDifference(const nsStyleUIReset& aOther) const;<br><br> PRUint8 mUserSelect; // [reset] (selection-style)<br> PRUnichar mKeyEquivalent; // [reset] XXX what type should this be?<br> PRUint8 mResizer; // [reset]<br> <b><a name="StyleContextMember"></a>PRUint8 mForceBrokenImageIcon; // [reset] (0 if not forcing, otherwise forcing)</b><br>};<br></pre>
|
||||
<pre>struct nsStyleUIReset: public nsStyleStruct {
|
||||
nsStyleUIReset(void);
|
||||
nsStyleUIReset(const nsStyleUIReset& aOther);
|
||||
~nsStyleUIReset(void);
|
||||
|
||||
NS_DEFINE_STATIC_STYLESTRUCTID_ACCESSOR(eStyleStruct_UIReset)
|
||||
|
||||
void* operator new(size_t sz, nsIPresContext* aContext) {
|
||||
void* result = nsnull;
|
||||
aContext->AllocateFromShell(sz, &result);
|
||||
return result;
|
||||
}
|
||||
void Destroy(nsIPresContext* aContext) {
|
||||
this->~nsStyleUIReset();
|
||||
aContext->FreeToShell(sizeof(nsStyleUIReset), this);
|
||||
};
|
||||
|
||||
PRInt32 CalcDifference(const nsStyleUIReset& aOther) const;
|
||||
|
||||
PRUint8 mUserSelect; // [reset] (selection-style)
|
||||
PRUnichar mKeyEquivalent; // [reset] XXX what type should this be?
|
||||
PRUint8 mResizer; // [reset]
|
||||
<b><a name="StyleContextMember"></a>PRUint8 mForceBrokenImageIcon; // [reset] (0 if not forcing, otherwise forcing)</b>
|
||||
};
|
||||
</pre>
|
||||
In the implementation file <a href="http://lxr.mozilla.org/seamonkey/source/content/shared/src/nsStyleStruct.cpp">
|
||||
nsStyleContext.cpp </a>
|
||||
add the new data member to the constructors of the style struct and the CalcDifference
|
||||
method, which must return the correct style-change hint when a change to
|
||||
your new property is detected. The constructor changes are obvious, but here
|
||||
is the CalcDifference change for our example:<br>
|
||||
<pre>PRInt32 nsStyleUIReset::CalcDifference(const nsStyleUIReset& aOther) const<br>{<br> <b> if (mForceBrokenImageIcon == aOther.mForceBrokenImageIcon) {</b><br> if (mResizer == aOther.mResizer) {<br> if (mUserSelect == aOther.mUserSelect) {<br> if (mKeyEquivalent == aOther.mKeyEquivalent) {<br> return NS_STYLE_HINT_NONE;<br> }<br> return NS_STYLE_HINT_CONTENT;<br> }<br> return NS_STYLE_HINT_VISUAL;<br> }<br> return NS_STYLE_HINT_VISUAL;<br> }<br> <b>return NS_STYLE_HINT_FRAMECHANGE;<br></b>}<br></pre>
|
||||
<pre>PRInt32 nsStyleUIReset::CalcDifference(const nsStyleUIReset& aOther) const
|
||||
{
|
||||
<b> if (mForceBrokenImageIcon == aOther.mForceBrokenImageIcon) {</b>
|
||||
if (mResizer == aOther.mResizer) {
|
||||
if (mUserSelect == aOther.mUserSelect) {
|
||||
if (mKeyEquivalent == aOther.mKeyEquivalent) {
|
||||
return NS_STYLE_HINT_NONE;
|
||||
}
|
||||
return NS_STYLE_HINT_CONTENT;
|
||||
}
|
||||
return NS_STYLE_HINT_VISUAL;
|
||||
}
|
||||
return NS_STYLE_HINT_VISUAL;
|
||||
}
|
||||
<b>return NS_STYLE_HINT_FRAMECHANGE;
|
||||
</b>}
|
||||
</pre>
|
||||
<h3>CSSStyleRule</h3>
|
||||
The nsCSSStyleRule must be updated to manage mapping the declaration to the
|
||||
style struct. In the file <a href="http://lxr.mozilla.org/seamonkey/source/content/html/style/src/nsCSSStyleRule.cpp">
|
||||
@ -187,21 +335,109 @@ nsCSSStyleRule.cpp</a>
|
||||
you have added your property to. For example, we <a href="http://bugzilla.mozilla.org/MapUIForDeclChange">
|
||||
update </a>
|
||||
MapUIForDeclaration:<br>
|
||||
<pre>static nsresult<br>MapUIForDeclaration(nsCSSDeclaration* aDecl, const nsStyleStructID& aID, nsCSSUserInterface& aUI)<br>{<br> if (!aDecl)<br> return NS_OK; // The rule must have a declaration.<br><br> nsCSSUserInterface* ourUI = (nsCSSUserInterface*)aDecl->GetData(kCSSUserInterfaceSID);<br> if (!ourUI)<br> return NS_OK; // We don't have any rules for UI.<br><br> if (aID == eStyleStruct_UserInterface) {<br> if (aUI.mUserFocus.GetUnit() == eCSSUnit_Null && ourUI->mUserFocus.GetUnit() != eCSSUnit_Null)<br> aUI.mUserFocus = ourUI->mUserFocus;<br> <br> if (aUI.mUserInput.GetUnit() == eCSSUnit_Null && ourUI->mUserInput.GetUnit() != eCSSUnit_Null)<br> aUI.mUserInput = ourUI->mUserInput;<br><br> if (aUI.mUserModify.GetUnit() == eCSSUnit_Null && ourUI->mUserModify.GetUnit() != eCSSUnit_Null)<br> aUI.mUserModify = ourUI->mUserModify;<br><br> if (!aUI.mCursor && ourUI->mCursor)<br> aUI.mCursor = ourUI->mCursor;<br><br><br> }<br> else if (aID == eStyleStruct_UIReset) {<br> if (aUI.mUserSelect.GetUnit() == eCSSUnit_Null && ourUI->mUserSelect.GetUnit() != eCSSUnit_Null)<br> aUI.mUserSelect = ourUI->mUserSelect;<br> <br> if (!aUI.mKeyEquivalent && ourUI->mKeyEquivalent)<br> aUI.mKeyEquivalent = ourUI->mKeyEquivalent;<br><br> if (aUI.mResizer.GetUnit() == eCSSUnit_Null && ourUI->mResizer.GetUnit() != eCSSUnit_Null)<br> aUI.mResizer = ourUI->mResizer;<br> <b><br> <a name="MapUIForDeclChange"></a>if (aUI.mForceBrokenImageIcon.GetUnit() == eCSSUnit_Null && ourUI->mForceBrokenImageIcon.GetUnit() == eCSSUnit_Integer)<br> aUI.mForceBrokenImageIcon = ourUI->mForceBrokenImageIcon;</b><br> }<br><br> return NS_OK;<br><br>}<br></pre>
|
||||
<pre>static nsresult
|
||||
MapUIForDeclaration(nsCSSDeclaration* aDecl, const nsStyleStructID& aID, nsCSSUserInterface& aUI)
|
||||
{
|
||||
if (!aDecl)
|
||||
return NS_OK; // The rule must have a declaration.
|
||||
|
||||
nsCSSUserInterface* ourUI = (nsCSSUserInterface*)aDecl->GetData(kCSSUserInterfaceSID);
|
||||
if (!ourUI)
|
||||
return NS_OK; // We don't have any rules for UI.
|
||||
|
||||
if (aID == eStyleStruct_UserInterface) {
|
||||
if (aUI.mUserFocus.GetUnit() == eCSSUnit_Null && ourUI->mUserFocus.GetUnit() != eCSSUnit_Null)
|
||||
aUI.mUserFocus = ourUI->mUserFocus;
|
||||
|
||||
if (aUI.mUserInput.GetUnit() == eCSSUnit_Null && ourUI->mUserInput.GetUnit() != eCSSUnit_Null)
|
||||
aUI.mUserInput = ourUI->mUserInput;
|
||||
|
||||
if (aUI.mUserModify.GetUnit() == eCSSUnit_Null && ourUI->mUserModify.GetUnit() != eCSSUnit_Null)
|
||||
aUI.mUserModify = ourUI->mUserModify;
|
||||
|
||||
if (!aUI.mCursor && ourUI->mCursor)
|
||||
aUI.mCursor = ourUI->mCursor;
|
||||
|
||||
|
||||
}
|
||||
else if (aID == eStyleStruct_UIReset) {
|
||||
if (aUI.mUserSelect.GetUnit() == eCSSUnit_Null && ourUI->mUserSelect.GetUnit() != eCSSUnit_Null)
|
||||
aUI.mUserSelect = ourUI->mUserSelect;
|
||||
|
||||
if (!aUI.mKeyEquivalent && ourUI->mKeyEquivalent)
|
||||
aUI.mKeyEquivalent = ourUI->mKeyEquivalent;
|
||||
|
||||
if (aUI.mResizer.GetUnit() == eCSSUnit_Null && ourUI->mResizer.GetUnit() != eCSSUnit_Null)
|
||||
aUI.mResizer = ourUI->mResizer;
|
||||
<b>
|
||||
<a name="MapUIForDeclChange"></a>if (aUI.mForceBrokenImageIcon.GetUnit() == eCSSUnit_Null && ourUI->mForceBrokenImageIcon.GetUnit() == eCSSUnit_Integer)
|
||||
aUI.mForceBrokenImageIcon = ourUI->mForceBrokenImageIcon;</b>
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
</pre>
|
||||
<h3>Rule Node</h3>
|
||||
Now we have to update the RuleNode code to know about the new property. First,
|
||||
locate the PropertyCheckData array for the data that you added the new property
|
||||
to. For this example, we add the following:<br>
|
||||
<pre>static const PropertyCheckData UIResetCheckProperties[] = {<br> CHECKDATA_PROP(nsCSSUserInterface, mUserSelect, CHECKDATA_VALUE, PR_FALSE),<br> CHECKDATA_PROP(nsCSSUserInterface, mResizer, CHECKDATA_VALUE, PR_FALSE),<br> CHECKDATA_PROP(nsCSSUserInterface, mKeyEquivalent, CHECKDATA_VALUELIST, PR_FALSE)<br> <b>CHECKDATA_PROP(nsCSSUserInterface, mForceBrokenImageIcon, CHECKDATA_VALUE, PR_FALSE)</b><br>};<br></pre>
|
||||
<pre>static const PropertyCheckData UIResetCheckProperties[] = {
|
||||
CHECKDATA_PROP(nsCSSUserInterface, mUserSelect, CHECKDATA_VALUE, PR_FALSE),
|
||||
CHECKDATA_PROP(nsCSSUserInterface, mResizer, CHECKDATA_VALUE, PR_FALSE),
|
||||
CHECKDATA_PROP(nsCSSUserInterface, mKeyEquivalent, CHECKDATA_VALUELIST, PR_FALSE)
|
||||
<b>CHECKDATA_PROP(nsCSSUserInterface, mForceBrokenImageIcon, CHECKDATA_VALUE, PR_FALSE)</b>
|
||||
};
|
||||
</pre>
|
||||
The first two arguments correspond to the structure and data member from
|
||||
teh CSSDeclaration, the third is the data type, the fourth indicates if it
|
||||
is a coord value or not.<br>
|
||||
the CSSDeclaration, the third is the data type, the fourth indicates
|
||||
whether it is a coord value that uses an explicit inherit value on the
|
||||
style data struct that must be computed by layout.<br>
|
||||
<br>
|
||||
Next, we have to make sure the ComputeXXX method for the structure the property
|
||||
was added to is updated to mange the new value. In this example we need to
|
||||
modify the nsRuleNode::ComputeUIResetData method to handle the CSS Declaration
|
||||
to the style struct:<br>
|
||||
<pre> ...<br> // resizer: auto, none, enum, inherit<br> if (eCSSUnit_Enumerated == uiData.mResizer.GetUnit()) {<br> ui->mResizer = uiData.mResizer.GetIntValue();<br> }<br> else if (eCSSUnit_Auto == uiData.mResizer.GetUnit()) {<br> ui->mResizer = NS_STYLE_RESIZER_AUTO;<br> }<br> else if (eCSSUnit_None == uiData.mResizer.GetUnit()) {<br> ui->mResizer = NS_STYLE_RESIZER_NONE;<br> }<br> else if (eCSSUnit_Inherit == uiData.mResizer.GetUnit()) {<br> inherited = PR_TRUE;<br> ui->mResizer = parentUI->mResizer;<br> }<br><br> <b>// force-broken-image-icons: integer<br> if (eCSSUnit_Integer == uiData.mForceBrokenImageIcons.GetUnit()) {<br> ui->mForceBrokenImageIcons = uiData.mForceBrokenImageIcons.GetIntValue();<br> }</b><br> <br> if (inherited)<br> // We inherited, and therefore can't be cached in the rule node. We have to be put right on the<br> // style context.<br> aContext->SetStyle(eStyleStruct_UIReset, *ui);<br> else {<br> // We were fully specified and can therefore be cached right on the rule node.<br> if (!aHighestNode->mStyleData.mResetData)<br> aHighestNode->mStyleData.mResetData = new (mPresContext) nsResetStyleData;<br> aHighestNode->mStyleData.mResetData->mUIData = ui;<br> // Propagate the bit down.<br> PropagateDependentBit(NS_STYLE_INHERIT_UI_RESET, aHighestNode);<br> }<br> ...<br></pre>
|
||||
<pre> ...
|
||||
// resizer: auto, none, enum, inherit
|
||||
if (eCSSUnit_Enumerated == uiData.mResizer.GetUnit()) {
|
||||
ui->mResizer = uiData.mResizer.GetIntValue();
|
||||
}
|
||||
else if (eCSSUnit_Auto == uiData.mResizer.GetUnit()) {
|
||||
ui->mResizer = NS_STYLE_RESIZER_AUTO;
|
||||
}
|
||||
else if (eCSSUnit_None == uiData.mResizer.GetUnit()) {
|
||||
ui->mResizer = NS_STYLE_RESIZER_NONE;
|
||||
}
|
||||
else if (eCSSUnit_Inherit == uiData.mResizer.GetUnit()) {
|
||||
inherited = PR_TRUE;
|
||||
ui->mResizer = parentUI->mResizer;
|
||||
}
|
||||
|
||||
<b>// force-broken-image-icons: integer, inherit, -moz-initial
|
||||
if (eCSSUnit_Integer == uiData.mForceBrokenImageIcons.GetUnit()) {
|
||||
ui->mForceBrokenImageIcons = uiData.mForceBrokenImageIcons.GetIntValue();
|
||||
} else if (eCSSUnit_Inherit == uiData.mForceBrokenImageIcons.GetUnit()) {
|
||||
inherited = PR_TRUE;
|
||||
ui->mForceBrokenImageIcons = parentUI->mForceBrokenImageIcons;
|
||||
} else if (eCSSUnit_Initial == uiData.mForceBrokenImageIcons.GetUnit()) {
|
||||
ui->mForceBrokenImageIcons = 0;
|
||||
}</b>
|
||||
|
||||
if (inherited)
|
||||
// We inherited, and therefore can't be cached in the rule node. We have to be put right on the
|
||||
// style context.
|
||||
aContext->SetStyle(eStyleStruct_UIReset, *ui);
|
||||
else {
|
||||
// We were fully specified and can therefore be cached right on the rule node.
|
||||
if (!aHighestNode->mStyleData.mResetData)
|
||||
aHighestNode->mStyleData.mResetData = new (mPresContext) nsResetStyleData;
|
||||
aHighestNode->mStyleData.mResetData->mUIData = ui;
|
||||
// Propagate the bit down.
|
||||
PropagateDependentBit(NS_STYLE_INHERIT_UI_RESET, aHighestNode);
|
||||
}
|
||||
...
|
||||
</pre>
|
||||
<h3>Layout</h3>
|
||||
OK, finally the style system is supporting the new property. It is time to
|
||||
actually make use of it now.<br>
|
||||
@ -209,10 +445,18 @@ actually make use of it now.<br>
|
||||
In layout, retrieve the styleStruct that has the new property from the frame's
|
||||
style context. Access the new property and get its value. It is that simple.
|
||||
For this example, it looks like this, in nsImageFrame:<br>
|
||||
<pre> PRBool forceIcon = PR_FALSE;<br><br> const nsStyleUIReset* styleData;<br> GetStyleData(eStyleStruct_UIReset, (const nsStyleStruct*&) styleData);<br> if (styleData->mForceBrokenImageIcon) {<br> forceIcon = PR_TRUE;<br> }<br><br></pre>
|
||||
<pre> PRBool forceIcon = PR_FALSE;
|
||||
|
||||
const nsStyleUIReset* styleData;
|
||||
GetStyleData(eStyleStruct_UIReset, (const nsStyleStruct*&) styleData);
|
||||
if (styleData->mForceBrokenImageIcon) {
|
||||
forceIcon = PR_TRUE;
|
||||
}
|
||||
|
||||
</pre>
|
||||
Create some testcases with style rules that use the new property, make sure
|
||||
it is being parsed correctly. Test it in an external stylesheet and in inline
|
||||
style. Test that it is inherited correctly, or not inherited as appropriate
|
||||
to your property. Update this document with any further details, or correcting
|
||||
any errors.<br>
|
||||
</body></html>
|
||||
</body></html>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user