More DHTML fixes.

git-svn-id: svn://10.0.0.236/branches/Style_20010518_Branch@95865 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
hyatt%netscape.com
2001-05-24 08:38:04 +00:00
parent 1d3fa61b0c
commit 3f53da6800
8 changed files with 135 additions and 26 deletions

View File

@@ -113,6 +113,7 @@ public:
PRBool aForceUnique = PR_FALSE);
NS_IMETHOD ClearRuleTree();
virtual nsresult GetRuleTree(nsIRuleNode** aResult);
NS_IMETHOD ReParentStyleContext(nsIPresContext* aPresContext,
nsIStyleContext* aStyleContext,
@@ -971,6 +972,14 @@ StyleSetImpl::ClearRuleTree()
return NS_OK;
}
nsresult
StyleSetImpl::GetRuleTree(nsIRuleNode** aResult)
{
*aResult = mRuleTree;
NS_IF_ADDREF(*aResult);
return NS_OK;
}
NS_IMETHODIMP
StyleSetImpl::ReParentStyleContext(nsIPresContext* aPresContext,
nsIStyleContext* aStyleContext,

View File

@@ -396,6 +396,7 @@ public:
NS_IMETHOD GetPresContext(nsIPresContext** aResult)=0;
NS_IMETHOD ClearCachedData(nsIStyleRule* aRule)=0;
NS_IMETHOD ClearCachedDataInSubtree(nsIStyleRule* aRule)=0;
virtual const nsStyleStruct* GetStyleData(nsStyleStructID aSID,
nsIStyleContext* aContext)=0;

View File

@@ -418,8 +418,10 @@ nsRuleNode::ClearCachedData(nsIStyleRule* aRule)
while (curr) {
if (curr->mRule == aRule) {
// We have a match. Blow away all data stored at this node.
if (mStyleData.mResetData || mStyleData.mInheritedData)
mStyleData.Destroy(0, mPresContext);
if (curr->mStyleData.mResetData || curr->mStyleData.mInheritedData)
curr->mStyleData.Destroy(0, mPresContext);
curr->mNoneBits &= ~NS_STYLE_INHERIT_MASK;
curr->mInheritBits &= ~NS_STYLE_INHERIT_MASK;
break;
}
curr = curr->mParent;
@@ -428,6 +430,31 @@ nsRuleNode::ClearCachedData(nsIStyleRule* aRule)
return NS_OK;
}
PRBool PR_CALLBACK ClearCachedDataHelper(nsHashKey* aKey, void* aData, void* aClosure)
{
nsIRuleNode* ruleNode = (nsIRuleNode*)aData;
nsIStyleRule* rule = (nsIStyleRule*)aClosure;
ruleNode->ClearCachedDataInSubtree(rule);
return PR_TRUE;
}
NS_IMETHODIMP
nsRuleNode::ClearCachedDataInSubtree(nsIStyleRule* aRule)
{
if (mRule == aRule) {
// We have a match. Blow away all data stored at this node.
if (mStyleData.mResetData || mStyleData.mInheritedData)
mStyleData.Destroy(0, mPresContext);
mNoneBits &= ~NS_STYLE_INHERIT_MASK;
mInheritBits &= ~NS_STYLE_INHERIT_MASK;
}
if (mChildren)
mChildren->Enumerate(ClearCachedDataHelper, (void*)aRule);
return NS_OK;
}
NS_IMETHODIMP
nsRuleNode::GetPresContext(nsIPresContext** aResult)
{

View File

@@ -232,6 +232,7 @@ public:
NS_IMETHOD IsRoot(PRBool* aResult);
NS_IMETHOD GetRule(nsIStyleRule** aResult);
NS_IMETHOD ClearCachedData(nsIStyleRule* aRule);
NS_IMETHOD ClearCachedDataInSubtree(nsIStyleRule* aRule);
NS_IMETHOD GetPresContext(nsIPresContext** aResult);
const nsStyleStruct* GetStyleData(nsStyleStructID aSID,
nsIStyleContext* aContext);

View File

@@ -105,6 +105,7 @@ public:
NS_IMETHOD ClearPlaceholderFrameMap() = 0;
// Mapping undisplayed content
NS_IMETHOD GetUndisplayedContent(nsIContent* aContent, nsIStyleContext** aStyleContext)=0;
NS_IMETHOD SetUndisplayedContent(nsIContent* aContent, nsIStyleContext* aStyleContext) = 0;
NS_IMETHOD SetUndisplayedPseudoIn(nsIStyleContext* aPseudoContext,
nsIContent* aParentContent) = 0;

View File

@@ -37,6 +37,7 @@ class nsIFrame;
class nsIDocument;
class nsIFrameManager;
class nsISupportsArray;
class nsIRuleNode;
struct nsFindFrameHint;
#include "nsVoidArray.h"
@@ -79,6 +80,8 @@ public:
virtual nsIStyleSheet* GetBackstopStyleSheetAt(PRInt32 aIndex) = 0;
virtual void ReplaceBackstopStyleSheets(nsISupportsArray* aNewSheets) = 0;
virtual nsresult GetRuleTree(nsIRuleNode** aResult) = 0;
// enable / disable the Quirk style sheet:
// returns NS_FAILURE if none is found, otherwise NS_OK
NS_IMETHOD EnableQuirkStyleSheet(PRBool aEnable) = 0;

View File

@@ -161,6 +161,8 @@ public:
nsresult RemoveNodeFor(nsIContent* aParentContent, UndisplayedNode* aNode);
nsresult RemoveNodesFor(nsIContent* aParentContent);
nsresult GetNodeFor(nsIContent* aContent, nsIStyleContext** aResult);
// Removes all entries from the hash table
void Clear(void);
@@ -223,6 +225,7 @@ public:
NS_IMETHOD ClearPlaceholderFrameMap();
// Undisplayed content functions
NS_IMETHOD GetUndisplayedContent(nsIContent* aContent, nsIStyleContext** aStyleContext);
NS_IMETHOD SetUndisplayedContent(nsIContent* aContent, nsIStyleContext* aStyleContext);
NS_IMETHOD SetUndisplayedPseudoIn(nsIStyleContext* aPseudoContext,
nsIContent* aParentContent);
@@ -675,6 +678,20 @@ FrameManager::ClearPlaceholderFrameMap()
//----------------------------------------------------------------------
NS_IMETHODIMP
FrameManager::GetUndisplayedContent(nsIContent* aContent, nsIStyleContext** aResult)
{
if (!aContent || !aResult) {
return NS_ERROR_NULL_POINTER;
}
*aResult = nsnull; // initialize out param
if (mUndisplayedMap)
mUndisplayedMap->GetNodeFor(aContent, aResult);
return NS_OK;
}
NS_IMETHODIMP
FrameManager::SetUndisplayedContent(nsIContent* aContent,
nsIStyleContext* aStyleContext)
@@ -2583,6 +2600,20 @@ UndisplayedMap::AddNodeFor(nsIContent* aParentContent, nsIStyleContext* aPseudoS
return AppendNodeFor(node, aParentContent);
}
nsresult
UndisplayedMap::GetNodeFor(nsIContent* aContent, nsIStyleContext** aResult)
{
PLHashEntry** entry = GetEntryFor(aContent);
if (*entry) {
UndisplayedNode* node = (UndisplayedNode*)((*entry)->value);
*aResult = node->mStyle;
NS_IF_ADDREF(*aResult);
}
else
*aResult = nsnull;
return NS_OK;
}
nsresult
UndisplayedMap::RemoveNodeFor(nsIContent* aParentContent, UndisplayedNode* aNode)
{

View File

@@ -9800,6 +9800,66 @@ nsCSSFrameConstructor::AttributeChanged(nsIPresContext* aPresContext,
}
#endif // INCLUDE_XUL
// check for inline style. we need to clear the data at the style context's rule
// node whenever the inline style property changes.
if (aAttribute == nsHTMLAtoms::style) {
nsCOMPtr<nsIHTMLContent> html(do_QueryInterface(aContent));
if (html) {
nsHTMLValue val;
html->GetHTMLAttribute(nsHTMLAtoms::style, val);
if (eHTMLUnit_ISupports == val.GetUnit()) {
// This style rule exists and we need to blow away any computed data that this
// rule cached in the rule tree.
nsCOMPtr<nsIStyleRule> rule = getter_AddRefs((nsIStyleRule*)val.GetISupportsValue());
nsCOMPtr<nsIStyleContext> context;
if (primaryFrame)
primaryFrame->GetStyleContext(getter_AddRefs(context));
else {
// We might be in the undisplayed map. Retrieve the style context from there.
nsCOMPtr<nsIFrameManager> frameManager;
shell->GetFrameManager(getter_AddRefs(frameManager));
frameManager->GetUndisplayedContent(aContent, getter_AddRefs(context));
if (!context) {
// Well, we don't have a context to use as a guide.
// Attempt #3 will be to resolve style if we at least have a parent frame.
nsCOMPtr<nsIContent> parent;
aContent->GetParent(*getter_AddRefs(parent));
if (parent) {
nsIFrame* parentFrame;
shell->GetPrimaryFrameFor(parent, &parentFrame);
if (parentFrame) {
nsCOMPtr<nsIStyleContext> parentContext;
parentFrame->GetStyleContext(getter_AddRefs(parentContext));
aPresContext->ResolveStyleContextFor(aContent, parentContext, PR_FALSE,
getter_AddRefs(context));
}
}
}
}
if (context) {
nsCOMPtr<nsIRuleNode> ruleNode;
context->GetRuleNode(getter_AddRefs(ruleNode));
ruleNode->ClearCachedData(rule); // XXXdwh. If we're willing to *really* special case
// inline style, we could only invalidate the struct data
// that actually changed. For example, if someone changes
// style.left, we really only need to blow away cached
// data in the position struct.
}
else {
// Ok, our only option left is to just crawl the entire rule
// tree and blow away the data that way.
nsCOMPtr<nsIStyleSet> set;
shell->GetStyleSet(getter_AddRefs(set));
nsCOMPtr<nsIRuleNode> rootNode;
set->GetRuleTree(getter_AddRefs(rootNode));
if (rootNode)
rootNode->ClearCachedDataInSubtree(rule);
}
}
}
}
// apply changes
if (primaryFrame && aHint == NS_STYLE_HINT_ATTRCHANGE)
result = primaryFrame->AttributeChanged(aPresContext, aContent, aNameSpaceID, aAttribute, aHint);
@@ -9814,30 +9874,6 @@ nsCSSFrameConstructor::AttributeChanged(nsIPresContext* aPresContext,
// is there?
if (primaryFrame) {
// check for inline style. we need to clear the data at the style context's rule
// node whenever the inline style property changes.
if (aAttribute == nsHTMLAtoms::style) {
nsCOMPtr<nsIHTMLContent> html(do_QueryInterface(aContent));
if (html) {
nsHTMLValue val;
html->GetHTMLAttribute(nsHTMLAtoms::style, val);
if (eHTMLUnit_ISupports == val.GetUnit()) {
// This style rule exists and we need to blow away any computed data that this
// rule cached in the rule tree.
nsCOMPtr<nsIStyleRule> rule = getter_AddRefs((nsIStyleRule*)val.GetISupportsValue());
nsCOMPtr<nsIStyleContext> context;
primaryFrame->GetStyleContext(getter_AddRefs(context));
nsCOMPtr<nsIRuleNode> ruleNode;
context->GetRuleNode(getter_AddRefs(ruleNode));
ruleNode->ClearCachedData(rule); // XXXdwh. If we're willing to *really* special case
// inline style, we could only invalidate the struct data
// that actually changed. For example, if someone changes
// style.left, we really only need to blow away cached
// data in the position struct.
}
}
}
PRInt32 maxHint = aHint;
nsStyleChangeList changeList;
// put primary frame on list to deal with, re-resolve may update or add next in flows