From eb3e56f574f9f22cc2a6c5107744e002801d4807 Mon Sep 17 00:00:00 2001 From: "rjc%netscape.com" Date: Fri, 7 May 1999 21:20:33 +0000 Subject: [PATCH] First cut at adding template and rule support for XUL builders. --- .../templates/src/nsXULTemplateBuilder.cpp | 467 +++++++++++++++++- rdf/content/src/nsRDFGenericBuilder.cpp | 467 +++++++++++++++++- rdf/content/src/nsRDFGenericBuilder.h | 18 + rdf/content/src/nsXULTemplateBuilder.cpp | 467 +++++++++++++++++- rdf/resources/sidebar.xul | 20 + 5 files changed, 1427 insertions(+), 12 deletions(-) diff --git a/content/xul/templates/src/nsXULTemplateBuilder.cpp b/content/xul/templates/src/nsXULTemplateBuilder.cpp index f808e004307..2ebf97ea4d6 100644 --- a/content/xul/templates/src/nsXULTemplateBuilder.cpp +++ b/content/xul/templates/src/nsXULTemplateBuilder.cpp @@ -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 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 isupports; + if (NS_FAILED(rv = arcs->GetNext(getter_AddRefs(isupports)))) break; + + nsCOMPtr property = do_QueryInterface(isupports); + // Ignore properties that are used to indicate "tree-ness" + if (IsContainmentProperty(aNode, property)) + { + markAsContainer = PR_TRUE; + continue; + } + PRInt32 nameSpaceID; + nsCOMPtr tag; + if (NS_FAILED(rv = mDocument->SplitProperty(property, &nameSpaceID, getter_AddRefs(tag)))) + break; + nsCOMPtr value; + if (NS_FAILED(rv = mDB->GetTarget(res, property, PR_TRUE, getter_AddRefs(value)))) + break; + if (rv == NS_RDF_NO_VALUE) + continue; + + nsCOMPtr resource; + nsCOMPtr 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 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 aTemplate; + + *theTemplate = nsnull; + if (NS_FAILED(rv = mRoot->ChildCount(count))) return(rv); + + for (PRInt32 loop=0; loopChildAt(loop, *getter_AddRefs(aTemplate)))) + continue; + PRInt32 nameSpaceID; + if (NS_FAILED(rv = aTemplate->GetNameSpaceID(nameSpaceID))) + continue; + if (nameSpaceID != kNameSpaceID_XUL) + continue; + + nsCOMPtr 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 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 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 containmentAtom = NS_NewAtom(templateContainmentValue); + if (nsnull == containmentAtom) + return(NS_ERROR_OUT_OF_MEMORY); + + for (PRInt32 loop=0; loop aTemplateKid; + if (NS_FAILED(rv = aTemplate->ChildAt(loop, *getter_AddRefs(aTemplateKid)))) + continue; + PRInt32 nameSpaceID; + if (NS_FAILED(rv = aTemplateKid->GetNameSpaceID(nameSpaceID))) + continue; + + nsCOMPtr tag; + if (NS_SUCCEEDED(rv = aTemplateKid->GetTag(*getter_AddRefs(tag)))) + { + nsCOMPtr 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)) + { + // 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 propRes; + if (NS_FAILED(rv = gRDFService->GetResource(prop, getter_AddRefs(propRes)))) + continue; + + nsCOMPtr 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 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 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 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 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; } diff --git a/rdf/content/src/nsRDFGenericBuilder.cpp b/rdf/content/src/nsRDFGenericBuilder.cpp index f808e004307..2ebf97ea4d6 100644 --- a/rdf/content/src/nsRDFGenericBuilder.cpp +++ b/rdf/content/src/nsRDFGenericBuilder.cpp @@ -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 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 isupports; + if (NS_FAILED(rv = arcs->GetNext(getter_AddRefs(isupports)))) break; + + nsCOMPtr property = do_QueryInterface(isupports); + // Ignore properties that are used to indicate "tree-ness" + if (IsContainmentProperty(aNode, property)) + { + markAsContainer = PR_TRUE; + continue; + } + PRInt32 nameSpaceID; + nsCOMPtr tag; + if (NS_FAILED(rv = mDocument->SplitProperty(property, &nameSpaceID, getter_AddRefs(tag)))) + break; + nsCOMPtr value; + if (NS_FAILED(rv = mDB->GetTarget(res, property, PR_TRUE, getter_AddRefs(value)))) + break; + if (rv == NS_RDF_NO_VALUE) + continue; + + nsCOMPtr resource; + nsCOMPtr 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 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 aTemplate; + + *theTemplate = nsnull; + if (NS_FAILED(rv = mRoot->ChildCount(count))) return(rv); + + for (PRInt32 loop=0; loopChildAt(loop, *getter_AddRefs(aTemplate)))) + continue; + PRInt32 nameSpaceID; + if (NS_FAILED(rv = aTemplate->GetNameSpaceID(nameSpaceID))) + continue; + if (nameSpaceID != kNameSpaceID_XUL) + continue; + + nsCOMPtr 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 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 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 containmentAtom = NS_NewAtom(templateContainmentValue); + if (nsnull == containmentAtom) + return(NS_ERROR_OUT_OF_MEMORY); + + for (PRInt32 loop=0; loop aTemplateKid; + if (NS_FAILED(rv = aTemplate->ChildAt(loop, *getter_AddRefs(aTemplateKid)))) + continue; + PRInt32 nameSpaceID; + if (NS_FAILED(rv = aTemplateKid->GetNameSpaceID(nameSpaceID))) + continue; + + nsCOMPtr tag; + if (NS_SUCCEEDED(rv = aTemplateKid->GetTag(*getter_AddRefs(tag)))) + { + nsCOMPtr 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)) + { + // 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 propRes; + if (NS_FAILED(rv = gRDFService->GetResource(prop, getter_AddRefs(propRes)))) + continue; + + nsCOMPtr 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 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 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 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 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; } diff --git a/rdf/content/src/nsRDFGenericBuilder.h b/rdf/content/src/nsRDFGenericBuilder.h index f40f12ef468..15128166b1d 100644 --- a/rdf/content/src/nsRDFGenericBuilder.h +++ b/rdf/content/src/nsRDFGenericBuilder.h @@ -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; diff --git a/rdf/content/src/nsXULTemplateBuilder.cpp b/rdf/content/src/nsXULTemplateBuilder.cpp index f808e004307..2ebf97ea4d6 100644 --- a/rdf/content/src/nsXULTemplateBuilder.cpp +++ b/rdf/content/src/nsXULTemplateBuilder.cpp @@ -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 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 isupports; + if (NS_FAILED(rv = arcs->GetNext(getter_AddRefs(isupports)))) break; + + nsCOMPtr property = do_QueryInterface(isupports); + // Ignore properties that are used to indicate "tree-ness" + if (IsContainmentProperty(aNode, property)) + { + markAsContainer = PR_TRUE; + continue; + } + PRInt32 nameSpaceID; + nsCOMPtr tag; + if (NS_FAILED(rv = mDocument->SplitProperty(property, &nameSpaceID, getter_AddRefs(tag)))) + break; + nsCOMPtr value; + if (NS_FAILED(rv = mDB->GetTarget(res, property, PR_TRUE, getter_AddRefs(value)))) + break; + if (rv == NS_RDF_NO_VALUE) + continue; + + nsCOMPtr resource; + nsCOMPtr 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 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 aTemplate; + + *theTemplate = nsnull; + if (NS_FAILED(rv = mRoot->ChildCount(count))) return(rv); + + for (PRInt32 loop=0; loopChildAt(loop, *getter_AddRefs(aTemplate)))) + continue; + PRInt32 nameSpaceID; + if (NS_FAILED(rv = aTemplate->GetNameSpaceID(nameSpaceID))) + continue; + if (nameSpaceID != kNameSpaceID_XUL) + continue; + + nsCOMPtr 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 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 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 containmentAtom = NS_NewAtom(templateContainmentValue); + if (nsnull == containmentAtom) + return(NS_ERROR_OUT_OF_MEMORY); + + for (PRInt32 loop=0; loop aTemplateKid; + if (NS_FAILED(rv = aTemplate->ChildAt(loop, *getter_AddRefs(aTemplateKid)))) + continue; + PRInt32 nameSpaceID; + if (NS_FAILED(rv = aTemplateKid->GetNameSpaceID(nameSpaceID))) + continue; + + nsCOMPtr tag; + if (NS_SUCCEEDED(rv = aTemplateKid->GetTag(*getter_AddRefs(tag)))) + { + nsCOMPtr 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)) + { + // 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 propRes; + if (NS_FAILED(rv = gRDFService->GetResource(prop, getter_AddRefs(propRes)))) + continue; + + nsCOMPtr 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 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 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 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 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; } diff --git a/rdf/resources/sidebar.xul b/rdf/resources/sidebar.xul index 59b3f5e4208..222db6cb580 100644 --- a/rdf/resources/sidebar.xul +++ b/rdf/resources/sidebar.xul @@ -90,6 +90,26 @@ function OpenURL(event,node) + + + + + + + + + + + + + + + + + + + +