First cut at adding template and rule support for XUL builders.

This commit is contained in:
rjc%netscape.com 1999-05-07 21:20:33 +00:00
Родитель 2025af025e
Коммит eb3e56f574
5 изменённых файлов: 1427 добавлений и 12 удалений

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

@ -102,6 +102,15 @@ nsIAtom* RDFGenericBuilderImpl::kResourceAtom;
nsIAtom* RDFGenericBuilderImpl::kContainmentAtom;
nsIAtom* RDFGenericBuilderImpl::kNaturalOrderPosAtom;
nsIAtom* RDFGenericBuilderImpl::kSubcontainmentAtom;
nsIAtom* RDFGenericBuilderImpl::kTreeTemplateAtom;
nsIAtom* RDFGenericBuilderImpl::kRuleAtom;
nsIAtom* RDFGenericBuilderImpl::kTempAtom;
nsIAtom* RDFGenericBuilderImpl::kTreeContentsGeneratedAtom;
nsIAtom* RDFGenericBuilderImpl::kTextAtom;
nsIAtom* RDFGenericBuilderImpl::kPropertyAtom;
nsIAtom* RDFGenericBuilderImpl::kInstanceOfAtom;
PRInt32 RDFGenericBuilderImpl::kNameSpaceID_RDF;
PRInt32 RDFGenericBuilderImpl::kNameSpaceID_XUL;
@ -130,6 +139,7 @@ RDFGenericBuilderImpl::RDFGenericBuilderImpl(void)
if (gRefCnt == 0) {
kContainerAtom = NS_NewAtom("container");
kItemContentsGeneratedAtom = NS_NewAtom("itemcontentsgenerated");
kTreeContentsGeneratedAtom = NS_NewAtom("treecontentsgenerated");
kIdAtom = NS_NewAtom("id");
kOpenAtom = NS_NewAtom("open");
@ -137,6 +147,15 @@ RDFGenericBuilderImpl::RDFGenericBuilderImpl(void)
kNaturalOrderPosAtom = NS_NewAtom("pos");
kContainmentAtom = NS_NewAtom("containment");
kSubcontainmentAtom = NS_NewAtom("subcontainment");
kTreeTemplateAtom = NS_NewAtom("template");
kRuleAtom = NS_NewAtom("rule");
kTempAtom = NS_NewAtom("temp");
kTextAtom = NS_NewAtom("text");
kPropertyAtom = NS_NewAtom("property");
kInstanceOfAtom = NS_NewAtom("instanceOf");
nsresult rv;
// Register the XUL and RDF namespaces: these'll just retrieve
@ -207,11 +226,18 @@ RDFGenericBuilderImpl::~RDFGenericBuilderImpl(void)
NS_RELEASE(kIdAtom);
NS_RELEASE(kOpenAtom);
NS_RELEASE(kResourceAtom);
NS_RELEASE(kContainmentAtom);
NS_RELEASE(kNaturalOrderPosAtom);
NS_RELEASE(kSubcontainmentAtom);
NS_RELEASE(kTreeTemplateAtom);
NS_RELEASE(kRuleAtom);
NS_RELEASE(kTempAtom);
NS_RELEASE(kTreeContentsGeneratedAtom);
NS_RELEASE(kTextAtom);
NS_RELEASE(kPropertyAtom);
NS_RELEASE(kInstanceOfAtom);
NS_RELEASE(kNC_Title);
NS_RELEASE(kNC_Column);
@ -546,7 +572,7 @@ RDFGenericBuilderImpl::CreateContents(nsIContent* aElement)
for (loop=0; loop<numElements; loop+=2)
{
if (NS_FAILED(rv = AddWidgetItem(aElement, flatArray[loop+1], flatArray[loop], loop+1)))
if (NS_FAILED(rv = CreateWidgetItem(aElement, flatArray[loop+1], flatArray[loop], loop+1)))
{
NS_ERROR("unable to create widget item");
}
@ -569,6 +595,439 @@ RDFGenericBuilderImpl::CreateContents(nsIContent* aElement)
}
NS_IMETHODIMP
RDFGenericBuilderImpl::SetAllAttributesOnElement(nsIContent *aNode, nsIRDFResource *res)
{
// get all arcs out, and if not a containment property, set attribute
nsresult rv = NS_OK;
PRBool markAsContainer = PR_FALSE;
nsCOMPtr<nsISimpleEnumerator> arcs;
if (NS_SUCCEEDED(rv = mDB->ArcLabelsOut(res, getter_AddRefs(arcs))))
{
PRBool hasMore = PR_TRUE;
while(hasMore)
{
rv = arcs->HasMoreElements(&hasMore);
if (NS_FAILED(rv)) break;
if (hasMore == PR_FALSE) break;
nsCOMPtr<nsISupports> isupports;
if (NS_FAILED(rv = arcs->GetNext(getter_AddRefs(isupports)))) break;
nsCOMPtr<nsIRDFResource> property = do_QueryInterface(isupports);
// Ignore properties that are used to indicate "tree-ness"
if (IsContainmentProperty(aNode, property))
{
markAsContainer = PR_TRUE;
continue;
}
PRInt32 nameSpaceID;
nsCOMPtr<nsIAtom> tag;
if (NS_FAILED(rv = mDocument->SplitProperty(property, &nameSpaceID, getter_AddRefs(tag))))
break;
nsCOMPtr<nsIRDFNode> value;
if (NS_FAILED(rv = mDB->GetTarget(res, property, PR_TRUE, getter_AddRefs(value))))
break;
if (rv == NS_RDF_NO_VALUE)
continue;
nsCOMPtr<nsIRDFResource> resource;
nsCOMPtr<nsIRDFLiteral> literal;
nsAutoString s;
if (NS_SUCCEEDED(rv = value->QueryInterface(kIRDFResourceIID, getter_AddRefs(resource))))
{
nsXPIDLCString uri;
resource->GetValue( getter_Copies(uri) );
s = uri;
}
else if (NS_SUCCEEDED(rv = value->QueryInterface(kIRDFLiteralIID, getter_AddRefs(literal))))
{
nsXPIDLString p;
literal->GetValue( getter_Copies(p) );
s = p;
}
else
{
NS_ERROR("not a resource or a literal");
return NS_ERROR_UNEXPECTED;
}
aNode->SetAttribute(nameSpaceID, tag, s, PR_FALSE);
}
}
if (markAsContainer == PR_TRUE)
{
// mark this as a "container" so that we know to
// recursively generate kids if they're asked for.
rv = aNode->SetAttribute(kNameSpaceID_RDF, kContainerAtom, "true", PR_FALSE);
}
return(rv);
}
NS_IMETHODIMP
RDFGenericBuilderImpl::IsTemplateRuleMatch(nsIContent *aNode, nsIContent *aRule, PRBool *matchingRuleFound)
{
nsresult rv = NS_OK;
PRInt32 count;
*matchingRuleFound = PR_FALSE;
if (NS_FAILED(rv = aRule->GetAttributeCount(count))) return(rv);
for (PRInt32 loop=0; loop<count; loop++)
{
PRInt32 attribNameSpaceID;
nsCOMPtr<nsIAtom> attribAtom;
if (NS_FAILED(rv = aRule->GetAttributeNameAt(loop, attribNameSpaceID, *getter_AddRefs(attribAtom))))
continue;
nsAutoString attribValue;
if (NS_FAILED(rv = aRule->GetAttribute(attribNameSpaceID, attribAtom, attribValue)))
continue;
if ((attribNameSpaceID == kNameSpaceID_XUL) && (attribAtom.get() == kContainerAtom))
{
// check and see if aNode is a container
nsAutoString nodeValue;
if (NS_SUCCEEDED(aNode->GetAttribute(kNameSpaceID_RDF, kContainerAtom, nodeValue)))
{
if (nodeValue.EqualsIgnoreCase(attribValue))
{
*matchingRuleFound = PR_TRUE;
break;
}
}
}
}
return(rv);
}
NS_IMETHODIMP
RDFGenericBuilderImpl::FindTemplateForElement(nsIContent *aNode, nsIContent **theTemplate)
{
nsresult rv;
PRInt32 count;
nsCOMPtr<nsIContent> aTemplate;
*theTemplate = nsnull;
if (NS_FAILED(rv = mRoot->ChildCount(count))) return(rv);
for (PRInt32 loop=0; loop<count; loop++)
{
if (NS_FAILED(rv = mRoot->ChildAt(loop, *getter_AddRefs(aTemplate))))
continue;
PRInt32 nameSpaceID;
if (NS_FAILED(rv = aTemplate->GetNameSpaceID(nameSpaceID)))
continue;
if (nameSpaceID != kNameSpaceID_XUL)
continue;
nsCOMPtr<nsIAtom> tag;
if (NS_FAILED(rv = aTemplate->GetTag(*getter_AddRefs(tag))))
continue;
if (tag.get() != kTreeTemplateAtom)
continue;
// found a template; check against any (optional) rules
PRInt32 numRuleChildren, numRulesFound = 0;
if (NS_FAILED(rv = aTemplate->ChildCount(numRuleChildren)))
continue;
for (PRInt32 ruleLoop=0; ruleLoop<numRuleChildren; ruleLoop++)
{
nsCOMPtr<nsIContent> aRule;
if (NS_FAILED(rv = aTemplate->ChildAt(ruleLoop, *getter_AddRefs(aRule))))
continue;
PRInt32 nameSpaceID;
if (NS_FAILED(rv = aTemplate->GetNameSpaceID(nameSpaceID)))
continue;
if (nameSpaceID != kNameSpaceID_XUL)
continue;
nsCOMPtr<nsIAtom> ruleTag;
if (NS_SUCCEEDED(rv = aTemplate->GetTag(*getter_AddRefs(ruleTag))))
{
if (ruleTag.get() == kRuleAtom)
{
++numRulesFound;
PRBool matchingRuleFound = PR_FALSE;
if (NS_SUCCEEDED(rv = IsTemplateRuleMatch(aNode, aRule,
&matchingRuleFound)))
{
if (matchingRuleFound == PR_TRUE)
{
// found a matching rule, use it as the template
*theTemplate = aRule;
NS_ADDREF(*theTemplate);
return(NS_OK);
}
}
}
}
}
if (numRulesFound == 0)
{
// if no rules are specified in the template, just use it
*theTemplate = aTemplate;
NS_ADDREF(*theTemplate);
break;
}
}
return(rv);
}
NS_IMETHODIMP
RDFGenericBuilderImpl::PopulateWidgetItemSubtree(nsIContent *aTemplateRoot, nsIContent *aTemplate,
nsIContent *treeChildren, nsIContent* aElement, nsIRDFResource* aProperty,
nsIRDFResource* aValue, PRInt32 aNaturalOrderPos)
{
PRInt32 count;
nsresult rv;
if (NS_FAILED(rv = aTemplate->ChildCount(count))) return(rv);
// get REQUIRED containment="..." off of template root
nsAutoString templateContainmentValue;
if (NS_FAILED(rv = aTemplateRoot->GetAttribute(kNameSpaceID_XUL, kContainmentAtom, templateContainmentValue)))
return(rv);
if (rv != NS_CONTENT_ATTR_HAS_VALUE)
return(NS_ERROR_FAILURE);
nsCOMPtr<nsIAtom> containmentAtom = NS_NewAtom(templateContainmentValue);
if (nsnull == containmentAtom)
return(NS_ERROR_OUT_OF_MEMORY);
for (PRInt32 loop=0; loop<count; loop++)
{
nsCOMPtr<nsIContent> aTemplateKid;
if (NS_FAILED(rv = aTemplate->ChildAt(loop, *getter_AddRefs(aTemplateKid))))
continue;
PRInt32 nameSpaceID;
if (NS_FAILED(rv = aTemplateKid->GetNameSpaceID(nameSpaceID)))
continue;
nsCOMPtr<nsIAtom> tag;
if (NS_SUCCEEDED(rv = aTemplateKid->GetTag(*getter_AddRefs(tag))))
{
nsCOMPtr<nsIContent> treeGrandchild;
#if 0
nsAutoString containmentValue;
if (NS_SUCCEEDED(rv = aTemplateKid->GetAttribute(kNameSpaceID_XUL,
kContainmentAtom, containmentValue)) && (rv == NS_CONTENT_ATTR_HAS_VALUE))
{
nsIAtom *containmentAtom = NS_NewAtom(containmentValue);
if (nsnull != containmentAtom)
{
if (tag.get() == containmentAtom)
{
if (NS_SUCCEEDED(rv = CreateResourceElement(kNameSpaceID_XUL,
containmentAtom, aValue, getter_AddRefs(treeGrandchild))))
{
}
}
NS_RELEASE(containmentAtom);
containmentAtom = nsnull;
}
}
else if (NS_SUCCEEDED(rv = aTemplate->GetAttribute(kNameSpaceID_XUL,
kItemAtom, containmentValue)) && (rv == NS_CONTENT_ATTR_HAS_VALUE))
{
nsIAtom *containmentAtom = NS_NewAtom(containmentValue);
if (nsnull != containmentAtom)
{
if (tag.get() == containmentAtom)
{
if (NS_SUCCEEDED(rv = CreateResourceElement(kNameSpaceID_XUL,
containmentAtom, aValue, getter_AddRefs(treeGrandchild))))
{
}
}
NS_RELEASE(containmentAtom);
containmentAtom = nsnull;
}
}
#endif
if ((tag.get() == containmentAtom) && (nameSpaceID == kNameSpaceID_XUL))
{
if (NS_FAILED(rv = CreateResourceElement(nameSpaceID,
containmentAtom, aValue, getter_AddRefs(treeGrandchild))))
continue;
if (NS_FAILED(rv = SetAllAttributesOnElement(treeGrandchild, aValue)))
continue;
}
else if ((tag.get() == kTextAtom) && (nameSpaceID == kNameSpaceID_XUL))
{
// <xul:text rdf:resource="..."> is replaced by text of the
// actual value of the rdf:resource attribute for the given node
nsAutoString attrValue;
if (NS_FAILED(rv = aTemplateKid->GetAttribute(kNameSpaceID_RDF,
kResourceAtom, attrValue)))
continue;
if (rv != NS_CONTENT_ATTR_HAS_VALUE)
continue;
if (attrValue.Length() < 1)
continue;
char *prop = attrValue.ToNewCString();
if (nsnull == prop)
continue;
nsCOMPtr<nsIRDFResource> propRes;
if (NS_FAILED(rv = gRDFService->GetResource(prop, getter_AddRefs(propRes))))
continue;
nsCOMPtr<nsIRDFNode> aResult;
if (NS_FAILED(rv = mDB->GetTarget(aValue,
propRes, PR_TRUE, getter_AddRefs(aResult))))
continue;
rv = nsRDFContentUtils::AttachTextNode(treeChildren, aResult);
delete [] prop;
prop = nsnull;
}
else
{
if (NS_FAILED(rv = NS_NewRDFElement(nameSpaceID, tag,
getter_AddRefs(treeGrandchild))))
continue;
}
if (treeGrandchild && treeGrandchild.get())
{
// copy all attributes from template to new node
PRInt32 numAttribs;
if (NS_SUCCEEDED(rv = aTemplateKid->GetAttributeCount(numAttribs)) && (rv == NS_CONTENT_ATTR_HAS_VALUE))
{
for (PRInt32 aLoop=0; aLoop<numAttribs; aLoop++)
{
PRInt32 attribNameSpaceID;
nsCOMPtr<nsIAtom> attribName;
if (NS_SUCCEEDED(rv = aTemplateKid->GetAttributeNameAt(aLoop,
attribNameSpaceID, *getter_AddRefs(attribName))))
{
// only copy attributes that aren't already set on the node
nsAutoString val;
if (NS_SUCCEEDED(rv = treeGrandchild->GetAttribute(attribNameSpaceID,
attribName, val)))
{
if (rv == NS_CONTENT_ATTR_HAS_VALUE) continue;
}
// never copy rdf:container attribute
if ((attribName.get() == kContainerAtom) &&
(attribNameSpaceID == kNameSpaceID_RDF))
continue;
// never copy rdf:property attribute
else if ((attribName.get() == kPropertyAtom) &&
(attribNameSpaceID == kNameSpaceID_RDF))
continue;
// never copy rdf:instanceOf attribute
else if ((attribName.get() == kInstanceOfAtom) &&
(attribNameSpaceID == kNameSpaceID_RDF))
continue;
// never copy {}:ID attribute
else if ((attribName.get() == kIdAtom) &&
(attribNameSpaceID == kNameSpaceID_None))
continue;
// never copy {}:itemcontentsgenerated attribute (bogus)
else if ((attribName.get() == kItemContentsGeneratedAtom) &&
(attribNameSpaceID == kNameSpaceID_None))
continue;
// never copy {}:treecontentsgenerated attribute (bogus)
else if ((attribName.get() == kTreeContentsGeneratedAtom) &&
(attribNameSpaceID == kNameSpaceID_None))
continue;
nsAutoString attribValue;
if (NS_SUCCEEDED(rv = aTemplateKid->GetAttribute(attribNameSpaceID,
attribName,attribValue)) && (rv == NS_CONTENT_ATTR_HAS_VALUE))
{
treeGrandchild->SetAttribute(attribNameSpaceID,
attribName, attribValue, PR_FALSE);
}
}
}
}
// set natural order hint
if (aNaturalOrderPos > 0)
{
nsAutoString pos, zero("0000");
pos.Append(aNaturalOrderPos, 10);
if (pos.Length() < 4)
{
pos.Insert(zero, 0, 4-pos.Length());
}
treeGrandchild->SetAttribute(kNameSpaceID_None, kNaturalOrderPosAtom, pos, PR_FALSE);
}
// recurse into template subtree
PRInt32 numTemplateKids;
if (NS_SUCCEEDED(rv = aTemplateKid->ChildCount(numTemplateKids)))
{
if (numTemplateKids > 0)
{
rv = PopulateWidgetItemSubtree(aTemplateRoot, aTemplateKid, treeGrandchild,
aElement, aProperty, aValue, aNaturalOrderPos);
}
}
// add into tree
if ((nsnull != XULSortService) && (tag.get() == containmentAtom))
{
XULSortService->InsertContainerNode(treeChildren, treeGrandchild);
}
else
{
treeChildren->AppendChildTo(treeGrandchild, PR_TRUE);
}
}
}
}
return(rv);
}
NS_IMETHODIMP
RDFGenericBuilderImpl::CreateWidgetItem(nsIContent *aElement, nsIRDFResource *aProperty,
nsIRDFResource *aValue, PRInt32 aNaturalOrderPos)
{
nsCOMPtr<nsIContent> aTemplate, tempNode;
nsresult rv;
if (NS_FAILED(rv = CreateResourceElement(kNameSpaceID_XUL, kTempAtom,
aValue, getter_AddRefs(tempNode))))
return(rv);
if (NS_FAILED(rv = SetAllAttributesOnElement(tempNode, aValue)))
return(rv);
if (NS_SUCCEEDED(rv = FindTemplateForElement(tempNode, getter_AddRefs(aTemplate))) &&
(nsnull != aTemplate))
{
nsCOMPtr<nsIContent> children = do_QueryInterface(aElement);
// if template specifies a subcontainment attribute, get it
// and make sure aElement contains it, otherwise use aElement
nsAutoString attrValue;
if (NS_SUCCEEDED(rv = aTemplate->GetAttribute(kNameSpaceID_XUL,
kSubcontainmentAtom, attrValue)) && (rv == NS_CONTENT_ATTR_HAS_VALUE))
{
nsCOMPtr<nsIAtom> childrenAtom = NS_NewAtom(attrValue);
if (nsnull != childrenAtom)
{
if (NS_SUCCEEDED(rv = EnsureElementHasGenericChild(aElement, kNameSpaceID_XUL,
childrenAtom, getter_AddRefs(children))))
{
}
}
}
rv = PopulateWidgetItemSubtree(aTemplate, aTemplate, children,
aElement, aProperty, aValue, aNaturalOrderPos);
}
else
{
rv = AddWidgetItem(aElement, aProperty, aValue, aNaturalOrderPos);
}
return(rv);
}
NS_IMETHODIMP
RDFGenericBuilderImpl::OnAssert(nsIRDFResource* aSubject,
nsIRDFResource* aPredicate,
@ -630,7 +1089,7 @@ RDFGenericBuilderImpl::OnAssert(nsIRDFResource* aSubject,
contentsGenerated.EqualsIgnoreCase("true")) {
// Okay, it's a "live" element, so go ahead and append the new
// child to this node.
if (NS_FAILED(rv = AddWidgetItem(element, aPredicate, resource, 0))) {
if (NS_FAILED(rv = CreateWidgetItem(element, aPredicate, resource, 0))) {
NS_ERROR("unable to create new widget item");
return rv;
}

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

@ -102,6 +102,15 @@ nsIAtom* RDFGenericBuilderImpl::kResourceAtom;
nsIAtom* RDFGenericBuilderImpl::kContainmentAtom;
nsIAtom* RDFGenericBuilderImpl::kNaturalOrderPosAtom;
nsIAtom* RDFGenericBuilderImpl::kSubcontainmentAtom;
nsIAtom* RDFGenericBuilderImpl::kTreeTemplateAtom;
nsIAtom* RDFGenericBuilderImpl::kRuleAtom;
nsIAtom* RDFGenericBuilderImpl::kTempAtom;
nsIAtom* RDFGenericBuilderImpl::kTreeContentsGeneratedAtom;
nsIAtom* RDFGenericBuilderImpl::kTextAtom;
nsIAtom* RDFGenericBuilderImpl::kPropertyAtom;
nsIAtom* RDFGenericBuilderImpl::kInstanceOfAtom;
PRInt32 RDFGenericBuilderImpl::kNameSpaceID_RDF;
PRInt32 RDFGenericBuilderImpl::kNameSpaceID_XUL;
@ -130,6 +139,7 @@ RDFGenericBuilderImpl::RDFGenericBuilderImpl(void)
if (gRefCnt == 0) {
kContainerAtom = NS_NewAtom("container");
kItemContentsGeneratedAtom = NS_NewAtom("itemcontentsgenerated");
kTreeContentsGeneratedAtom = NS_NewAtom("treecontentsgenerated");
kIdAtom = NS_NewAtom("id");
kOpenAtom = NS_NewAtom("open");
@ -137,6 +147,15 @@ RDFGenericBuilderImpl::RDFGenericBuilderImpl(void)
kNaturalOrderPosAtom = NS_NewAtom("pos");
kContainmentAtom = NS_NewAtom("containment");
kSubcontainmentAtom = NS_NewAtom("subcontainment");
kTreeTemplateAtom = NS_NewAtom("template");
kRuleAtom = NS_NewAtom("rule");
kTempAtom = NS_NewAtom("temp");
kTextAtom = NS_NewAtom("text");
kPropertyAtom = NS_NewAtom("property");
kInstanceOfAtom = NS_NewAtom("instanceOf");
nsresult rv;
// Register the XUL and RDF namespaces: these'll just retrieve
@ -207,11 +226,18 @@ RDFGenericBuilderImpl::~RDFGenericBuilderImpl(void)
NS_RELEASE(kIdAtom);
NS_RELEASE(kOpenAtom);
NS_RELEASE(kResourceAtom);
NS_RELEASE(kContainmentAtom);
NS_RELEASE(kNaturalOrderPosAtom);
NS_RELEASE(kSubcontainmentAtom);
NS_RELEASE(kTreeTemplateAtom);
NS_RELEASE(kRuleAtom);
NS_RELEASE(kTempAtom);
NS_RELEASE(kTreeContentsGeneratedAtom);
NS_RELEASE(kTextAtom);
NS_RELEASE(kPropertyAtom);
NS_RELEASE(kInstanceOfAtom);
NS_RELEASE(kNC_Title);
NS_RELEASE(kNC_Column);
@ -546,7 +572,7 @@ RDFGenericBuilderImpl::CreateContents(nsIContent* aElement)
for (loop=0; loop<numElements; loop+=2)
{
if (NS_FAILED(rv = AddWidgetItem(aElement, flatArray[loop+1], flatArray[loop], loop+1)))
if (NS_FAILED(rv = CreateWidgetItem(aElement, flatArray[loop+1], flatArray[loop], loop+1)))
{
NS_ERROR("unable to create widget item");
}
@ -569,6 +595,439 @@ RDFGenericBuilderImpl::CreateContents(nsIContent* aElement)
}
NS_IMETHODIMP
RDFGenericBuilderImpl::SetAllAttributesOnElement(nsIContent *aNode, nsIRDFResource *res)
{
// get all arcs out, and if not a containment property, set attribute
nsresult rv = NS_OK;
PRBool markAsContainer = PR_FALSE;
nsCOMPtr<nsISimpleEnumerator> arcs;
if (NS_SUCCEEDED(rv = mDB->ArcLabelsOut(res, getter_AddRefs(arcs))))
{
PRBool hasMore = PR_TRUE;
while(hasMore)
{
rv = arcs->HasMoreElements(&hasMore);
if (NS_FAILED(rv)) break;
if (hasMore == PR_FALSE) break;
nsCOMPtr<nsISupports> isupports;
if (NS_FAILED(rv = arcs->GetNext(getter_AddRefs(isupports)))) break;
nsCOMPtr<nsIRDFResource> property = do_QueryInterface(isupports);
// Ignore properties that are used to indicate "tree-ness"
if (IsContainmentProperty(aNode, property))
{
markAsContainer = PR_TRUE;
continue;
}
PRInt32 nameSpaceID;
nsCOMPtr<nsIAtom> tag;
if (NS_FAILED(rv = mDocument->SplitProperty(property, &nameSpaceID, getter_AddRefs(tag))))
break;
nsCOMPtr<nsIRDFNode> value;
if (NS_FAILED(rv = mDB->GetTarget(res, property, PR_TRUE, getter_AddRefs(value))))
break;
if (rv == NS_RDF_NO_VALUE)
continue;
nsCOMPtr<nsIRDFResource> resource;
nsCOMPtr<nsIRDFLiteral> literal;
nsAutoString s;
if (NS_SUCCEEDED(rv = value->QueryInterface(kIRDFResourceIID, getter_AddRefs(resource))))
{
nsXPIDLCString uri;
resource->GetValue( getter_Copies(uri) );
s = uri;
}
else if (NS_SUCCEEDED(rv = value->QueryInterface(kIRDFLiteralIID, getter_AddRefs(literal))))
{
nsXPIDLString p;
literal->GetValue( getter_Copies(p) );
s = p;
}
else
{
NS_ERROR("not a resource or a literal");
return NS_ERROR_UNEXPECTED;
}
aNode->SetAttribute(nameSpaceID, tag, s, PR_FALSE);
}
}
if (markAsContainer == PR_TRUE)
{
// mark this as a "container" so that we know to
// recursively generate kids if they're asked for.
rv = aNode->SetAttribute(kNameSpaceID_RDF, kContainerAtom, "true", PR_FALSE);
}
return(rv);
}
NS_IMETHODIMP
RDFGenericBuilderImpl::IsTemplateRuleMatch(nsIContent *aNode, nsIContent *aRule, PRBool *matchingRuleFound)
{
nsresult rv = NS_OK;
PRInt32 count;
*matchingRuleFound = PR_FALSE;
if (NS_FAILED(rv = aRule->GetAttributeCount(count))) return(rv);
for (PRInt32 loop=0; loop<count; loop++)
{
PRInt32 attribNameSpaceID;
nsCOMPtr<nsIAtom> attribAtom;
if (NS_FAILED(rv = aRule->GetAttributeNameAt(loop, attribNameSpaceID, *getter_AddRefs(attribAtom))))
continue;
nsAutoString attribValue;
if (NS_FAILED(rv = aRule->GetAttribute(attribNameSpaceID, attribAtom, attribValue)))
continue;
if ((attribNameSpaceID == kNameSpaceID_XUL) && (attribAtom.get() == kContainerAtom))
{
// check and see if aNode is a container
nsAutoString nodeValue;
if (NS_SUCCEEDED(aNode->GetAttribute(kNameSpaceID_RDF, kContainerAtom, nodeValue)))
{
if (nodeValue.EqualsIgnoreCase(attribValue))
{
*matchingRuleFound = PR_TRUE;
break;
}
}
}
}
return(rv);
}
NS_IMETHODIMP
RDFGenericBuilderImpl::FindTemplateForElement(nsIContent *aNode, nsIContent **theTemplate)
{
nsresult rv;
PRInt32 count;
nsCOMPtr<nsIContent> aTemplate;
*theTemplate = nsnull;
if (NS_FAILED(rv = mRoot->ChildCount(count))) return(rv);
for (PRInt32 loop=0; loop<count; loop++)
{
if (NS_FAILED(rv = mRoot->ChildAt(loop, *getter_AddRefs(aTemplate))))
continue;
PRInt32 nameSpaceID;
if (NS_FAILED(rv = aTemplate->GetNameSpaceID(nameSpaceID)))
continue;
if (nameSpaceID != kNameSpaceID_XUL)
continue;
nsCOMPtr<nsIAtom> tag;
if (NS_FAILED(rv = aTemplate->GetTag(*getter_AddRefs(tag))))
continue;
if (tag.get() != kTreeTemplateAtom)
continue;
// found a template; check against any (optional) rules
PRInt32 numRuleChildren, numRulesFound = 0;
if (NS_FAILED(rv = aTemplate->ChildCount(numRuleChildren)))
continue;
for (PRInt32 ruleLoop=0; ruleLoop<numRuleChildren; ruleLoop++)
{
nsCOMPtr<nsIContent> aRule;
if (NS_FAILED(rv = aTemplate->ChildAt(ruleLoop, *getter_AddRefs(aRule))))
continue;
PRInt32 nameSpaceID;
if (NS_FAILED(rv = aTemplate->GetNameSpaceID(nameSpaceID)))
continue;
if (nameSpaceID != kNameSpaceID_XUL)
continue;
nsCOMPtr<nsIAtom> ruleTag;
if (NS_SUCCEEDED(rv = aTemplate->GetTag(*getter_AddRefs(ruleTag))))
{
if (ruleTag.get() == kRuleAtom)
{
++numRulesFound;
PRBool matchingRuleFound = PR_FALSE;
if (NS_SUCCEEDED(rv = IsTemplateRuleMatch(aNode, aRule,
&matchingRuleFound)))
{
if (matchingRuleFound == PR_TRUE)
{
// found a matching rule, use it as the template
*theTemplate = aRule;
NS_ADDREF(*theTemplate);
return(NS_OK);
}
}
}
}
}
if (numRulesFound == 0)
{
// if no rules are specified in the template, just use it
*theTemplate = aTemplate;
NS_ADDREF(*theTemplate);
break;
}
}
return(rv);
}
NS_IMETHODIMP
RDFGenericBuilderImpl::PopulateWidgetItemSubtree(nsIContent *aTemplateRoot, nsIContent *aTemplate,
nsIContent *treeChildren, nsIContent* aElement, nsIRDFResource* aProperty,
nsIRDFResource* aValue, PRInt32 aNaturalOrderPos)
{
PRInt32 count;
nsresult rv;
if (NS_FAILED(rv = aTemplate->ChildCount(count))) return(rv);
// get REQUIRED containment="..." off of template root
nsAutoString templateContainmentValue;
if (NS_FAILED(rv = aTemplateRoot->GetAttribute(kNameSpaceID_XUL, kContainmentAtom, templateContainmentValue)))
return(rv);
if (rv != NS_CONTENT_ATTR_HAS_VALUE)
return(NS_ERROR_FAILURE);
nsCOMPtr<nsIAtom> containmentAtom = NS_NewAtom(templateContainmentValue);
if (nsnull == containmentAtom)
return(NS_ERROR_OUT_OF_MEMORY);
for (PRInt32 loop=0; loop<count; loop++)
{
nsCOMPtr<nsIContent> aTemplateKid;
if (NS_FAILED(rv = aTemplate->ChildAt(loop, *getter_AddRefs(aTemplateKid))))
continue;
PRInt32 nameSpaceID;
if (NS_FAILED(rv = aTemplateKid->GetNameSpaceID(nameSpaceID)))
continue;
nsCOMPtr<nsIAtom> tag;
if (NS_SUCCEEDED(rv = aTemplateKid->GetTag(*getter_AddRefs(tag))))
{
nsCOMPtr<nsIContent> treeGrandchild;
#if 0
nsAutoString containmentValue;
if (NS_SUCCEEDED(rv = aTemplateKid->GetAttribute(kNameSpaceID_XUL,
kContainmentAtom, containmentValue)) && (rv == NS_CONTENT_ATTR_HAS_VALUE))
{
nsIAtom *containmentAtom = NS_NewAtom(containmentValue);
if (nsnull != containmentAtom)
{
if (tag.get() == containmentAtom)
{
if (NS_SUCCEEDED(rv = CreateResourceElement(kNameSpaceID_XUL,
containmentAtom, aValue, getter_AddRefs(treeGrandchild))))
{
}
}
NS_RELEASE(containmentAtom);
containmentAtom = nsnull;
}
}
else if (NS_SUCCEEDED(rv = aTemplate->GetAttribute(kNameSpaceID_XUL,
kItemAtom, containmentValue)) && (rv == NS_CONTENT_ATTR_HAS_VALUE))
{
nsIAtom *containmentAtom = NS_NewAtom(containmentValue);
if (nsnull != containmentAtom)
{
if (tag.get() == containmentAtom)
{
if (NS_SUCCEEDED(rv = CreateResourceElement(kNameSpaceID_XUL,
containmentAtom, aValue, getter_AddRefs(treeGrandchild))))
{
}
}
NS_RELEASE(containmentAtom);
containmentAtom = nsnull;
}
}
#endif
if ((tag.get() == containmentAtom) && (nameSpaceID == kNameSpaceID_XUL))
{
if (NS_FAILED(rv = CreateResourceElement(nameSpaceID,
containmentAtom, aValue, getter_AddRefs(treeGrandchild))))
continue;
if (NS_FAILED(rv = SetAllAttributesOnElement(treeGrandchild, aValue)))
continue;
}
else if ((tag.get() == kTextAtom) && (nameSpaceID == kNameSpaceID_XUL))
{
// <xul:text rdf:resource="..."> is replaced by text of the
// actual value of the rdf:resource attribute for the given node
nsAutoString attrValue;
if (NS_FAILED(rv = aTemplateKid->GetAttribute(kNameSpaceID_RDF,
kResourceAtom, attrValue)))
continue;
if (rv != NS_CONTENT_ATTR_HAS_VALUE)
continue;
if (attrValue.Length() < 1)
continue;
char *prop = attrValue.ToNewCString();
if (nsnull == prop)
continue;
nsCOMPtr<nsIRDFResource> propRes;
if (NS_FAILED(rv = gRDFService->GetResource(prop, getter_AddRefs(propRes))))
continue;
nsCOMPtr<nsIRDFNode> aResult;
if (NS_FAILED(rv = mDB->GetTarget(aValue,
propRes, PR_TRUE, getter_AddRefs(aResult))))
continue;
rv = nsRDFContentUtils::AttachTextNode(treeChildren, aResult);
delete [] prop;
prop = nsnull;
}
else
{
if (NS_FAILED(rv = NS_NewRDFElement(nameSpaceID, tag,
getter_AddRefs(treeGrandchild))))
continue;
}
if (treeGrandchild && treeGrandchild.get())
{
// copy all attributes from template to new node
PRInt32 numAttribs;
if (NS_SUCCEEDED(rv = aTemplateKid->GetAttributeCount(numAttribs)) && (rv == NS_CONTENT_ATTR_HAS_VALUE))
{
for (PRInt32 aLoop=0; aLoop<numAttribs; aLoop++)
{
PRInt32 attribNameSpaceID;
nsCOMPtr<nsIAtom> attribName;
if (NS_SUCCEEDED(rv = aTemplateKid->GetAttributeNameAt(aLoop,
attribNameSpaceID, *getter_AddRefs(attribName))))
{
// only copy attributes that aren't already set on the node
nsAutoString val;
if (NS_SUCCEEDED(rv = treeGrandchild->GetAttribute(attribNameSpaceID,
attribName, val)))
{
if (rv == NS_CONTENT_ATTR_HAS_VALUE) continue;
}
// never copy rdf:container attribute
if ((attribName.get() == kContainerAtom) &&
(attribNameSpaceID == kNameSpaceID_RDF))
continue;
// never copy rdf:property attribute
else if ((attribName.get() == kPropertyAtom) &&
(attribNameSpaceID == kNameSpaceID_RDF))
continue;
// never copy rdf:instanceOf attribute
else if ((attribName.get() == kInstanceOfAtom) &&
(attribNameSpaceID == kNameSpaceID_RDF))
continue;
// never copy {}:ID attribute
else if ((attribName.get() == kIdAtom) &&
(attribNameSpaceID == kNameSpaceID_None))
continue;
// never copy {}:itemcontentsgenerated attribute (bogus)
else if ((attribName.get() == kItemContentsGeneratedAtom) &&
(attribNameSpaceID == kNameSpaceID_None))
continue;
// never copy {}:treecontentsgenerated attribute (bogus)
else if ((attribName.get() == kTreeContentsGeneratedAtom) &&
(attribNameSpaceID == kNameSpaceID_None))
continue;
nsAutoString attribValue;
if (NS_SUCCEEDED(rv = aTemplateKid->GetAttribute(attribNameSpaceID,
attribName,attribValue)) && (rv == NS_CONTENT_ATTR_HAS_VALUE))
{
treeGrandchild->SetAttribute(attribNameSpaceID,
attribName, attribValue, PR_FALSE);
}
}
}
}
// set natural order hint
if (aNaturalOrderPos > 0)
{
nsAutoString pos, zero("0000");
pos.Append(aNaturalOrderPos, 10);
if (pos.Length() < 4)
{
pos.Insert(zero, 0, 4-pos.Length());
}
treeGrandchild->SetAttribute(kNameSpaceID_None, kNaturalOrderPosAtom, pos, PR_FALSE);
}
// recurse into template subtree
PRInt32 numTemplateKids;
if (NS_SUCCEEDED(rv = aTemplateKid->ChildCount(numTemplateKids)))
{
if (numTemplateKids > 0)
{
rv = PopulateWidgetItemSubtree(aTemplateRoot, aTemplateKid, treeGrandchild,
aElement, aProperty, aValue, aNaturalOrderPos);
}
}
// add into tree
if ((nsnull != XULSortService) && (tag.get() == containmentAtom))
{
XULSortService->InsertContainerNode(treeChildren, treeGrandchild);
}
else
{
treeChildren->AppendChildTo(treeGrandchild, PR_TRUE);
}
}
}
}
return(rv);
}
NS_IMETHODIMP
RDFGenericBuilderImpl::CreateWidgetItem(nsIContent *aElement, nsIRDFResource *aProperty,
nsIRDFResource *aValue, PRInt32 aNaturalOrderPos)
{
nsCOMPtr<nsIContent> aTemplate, tempNode;
nsresult rv;
if (NS_FAILED(rv = CreateResourceElement(kNameSpaceID_XUL, kTempAtom,
aValue, getter_AddRefs(tempNode))))
return(rv);
if (NS_FAILED(rv = SetAllAttributesOnElement(tempNode, aValue)))
return(rv);
if (NS_SUCCEEDED(rv = FindTemplateForElement(tempNode, getter_AddRefs(aTemplate))) &&
(nsnull != aTemplate))
{
nsCOMPtr<nsIContent> children = do_QueryInterface(aElement);
// if template specifies a subcontainment attribute, get it
// and make sure aElement contains it, otherwise use aElement
nsAutoString attrValue;
if (NS_SUCCEEDED(rv = aTemplate->GetAttribute(kNameSpaceID_XUL,
kSubcontainmentAtom, attrValue)) && (rv == NS_CONTENT_ATTR_HAS_VALUE))
{
nsCOMPtr<nsIAtom> childrenAtom = NS_NewAtom(attrValue);
if (nsnull != childrenAtom)
{
if (NS_SUCCEEDED(rv = EnsureElementHasGenericChild(aElement, kNameSpaceID_XUL,
childrenAtom, getter_AddRefs(children))))
{
}
}
}
rv = PopulateWidgetItemSubtree(aTemplate, aTemplate, children,
aElement, aProperty, aValue, aNaturalOrderPos);
}
else
{
rv = AddWidgetItem(aElement, aProperty, aValue, aNaturalOrderPos);
}
return(rv);
}
NS_IMETHODIMP
RDFGenericBuilderImpl::OnAssert(nsIRDFResource* aSubject,
nsIRDFResource* aPredicate,
@ -630,7 +1089,7 @@ RDFGenericBuilderImpl::OnAssert(nsIRDFResource* aSubject,
contentsGenerated.EqualsIgnoreCase("true")) {
// Okay, it's a "live" element, so go ahead and append the new
// child to this node.
if (NS_FAILED(rv = AddWidgetItem(element, aPredicate, resource, 0))) {
if (NS_FAILED(rv = CreateWidgetItem(element, aPredicate, resource, 0))) {
NS_ERROR("unable to create new widget item");
return rv;
}

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

@ -62,6 +62,15 @@ public:
NS_IMETHOD SetRootContent(nsIContent* aElement);
NS_IMETHOD CreateContents(nsIContent* aElement);
NS_IMETHOD SetAllAttributesOnElement(nsIContent *aNode, nsIRDFResource *res);
NS_IMETHOD FindTemplateForElement(nsIContent *aNode, nsIContent **theTemplate);
NS_IMETHOD IsTemplateRuleMatch(nsIContent *aNode, nsIContent *aRule, PRBool *matchingRuleFound);
NS_IMETHOD PopulateWidgetItemSubtree(nsIContent *aTemplateRoot, nsIContent *aTemplate,
nsIContent *treeCell, nsIContent* aElement, nsIRDFResource* aProperty,
nsIRDFResource* aValue, PRInt32 aNaturalOrderPos);
NS_IMETHOD CreateWidgetItem(nsIContent* aElement, nsIRDFResource* aProperty,
nsIRDFResource* aValue, PRInt32 aNaturalOrderPos);
// nsIRDFObserver interface
NS_IMETHOD OnAssert(nsIRDFResource* aSubject, nsIRDFResource* aPredicate, nsIRDFNode* aObject);
NS_IMETHOD OnUnassert(nsIRDFResource* aSubject, nsIRDFResource* aPredicate, nsIRDFNode* aObjetct);
@ -182,6 +191,15 @@ protected:
static nsIAtom* kResourceAtom;
static nsIAtom* kContainmentAtom;
static nsIAtom* kSubcontainmentAtom;
static nsIAtom* kTreeTemplateAtom;
static nsIAtom* kRuleAtom;
static nsIAtom* kTempAtom;
static nsIAtom* kTreeContentsGeneratedAtom;
static nsIAtom* kTextAtom;
static nsIAtom* kPropertyAtom;
static nsIAtom* kInstanceOfAtom;
static PRInt32 kNameSpaceID_RDF;
static PRInt32 kNameSpaceID_XUL;

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

@ -102,6 +102,15 @@ nsIAtom* RDFGenericBuilderImpl::kResourceAtom;
nsIAtom* RDFGenericBuilderImpl::kContainmentAtom;
nsIAtom* RDFGenericBuilderImpl::kNaturalOrderPosAtom;
nsIAtom* RDFGenericBuilderImpl::kSubcontainmentAtom;
nsIAtom* RDFGenericBuilderImpl::kTreeTemplateAtom;
nsIAtom* RDFGenericBuilderImpl::kRuleAtom;
nsIAtom* RDFGenericBuilderImpl::kTempAtom;
nsIAtom* RDFGenericBuilderImpl::kTreeContentsGeneratedAtom;
nsIAtom* RDFGenericBuilderImpl::kTextAtom;
nsIAtom* RDFGenericBuilderImpl::kPropertyAtom;
nsIAtom* RDFGenericBuilderImpl::kInstanceOfAtom;
PRInt32 RDFGenericBuilderImpl::kNameSpaceID_RDF;
PRInt32 RDFGenericBuilderImpl::kNameSpaceID_XUL;
@ -130,6 +139,7 @@ RDFGenericBuilderImpl::RDFGenericBuilderImpl(void)
if (gRefCnt == 0) {
kContainerAtom = NS_NewAtom("container");
kItemContentsGeneratedAtom = NS_NewAtom("itemcontentsgenerated");
kTreeContentsGeneratedAtom = NS_NewAtom("treecontentsgenerated");
kIdAtom = NS_NewAtom("id");
kOpenAtom = NS_NewAtom("open");
@ -137,6 +147,15 @@ RDFGenericBuilderImpl::RDFGenericBuilderImpl(void)
kNaturalOrderPosAtom = NS_NewAtom("pos");
kContainmentAtom = NS_NewAtom("containment");
kSubcontainmentAtom = NS_NewAtom("subcontainment");
kTreeTemplateAtom = NS_NewAtom("template");
kRuleAtom = NS_NewAtom("rule");
kTempAtom = NS_NewAtom("temp");
kTextAtom = NS_NewAtom("text");
kPropertyAtom = NS_NewAtom("property");
kInstanceOfAtom = NS_NewAtom("instanceOf");
nsresult rv;
// Register the XUL and RDF namespaces: these'll just retrieve
@ -207,11 +226,18 @@ RDFGenericBuilderImpl::~RDFGenericBuilderImpl(void)
NS_RELEASE(kIdAtom);
NS_RELEASE(kOpenAtom);
NS_RELEASE(kResourceAtom);
NS_RELEASE(kContainmentAtom);
NS_RELEASE(kNaturalOrderPosAtom);
NS_RELEASE(kSubcontainmentAtom);
NS_RELEASE(kTreeTemplateAtom);
NS_RELEASE(kRuleAtom);
NS_RELEASE(kTempAtom);
NS_RELEASE(kTreeContentsGeneratedAtom);
NS_RELEASE(kTextAtom);
NS_RELEASE(kPropertyAtom);
NS_RELEASE(kInstanceOfAtom);
NS_RELEASE(kNC_Title);
NS_RELEASE(kNC_Column);
@ -546,7 +572,7 @@ RDFGenericBuilderImpl::CreateContents(nsIContent* aElement)
for (loop=0; loop<numElements; loop+=2)
{
if (NS_FAILED(rv = AddWidgetItem(aElement, flatArray[loop+1], flatArray[loop], loop+1)))
if (NS_FAILED(rv = CreateWidgetItem(aElement, flatArray[loop+1], flatArray[loop], loop+1)))
{
NS_ERROR("unable to create widget item");
}
@ -569,6 +595,439 @@ RDFGenericBuilderImpl::CreateContents(nsIContent* aElement)
}
NS_IMETHODIMP
RDFGenericBuilderImpl::SetAllAttributesOnElement(nsIContent *aNode, nsIRDFResource *res)
{
// get all arcs out, and if not a containment property, set attribute
nsresult rv = NS_OK;
PRBool markAsContainer = PR_FALSE;
nsCOMPtr<nsISimpleEnumerator> arcs;
if (NS_SUCCEEDED(rv = mDB->ArcLabelsOut(res, getter_AddRefs(arcs))))
{
PRBool hasMore = PR_TRUE;
while(hasMore)
{
rv = arcs->HasMoreElements(&hasMore);
if (NS_FAILED(rv)) break;
if (hasMore == PR_FALSE) break;
nsCOMPtr<nsISupports> isupports;
if (NS_FAILED(rv = arcs->GetNext(getter_AddRefs(isupports)))) break;
nsCOMPtr<nsIRDFResource> property = do_QueryInterface(isupports);
// Ignore properties that are used to indicate "tree-ness"
if (IsContainmentProperty(aNode, property))
{
markAsContainer = PR_TRUE;
continue;
}
PRInt32 nameSpaceID;
nsCOMPtr<nsIAtom> tag;
if (NS_FAILED(rv = mDocument->SplitProperty(property, &nameSpaceID, getter_AddRefs(tag))))
break;
nsCOMPtr<nsIRDFNode> value;
if (NS_FAILED(rv = mDB->GetTarget(res, property, PR_TRUE, getter_AddRefs(value))))
break;
if (rv == NS_RDF_NO_VALUE)
continue;
nsCOMPtr<nsIRDFResource> resource;
nsCOMPtr<nsIRDFLiteral> literal;
nsAutoString s;
if (NS_SUCCEEDED(rv = value->QueryInterface(kIRDFResourceIID, getter_AddRefs(resource))))
{
nsXPIDLCString uri;
resource->GetValue( getter_Copies(uri) );
s = uri;
}
else if (NS_SUCCEEDED(rv = value->QueryInterface(kIRDFLiteralIID, getter_AddRefs(literal))))
{
nsXPIDLString p;
literal->GetValue( getter_Copies(p) );
s = p;
}
else
{
NS_ERROR("not a resource or a literal");
return NS_ERROR_UNEXPECTED;
}
aNode->SetAttribute(nameSpaceID, tag, s, PR_FALSE);
}
}
if (markAsContainer == PR_TRUE)
{
// mark this as a "container" so that we know to
// recursively generate kids if they're asked for.
rv = aNode->SetAttribute(kNameSpaceID_RDF, kContainerAtom, "true", PR_FALSE);
}
return(rv);
}
NS_IMETHODIMP
RDFGenericBuilderImpl::IsTemplateRuleMatch(nsIContent *aNode, nsIContent *aRule, PRBool *matchingRuleFound)
{
nsresult rv = NS_OK;
PRInt32 count;
*matchingRuleFound = PR_FALSE;
if (NS_FAILED(rv = aRule->GetAttributeCount(count))) return(rv);
for (PRInt32 loop=0; loop<count; loop++)
{
PRInt32 attribNameSpaceID;
nsCOMPtr<nsIAtom> attribAtom;
if (NS_FAILED(rv = aRule->GetAttributeNameAt(loop, attribNameSpaceID, *getter_AddRefs(attribAtom))))
continue;
nsAutoString attribValue;
if (NS_FAILED(rv = aRule->GetAttribute(attribNameSpaceID, attribAtom, attribValue)))
continue;
if ((attribNameSpaceID == kNameSpaceID_XUL) && (attribAtom.get() == kContainerAtom))
{
// check and see if aNode is a container
nsAutoString nodeValue;
if (NS_SUCCEEDED(aNode->GetAttribute(kNameSpaceID_RDF, kContainerAtom, nodeValue)))
{
if (nodeValue.EqualsIgnoreCase(attribValue))
{
*matchingRuleFound = PR_TRUE;
break;
}
}
}
}
return(rv);
}
NS_IMETHODIMP
RDFGenericBuilderImpl::FindTemplateForElement(nsIContent *aNode, nsIContent **theTemplate)
{
nsresult rv;
PRInt32 count;
nsCOMPtr<nsIContent> aTemplate;
*theTemplate = nsnull;
if (NS_FAILED(rv = mRoot->ChildCount(count))) return(rv);
for (PRInt32 loop=0; loop<count; loop++)
{
if (NS_FAILED(rv = mRoot->ChildAt(loop, *getter_AddRefs(aTemplate))))
continue;
PRInt32 nameSpaceID;
if (NS_FAILED(rv = aTemplate->GetNameSpaceID(nameSpaceID)))
continue;
if (nameSpaceID != kNameSpaceID_XUL)
continue;
nsCOMPtr<nsIAtom> tag;
if (NS_FAILED(rv = aTemplate->GetTag(*getter_AddRefs(tag))))
continue;
if (tag.get() != kTreeTemplateAtom)
continue;
// found a template; check against any (optional) rules
PRInt32 numRuleChildren, numRulesFound = 0;
if (NS_FAILED(rv = aTemplate->ChildCount(numRuleChildren)))
continue;
for (PRInt32 ruleLoop=0; ruleLoop<numRuleChildren; ruleLoop++)
{
nsCOMPtr<nsIContent> aRule;
if (NS_FAILED(rv = aTemplate->ChildAt(ruleLoop, *getter_AddRefs(aRule))))
continue;
PRInt32 nameSpaceID;
if (NS_FAILED(rv = aTemplate->GetNameSpaceID(nameSpaceID)))
continue;
if (nameSpaceID != kNameSpaceID_XUL)
continue;
nsCOMPtr<nsIAtom> ruleTag;
if (NS_SUCCEEDED(rv = aTemplate->GetTag(*getter_AddRefs(ruleTag))))
{
if (ruleTag.get() == kRuleAtom)
{
++numRulesFound;
PRBool matchingRuleFound = PR_FALSE;
if (NS_SUCCEEDED(rv = IsTemplateRuleMatch(aNode, aRule,
&matchingRuleFound)))
{
if (matchingRuleFound == PR_TRUE)
{
// found a matching rule, use it as the template
*theTemplate = aRule;
NS_ADDREF(*theTemplate);
return(NS_OK);
}
}
}
}
}
if (numRulesFound == 0)
{
// if no rules are specified in the template, just use it
*theTemplate = aTemplate;
NS_ADDREF(*theTemplate);
break;
}
}
return(rv);
}
NS_IMETHODIMP
RDFGenericBuilderImpl::PopulateWidgetItemSubtree(nsIContent *aTemplateRoot, nsIContent *aTemplate,
nsIContent *treeChildren, nsIContent* aElement, nsIRDFResource* aProperty,
nsIRDFResource* aValue, PRInt32 aNaturalOrderPos)
{
PRInt32 count;
nsresult rv;
if (NS_FAILED(rv = aTemplate->ChildCount(count))) return(rv);
// get REQUIRED containment="..." off of template root
nsAutoString templateContainmentValue;
if (NS_FAILED(rv = aTemplateRoot->GetAttribute(kNameSpaceID_XUL, kContainmentAtom, templateContainmentValue)))
return(rv);
if (rv != NS_CONTENT_ATTR_HAS_VALUE)
return(NS_ERROR_FAILURE);
nsCOMPtr<nsIAtom> containmentAtom = NS_NewAtom(templateContainmentValue);
if (nsnull == containmentAtom)
return(NS_ERROR_OUT_OF_MEMORY);
for (PRInt32 loop=0; loop<count; loop++)
{
nsCOMPtr<nsIContent> aTemplateKid;
if (NS_FAILED(rv = aTemplate->ChildAt(loop, *getter_AddRefs(aTemplateKid))))
continue;
PRInt32 nameSpaceID;
if (NS_FAILED(rv = aTemplateKid->GetNameSpaceID(nameSpaceID)))
continue;
nsCOMPtr<nsIAtom> tag;
if (NS_SUCCEEDED(rv = aTemplateKid->GetTag(*getter_AddRefs(tag))))
{
nsCOMPtr<nsIContent> treeGrandchild;
#if 0
nsAutoString containmentValue;
if (NS_SUCCEEDED(rv = aTemplateKid->GetAttribute(kNameSpaceID_XUL,
kContainmentAtom, containmentValue)) && (rv == NS_CONTENT_ATTR_HAS_VALUE))
{
nsIAtom *containmentAtom = NS_NewAtom(containmentValue);
if (nsnull != containmentAtom)
{
if (tag.get() == containmentAtom)
{
if (NS_SUCCEEDED(rv = CreateResourceElement(kNameSpaceID_XUL,
containmentAtom, aValue, getter_AddRefs(treeGrandchild))))
{
}
}
NS_RELEASE(containmentAtom);
containmentAtom = nsnull;
}
}
else if (NS_SUCCEEDED(rv = aTemplate->GetAttribute(kNameSpaceID_XUL,
kItemAtom, containmentValue)) && (rv == NS_CONTENT_ATTR_HAS_VALUE))
{
nsIAtom *containmentAtom = NS_NewAtom(containmentValue);
if (nsnull != containmentAtom)
{
if (tag.get() == containmentAtom)
{
if (NS_SUCCEEDED(rv = CreateResourceElement(kNameSpaceID_XUL,
containmentAtom, aValue, getter_AddRefs(treeGrandchild))))
{
}
}
NS_RELEASE(containmentAtom);
containmentAtom = nsnull;
}
}
#endif
if ((tag.get() == containmentAtom) && (nameSpaceID == kNameSpaceID_XUL))
{
if (NS_FAILED(rv = CreateResourceElement(nameSpaceID,
containmentAtom, aValue, getter_AddRefs(treeGrandchild))))
continue;
if (NS_FAILED(rv = SetAllAttributesOnElement(treeGrandchild, aValue)))
continue;
}
else if ((tag.get() == kTextAtom) && (nameSpaceID == kNameSpaceID_XUL))
{
// <xul:text rdf:resource="..."> is replaced by text of the
// actual value of the rdf:resource attribute for the given node
nsAutoString attrValue;
if (NS_FAILED(rv = aTemplateKid->GetAttribute(kNameSpaceID_RDF,
kResourceAtom, attrValue)))
continue;
if (rv != NS_CONTENT_ATTR_HAS_VALUE)
continue;
if (attrValue.Length() < 1)
continue;
char *prop = attrValue.ToNewCString();
if (nsnull == prop)
continue;
nsCOMPtr<nsIRDFResource> propRes;
if (NS_FAILED(rv = gRDFService->GetResource(prop, getter_AddRefs(propRes))))
continue;
nsCOMPtr<nsIRDFNode> aResult;
if (NS_FAILED(rv = mDB->GetTarget(aValue,
propRes, PR_TRUE, getter_AddRefs(aResult))))
continue;
rv = nsRDFContentUtils::AttachTextNode(treeChildren, aResult);
delete [] prop;
prop = nsnull;
}
else
{
if (NS_FAILED(rv = NS_NewRDFElement(nameSpaceID, tag,
getter_AddRefs(treeGrandchild))))
continue;
}
if (treeGrandchild && treeGrandchild.get())
{
// copy all attributes from template to new node
PRInt32 numAttribs;
if (NS_SUCCEEDED(rv = aTemplateKid->GetAttributeCount(numAttribs)) && (rv == NS_CONTENT_ATTR_HAS_VALUE))
{
for (PRInt32 aLoop=0; aLoop<numAttribs; aLoop++)
{
PRInt32 attribNameSpaceID;
nsCOMPtr<nsIAtom> attribName;
if (NS_SUCCEEDED(rv = aTemplateKid->GetAttributeNameAt(aLoop,
attribNameSpaceID, *getter_AddRefs(attribName))))
{
// only copy attributes that aren't already set on the node
nsAutoString val;
if (NS_SUCCEEDED(rv = treeGrandchild->GetAttribute(attribNameSpaceID,
attribName, val)))
{
if (rv == NS_CONTENT_ATTR_HAS_VALUE) continue;
}
// never copy rdf:container attribute
if ((attribName.get() == kContainerAtom) &&
(attribNameSpaceID == kNameSpaceID_RDF))
continue;
// never copy rdf:property attribute
else if ((attribName.get() == kPropertyAtom) &&
(attribNameSpaceID == kNameSpaceID_RDF))
continue;
// never copy rdf:instanceOf attribute
else if ((attribName.get() == kInstanceOfAtom) &&
(attribNameSpaceID == kNameSpaceID_RDF))
continue;
// never copy {}:ID attribute
else if ((attribName.get() == kIdAtom) &&
(attribNameSpaceID == kNameSpaceID_None))
continue;
// never copy {}:itemcontentsgenerated attribute (bogus)
else if ((attribName.get() == kItemContentsGeneratedAtom) &&
(attribNameSpaceID == kNameSpaceID_None))
continue;
// never copy {}:treecontentsgenerated attribute (bogus)
else if ((attribName.get() == kTreeContentsGeneratedAtom) &&
(attribNameSpaceID == kNameSpaceID_None))
continue;
nsAutoString attribValue;
if (NS_SUCCEEDED(rv = aTemplateKid->GetAttribute(attribNameSpaceID,
attribName,attribValue)) && (rv == NS_CONTENT_ATTR_HAS_VALUE))
{
treeGrandchild->SetAttribute(attribNameSpaceID,
attribName, attribValue, PR_FALSE);
}
}
}
}
// set natural order hint
if (aNaturalOrderPos > 0)
{
nsAutoString pos, zero("0000");
pos.Append(aNaturalOrderPos, 10);
if (pos.Length() < 4)
{
pos.Insert(zero, 0, 4-pos.Length());
}
treeGrandchild->SetAttribute(kNameSpaceID_None, kNaturalOrderPosAtom, pos, PR_FALSE);
}
// recurse into template subtree
PRInt32 numTemplateKids;
if (NS_SUCCEEDED(rv = aTemplateKid->ChildCount(numTemplateKids)))
{
if (numTemplateKids > 0)
{
rv = PopulateWidgetItemSubtree(aTemplateRoot, aTemplateKid, treeGrandchild,
aElement, aProperty, aValue, aNaturalOrderPos);
}
}
// add into tree
if ((nsnull != XULSortService) && (tag.get() == containmentAtom))
{
XULSortService->InsertContainerNode(treeChildren, treeGrandchild);
}
else
{
treeChildren->AppendChildTo(treeGrandchild, PR_TRUE);
}
}
}
}
return(rv);
}
NS_IMETHODIMP
RDFGenericBuilderImpl::CreateWidgetItem(nsIContent *aElement, nsIRDFResource *aProperty,
nsIRDFResource *aValue, PRInt32 aNaturalOrderPos)
{
nsCOMPtr<nsIContent> aTemplate, tempNode;
nsresult rv;
if (NS_FAILED(rv = CreateResourceElement(kNameSpaceID_XUL, kTempAtom,
aValue, getter_AddRefs(tempNode))))
return(rv);
if (NS_FAILED(rv = SetAllAttributesOnElement(tempNode, aValue)))
return(rv);
if (NS_SUCCEEDED(rv = FindTemplateForElement(tempNode, getter_AddRefs(aTemplate))) &&
(nsnull != aTemplate))
{
nsCOMPtr<nsIContent> children = do_QueryInterface(aElement);
// if template specifies a subcontainment attribute, get it
// and make sure aElement contains it, otherwise use aElement
nsAutoString attrValue;
if (NS_SUCCEEDED(rv = aTemplate->GetAttribute(kNameSpaceID_XUL,
kSubcontainmentAtom, attrValue)) && (rv == NS_CONTENT_ATTR_HAS_VALUE))
{
nsCOMPtr<nsIAtom> childrenAtom = NS_NewAtom(attrValue);
if (nsnull != childrenAtom)
{
if (NS_SUCCEEDED(rv = EnsureElementHasGenericChild(aElement, kNameSpaceID_XUL,
childrenAtom, getter_AddRefs(children))))
{
}
}
}
rv = PopulateWidgetItemSubtree(aTemplate, aTemplate, children,
aElement, aProperty, aValue, aNaturalOrderPos);
}
else
{
rv = AddWidgetItem(aElement, aProperty, aValue, aNaturalOrderPos);
}
return(rv);
}
NS_IMETHODIMP
RDFGenericBuilderImpl::OnAssert(nsIRDFResource* aSubject,
nsIRDFResource* aPredicate,
@ -630,7 +1089,7 @@ RDFGenericBuilderImpl::OnAssert(nsIRDFResource* aSubject,
contentsGenerated.EqualsIgnoreCase("true")) {
// Okay, it's a "live" element, so go ahead and append the new
// child to this node.
if (NS_FAILED(rv = AddWidgetItem(element, aPredicate, resource, 0))) {
if (NS_FAILED(rv = CreateWidgetItem(element, aPredicate, resource, 0))) {
NS_ERROR("unable to create new widget item");
return rv;
}

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

@ -90,6 +90,26 @@ function OpenURL(event,node)
<xul:treecol id="ShortcutURLColumn" rdf:resource="http://home.netscape.com/NC-rdf#ShortcutURL"/>
<xul:treecol id="LastModColumn" rdf:resource="http://home.netscape.com/WEB-rdf#LastModifiedDate"/>
<xul:template xul:containment="treeitem" xul:subcontainment="treechildren">
<xul:treeitem>
<xul:treecell>
<xul:treeindentation />
<xul:titledbutton>
</xul:titledbutton>
<xul:text rdf:resource="http://home.netscape.com/NC-rdf#Name" />
</xul:treecell>
<xul:treecell>
<xul:text rdf:resource="http://home.netscape.com/NC-rdf#URL" />
</xul:treecell>
<xul:treecell>
<xul:text rdf:resource="http://home.netscape.com/NC-rdf#ShortcutURL" />
</xul:treecell>
<xul:treecell>
<xul:text rdf:resource="http://home.netscape.com/WEB-rdf#LastModifiedDate" />
</xul:treecell>
</xul:treeitem>
</xul:template>
<xul:treehead>
<xul:treeitem>
<xul:treecell resource='http://home.netscape.com/NC-rdf#Name' onclick="return doSort('NameColumn');">