зеркало из https://github.com/mozilla/gecko-dev.git
Bug 12811. Fix frame system notifications s.t. as _few_ as possible get forwarded through to layout. Temporarily remove timer hacks from tree widget.
This commit is contained in:
Родитель
5a7eac87ed
Коммит
c1ca0ebd36
|
@ -802,7 +802,7 @@ public:
|
|||
|
||||
nsresult OpenWidgetItem(nsIContent* aElement);
|
||||
nsresult CloseWidgetItem(nsIContent* aElement);
|
||||
nsresult RemoveAndRebuildGeneratedChildren(nsIContent* aElement);
|
||||
nsresult RebuildWidgetItem(nsIContent* aElement);
|
||||
|
||||
nsresult
|
||||
AddElementToMap(nsIContent* aElement, PRBool aDeep);
|
||||
|
@ -2101,14 +2101,14 @@ XULDocumentImpl::ContentStatesChanged(nsIContent* aContent1, nsIContent* aConten
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
XULDocumentImpl::AttributeChanged(nsIContent* aChild,
|
||||
XULDocumentImpl::AttributeChanged(nsIContent* aElement,
|
||||
nsIAtom* aAttribute,
|
||||
PRInt32 aHint)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
PRInt32 nameSpaceID;
|
||||
rv = aChild->GetNameSpaceID(nameSpaceID);
|
||||
rv = aElement->GetNameSpaceID(nameSpaceID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// First see if we need to update our element map.
|
||||
|
@ -2120,27 +2120,7 @@ XULDocumentImpl::AttributeChanged(nsIContent* aChild,
|
|||
|
||||
// That'll have removed _both_ the 'ref' and 'id' entries from
|
||||
// the map. So add 'em back now.
|
||||
rv = AddElementToMap(aChild, PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle "special" cases.
|
||||
if (nameSpaceID == kNameSpaceID_XUL) {
|
||||
if (aAttribute == kOpenAtom) {
|
||||
nsAutoString open;
|
||||
rv = aChild->GetAttribute(kNameSpaceID_None, kOpenAtom, open);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if ((rv == NS_CONTENT_ATTR_HAS_VALUE) && (open.Equals("true"))) {
|
||||
OpenWidgetItem(aChild);
|
||||
}
|
||||
else {
|
||||
CloseWidgetItem(aChild);
|
||||
}
|
||||
}
|
||||
else if (aAttribute == kRefAtom) {
|
||||
rv = RemoveAndRebuildGeneratedChildren(aChild);
|
||||
rv = AddElementToMap(aElement, PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
|
@ -2148,11 +2128,34 @@ XULDocumentImpl::AttributeChanged(nsIContent* aChild,
|
|||
// Now notify external observers
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); i++) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
|
||||
observer->AttributeChanged(this, aChild, aAttribute, aHint);
|
||||
observer->AttributeChanged(this, aElement, aAttribute, aHint);
|
||||
if (observer != (nsIDocumentObserver*)mObservers.ElementAt(i)) {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle "special" cases. We do this handling _after_ we've
|
||||
// notified the observer to ensure that any frames that are
|
||||
// caching information (e.g., the tree widget and the 'open'
|
||||
// attribute) will notice things properly.
|
||||
if (nameSpaceID == kNameSpaceID_XUL) {
|
||||
if (aAttribute == kOpenAtom) {
|
||||
nsAutoString open;
|
||||
rv = aElement->GetAttribute(kNameSpaceID_None, kOpenAtom, open);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if ((rv == NS_CONTENT_ATTR_HAS_VALUE) && (open.Equals("true"))) {
|
||||
OpenWidgetItem(aElement);
|
||||
}
|
||||
else {
|
||||
CloseWidgetItem(aElement);
|
||||
}
|
||||
}
|
||||
else if (aAttribute == kRefAtom) {
|
||||
RebuildWidgetItem(aElement);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -4483,10 +4486,17 @@ XULDocumentImpl::ReleaseEvent(const nsString& aType)
|
|||
nsresult
|
||||
XULDocumentImpl::OpenWidgetItem(nsIContent* aElement)
|
||||
{
|
||||
NS_PRECONDITION(aElement != nsnull, "null ptr");
|
||||
if (! aElement)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (! mBuilders)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
if (PR_LOG_TEST(gXULLog, PR_LOG_DEBUG)) {
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
rv = aElement->GetTag(*getter_AddRefs(tag));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
@ -4499,12 +4509,39 @@ XULDocumentImpl::OpenWidgetItem(nsIContent* aElement)
|
|||
(const char*) nsCAutoString(tagStr)));
|
||||
}
|
||||
#endif
|
||||
return CreateContents(aElement);
|
||||
|
||||
PRUint32 cnt = 0;
|
||||
rv = mBuilders->Count(&cnt);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Count failed");
|
||||
for (PRUint32 i = 0; i < cnt; ++i) {
|
||||
// XXX we should QueryInterface() here
|
||||
nsIRDFContentModelBuilder* builder
|
||||
= (nsIRDFContentModelBuilder*) mBuilders->ElementAt(i);
|
||||
|
||||
NS_ASSERTION(builder != nsnull, "null ptr");
|
||||
if (! builder)
|
||||
continue;
|
||||
|
||||
rv = builder->OpenContainer(aElement);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "error opening container");
|
||||
// XXX ignore error code?
|
||||
|
||||
NS_RELEASE(builder);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
XULDocumentImpl::CloseWidgetItem(nsIContent* aElement)
|
||||
{
|
||||
NS_PRECONDITION(aElement != nsnull, "null ptr");
|
||||
if (! aElement)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (! mBuilders)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
|
@ -4522,163 +4559,78 @@ XULDocumentImpl::CloseWidgetItem(nsIContent* aElement)
|
|||
}
|
||||
#endif
|
||||
|
||||
// Find the tag that contains the children so that we can remove
|
||||
// all of the children.
|
||||
//
|
||||
// XXX We make a bit of a leap here and assume that the same
|
||||
// template that was used to generate _us_ was used to generate
|
||||
// our _kids_. I'm sure this'll break when we do toolbars or
|
||||
// something.
|
||||
nsAutoString tmplID;
|
||||
rv = aElement->GetAttribute(kNameSpaceID_None, kTemplateAtom, tmplID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
PRUint32 cnt = 0;
|
||||
rv = mBuilders->Count(&cnt);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Count failed");
|
||||
for (PRUint32 i = 0; i < cnt; ++i) {
|
||||
// XXX we should QueryInterface() here
|
||||
nsIRDFContentModelBuilder* builder
|
||||
= (nsIRDFContentModelBuilder*) mBuilders->ElementAt(i);
|
||||
|
||||
if (rv != NS_CONTENT_ATTR_HAS_VALUE)
|
||||
return NS_OK;
|
||||
NS_ASSERTION(builder != nsnull, "null ptr");
|
||||
if (! builder)
|
||||
continue;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> tmplDOMEle;
|
||||
rv = GetElementById(tmplID, getter_AddRefs(tmplDOMEle));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = builder->CloseContainer(aElement);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "error closing container");
|
||||
// XXX ignore error code?
|
||||
|
||||
nsCOMPtr<nsIContent> tmpl = do_QueryInterface(tmplDOMEle);
|
||||
if (! tmpl)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIContent> tmplParent;
|
||||
rv = tmpl->GetParent(*getter_AddRefs(tmplParent));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
NS_ASSERTION(tmplParent != nsnull, "template node has no parent");
|
||||
if (! tmplParent)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIAtom> tmplParentTag;
|
||||
rv = tmplParent->GetTag(*getter_AddRefs(tmplParentTag));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIContent> childcontainer;
|
||||
if ((tmplParentTag.get() == kRuleAtom) || (tmplParentTag.get() == kTemplateAtom)) {
|
||||
childcontainer = dont_QueryInterface(aElement);
|
||||
NS_RELEASE(builder);
|
||||
}
|
||||
else {
|
||||
rv = nsRDFContentUtils::FindChildByTag(aElement,
|
||||
kNameSpaceID_XUL,
|
||||
tmplParentTag,
|
||||
getter_AddRefs(childcontainer));
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (rv == NS_RDF_NO_VALUE) {
|
||||
// No tag; must've already been closed
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
PRInt32 count;
|
||||
rv = childcontainer->ChildCount(count);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get count of the parent's children");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
while (--count >= 0) {
|
||||
nsCOMPtr<nsIContent> child;
|
||||
rv = childcontainer->ChildAt(count, *getter_AddRefs(child));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = childcontainer->RemoveChildAt(count, PR_TRUE);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "error removing child");
|
||||
|
||||
do {
|
||||
// If it's _not_ a XUL element, then we want to blow it and
|
||||
// all of its kids out of the XUL document's
|
||||
// resource-to-element map.
|
||||
nsCOMPtr<nsIRDFResource> resource;
|
||||
rv = nsRDFContentUtils::GetElementResource(child, getter_AddRefs(resource));
|
||||
if (NS_FAILED(rv)) break;
|
||||
|
||||
PRBool isXULElement;
|
||||
rv = mDocumentDataSource->HasAssertion(resource, kRDF_instanceOf, kXUL_element, PR_TRUE, &isXULElement);
|
||||
if (NS_FAILED(rv)) break;
|
||||
|
||||
if (! isXULElement)
|
||||
break;
|
||||
|
||||
rv = child->SetDocument(nsnull, PR_TRUE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
} while (0);
|
||||
}
|
||||
|
||||
// Clear the container-contents-generated attribute so that the next time we
|
||||
// come back, we'll regenerate the kids we just killed.
|
||||
rv = aElement->UnsetAttribute(kNameSpaceID_None,
|
||||
kContainerContentsGeneratedAtom,
|
||||
PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// This is a _total_ hack to make sure that any XUL we blow away
|
||||
// gets rebuilt.
|
||||
rv = childcontainer->UnsetAttribute(kNameSpaceID_None,
|
||||
kXULContentsGeneratedAtom,
|
||||
PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = childcontainer->SetAttribute(kNameSpaceID_None,
|
||||
kLazyContentAtom,
|
||||
"true",
|
||||
PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
XULDocumentImpl::RemoveAndRebuildGeneratedChildren(nsIContent* aElement)
|
||||
XULDocumentImpl::RebuildWidgetItem(nsIContent* aElement)
|
||||
{
|
||||
NS_PRECONDITION(aElement != nsnull, "null ptr");
|
||||
if (! aElement)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (! mBuilders)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
PRInt32 count;
|
||||
rv = aElement->ChildCount(count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
while (--count >= 0) {
|
||||
nsCOMPtr<nsIContent> child;
|
||||
rv = aElement->ChildAt(count, *getter_AddRefs(child));
|
||||
#ifdef PR_LOGGING
|
||||
if (PR_LOG_TEST(gXULLog, PR_LOG_DEBUG)) {
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
rv = aElement->GetTag(*getter_AddRefs(tag));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsAutoString tmplID;
|
||||
rv = child->GetAttribute(kNameSpaceID_None, kTemplateAtom, tmplID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
nsAutoString tagStr;
|
||||
tag->ToString(tagStr);
|
||||
|
||||
if (rv != NS_CONTENT_ATTR_HAS_VALUE)
|
||||
PR_LOG(gXULLog, PR_LOG_DEBUG,
|
||||
("xuldoc close-widget-item %s",
|
||||
(const char*) nsCAutoString(tagStr)));
|
||||
}
|
||||
#endif
|
||||
|
||||
PRUint32 cnt = 0;
|
||||
rv = mBuilders->Count(&cnt);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Count failed");
|
||||
for (PRUint32 i = 0; i < cnt; ++i) {
|
||||
// XXX we should QueryInterface() here
|
||||
nsIRDFContentModelBuilder* builder
|
||||
= (nsIRDFContentModelBuilder*) mBuilders->ElementAt(i);
|
||||
|
||||
NS_ASSERTION(builder != nsnull, "null ptr");
|
||||
if (! builder)
|
||||
continue;
|
||||
|
||||
// It's a generated element. Remove it, and set its document
|
||||
// to null so that it'll get knocked out of the XUL doc's
|
||||
// resource-to-element map.
|
||||
rv = aElement->RemoveChildAt(count, PR_TRUE);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "error removing child");
|
||||
rv = builder->RebuildContainer(aElement);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "error rebuilding container");
|
||||
// XXX ignore error code?
|
||||
|
||||
rv = child->SetDocument(nsnull, PR_TRUE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
NS_RELEASE(builder);
|
||||
}
|
||||
|
||||
// Clear the contents-generated attribute so that the next time we
|
||||
// come back, we'll regenerate the kids we just killed.
|
||||
rv = aElement->UnsetAttribute(kNameSpaceID_None,
|
||||
kTemplateContentsGeneratedAtom,
|
||||
PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = aElement->UnsetAttribute(kNameSpaceID_None,
|
||||
kContainerContentsGeneratedAtom,
|
||||
PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = CreateContents(aElement);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -41,38 +41,36 @@
|
|||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMXULDocument.h"
|
||||
#include "nsIDOMXULElement.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIHTMLContent.h"
|
||||
#include "nsIHTMLElementFactory.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsIRDFContentModelBuilder.h"
|
||||
#include "nsIRDFCompositeDataSource.h"
|
||||
#include "nsIRDFContainerUtils.h"
|
||||
#include "nsIRDFContentModelBuilder.h"
|
||||
#include "nsIRDFDocument.h"
|
||||
#include "nsIRDFNode.h"
|
||||
#include "nsIRDFObserver.h"
|
||||
#include "nsIRDFRemoteDataSource.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsITextContent.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsIXULSortService.h"
|
||||
#include "nsLayoutCID.h"
|
||||
#include "nsRDFCID.h"
|
||||
#include "nsRDFContentUtils.h"
|
||||
#include "nsString.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "prlog.h"
|
||||
#include "rdf.h"
|
||||
#include "rdfutil.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsIDOMXULElement.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsIXULSortService.h"
|
||||
#include "nsIHTMLElementFactory.h"
|
||||
#include "nsIHTMLContent.h"
|
||||
#include "nsRDFGenericBuilder.h"
|
||||
#include "prlog.h"
|
||||
#include "nsIRDFRemoteDataSource.h"
|
||||
|
||||
|
||||
// Return values for EnsureElementHasGenericChild()
|
||||
#define NS_RDF_ELEMENT_WAS_CREATED NS_RDF_NO_VALUE
|
||||
#define NS_RDF_ELEMENT_WAS_THERE NS_OK
|
||||
|
||||
|
@ -107,8 +105,252 @@ static NS_DEFINE_CID(kIHTMLElementFactoryIID, NS_IHTML_ELEMENT_FACTORY_IID);
|
|||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class RDFGenericBuilderImpl : public nsIRDFContentModelBuilder,
|
||||
public nsIRDFObserver
|
||||
{
|
||||
public:
|
||||
RDFGenericBuilderImpl();
|
||||
virtual ~RDFGenericBuilderImpl();
|
||||
|
||||
nsresult Init();
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIRDFContentModelBuilder interface
|
||||
NS_IMETHOD SetDocument(nsIRDFDocument* aDocument);
|
||||
NS_IMETHOD SetDataBase(nsIRDFCompositeDataSource* aDataBase);
|
||||
NS_IMETHOD GetDataBase(nsIRDFCompositeDataSource** aDataBase);
|
||||
NS_IMETHOD CreateRootContent(nsIRDFResource* aResource);
|
||||
NS_IMETHOD SetRootContent(nsIContent* aElement);
|
||||
NS_IMETHOD CreateContents(nsIContent* aElement);
|
||||
NS_IMETHOD OpenContainer(nsIContent* aContainer);
|
||||
NS_IMETHOD CloseContainer(nsIContent* aContainer);
|
||||
NS_IMETHOD RebuildContainer(nsIContent* aContainer);
|
||||
NS_IMETHOD CreateElement(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aTag,
|
||||
nsIRDFResource* aResource,
|
||||
nsIContent** aResult);
|
||||
|
||||
// nsIRDFObserver interface
|
||||
NS_IMETHOD OnAssert(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget);
|
||||
|
||||
NS_IMETHOD OnUnassert(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget);
|
||||
|
||||
NS_IMETHOD OnChange(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aOldTarget,
|
||||
nsIRDFNode* aNewTarget);
|
||||
|
||||
NS_IMETHOD OnMove(nsIRDFResource* aOldSource,
|
||||
nsIRDFResource* aNewSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget);
|
||||
|
||||
// Implementation methods
|
||||
nsresult
|
||||
FindTemplate(nsIContent* aElement,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFResource* aChild,
|
||||
nsIContent **theTemplate);
|
||||
|
||||
nsresult
|
||||
IsTemplateRuleMatch(nsIContent* aElement,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFResource* aChild,
|
||||
nsIContent *aRule,
|
||||
PRBool *isMatch);
|
||||
|
||||
PRBool
|
||||
IsIgnoreableAttribute(PRInt32 aNameSpaceID, nsIAtom* aAtom);
|
||||
|
||||
nsresult
|
||||
GetSubstitutionText(nsIRDFResource* aResource,
|
||||
const nsString& aSubstitution,
|
||||
nsString& aResult);
|
||||
|
||||
nsresult
|
||||
BuildContentFromTemplate(nsIContent *aTemplateNode,
|
||||
nsIContent *aRealNode,
|
||||
PRBool aIsUnique,
|
||||
nsIRDFResource* aChild,
|
||||
PRInt32 aNaturalOrderPos,
|
||||
PRBool aNotify);
|
||||
|
||||
nsresult
|
||||
CreateWidgetItem(nsIContent* aElement,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFResource* aChild,
|
||||
PRInt32 aNaturalOrderPos,
|
||||
PRBool aNotify);
|
||||
|
||||
enum eUpdateAction { eSet, eClear };
|
||||
|
||||
#if 0
|
||||
PRBool
|
||||
IsAttributePersisent(nsIContent *element, PRInt32 aNameSpaceID, nsIAtom* aAtom);
|
||||
|
||||
void
|
||||
GetPersistentAttributes(nsIContent *realKid);
|
||||
|
||||
void
|
||||
PersistAttribute(nsIContent *element,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAtom,
|
||||
nsString aValue,
|
||||
eUpdateAction action);
|
||||
|
||||
void
|
||||
PersistProperty(nsIContent *element,
|
||||
nsIRDFResource *aProperty,
|
||||
nsIRDFNode *aTarget,
|
||||
eUpdateAction action);
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
SynchronizeUsingTemplate(nsIContent *aTemplateNode,
|
||||
nsIContent* aRealNode,
|
||||
eUpdateAction aAction,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aValue);
|
||||
|
||||
nsresult
|
||||
RemoveWidgetItem(nsIContent* aElement,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFResource* aValue,
|
||||
PRBool aNotify);
|
||||
|
||||
nsresult
|
||||
CreateContainerContents(nsIContent* aElement, nsIRDFResource* aResource, PRBool aNotify);
|
||||
|
||||
nsresult
|
||||
CreateTemplateContents(nsIContent* aElement, const nsString& aTemplateID);
|
||||
|
||||
nsresult
|
||||
EnsureElementHasGenericChild(nsIContent* aParent,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aTag,
|
||||
PRBool aNotify,
|
||||
nsIContent** aResult);
|
||||
|
||||
PRBool
|
||||
IsContainmentProperty(nsIContent* aElement, nsIRDFResource* aProperty);
|
||||
|
||||
PRBool
|
||||
IsIgnoredProperty(nsIContent* aElement, nsIRDFResource* aProperty);
|
||||
|
||||
PRBool
|
||||
IsContainer(nsIContent* aParentElement, nsIRDFResource* aTargetResource);
|
||||
|
||||
PRBool
|
||||
IsEmpty(nsIContent* aParentElement, nsIRDFResource* aContainer);
|
||||
|
||||
PRBool
|
||||
IsOpen(nsIContent* aElement);
|
||||
|
||||
PRBool
|
||||
IsElementInWidget(nsIContent* aElement);
|
||||
|
||||
PRBool
|
||||
IsResourceElement(nsIContent* aElement);
|
||||
|
||||
nsresult
|
||||
GetDOMNodeResource(nsIDOMNode* aNode, nsIRDFResource** aResource);
|
||||
|
||||
nsresult
|
||||
GetResource(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aNameAtom,
|
||||
nsIRDFResource** aResource);
|
||||
|
||||
nsresult FindInsertionPoint(nsIContent* aElement, nsIContent** aResult);
|
||||
nsresult RemoveGeneratedContent(nsIContent* aElement);
|
||||
nsresult FindFirstGeneratedChild(nsIContent* aElement, PRInt32* aIndex);
|
||||
|
||||
// XXX. Urg. Hack until layout can batch reflows. See bug 10818.
|
||||
PRBool
|
||||
IsTreeWidgetItem(nsIContent* aElement);
|
||||
|
||||
PRBool
|
||||
IsReflowScheduled();
|
||||
|
||||
nsresult
|
||||
ScheduleReflow();
|
||||
|
||||
static void
|
||||
ForceTreeReflow(nsITimer* aTimer, void* aClosure);
|
||||
|
||||
protected:
|
||||
nsIRDFDocument* mDocument; // [WEAK]
|
||||
|
||||
// We are an observer of the composite datasource. The cycle is
|
||||
// broken by out-of-band SetDataBase(nsnull) call when document is
|
||||
// destroyed.
|
||||
nsCOMPtr<nsIRDFCompositeDataSource> mDB;
|
||||
nsCOMPtr<nsIContent> mRoot;
|
||||
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
|
||||
static nsIRDFDataSource *mLocalstore;
|
||||
static PRBool persistLock;
|
||||
|
||||
// pseudo-constants
|
||||
static nsrefcnt gRefCnt;
|
||||
static nsIRDFService* gRDFService;
|
||||
static nsIRDFContainerUtils* gRDFContainerUtils;
|
||||
static nsINameSpaceManager* gNameSpaceManager;
|
||||
static nsIHTMLElementFactory* gHTMLElementFactory;
|
||||
|
||||
static nsIAtom* kContainerAtom;
|
||||
static nsIAtom* kLazyContentAtom;
|
||||
static nsIAtom* kIsContainerAtom;
|
||||
static nsIAtom* kIsEmptyAtom;
|
||||
static nsIAtom* kXULContentsGeneratedAtom;
|
||||
static nsIAtom* kTemplateContentsGeneratedAtom;
|
||||
static nsIAtom* kContainerContentsGeneratedAtom;
|
||||
static nsIAtom* kNaturalOrderPosAtom;
|
||||
static nsIAtom* kIdAtom;
|
||||
static nsIAtom* kPersistAtom;
|
||||
static nsIAtom* kOpenAtom;
|
||||
static nsIAtom* kEmptyAtom;
|
||||
static nsIAtom* kResourceAtom;
|
||||
static nsIAtom* kURIAtom;
|
||||
static nsIAtom* kContainmentAtom;
|
||||
static nsIAtom* kIgnoreAtom;
|
||||
static nsIAtom* kRefAtom;
|
||||
static nsIAtom* kValueAtom;
|
||||
|
||||
static nsIAtom* kTemplateAtom;
|
||||
static nsIAtom* kRuleAtom;
|
||||
static nsIAtom* kTextAtom;
|
||||
static nsIAtom* kPropertyAtom;
|
||||
static nsIAtom* kInstanceOfAtom;
|
||||
|
||||
static nsIAtom* kTreeAtom;
|
||||
static nsIAtom* kTreeChildrenAtom;
|
||||
static nsIAtom* kTreeItemAtom;
|
||||
|
||||
static PRInt32 kNameSpaceID_RDF;
|
||||
static PRInt32 kNameSpaceID_XUL;
|
||||
|
||||
static nsIRDFResource* kNC_Title;
|
||||
static nsIRDFResource* kNC_child;
|
||||
static nsIRDFResource* kNC_Column;
|
||||
static nsIRDFResource* kNC_Folder;
|
||||
static nsIRDFResource* kRDF_child;
|
||||
static nsIRDFResource* kRDF_instanceOf;
|
||||
static nsIRDFResource* kXUL_element;
|
||||
|
||||
static nsIXULSortService* gXULSortService;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsrefcnt RDFGenericBuilderImpl::gRefCnt = 0;
|
||||
nsIXULSortService* RDFGenericBuilderImpl::XULSortService = nsnull;
|
||||
nsIXULSortService* RDFGenericBuilderImpl::gXULSortService = nsnull;
|
||||
|
||||
nsIAtom* RDFGenericBuilderImpl::kContainerAtom;
|
||||
nsIAtom* RDFGenericBuilderImpl::kLazyContentAtom;
|
||||
|
@ -252,7 +494,7 @@ RDFGenericBuilderImpl::~RDFGenericBuilderImpl(void)
|
|||
|
||||
nsServiceManager::ReleaseService(kRDFServiceCID, gRDFService);
|
||||
nsServiceManager::ReleaseService(kRDFContainerUtilsCID, gRDFContainerUtils);
|
||||
nsServiceManager::ReleaseService(kXULSortServiceCID, XULSortService);
|
||||
nsServiceManager::ReleaseService(kXULSortServiceCID, gXULSortService);
|
||||
NS_RELEASE(gNameSpaceManager);
|
||||
NS_IF_RELEASE(gHTMLElementFactory);
|
||||
}
|
||||
|
@ -351,7 +593,7 @@ RDFGenericBuilderImpl::Init()
|
|||
|
||||
rv = nsServiceManager::GetService(kXULSortServiceCID,
|
||||
kIXULSortServiceIID,
|
||||
(nsISupports**) &XULSortService);
|
||||
(nsISupports**) &gXULSortService);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = nsComponentManager::CreateInstance(kHTMLElementFactoryCID,
|
||||
|
@ -475,19 +717,23 @@ RDFGenericBuilderImpl::SetRootContent(nsIContent* aElement)
|
|||
NS_IMETHODIMP
|
||||
RDFGenericBuilderImpl::CreateContents(nsIContent* aElement)
|
||||
{
|
||||
nsresult rv;
|
||||
NS_PRECONDITION(aElement != nsnull, "null ptr");
|
||||
if (! aElement)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// First, make sure that the element is in the right widget -- ours.
|
||||
if (!IsElementInWidget(aElement))
|
||||
return NS_OK;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIRDFResource> resource;
|
||||
rv = nsRDFContentUtils::GetElementRefResource(aElement, getter_AddRefs(resource));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// The element has a resource; that means that it corresponds
|
||||
// to something in the graph, so we need to go to the graph to
|
||||
// create its contents.
|
||||
rv = CreateContainerContents(aElement, resource);
|
||||
rv = CreateContainerContents(aElement, resource, PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
|
@ -505,6 +751,192 @@ RDFGenericBuilderImpl::CreateContents(nsIContent* aElement)
|
|||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFGenericBuilderImpl::OpenContainer(nsIContent* aElement)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// First, make sure that the element is in the right widget -- ours.
|
||||
if (!IsElementInWidget(aElement))
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIRDFResource> resource;
|
||||
rv = nsRDFContentUtils::GetElementRefResource(aElement, getter_AddRefs(resource));
|
||||
|
||||
// If it has no resource, there's nothing that we need to be
|
||||
// concerned about here.
|
||||
if (NS_FAILED(rv))
|
||||
return NS_OK;
|
||||
|
||||
// The element has a resource; that means that it corresponds
|
||||
// to something in the graph, so we need to go to the graph to
|
||||
// create its contents.
|
||||
rv = CreateContainerContents(aElement, resource, PR_TRUE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (rv == NS_RDF_ELEMENT_WAS_CREATED) {
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
rv = aElement->GetTag(*getter_AddRefs(tag));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (tag.get() == kTreeItemAtom) {
|
||||
nsCOMPtr<nsIContent> insertionpoint;
|
||||
rv = FindInsertionPoint(aElement, getter_AddRefs(insertionpoint));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (! insertionpoint) {
|
||||
// No content got built. Bail!
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Find the first element beneath the insertion point that
|
||||
// is generated from a template.
|
||||
PRInt32 indx;
|
||||
rv = FindFirstGeneratedChild(insertionpoint, &indx);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (indx != -1) {
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(mDocument);
|
||||
if (! doc)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
rv = doc->ContentAppended(insertionpoint, indx);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFGenericBuilderImpl::CloseContainer(nsIContent* aElement)
|
||||
{
|
||||
NS_PRECONDITION(aElement != nsnull, "null ptr");
|
||||
if (! aElement)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// First, make sure that the element is in the right widget -- ours.
|
||||
if (!IsElementInWidget(aElement))
|
||||
return NS_OK;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
rv = aElement->GetTag(*getter_AddRefs(tag));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// If it's not a tree, just bail. Keep the content around until
|
||||
// the cows come home.
|
||||
if (tag.get() != kTreeItemAtom)
|
||||
return NS_OK;
|
||||
|
||||
// Find the tag that contains the children so that we can remove
|
||||
// all of the children.
|
||||
//
|
||||
// XXX We do this as a (premature?) optimization so that nodes
|
||||
// which are not being displayed don't hang around taking up
|
||||
// space. Unfortunately, the tree widget currently _relies_ on
|
||||
// this behavior and will break if we don't do it :-(.
|
||||
nsCOMPtr<nsIContent> insertionpoint;
|
||||
rv = FindInsertionPoint(aElement, getter_AddRefs(insertionpoint));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (insertionpoint) {
|
||||
PRInt32 count;
|
||||
rv = insertionpoint->ChildCount(count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = RemoveGeneratedContent(insertionpoint);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
// Clear the contents-generated attribute so that the next time we
|
||||
// come back, we'll regenerate the kids we just killed.
|
||||
rv = aElement->UnsetAttribute(kNameSpaceID_None,
|
||||
kContainerContentsGeneratedAtom,
|
||||
PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// XXX Hack. Setting this attribute forces the RDF element to
|
||||
// remember that it needs to be re-generated next time around.
|
||||
rv = aElement->SetAttribute(kNameSpaceID_None,
|
||||
kLazyContentAtom,
|
||||
"true",
|
||||
PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFGenericBuilderImpl::RebuildContainer(nsIContent* aElement)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// Remove any generated children from this node
|
||||
rv = RemoveGeneratedContent(aElement);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Clear the contents-generated attribute so that the next time we
|
||||
// come back, we'll regenerate the kids we just killed.
|
||||
rv = aElement->UnsetAttribute(kNameSpaceID_None,
|
||||
kContainerContentsGeneratedAtom,
|
||||
PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// XXX Hack. Setting this attribute forces the RDF element to
|
||||
// remember that it needs to be re-generated next time around.
|
||||
rv = aElement->SetAttribute(kNameSpaceID_None,
|
||||
kLazyContentAtom,
|
||||
"true",
|
||||
PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Since we're changing the 'ref' attribute, we'll need to
|
||||
// rebuild content for _this_ resource template, too.
|
||||
rv = aElement->UnsetAttribute(kNameSpaceID_None,
|
||||
kTemplateContentsGeneratedAtom,
|
||||
PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Do it!!!
|
||||
rv = CreateContents(aElement);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Now see where on earth the content was _really_ appended so we
|
||||
// can tell the frames to go reflow themselves. Start with _this_
|
||||
// element.
|
||||
nsCOMPtr<nsIContent> insertionpoint = dont_QueryInterface(aElement);
|
||||
|
||||
PRInt32 indx;
|
||||
rv = FindFirstGeneratedChild(insertionpoint, &indx);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (indx == -1) {
|
||||
// Okay, nothing got inserted directly beneath this node; see
|
||||
// if the it was inserted somewhere _below_ us...
|
||||
rv = FindInsertionPoint(aElement, getter_AddRefs(insertionpoint));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if ((insertionpoint != nsnull) && (insertionpoint.get() != aElement)) {
|
||||
rv = FindFirstGeneratedChild(insertionpoint, &indx);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
|
||||
if (indx != -1) {
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(mDocument);
|
||||
|
||||
rv = doc->ContentAppended(insertionpoint, indx);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFGenericBuilderImpl::CreateElement(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aTag,
|
||||
|
@ -634,27 +1066,19 @@ RDFGenericBuilderImpl::OnAssert(nsIRDFResource* aSource,
|
|||
|
||||
// Okay, it's a "live" element, so go ahead and append the new
|
||||
// child to this node.
|
||||
|
||||
// XXX Bug 10818.
|
||||
PRBool notify = PR_TRUE;
|
||||
if (IsTreeWidgetItem(element)) {
|
||||
if (!IsReflowScheduled()) {
|
||||
rv = ScheduleReflow();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
else {
|
||||
// a reflow has been scheduled. we'll add the
|
||||
// element but won't notify right now.
|
||||
notify = PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
rv = CreateWidgetItem(element, aProperty, resource, 0, notify);
|
||||
rv = CreateWidgetItem(element, aProperty, resource, 0, PR_TRUE);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create widget item");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = element->SetAttribute(kNameSpaceID_None, kEmptyAtom, "false", PR_TRUE);
|
||||
|
||||
// Update the "empty" attribute
|
||||
nsAutoString empty;
|
||||
rv = element->GetAttribute(kNameSpaceID_None, kEmptyAtom, empty);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if ((rv != NS_CONTENT_ATTR_HAS_VALUE) || (! empty.Equals("false"))) {
|
||||
rv = element->SetAttribute(kNameSpaceID_None, kEmptyAtom, "false", PR_TRUE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Either the target of the assertion is not a resource,
|
||||
|
@ -762,8 +1186,14 @@ RDFGenericBuilderImpl::OnUnassert(nsIRDFResource* aSource,
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (numKids == 0) {
|
||||
rv = element->SetAttribute(kNameSpaceID_None, kEmptyAtom, "true", PR_TRUE);
|
||||
nsAutoString empty;
|
||||
rv = element->GetAttribute(kNameSpaceID_None, kEmptyAtom, empty);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if ((rv != NS_CONTENT_ATTR_HAS_VALUE) && (! empty.Equals("true"))) {
|
||||
rv = element->SetAttribute(kNameSpaceID_None, kEmptyAtom, "true", PR_TRUE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1020,7 +1450,7 @@ RDFGenericBuilderImpl::GetPersistentAttributes(nsIContent *element)
|
|||
literal->GetValueConst(&uniLiteral);
|
||||
if (uniLiteral)
|
||||
{
|
||||
rv = element->SetAttribute(nameSpaceID, tag, uniLiteral, PR_TRUE);
|
||||
rv = element->SetAttribute(nameSpaceID, tag, uniLiteral, PR_FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1430,7 +1860,7 @@ RDFGenericBuilderImpl::BuildContentFromTemplate(nsIContent *aTemplateNode,
|
|||
|
||||
nsCOMPtr<nsIContent> realKid;
|
||||
if (aIsUnique) {
|
||||
rv = EnsureElementHasGenericChild(aRealNode, nameSpaceID, tag, getter_AddRefs(realKid));
|
||||
rv = EnsureElementHasGenericChild(aRealNode, nameSpaceID, tag, aNotify, getter_AddRefs(realKid));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (rv == NS_RDF_ELEMENT_WAS_THERE) {
|
||||
|
@ -1489,7 +1919,7 @@ RDFGenericBuilderImpl::BuildContentFromTemplate(nsIContent *aTemplateNode,
|
|||
rv = content->SetText(text.GetUnicode(), text.Length(), PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = aRealNode->AppendChildTo(nsCOMPtr<nsIContent>( do_QueryInterface(content) ), PR_FALSE);
|
||||
rv = aRealNode->AppendChildTo(nsCOMPtr<nsIContent>( do_QueryInterface(content) ), aNotify);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
|
@ -1564,15 +1994,14 @@ RDFGenericBuilderImpl::BuildContentFromTemplate(nsIContent *aTemplateNode,
|
|||
|
||||
// We'll _already_ have added the unique elements.
|
||||
if (! aIsUnique) {
|
||||
// Note: add into tree, but only sort if its a resource element!
|
||||
if ((nsnull != XULSortService) && (isResourceElement)) {
|
||||
rv = XULSortService->InsertContainerNode(aRealNode, realKid, aNotify);
|
||||
if (NS_FAILED(rv)) {
|
||||
aRealNode->AppendChildTo(realKid, aNotify);
|
||||
}
|
||||
// Add into content model, special casing treeitems.
|
||||
if ((nsnull != gXULSortService) && (isResourceElement) && (tag.get() == kTreeItemAtom)) {
|
||||
rv = gXULSortService->InsertContainerNode(aRealNode, realKid, aNotify);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to insert element via sort service");
|
||||
}
|
||||
else {
|
||||
aRealNode->AppendChildTo(realKid, aNotify);
|
||||
rv = aRealNode->AppendChildTo(realKid, aNotify);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to insert element");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1605,12 +2034,8 @@ RDFGenericBuilderImpl::CreateWidgetItem(nsIContent *aElement,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
rv = BuildContentFromTemplate(tmpl,
|
||||
aElement,
|
||||
PR_TRUE,
|
||||
aChild,
|
||||
aNaturalOrderPos,
|
||||
aNotify);
|
||||
rv = BuildContentFromTemplate(tmpl, aElement, PR_TRUE, aChild, aNaturalOrderPos, aNotify);
|
||||
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to build content from template");
|
||||
return rv;
|
||||
}
|
||||
|
@ -1777,7 +2202,7 @@ RDFGenericBuilderImpl::RemoveWidgetItem(nsIContent* aElement,
|
|||
|
||||
|
||||
nsresult
|
||||
RDFGenericBuilderImpl::CreateContainerContents(nsIContent* aElement, nsIRDFResource* aResource)
|
||||
RDFGenericBuilderImpl::CreateContainerContents(nsIContent* aElement, nsIRDFResource* aResource, PRBool aNotify)
|
||||
{
|
||||
// Create the contents of a container by iterating over all of the
|
||||
// "containment" arcs out of the element's resource.
|
||||
|
@ -1801,7 +2226,7 @@ RDFGenericBuilderImpl::CreateContainerContents(nsIContent* aElement, nsIRDFResou
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if ((rv == NS_CONTENT_ATTR_HAS_VALUE) && (attrValue.EqualsIgnoreCase("true")))
|
||||
return NS_OK;
|
||||
return NS_RDF_ELEMENT_WAS_CREATED;
|
||||
|
||||
// Now mark the element's contents as being generated so that
|
||||
// any re-entrant calls don't trigger an infinite recursion.
|
||||
|
@ -1821,11 +2246,6 @@ RDFGenericBuilderImpl::CreateContainerContents(nsIContent* aElement, nsIRDFResou
|
|||
rv = mDB->ArcLabelsOut(aResource, getter_AddRefs(properties));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// rjc - sort
|
||||
nsCOMPtr<nsISupportsArray> tempArray;
|
||||
rv = NS_NewISupportsArray(getter_AddRefs(tempArray));
|
||||
if NS_FAILED(rv) return rv;
|
||||
|
||||
while (1) {
|
||||
PRBool hasMore;
|
||||
rv = properties->HasMoreElements(&hasMore);
|
||||
|
@ -1865,74 +2285,13 @@ RDFGenericBuilderImpl::CreateContainerContents(nsIContent* aElement, nsIRDFResou
|
|||
rv = targets->GetNext(getter_AddRefs(isupportsNext));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIRDFResource> valueResource = do_QueryInterface(isupportsNext);
|
||||
NS_ASSERTION(valueResource != nsnull, "not a resource");
|
||||
if (! valueResource)
|
||||
nsCOMPtr<nsIRDFResource> target = do_QueryInterface(isupportsNext);
|
||||
NS_ASSERTION(target != nsnull, "not a resource");
|
||||
if (! target)
|
||||
continue;
|
||||
|
||||
// XXX hack: always append value resource 1st due to sort
|
||||
// callback implementation
|
||||
tempArray->AppendElement(valueResource);
|
||||
tempArray->AppendElement(property);
|
||||
}
|
||||
}
|
||||
|
||||
PRUint32 numElements;
|
||||
rv = tempArray->Count(&numElements);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (numElements == 0)
|
||||
return NS_OK;
|
||||
|
||||
// Tree widget hackery. To be removed if and when the
|
||||
// reflow lock is exposed. See bug 10818.
|
||||
PRBool istree = IsTreeWidgetItem(aElement);
|
||||
|
||||
{
|
||||
// XXX change to use nsVoidArray?
|
||||
nsIRDFResource** flatArray = new nsIRDFResource*[numElements];
|
||||
if (! flatArray) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// flatten array of resources, sort them, then add as item elements
|
||||
PRUint32 loop;
|
||||
for (loop=0; loop<numElements; loop++)
|
||||
flatArray[loop] = (nsIRDFResource *)tempArray->ElementAt(loop);
|
||||
|
||||
if (XULSortService) {
|
||||
XULSortService->OpenContainer(mDB, aElement, flatArray, numElements/2, 2*sizeof(nsIRDFResource *));
|
||||
}
|
||||
|
||||
// This will insert all of the elements into the
|
||||
// container, but _won't_ bother layout about it.
|
||||
for (loop=0; loop<numElements; loop+=2) {
|
||||
rv = CreateWidgetItem(aElement, flatArray[loop+1], flatArray[loop], loop+1, PR_FALSE);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create widget item");
|
||||
if (NS_FAILED(rv)) break;
|
||||
}
|
||||
|
||||
for (PRInt32 i = PRInt32(numElements) - 1; i >=0; i--) {
|
||||
NS_IF_RELEASE(flatArray[i]);
|
||||
}
|
||||
|
||||
delete [] flatArray;
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
if (istree) {
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(mDocument);
|
||||
if (! doc)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIContent> treechildren;
|
||||
rv = nsRDFContentUtils::FindChildByTag(aElement,
|
||||
kNameSpaceID_XUL,
|
||||
kTreeChildrenAtom,
|
||||
getter_AddRefs(treechildren));
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// _Now_ tell layout that we've mucked with the container. This'll
|
||||
// force a reflow and get the content displayed.
|
||||
rv = doc->ContentAppended(treechildren, 0);
|
||||
rv = CreateWidgetItem(aElement, property, target, -1, aNotify);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create item");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
|
@ -2000,7 +2359,7 @@ RDFGenericBuilderImpl::CreateTemplateContents(nsIContent* aElement, const nsStri
|
|||
element = parent;
|
||||
}
|
||||
|
||||
rv = BuildContentFromTemplate(tmpl, aElement, PR_FALSE, resource, -1, PR_TRUE);
|
||||
rv = BuildContentFromTemplate(tmpl, aElement, PR_FALSE, resource, -1, PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
|
@ -2010,6 +2369,7 @@ nsresult
|
|||
RDFGenericBuilderImpl::EnsureElementHasGenericChild(nsIContent* parent,
|
||||
PRInt32 nameSpaceID,
|
||||
nsIAtom* tag,
|
||||
PRBool aNotify,
|
||||
nsIContent** result)
|
||||
{
|
||||
nsresult rv;
|
||||
|
@ -2026,7 +2386,7 @@ RDFGenericBuilderImpl::EnsureElementHasGenericChild(nsIContent* parent,
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// XXX Note that the notification ensures we won't batch insertions! This could be bad! - Dave
|
||||
rv = parent->AppendChildTo(element, PR_TRUE);
|
||||
rv = parent->AppendChildTo(element, aNotify);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
*result = element;
|
||||
|
@ -2381,6 +2741,109 @@ RDFGenericBuilderImpl::GetResource(PRInt32 aNameSpaceID,
|
|||
}
|
||||
|
||||
|
||||
nsresult
|
||||
RDFGenericBuilderImpl::FindInsertionPoint(nsIContent* aElement, nsIContent** aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// XXX Hack-o-rama. This needs to be fixed to actually grovel over
|
||||
// the template n' stuff.
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
rv = aElement->GetTag(*getter_AddRefs(tag));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsAutoString tagName;
|
||||
rv = tag->ToString(tagName);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (tagName.Equals("tree") || tagName.Equals("treeitem")) {
|
||||
rv = nsRDFContentUtils::FindChildByTag(aElement, kNameSpaceID_XUL, NS_NewAtom("treechildren"), aResult);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
else if (tagName.Equals("menu")) {
|
||||
rv = nsRDFContentUtils::FindChildByTag(aElement, kNameSpaceID_XUL, NS_NewAtom("menupopup"), aResult);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
else {
|
||||
*aResult = aElement;
|
||||
NS_ADDREF(*aResult);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
RDFGenericBuilderImpl::RemoveGeneratedContent(nsIContent* aElement)
|
||||
{
|
||||
// Remove all the content beneath aElement that has been generated
|
||||
// from a template.
|
||||
|
||||
nsresult rv;
|
||||
|
||||
PRInt32 count;
|
||||
rv = aElement->ChildCount(count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
while (--count >= 0) {
|
||||
nsCOMPtr<nsIContent> child;
|
||||
rv = aElement->ChildAt(count, *getter_AddRefs(child));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsAutoString tmplID;
|
||||
rv = child->GetAttribute(kNameSpaceID_None, kTemplateAtom, tmplID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (rv != NS_CONTENT_ATTR_HAS_VALUE)
|
||||
continue;
|
||||
|
||||
// It's a generated element. Remove it, and set its document
|
||||
// to null so that it'll get knocked out of the XUL doc's
|
||||
// resource-to-element map.
|
||||
rv = aElement->RemoveChildAt(count, PR_TRUE);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "error removing child");
|
||||
|
||||
rv = child->SetDocument(nsnull, PR_TRUE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
RDFGenericBuilderImpl::FindFirstGeneratedChild(nsIContent* aElement, PRInt32* aIndex)
|
||||
{
|
||||
// Find the first kid of aElement that has been generated from a
|
||||
// template.
|
||||
|
||||
nsresult rv;
|
||||
|
||||
PRInt32 count;
|
||||
rv = aElement->ChildCount(count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRInt32 i = 0;
|
||||
while (i < count) {
|
||||
nsCOMPtr<nsIContent> child;
|
||||
rv = aElement->ChildAt(i, *getter_AddRefs(child));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsAutoString tmplID;
|
||||
rv = child->GetAttribute(kNameSpaceID_None, kTemplateAtom, tmplID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (rv == NS_CONTENT_ATTR_HAS_VALUE)
|
||||
break;
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
*aIndex = (i < count) ? i : -1;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
RDFGenericBuilderImpl::IsTreeWidgetItem(nsIContent* aElement)
|
||||
{
|
||||
|
|
|
@ -67,6 +67,23 @@ public:
|
|||
*/
|
||||
NS_IMETHOD CreateContents(nsIContent* aElement) = 0;
|
||||
|
||||
/**
|
||||
* 'Open' a container element that was closed before. This gives
|
||||
* the container a chance to populate its contents.
|
||||
*/
|
||||
NS_IMETHOD OpenContainer(nsIContent* aContainer) = 0;
|
||||
|
||||
/**
|
||||
* 'Close' an open container. This gives the container a chance to
|
||||
* release unused content nodes.
|
||||
*/
|
||||
NS_IMETHOD CloseContainer(nsIContent* aContainer) = 0;
|
||||
|
||||
/**
|
||||
* Rebuild the contents of a container.
|
||||
*/
|
||||
NS_IMETHOD RebuildContainer(nsIContent* aContainer) = 0;
|
||||
|
||||
/**
|
||||
* Construct an element. This is exposed as a public method,
|
||||
* because the document implementation may need to call it to
|
||||
|
@ -76,6 +93,7 @@ public:
|
|||
nsIAtom* aTag,
|
||||
nsIRDFResource* aResource,
|
||||
nsIContent** aResult) = 0;
|
||||
|
||||
};
|
||||
|
||||
extern nsresult NS_NewXULTemplateBuilder(nsIRDFContentModelBuilder** aResult);
|
||||
|
|
|
@ -93,7 +93,7 @@ nsRDFContentUtils::AttachTextNode(nsIContent* parent, nsIRDFNode* value)
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// hook it up to the child
|
||||
rv = parent->AppendChildTo(nsCOMPtr<nsIContent>( do_QueryInterface(text) ), PR_TRUE);
|
||||
rv = parent->AppendChildTo(nsCOMPtr<nsIContent>( do_QueryInterface(text) ), PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -41,38 +41,36 @@
|
|||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMXULDocument.h"
|
||||
#include "nsIDOMXULElement.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIHTMLContent.h"
|
||||
#include "nsIHTMLElementFactory.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsIRDFContentModelBuilder.h"
|
||||
#include "nsIRDFCompositeDataSource.h"
|
||||
#include "nsIRDFContainerUtils.h"
|
||||
#include "nsIRDFContentModelBuilder.h"
|
||||
#include "nsIRDFDocument.h"
|
||||
#include "nsIRDFNode.h"
|
||||
#include "nsIRDFObserver.h"
|
||||
#include "nsIRDFRemoteDataSource.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsITextContent.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsIXULSortService.h"
|
||||
#include "nsLayoutCID.h"
|
||||
#include "nsRDFCID.h"
|
||||
#include "nsRDFContentUtils.h"
|
||||
#include "nsString.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "prlog.h"
|
||||
#include "rdf.h"
|
||||
#include "rdfutil.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsIDOMXULElement.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsIXULSortService.h"
|
||||
#include "nsIHTMLElementFactory.h"
|
||||
#include "nsIHTMLContent.h"
|
||||
#include "nsRDFGenericBuilder.h"
|
||||
#include "prlog.h"
|
||||
#include "nsIRDFRemoteDataSource.h"
|
||||
|
||||
|
||||
// Return values for EnsureElementHasGenericChild()
|
||||
#define NS_RDF_ELEMENT_WAS_CREATED NS_RDF_NO_VALUE
|
||||
#define NS_RDF_ELEMENT_WAS_THERE NS_OK
|
||||
|
||||
|
@ -107,8 +105,252 @@ static NS_DEFINE_CID(kIHTMLElementFactoryIID, NS_IHTML_ELEMENT_FACTORY_IID);
|
|||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class RDFGenericBuilderImpl : public nsIRDFContentModelBuilder,
|
||||
public nsIRDFObserver
|
||||
{
|
||||
public:
|
||||
RDFGenericBuilderImpl();
|
||||
virtual ~RDFGenericBuilderImpl();
|
||||
|
||||
nsresult Init();
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIRDFContentModelBuilder interface
|
||||
NS_IMETHOD SetDocument(nsIRDFDocument* aDocument);
|
||||
NS_IMETHOD SetDataBase(nsIRDFCompositeDataSource* aDataBase);
|
||||
NS_IMETHOD GetDataBase(nsIRDFCompositeDataSource** aDataBase);
|
||||
NS_IMETHOD CreateRootContent(nsIRDFResource* aResource);
|
||||
NS_IMETHOD SetRootContent(nsIContent* aElement);
|
||||
NS_IMETHOD CreateContents(nsIContent* aElement);
|
||||
NS_IMETHOD OpenContainer(nsIContent* aContainer);
|
||||
NS_IMETHOD CloseContainer(nsIContent* aContainer);
|
||||
NS_IMETHOD RebuildContainer(nsIContent* aContainer);
|
||||
NS_IMETHOD CreateElement(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aTag,
|
||||
nsIRDFResource* aResource,
|
||||
nsIContent** aResult);
|
||||
|
||||
// nsIRDFObserver interface
|
||||
NS_IMETHOD OnAssert(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget);
|
||||
|
||||
NS_IMETHOD OnUnassert(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget);
|
||||
|
||||
NS_IMETHOD OnChange(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aOldTarget,
|
||||
nsIRDFNode* aNewTarget);
|
||||
|
||||
NS_IMETHOD OnMove(nsIRDFResource* aOldSource,
|
||||
nsIRDFResource* aNewSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget);
|
||||
|
||||
// Implementation methods
|
||||
nsresult
|
||||
FindTemplate(nsIContent* aElement,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFResource* aChild,
|
||||
nsIContent **theTemplate);
|
||||
|
||||
nsresult
|
||||
IsTemplateRuleMatch(nsIContent* aElement,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFResource* aChild,
|
||||
nsIContent *aRule,
|
||||
PRBool *isMatch);
|
||||
|
||||
PRBool
|
||||
IsIgnoreableAttribute(PRInt32 aNameSpaceID, nsIAtom* aAtom);
|
||||
|
||||
nsresult
|
||||
GetSubstitutionText(nsIRDFResource* aResource,
|
||||
const nsString& aSubstitution,
|
||||
nsString& aResult);
|
||||
|
||||
nsresult
|
||||
BuildContentFromTemplate(nsIContent *aTemplateNode,
|
||||
nsIContent *aRealNode,
|
||||
PRBool aIsUnique,
|
||||
nsIRDFResource* aChild,
|
||||
PRInt32 aNaturalOrderPos,
|
||||
PRBool aNotify);
|
||||
|
||||
nsresult
|
||||
CreateWidgetItem(nsIContent* aElement,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFResource* aChild,
|
||||
PRInt32 aNaturalOrderPos,
|
||||
PRBool aNotify);
|
||||
|
||||
enum eUpdateAction { eSet, eClear };
|
||||
|
||||
#if 0
|
||||
PRBool
|
||||
IsAttributePersisent(nsIContent *element, PRInt32 aNameSpaceID, nsIAtom* aAtom);
|
||||
|
||||
void
|
||||
GetPersistentAttributes(nsIContent *realKid);
|
||||
|
||||
void
|
||||
PersistAttribute(nsIContent *element,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAtom,
|
||||
nsString aValue,
|
||||
eUpdateAction action);
|
||||
|
||||
void
|
||||
PersistProperty(nsIContent *element,
|
||||
nsIRDFResource *aProperty,
|
||||
nsIRDFNode *aTarget,
|
||||
eUpdateAction action);
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
SynchronizeUsingTemplate(nsIContent *aTemplateNode,
|
||||
nsIContent* aRealNode,
|
||||
eUpdateAction aAction,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aValue);
|
||||
|
||||
nsresult
|
||||
RemoveWidgetItem(nsIContent* aElement,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFResource* aValue,
|
||||
PRBool aNotify);
|
||||
|
||||
nsresult
|
||||
CreateContainerContents(nsIContent* aElement, nsIRDFResource* aResource, PRBool aNotify);
|
||||
|
||||
nsresult
|
||||
CreateTemplateContents(nsIContent* aElement, const nsString& aTemplateID);
|
||||
|
||||
nsresult
|
||||
EnsureElementHasGenericChild(nsIContent* aParent,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aTag,
|
||||
PRBool aNotify,
|
||||
nsIContent** aResult);
|
||||
|
||||
PRBool
|
||||
IsContainmentProperty(nsIContent* aElement, nsIRDFResource* aProperty);
|
||||
|
||||
PRBool
|
||||
IsIgnoredProperty(nsIContent* aElement, nsIRDFResource* aProperty);
|
||||
|
||||
PRBool
|
||||
IsContainer(nsIContent* aParentElement, nsIRDFResource* aTargetResource);
|
||||
|
||||
PRBool
|
||||
IsEmpty(nsIContent* aParentElement, nsIRDFResource* aContainer);
|
||||
|
||||
PRBool
|
||||
IsOpen(nsIContent* aElement);
|
||||
|
||||
PRBool
|
||||
IsElementInWidget(nsIContent* aElement);
|
||||
|
||||
PRBool
|
||||
IsResourceElement(nsIContent* aElement);
|
||||
|
||||
nsresult
|
||||
GetDOMNodeResource(nsIDOMNode* aNode, nsIRDFResource** aResource);
|
||||
|
||||
nsresult
|
||||
GetResource(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aNameAtom,
|
||||
nsIRDFResource** aResource);
|
||||
|
||||
nsresult FindInsertionPoint(nsIContent* aElement, nsIContent** aResult);
|
||||
nsresult RemoveGeneratedContent(nsIContent* aElement);
|
||||
nsresult FindFirstGeneratedChild(nsIContent* aElement, PRInt32* aIndex);
|
||||
|
||||
// XXX. Urg. Hack until layout can batch reflows. See bug 10818.
|
||||
PRBool
|
||||
IsTreeWidgetItem(nsIContent* aElement);
|
||||
|
||||
PRBool
|
||||
IsReflowScheduled();
|
||||
|
||||
nsresult
|
||||
ScheduleReflow();
|
||||
|
||||
static void
|
||||
ForceTreeReflow(nsITimer* aTimer, void* aClosure);
|
||||
|
||||
protected:
|
||||
nsIRDFDocument* mDocument; // [WEAK]
|
||||
|
||||
// We are an observer of the composite datasource. The cycle is
|
||||
// broken by out-of-band SetDataBase(nsnull) call when document is
|
||||
// destroyed.
|
||||
nsCOMPtr<nsIRDFCompositeDataSource> mDB;
|
||||
nsCOMPtr<nsIContent> mRoot;
|
||||
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
|
||||
static nsIRDFDataSource *mLocalstore;
|
||||
static PRBool persistLock;
|
||||
|
||||
// pseudo-constants
|
||||
static nsrefcnt gRefCnt;
|
||||
static nsIRDFService* gRDFService;
|
||||
static nsIRDFContainerUtils* gRDFContainerUtils;
|
||||
static nsINameSpaceManager* gNameSpaceManager;
|
||||
static nsIHTMLElementFactory* gHTMLElementFactory;
|
||||
|
||||
static nsIAtom* kContainerAtom;
|
||||
static nsIAtom* kLazyContentAtom;
|
||||
static nsIAtom* kIsContainerAtom;
|
||||
static nsIAtom* kIsEmptyAtom;
|
||||
static nsIAtom* kXULContentsGeneratedAtom;
|
||||
static nsIAtom* kTemplateContentsGeneratedAtom;
|
||||
static nsIAtom* kContainerContentsGeneratedAtom;
|
||||
static nsIAtom* kNaturalOrderPosAtom;
|
||||
static nsIAtom* kIdAtom;
|
||||
static nsIAtom* kPersistAtom;
|
||||
static nsIAtom* kOpenAtom;
|
||||
static nsIAtom* kEmptyAtom;
|
||||
static nsIAtom* kResourceAtom;
|
||||
static nsIAtom* kURIAtom;
|
||||
static nsIAtom* kContainmentAtom;
|
||||
static nsIAtom* kIgnoreAtom;
|
||||
static nsIAtom* kRefAtom;
|
||||
static nsIAtom* kValueAtom;
|
||||
|
||||
static nsIAtom* kTemplateAtom;
|
||||
static nsIAtom* kRuleAtom;
|
||||
static nsIAtom* kTextAtom;
|
||||
static nsIAtom* kPropertyAtom;
|
||||
static nsIAtom* kInstanceOfAtom;
|
||||
|
||||
static nsIAtom* kTreeAtom;
|
||||
static nsIAtom* kTreeChildrenAtom;
|
||||
static nsIAtom* kTreeItemAtom;
|
||||
|
||||
static PRInt32 kNameSpaceID_RDF;
|
||||
static PRInt32 kNameSpaceID_XUL;
|
||||
|
||||
static nsIRDFResource* kNC_Title;
|
||||
static nsIRDFResource* kNC_child;
|
||||
static nsIRDFResource* kNC_Column;
|
||||
static nsIRDFResource* kNC_Folder;
|
||||
static nsIRDFResource* kRDF_child;
|
||||
static nsIRDFResource* kRDF_instanceOf;
|
||||
static nsIRDFResource* kXUL_element;
|
||||
|
||||
static nsIXULSortService* gXULSortService;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsrefcnt RDFGenericBuilderImpl::gRefCnt = 0;
|
||||
nsIXULSortService* RDFGenericBuilderImpl::XULSortService = nsnull;
|
||||
nsIXULSortService* RDFGenericBuilderImpl::gXULSortService = nsnull;
|
||||
|
||||
nsIAtom* RDFGenericBuilderImpl::kContainerAtom;
|
||||
nsIAtom* RDFGenericBuilderImpl::kLazyContentAtom;
|
||||
|
@ -252,7 +494,7 @@ RDFGenericBuilderImpl::~RDFGenericBuilderImpl(void)
|
|||
|
||||
nsServiceManager::ReleaseService(kRDFServiceCID, gRDFService);
|
||||
nsServiceManager::ReleaseService(kRDFContainerUtilsCID, gRDFContainerUtils);
|
||||
nsServiceManager::ReleaseService(kXULSortServiceCID, XULSortService);
|
||||
nsServiceManager::ReleaseService(kXULSortServiceCID, gXULSortService);
|
||||
NS_RELEASE(gNameSpaceManager);
|
||||
NS_IF_RELEASE(gHTMLElementFactory);
|
||||
}
|
||||
|
@ -351,7 +593,7 @@ RDFGenericBuilderImpl::Init()
|
|||
|
||||
rv = nsServiceManager::GetService(kXULSortServiceCID,
|
||||
kIXULSortServiceIID,
|
||||
(nsISupports**) &XULSortService);
|
||||
(nsISupports**) &gXULSortService);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = nsComponentManager::CreateInstance(kHTMLElementFactoryCID,
|
||||
|
@ -475,19 +717,23 @@ RDFGenericBuilderImpl::SetRootContent(nsIContent* aElement)
|
|||
NS_IMETHODIMP
|
||||
RDFGenericBuilderImpl::CreateContents(nsIContent* aElement)
|
||||
{
|
||||
nsresult rv;
|
||||
NS_PRECONDITION(aElement != nsnull, "null ptr");
|
||||
if (! aElement)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// First, make sure that the element is in the right widget -- ours.
|
||||
if (!IsElementInWidget(aElement))
|
||||
return NS_OK;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIRDFResource> resource;
|
||||
rv = nsRDFContentUtils::GetElementRefResource(aElement, getter_AddRefs(resource));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// The element has a resource; that means that it corresponds
|
||||
// to something in the graph, so we need to go to the graph to
|
||||
// create its contents.
|
||||
rv = CreateContainerContents(aElement, resource);
|
||||
rv = CreateContainerContents(aElement, resource, PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
|
@ -505,6 +751,192 @@ RDFGenericBuilderImpl::CreateContents(nsIContent* aElement)
|
|||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFGenericBuilderImpl::OpenContainer(nsIContent* aElement)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// First, make sure that the element is in the right widget -- ours.
|
||||
if (!IsElementInWidget(aElement))
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIRDFResource> resource;
|
||||
rv = nsRDFContentUtils::GetElementRefResource(aElement, getter_AddRefs(resource));
|
||||
|
||||
// If it has no resource, there's nothing that we need to be
|
||||
// concerned about here.
|
||||
if (NS_FAILED(rv))
|
||||
return NS_OK;
|
||||
|
||||
// The element has a resource; that means that it corresponds
|
||||
// to something in the graph, so we need to go to the graph to
|
||||
// create its contents.
|
||||
rv = CreateContainerContents(aElement, resource, PR_TRUE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (rv == NS_RDF_ELEMENT_WAS_CREATED) {
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
rv = aElement->GetTag(*getter_AddRefs(tag));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (tag.get() == kTreeItemAtom) {
|
||||
nsCOMPtr<nsIContent> insertionpoint;
|
||||
rv = FindInsertionPoint(aElement, getter_AddRefs(insertionpoint));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (! insertionpoint) {
|
||||
// No content got built. Bail!
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Find the first element beneath the insertion point that
|
||||
// is generated from a template.
|
||||
PRInt32 indx;
|
||||
rv = FindFirstGeneratedChild(insertionpoint, &indx);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (indx != -1) {
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(mDocument);
|
||||
if (! doc)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
rv = doc->ContentAppended(insertionpoint, indx);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFGenericBuilderImpl::CloseContainer(nsIContent* aElement)
|
||||
{
|
||||
NS_PRECONDITION(aElement != nsnull, "null ptr");
|
||||
if (! aElement)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// First, make sure that the element is in the right widget -- ours.
|
||||
if (!IsElementInWidget(aElement))
|
||||
return NS_OK;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
rv = aElement->GetTag(*getter_AddRefs(tag));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// If it's not a tree, just bail. Keep the content around until
|
||||
// the cows come home.
|
||||
if (tag.get() != kTreeItemAtom)
|
||||
return NS_OK;
|
||||
|
||||
// Find the tag that contains the children so that we can remove
|
||||
// all of the children.
|
||||
//
|
||||
// XXX We do this as a (premature?) optimization so that nodes
|
||||
// which are not being displayed don't hang around taking up
|
||||
// space. Unfortunately, the tree widget currently _relies_ on
|
||||
// this behavior and will break if we don't do it :-(.
|
||||
nsCOMPtr<nsIContent> insertionpoint;
|
||||
rv = FindInsertionPoint(aElement, getter_AddRefs(insertionpoint));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (insertionpoint) {
|
||||
PRInt32 count;
|
||||
rv = insertionpoint->ChildCount(count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = RemoveGeneratedContent(insertionpoint);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
// Clear the contents-generated attribute so that the next time we
|
||||
// come back, we'll regenerate the kids we just killed.
|
||||
rv = aElement->UnsetAttribute(kNameSpaceID_None,
|
||||
kContainerContentsGeneratedAtom,
|
||||
PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// XXX Hack. Setting this attribute forces the RDF element to
|
||||
// remember that it needs to be re-generated next time around.
|
||||
rv = aElement->SetAttribute(kNameSpaceID_None,
|
||||
kLazyContentAtom,
|
||||
"true",
|
||||
PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFGenericBuilderImpl::RebuildContainer(nsIContent* aElement)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// Remove any generated children from this node
|
||||
rv = RemoveGeneratedContent(aElement);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Clear the contents-generated attribute so that the next time we
|
||||
// come back, we'll regenerate the kids we just killed.
|
||||
rv = aElement->UnsetAttribute(kNameSpaceID_None,
|
||||
kContainerContentsGeneratedAtom,
|
||||
PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// XXX Hack. Setting this attribute forces the RDF element to
|
||||
// remember that it needs to be re-generated next time around.
|
||||
rv = aElement->SetAttribute(kNameSpaceID_None,
|
||||
kLazyContentAtom,
|
||||
"true",
|
||||
PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Since we're changing the 'ref' attribute, we'll need to
|
||||
// rebuild content for _this_ resource template, too.
|
||||
rv = aElement->UnsetAttribute(kNameSpaceID_None,
|
||||
kTemplateContentsGeneratedAtom,
|
||||
PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Do it!!!
|
||||
rv = CreateContents(aElement);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Now see where on earth the content was _really_ appended so we
|
||||
// can tell the frames to go reflow themselves. Start with _this_
|
||||
// element.
|
||||
nsCOMPtr<nsIContent> insertionpoint = dont_QueryInterface(aElement);
|
||||
|
||||
PRInt32 indx;
|
||||
rv = FindFirstGeneratedChild(insertionpoint, &indx);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (indx == -1) {
|
||||
// Okay, nothing got inserted directly beneath this node; see
|
||||
// if the it was inserted somewhere _below_ us...
|
||||
rv = FindInsertionPoint(aElement, getter_AddRefs(insertionpoint));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if ((insertionpoint != nsnull) && (insertionpoint.get() != aElement)) {
|
||||
rv = FindFirstGeneratedChild(insertionpoint, &indx);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
|
||||
if (indx != -1) {
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(mDocument);
|
||||
|
||||
rv = doc->ContentAppended(insertionpoint, indx);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFGenericBuilderImpl::CreateElement(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aTag,
|
||||
|
@ -634,27 +1066,19 @@ RDFGenericBuilderImpl::OnAssert(nsIRDFResource* aSource,
|
|||
|
||||
// Okay, it's a "live" element, so go ahead and append the new
|
||||
// child to this node.
|
||||
|
||||
// XXX Bug 10818.
|
||||
PRBool notify = PR_TRUE;
|
||||
if (IsTreeWidgetItem(element)) {
|
||||
if (!IsReflowScheduled()) {
|
||||
rv = ScheduleReflow();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
else {
|
||||
// a reflow has been scheduled. we'll add the
|
||||
// element but won't notify right now.
|
||||
notify = PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
rv = CreateWidgetItem(element, aProperty, resource, 0, notify);
|
||||
rv = CreateWidgetItem(element, aProperty, resource, 0, PR_TRUE);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create widget item");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = element->SetAttribute(kNameSpaceID_None, kEmptyAtom, "false", PR_TRUE);
|
||||
|
||||
// Update the "empty" attribute
|
||||
nsAutoString empty;
|
||||
rv = element->GetAttribute(kNameSpaceID_None, kEmptyAtom, empty);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if ((rv != NS_CONTENT_ATTR_HAS_VALUE) || (! empty.Equals("false"))) {
|
||||
rv = element->SetAttribute(kNameSpaceID_None, kEmptyAtom, "false", PR_TRUE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Either the target of the assertion is not a resource,
|
||||
|
@ -762,8 +1186,14 @@ RDFGenericBuilderImpl::OnUnassert(nsIRDFResource* aSource,
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (numKids == 0) {
|
||||
rv = element->SetAttribute(kNameSpaceID_None, kEmptyAtom, "true", PR_TRUE);
|
||||
nsAutoString empty;
|
||||
rv = element->GetAttribute(kNameSpaceID_None, kEmptyAtom, empty);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if ((rv != NS_CONTENT_ATTR_HAS_VALUE) && (! empty.Equals("true"))) {
|
||||
rv = element->SetAttribute(kNameSpaceID_None, kEmptyAtom, "true", PR_TRUE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1020,7 +1450,7 @@ RDFGenericBuilderImpl::GetPersistentAttributes(nsIContent *element)
|
|||
literal->GetValueConst(&uniLiteral);
|
||||
if (uniLiteral)
|
||||
{
|
||||
rv = element->SetAttribute(nameSpaceID, tag, uniLiteral, PR_TRUE);
|
||||
rv = element->SetAttribute(nameSpaceID, tag, uniLiteral, PR_FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1430,7 +1860,7 @@ RDFGenericBuilderImpl::BuildContentFromTemplate(nsIContent *aTemplateNode,
|
|||
|
||||
nsCOMPtr<nsIContent> realKid;
|
||||
if (aIsUnique) {
|
||||
rv = EnsureElementHasGenericChild(aRealNode, nameSpaceID, tag, getter_AddRefs(realKid));
|
||||
rv = EnsureElementHasGenericChild(aRealNode, nameSpaceID, tag, aNotify, getter_AddRefs(realKid));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (rv == NS_RDF_ELEMENT_WAS_THERE) {
|
||||
|
@ -1489,7 +1919,7 @@ RDFGenericBuilderImpl::BuildContentFromTemplate(nsIContent *aTemplateNode,
|
|||
rv = content->SetText(text.GetUnicode(), text.Length(), PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = aRealNode->AppendChildTo(nsCOMPtr<nsIContent>( do_QueryInterface(content) ), PR_FALSE);
|
||||
rv = aRealNode->AppendChildTo(nsCOMPtr<nsIContent>( do_QueryInterface(content) ), aNotify);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
|
@ -1564,15 +1994,14 @@ RDFGenericBuilderImpl::BuildContentFromTemplate(nsIContent *aTemplateNode,
|
|||
|
||||
// We'll _already_ have added the unique elements.
|
||||
if (! aIsUnique) {
|
||||
// Note: add into tree, but only sort if its a resource element!
|
||||
if ((nsnull != XULSortService) && (isResourceElement)) {
|
||||
rv = XULSortService->InsertContainerNode(aRealNode, realKid, aNotify);
|
||||
if (NS_FAILED(rv)) {
|
||||
aRealNode->AppendChildTo(realKid, aNotify);
|
||||
}
|
||||
// Add into content model, special casing treeitems.
|
||||
if ((nsnull != gXULSortService) && (isResourceElement) && (tag.get() == kTreeItemAtom)) {
|
||||
rv = gXULSortService->InsertContainerNode(aRealNode, realKid, aNotify);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to insert element via sort service");
|
||||
}
|
||||
else {
|
||||
aRealNode->AppendChildTo(realKid, aNotify);
|
||||
rv = aRealNode->AppendChildTo(realKid, aNotify);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to insert element");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1605,12 +2034,8 @@ RDFGenericBuilderImpl::CreateWidgetItem(nsIContent *aElement,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
rv = BuildContentFromTemplate(tmpl,
|
||||
aElement,
|
||||
PR_TRUE,
|
||||
aChild,
|
||||
aNaturalOrderPos,
|
||||
aNotify);
|
||||
rv = BuildContentFromTemplate(tmpl, aElement, PR_TRUE, aChild, aNaturalOrderPos, aNotify);
|
||||
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to build content from template");
|
||||
return rv;
|
||||
}
|
||||
|
@ -1777,7 +2202,7 @@ RDFGenericBuilderImpl::RemoveWidgetItem(nsIContent* aElement,
|
|||
|
||||
|
||||
nsresult
|
||||
RDFGenericBuilderImpl::CreateContainerContents(nsIContent* aElement, nsIRDFResource* aResource)
|
||||
RDFGenericBuilderImpl::CreateContainerContents(nsIContent* aElement, nsIRDFResource* aResource, PRBool aNotify)
|
||||
{
|
||||
// Create the contents of a container by iterating over all of the
|
||||
// "containment" arcs out of the element's resource.
|
||||
|
@ -1801,7 +2226,7 @@ RDFGenericBuilderImpl::CreateContainerContents(nsIContent* aElement, nsIRDFResou
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if ((rv == NS_CONTENT_ATTR_HAS_VALUE) && (attrValue.EqualsIgnoreCase("true")))
|
||||
return NS_OK;
|
||||
return NS_RDF_ELEMENT_WAS_CREATED;
|
||||
|
||||
// Now mark the element's contents as being generated so that
|
||||
// any re-entrant calls don't trigger an infinite recursion.
|
||||
|
@ -1821,11 +2246,6 @@ RDFGenericBuilderImpl::CreateContainerContents(nsIContent* aElement, nsIRDFResou
|
|||
rv = mDB->ArcLabelsOut(aResource, getter_AddRefs(properties));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// rjc - sort
|
||||
nsCOMPtr<nsISupportsArray> tempArray;
|
||||
rv = NS_NewISupportsArray(getter_AddRefs(tempArray));
|
||||
if NS_FAILED(rv) return rv;
|
||||
|
||||
while (1) {
|
||||
PRBool hasMore;
|
||||
rv = properties->HasMoreElements(&hasMore);
|
||||
|
@ -1865,74 +2285,13 @@ RDFGenericBuilderImpl::CreateContainerContents(nsIContent* aElement, nsIRDFResou
|
|||
rv = targets->GetNext(getter_AddRefs(isupportsNext));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIRDFResource> valueResource = do_QueryInterface(isupportsNext);
|
||||
NS_ASSERTION(valueResource != nsnull, "not a resource");
|
||||
if (! valueResource)
|
||||
nsCOMPtr<nsIRDFResource> target = do_QueryInterface(isupportsNext);
|
||||
NS_ASSERTION(target != nsnull, "not a resource");
|
||||
if (! target)
|
||||
continue;
|
||||
|
||||
// XXX hack: always append value resource 1st due to sort
|
||||
// callback implementation
|
||||
tempArray->AppendElement(valueResource);
|
||||
tempArray->AppendElement(property);
|
||||
}
|
||||
}
|
||||
|
||||
PRUint32 numElements;
|
||||
rv = tempArray->Count(&numElements);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (numElements == 0)
|
||||
return NS_OK;
|
||||
|
||||
// Tree widget hackery. To be removed if and when the
|
||||
// reflow lock is exposed. See bug 10818.
|
||||
PRBool istree = IsTreeWidgetItem(aElement);
|
||||
|
||||
{
|
||||
// XXX change to use nsVoidArray?
|
||||
nsIRDFResource** flatArray = new nsIRDFResource*[numElements];
|
||||
if (! flatArray) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// flatten array of resources, sort them, then add as item elements
|
||||
PRUint32 loop;
|
||||
for (loop=0; loop<numElements; loop++)
|
||||
flatArray[loop] = (nsIRDFResource *)tempArray->ElementAt(loop);
|
||||
|
||||
if (XULSortService) {
|
||||
XULSortService->OpenContainer(mDB, aElement, flatArray, numElements/2, 2*sizeof(nsIRDFResource *));
|
||||
}
|
||||
|
||||
// This will insert all of the elements into the
|
||||
// container, but _won't_ bother layout about it.
|
||||
for (loop=0; loop<numElements; loop+=2) {
|
||||
rv = CreateWidgetItem(aElement, flatArray[loop+1], flatArray[loop], loop+1, PR_FALSE);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create widget item");
|
||||
if (NS_FAILED(rv)) break;
|
||||
}
|
||||
|
||||
for (PRInt32 i = PRInt32(numElements) - 1; i >=0; i--) {
|
||||
NS_IF_RELEASE(flatArray[i]);
|
||||
}
|
||||
|
||||
delete [] flatArray;
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
if (istree) {
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(mDocument);
|
||||
if (! doc)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIContent> treechildren;
|
||||
rv = nsRDFContentUtils::FindChildByTag(aElement,
|
||||
kNameSpaceID_XUL,
|
||||
kTreeChildrenAtom,
|
||||
getter_AddRefs(treechildren));
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// _Now_ tell layout that we've mucked with the container. This'll
|
||||
// force a reflow and get the content displayed.
|
||||
rv = doc->ContentAppended(treechildren, 0);
|
||||
rv = CreateWidgetItem(aElement, property, target, -1, aNotify);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create item");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
|
@ -2000,7 +2359,7 @@ RDFGenericBuilderImpl::CreateTemplateContents(nsIContent* aElement, const nsStri
|
|||
element = parent;
|
||||
}
|
||||
|
||||
rv = BuildContentFromTemplate(tmpl, aElement, PR_FALSE, resource, -1, PR_TRUE);
|
||||
rv = BuildContentFromTemplate(tmpl, aElement, PR_FALSE, resource, -1, PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
|
@ -2010,6 +2369,7 @@ nsresult
|
|||
RDFGenericBuilderImpl::EnsureElementHasGenericChild(nsIContent* parent,
|
||||
PRInt32 nameSpaceID,
|
||||
nsIAtom* tag,
|
||||
PRBool aNotify,
|
||||
nsIContent** result)
|
||||
{
|
||||
nsresult rv;
|
||||
|
@ -2026,7 +2386,7 @@ RDFGenericBuilderImpl::EnsureElementHasGenericChild(nsIContent* parent,
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// XXX Note that the notification ensures we won't batch insertions! This could be bad! - Dave
|
||||
rv = parent->AppendChildTo(element, PR_TRUE);
|
||||
rv = parent->AppendChildTo(element, aNotify);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
*result = element;
|
||||
|
@ -2381,6 +2741,109 @@ RDFGenericBuilderImpl::GetResource(PRInt32 aNameSpaceID,
|
|||
}
|
||||
|
||||
|
||||
nsresult
|
||||
RDFGenericBuilderImpl::FindInsertionPoint(nsIContent* aElement, nsIContent** aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// XXX Hack-o-rama. This needs to be fixed to actually grovel over
|
||||
// the template n' stuff.
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
rv = aElement->GetTag(*getter_AddRefs(tag));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsAutoString tagName;
|
||||
rv = tag->ToString(tagName);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (tagName.Equals("tree") || tagName.Equals("treeitem")) {
|
||||
rv = nsRDFContentUtils::FindChildByTag(aElement, kNameSpaceID_XUL, NS_NewAtom("treechildren"), aResult);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
else if (tagName.Equals("menu")) {
|
||||
rv = nsRDFContentUtils::FindChildByTag(aElement, kNameSpaceID_XUL, NS_NewAtom("menupopup"), aResult);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
else {
|
||||
*aResult = aElement;
|
||||
NS_ADDREF(*aResult);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
RDFGenericBuilderImpl::RemoveGeneratedContent(nsIContent* aElement)
|
||||
{
|
||||
// Remove all the content beneath aElement that has been generated
|
||||
// from a template.
|
||||
|
||||
nsresult rv;
|
||||
|
||||
PRInt32 count;
|
||||
rv = aElement->ChildCount(count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
while (--count >= 0) {
|
||||
nsCOMPtr<nsIContent> child;
|
||||
rv = aElement->ChildAt(count, *getter_AddRefs(child));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsAutoString tmplID;
|
||||
rv = child->GetAttribute(kNameSpaceID_None, kTemplateAtom, tmplID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (rv != NS_CONTENT_ATTR_HAS_VALUE)
|
||||
continue;
|
||||
|
||||
// It's a generated element. Remove it, and set its document
|
||||
// to null so that it'll get knocked out of the XUL doc's
|
||||
// resource-to-element map.
|
||||
rv = aElement->RemoveChildAt(count, PR_TRUE);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "error removing child");
|
||||
|
||||
rv = child->SetDocument(nsnull, PR_TRUE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
RDFGenericBuilderImpl::FindFirstGeneratedChild(nsIContent* aElement, PRInt32* aIndex)
|
||||
{
|
||||
// Find the first kid of aElement that has been generated from a
|
||||
// template.
|
||||
|
||||
nsresult rv;
|
||||
|
||||
PRInt32 count;
|
||||
rv = aElement->ChildCount(count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRInt32 i = 0;
|
||||
while (i < count) {
|
||||
nsCOMPtr<nsIContent> child;
|
||||
rv = aElement->ChildAt(i, *getter_AddRefs(child));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsAutoString tmplID;
|
||||
rv = child->GetAttribute(kNameSpaceID_None, kTemplateAtom, tmplID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (rv == NS_CONTENT_ATTR_HAS_VALUE)
|
||||
break;
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
*aIndex = (i < count) ? i : -1;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
RDFGenericBuilderImpl::IsTreeWidgetItem(nsIContent* aElement)
|
||||
{
|
||||
|
|
|
@ -1,274 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
An implementation that builds a XUL
|
||||
content model that is to be used with a certain widget. This class
|
||||
is abstract.
|
||||
*/
|
||||
|
||||
#include "nsIRDFContainerUtils.h"
|
||||
#include "nsIRDFContentModelBuilder.h"
|
||||
#include "nsIRDFObserver.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsIXULSortService.h"
|
||||
|
||||
class nsIRDFDocument;
|
||||
class nsIRDFCompositeDataSource;
|
||||
class nsIRDFResource;
|
||||
class nsIContent;
|
||||
class nsIRDFNode;
|
||||
class nsIAtom;
|
||||
class nsIRDFService;
|
||||
class nsIHTMLElementFactory;
|
||||
|
||||
class RDFGenericBuilderImpl : public nsIRDFContentModelBuilder,
|
||||
public nsIRDFObserver
|
||||
{
|
||||
public:
|
||||
RDFGenericBuilderImpl();
|
||||
virtual ~RDFGenericBuilderImpl();
|
||||
|
||||
nsresult Init();
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIRDFContentModelBuilder interface
|
||||
NS_IMETHOD SetDocument(nsIRDFDocument* aDocument);
|
||||
NS_IMETHOD SetDataBase(nsIRDFCompositeDataSource* aDataBase);
|
||||
NS_IMETHOD GetDataBase(nsIRDFCompositeDataSource** aDataBase);
|
||||
NS_IMETHOD CreateRootContent(nsIRDFResource* aResource);
|
||||
NS_IMETHOD SetRootContent(nsIContent* aElement);
|
||||
NS_IMETHOD CreateContents(nsIContent* aElement);
|
||||
NS_IMETHOD CreateElement(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aTag,
|
||||
nsIRDFResource* aResource,
|
||||
nsIContent** aResult);
|
||||
|
||||
// nsIRDFObserver interface
|
||||
NS_IMETHOD OnAssert(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget);
|
||||
|
||||
NS_IMETHOD OnUnassert(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget);
|
||||
|
||||
NS_IMETHOD OnChange(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aOldTarget,
|
||||
nsIRDFNode* aNewTarget);
|
||||
|
||||
NS_IMETHOD OnMove(nsIRDFResource* aOldSource,
|
||||
nsIRDFResource* aNewSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget);
|
||||
|
||||
// Implementation methods
|
||||
nsresult
|
||||
FindTemplate(nsIContent* aElement,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFResource* aChild,
|
||||
nsIContent **theTemplate);
|
||||
|
||||
nsresult
|
||||
IsTemplateRuleMatch(nsIContent* aElement,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFResource* aChild,
|
||||
nsIContent *aRule,
|
||||
PRBool *isMatch);
|
||||
|
||||
PRBool
|
||||
IsIgnoreableAttribute(PRInt32 aNameSpaceID, nsIAtom* aAtom);
|
||||
|
||||
nsresult
|
||||
GetSubstitutionText(nsIRDFResource* aResource,
|
||||
const nsString& aSubstitution,
|
||||
nsString& aResult);
|
||||
|
||||
nsresult
|
||||
BuildContentFromTemplate(nsIContent *aTemplateNode,
|
||||
nsIContent *aRealNode,
|
||||
PRBool aIsUnique,
|
||||
nsIRDFResource* aChild,
|
||||
PRInt32 aNaturalOrderPos,
|
||||
PRBool aNotify);
|
||||
|
||||
nsresult
|
||||
CreateWidgetItem(nsIContent* aElement,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFResource* aChild,
|
||||
PRInt32 aNaturalOrderPos,
|
||||
PRBool aNotify);
|
||||
|
||||
enum eUpdateAction { eSet, eClear };
|
||||
|
||||
#if 0
|
||||
PRBool
|
||||
IsAttributePersisent(nsIContent *element, PRInt32 aNameSpaceID, nsIAtom* aAtom);
|
||||
|
||||
void
|
||||
GetPersistentAttributes(nsIContent *realKid);
|
||||
|
||||
void
|
||||
PersistAttribute(nsIContent *element,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAtom,
|
||||
nsString aValue,
|
||||
eUpdateAction action);
|
||||
|
||||
void
|
||||
PersistProperty(nsIContent *element,
|
||||
nsIRDFResource *aProperty,
|
||||
nsIRDFNode *aTarget,
|
||||
eUpdateAction action);
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
SynchronizeUsingTemplate(nsIContent *aTemplateNode,
|
||||
nsIContent* aRealNode,
|
||||
eUpdateAction aAction,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aValue);
|
||||
|
||||
nsresult
|
||||
RemoveWidgetItem(nsIContent* aElement,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFResource* aValue,
|
||||
PRBool aNotify);
|
||||
|
||||
nsresult
|
||||
CreateContainerContents(nsIContent* aElement, nsIRDFResource* aResource);
|
||||
|
||||
nsresult
|
||||
CreateTemplateContents(nsIContent* aElement, const nsString& aTemplateID);
|
||||
|
||||
nsresult
|
||||
EnsureElementHasGenericChild(nsIContent* aParent,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aTag,
|
||||
nsIContent** aResult);
|
||||
|
||||
PRBool
|
||||
IsContainmentProperty(nsIContent* aElement, nsIRDFResource* aProperty);
|
||||
|
||||
PRBool
|
||||
IsIgnoredProperty(nsIContent* aElement, nsIRDFResource* aProperty);
|
||||
|
||||
PRBool
|
||||
IsContainer(nsIContent* aParentElement, nsIRDFResource* aTargetResource);
|
||||
|
||||
PRBool
|
||||
IsEmpty(nsIContent* aParentElement, nsIRDFResource* aContainer);
|
||||
|
||||
PRBool
|
||||
IsOpen(nsIContent* aElement);
|
||||
|
||||
PRBool
|
||||
IsElementInWidget(nsIContent* aElement);
|
||||
|
||||
PRBool
|
||||
IsResourceElement(nsIContent* aElement);
|
||||
|
||||
nsresult
|
||||
GetDOMNodeResource(nsIDOMNode* aNode, nsIRDFResource** aResource);
|
||||
|
||||
nsresult
|
||||
GetResource(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aNameAtom,
|
||||
nsIRDFResource** aResource);
|
||||
|
||||
// XXX. Urg. Hack until layout can batch reflows. See bug 10818.
|
||||
PRBool
|
||||
IsTreeWidgetItem(nsIContent* aElement);
|
||||
|
||||
PRBool
|
||||
IsReflowScheduled();
|
||||
|
||||
nsresult
|
||||
ScheduleReflow();
|
||||
|
||||
static void
|
||||
ForceTreeReflow(nsITimer* aTimer, void* aClosure);
|
||||
|
||||
protected:
|
||||
nsIRDFDocument* mDocument; // [WEAK]
|
||||
|
||||
// We are an observer of the composite datasource. The cycle is
|
||||
// broken by out-of-band SetDataBase(nsnull) call when document is
|
||||
// destroyed.
|
||||
nsCOMPtr<nsIRDFCompositeDataSource> mDB;
|
||||
nsCOMPtr<nsIContent> mRoot;
|
||||
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
|
||||
static nsIRDFDataSource *mLocalstore;
|
||||
static PRBool persistLock;
|
||||
|
||||
// pseudo-constants
|
||||
static nsrefcnt gRefCnt;
|
||||
static nsIRDFService* gRDFService;
|
||||
static nsIRDFContainerUtils* gRDFContainerUtils;
|
||||
static nsINameSpaceManager* gNameSpaceManager;
|
||||
static nsIHTMLElementFactory* gHTMLElementFactory;
|
||||
|
||||
static nsIAtom* kContainerAtom;
|
||||
static nsIAtom* kLazyContentAtom;
|
||||
static nsIAtom* kIsContainerAtom;
|
||||
static nsIAtom* kIsEmptyAtom;
|
||||
static nsIAtom* kXULContentsGeneratedAtom;
|
||||
static nsIAtom* kTemplateContentsGeneratedAtom;
|
||||
static nsIAtom* kContainerContentsGeneratedAtom;
|
||||
static nsIAtom* kNaturalOrderPosAtom;
|
||||
static nsIAtom* kIdAtom;
|
||||
static nsIAtom* kPersistAtom;
|
||||
static nsIAtom* kOpenAtom;
|
||||
static nsIAtom* kEmptyAtom;
|
||||
static nsIAtom* kResourceAtom;
|
||||
static nsIAtom* kURIAtom;
|
||||
static nsIAtom* kContainmentAtom;
|
||||
static nsIAtom* kIgnoreAtom;
|
||||
static nsIAtom* kRefAtom;
|
||||
static nsIAtom* kValueAtom;
|
||||
|
||||
static nsIAtom* kTemplateAtom;
|
||||
static nsIAtom* kRuleAtom;
|
||||
static nsIAtom* kTextAtom;
|
||||
static nsIAtom* kPropertyAtom;
|
||||
static nsIAtom* kInstanceOfAtom;
|
||||
|
||||
static nsIAtom* kTreeAtom;
|
||||
static nsIAtom* kTreeChildrenAtom;
|
||||
static nsIAtom* kTreeItemAtom;
|
||||
|
||||
static PRInt32 kNameSpaceID_RDF;
|
||||
static PRInt32 kNameSpaceID_XUL;
|
||||
|
||||
static nsIRDFResource* kNC_Title;
|
||||
static nsIRDFResource* kNC_child;
|
||||
static nsIRDFResource* kNC_Column;
|
||||
static nsIRDFResource* kNC_Folder;
|
||||
static nsIRDFResource* kRDF_child;
|
||||
static nsIRDFResource* kRDF_instanceOf;
|
||||
static nsIRDFResource* kXUL_element;
|
||||
|
||||
static nsIXULSortService *XULSortService;
|
||||
};
|
|
@ -188,8 +188,6 @@ private:
|
|||
static nsIAtom* kDataSourcesAtom;
|
||||
static nsIAtom* kIdAtom;
|
||||
static nsIAtom* kInstanceOfAtom;
|
||||
static nsIAtom* kTemplateContentsGeneratedAtom;
|
||||
static nsIAtom* kContainerContentsGeneratedAtom;
|
||||
static nsIAtom* kMenuAtom;
|
||||
static nsIAtom* kMenuBarAtom;
|
||||
static nsIAtom* kKeysetAtom;
|
||||
|
@ -225,6 +223,9 @@ public:
|
|||
NS_IMETHOD CreateRootContent(nsIRDFResource* aResource);
|
||||
NS_IMETHOD SetRootContent(nsIContent* aResource);
|
||||
NS_IMETHOD CreateContents(nsIContent* aElement);
|
||||
NS_IMETHOD OpenContainer(nsIContent* aElement);
|
||||
NS_IMETHOD CloseContainer(nsIContent* aElement);
|
||||
NS_IMETHOD RebuildContainer(nsIContent* aElement);
|
||||
NS_IMETHOD CreateElement(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aTagName,
|
||||
nsIRDFResource* aResource,
|
||||
|
@ -342,8 +343,6 @@ nsIAtom* RDFXULBuilderImpl::kLazyContentAtom;
|
|||
nsIAtom* RDFXULBuilderImpl::kDataSourcesAtom;
|
||||
nsIAtom* RDFXULBuilderImpl::kIdAtom;
|
||||
nsIAtom* RDFXULBuilderImpl::kInstanceOfAtom;
|
||||
nsIAtom* RDFXULBuilderImpl::kTemplateContentsGeneratedAtom;
|
||||
nsIAtom* RDFXULBuilderImpl::kContainerContentsGeneratedAtom;
|
||||
nsIAtom* RDFXULBuilderImpl::kMenuAtom;
|
||||
nsIAtom* RDFXULBuilderImpl::kMenuBarAtom;
|
||||
nsIAtom* RDFXULBuilderImpl::kKeysetAtom;
|
||||
|
@ -418,8 +417,6 @@ RDFXULBuilderImpl::Init()
|
|||
kDataSourcesAtom = NS_NewAtom("datasources");
|
||||
kIdAtom = NS_NewAtom("id");
|
||||
kInstanceOfAtom = NS_NewAtom("instanceof");
|
||||
kTemplateContentsGeneratedAtom = NS_NewAtom("itemcontentsgenerated");
|
||||
kContainerContentsGeneratedAtom = NS_NewAtom("containercontentsgenerated");
|
||||
kMenuAtom = NS_NewAtom("menu");
|
||||
kMenuBarAtom = NS_NewAtom("menubar");
|
||||
kKeysetAtom = NS_NewAtom("keyset");
|
||||
|
@ -491,8 +488,6 @@ RDFXULBuilderImpl::~RDFXULBuilderImpl(void)
|
|||
NS_IF_RELEASE(kLazyContentAtom);
|
||||
NS_IF_RELEASE(kXULContentsGeneratedAtom);
|
||||
NS_IF_RELEASE(kIdAtom);
|
||||
NS_IF_RELEASE(kTemplateContentsGeneratedAtom);
|
||||
NS_IF_RELEASE(kContainerContentsGeneratedAtom);
|
||||
NS_IF_RELEASE(kDataSourcesAtom);
|
||||
NS_IF_RELEASE(kTreeAtom);
|
||||
NS_IF_RELEASE(kMenuAtom);
|
||||
|
@ -749,6 +744,27 @@ RDFXULBuilderImpl::CreateContents(nsIContent* aElement)
|
|||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXULBuilderImpl::OpenContainer(nsIContent* aContainer)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXULBuilderImpl::CloseContainer(nsIContent* aContainer)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXULBuilderImpl::RebuildContainer(nsIContent* aContainer)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFXULBuilderImpl::CreateElement(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aTagName,
|
||||
|
@ -1318,7 +1334,7 @@ RDFXULBuilderImpl::InsertChildAt(nsINameSpace* aNameSpace,
|
|||
}
|
||||
#endif
|
||||
|
||||
rv = aElement->InsertChildAt(child, aIndex, PR_TRUE);
|
||||
rv = aElement->InsertChildAt(child, aIndex, PR_FALSE);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to add element to content model");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
@ -1398,7 +1414,7 @@ RDFXULBuilderImpl::ReplaceChildAt(nsINameSpace* aNameSpace,
|
|||
}
|
||||
#endif
|
||||
|
||||
rv = aElement->ReplaceChildAt(child, aIndex, PR_TRUE);
|
||||
rv = aElement->ReplaceChildAt(child, aIndex, PR_FALSE);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to add element to content model");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
|
|
@ -802,7 +802,7 @@ public:
|
|||
|
||||
nsresult OpenWidgetItem(nsIContent* aElement);
|
||||
nsresult CloseWidgetItem(nsIContent* aElement);
|
||||
nsresult RemoveAndRebuildGeneratedChildren(nsIContent* aElement);
|
||||
nsresult RebuildWidgetItem(nsIContent* aElement);
|
||||
|
||||
nsresult
|
||||
AddElementToMap(nsIContent* aElement, PRBool aDeep);
|
||||
|
@ -2101,14 +2101,14 @@ XULDocumentImpl::ContentStatesChanged(nsIContent* aContent1, nsIContent* aConten
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
XULDocumentImpl::AttributeChanged(nsIContent* aChild,
|
||||
XULDocumentImpl::AttributeChanged(nsIContent* aElement,
|
||||
nsIAtom* aAttribute,
|
||||
PRInt32 aHint)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
PRInt32 nameSpaceID;
|
||||
rv = aChild->GetNameSpaceID(nameSpaceID);
|
||||
rv = aElement->GetNameSpaceID(nameSpaceID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// First see if we need to update our element map.
|
||||
|
@ -2120,27 +2120,7 @@ XULDocumentImpl::AttributeChanged(nsIContent* aChild,
|
|||
|
||||
// That'll have removed _both_ the 'ref' and 'id' entries from
|
||||
// the map. So add 'em back now.
|
||||
rv = AddElementToMap(aChild, PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle "special" cases.
|
||||
if (nameSpaceID == kNameSpaceID_XUL) {
|
||||
if (aAttribute == kOpenAtom) {
|
||||
nsAutoString open;
|
||||
rv = aChild->GetAttribute(kNameSpaceID_None, kOpenAtom, open);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if ((rv == NS_CONTENT_ATTR_HAS_VALUE) && (open.Equals("true"))) {
|
||||
OpenWidgetItem(aChild);
|
||||
}
|
||||
else {
|
||||
CloseWidgetItem(aChild);
|
||||
}
|
||||
}
|
||||
else if (aAttribute == kRefAtom) {
|
||||
rv = RemoveAndRebuildGeneratedChildren(aChild);
|
||||
rv = AddElementToMap(aElement, PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
|
@ -2148,11 +2128,34 @@ XULDocumentImpl::AttributeChanged(nsIContent* aChild,
|
|||
// Now notify external observers
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); i++) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
|
||||
observer->AttributeChanged(this, aChild, aAttribute, aHint);
|
||||
observer->AttributeChanged(this, aElement, aAttribute, aHint);
|
||||
if (observer != (nsIDocumentObserver*)mObservers.ElementAt(i)) {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle "special" cases. We do this handling _after_ we've
|
||||
// notified the observer to ensure that any frames that are
|
||||
// caching information (e.g., the tree widget and the 'open'
|
||||
// attribute) will notice things properly.
|
||||
if (nameSpaceID == kNameSpaceID_XUL) {
|
||||
if (aAttribute == kOpenAtom) {
|
||||
nsAutoString open;
|
||||
rv = aElement->GetAttribute(kNameSpaceID_None, kOpenAtom, open);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if ((rv == NS_CONTENT_ATTR_HAS_VALUE) && (open.Equals("true"))) {
|
||||
OpenWidgetItem(aElement);
|
||||
}
|
||||
else {
|
||||
CloseWidgetItem(aElement);
|
||||
}
|
||||
}
|
||||
else if (aAttribute == kRefAtom) {
|
||||
RebuildWidgetItem(aElement);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -4483,10 +4486,17 @@ XULDocumentImpl::ReleaseEvent(const nsString& aType)
|
|||
nsresult
|
||||
XULDocumentImpl::OpenWidgetItem(nsIContent* aElement)
|
||||
{
|
||||
NS_PRECONDITION(aElement != nsnull, "null ptr");
|
||||
if (! aElement)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (! mBuilders)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
if (PR_LOG_TEST(gXULLog, PR_LOG_DEBUG)) {
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
rv = aElement->GetTag(*getter_AddRefs(tag));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
@ -4499,12 +4509,39 @@ XULDocumentImpl::OpenWidgetItem(nsIContent* aElement)
|
|||
(const char*) nsCAutoString(tagStr)));
|
||||
}
|
||||
#endif
|
||||
return CreateContents(aElement);
|
||||
|
||||
PRUint32 cnt = 0;
|
||||
rv = mBuilders->Count(&cnt);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Count failed");
|
||||
for (PRUint32 i = 0; i < cnt; ++i) {
|
||||
// XXX we should QueryInterface() here
|
||||
nsIRDFContentModelBuilder* builder
|
||||
= (nsIRDFContentModelBuilder*) mBuilders->ElementAt(i);
|
||||
|
||||
NS_ASSERTION(builder != nsnull, "null ptr");
|
||||
if (! builder)
|
||||
continue;
|
||||
|
||||
rv = builder->OpenContainer(aElement);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "error opening container");
|
||||
// XXX ignore error code?
|
||||
|
||||
NS_RELEASE(builder);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
XULDocumentImpl::CloseWidgetItem(nsIContent* aElement)
|
||||
{
|
||||
NS_PRECONDITION(aElement != nsnull, "null ptr");
|
||||
if (! aElement)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (! mBuilders)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
|
@ -4522,163 +4559,78 @@ XULDocumentImpl::CloseWidgetItem(nsIContent* aElement)
|
|||
}
|
||||
#endif
|
||||
|
||||
// Find the tag that contains the children so that we can remove
|
||||
// all of the children.
|
||||
//
|
||||
// XXX We make a bit of a leap here and assume that the same
|
||||
// template that was used to generate _us_ was used to generate
|
||||
// our _kids_. I'm sure this'll break when we do toolbars or
|
||||
// something.
|
||||
nsAutoString tmplID;
|
||||
rv = aElement->GetAttribute(kNameSpaceID_None, kTemplateAtom, tmplID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
PRUint32 cnt = 0;
|
||||
rv = mBuilders->Count(&cnt);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Count failed");
|
||||
for (PRUint32 i = 0; i < cnt; ++i) {
|
||||
// XXX we should QueryInterface() here
|
||||
nsIRDFContentModelBuilder* builder
|
||||
= (nsIRDFContentModelBuilder*) mBuilders->ElementAt(i);
|
||||
|
||||
if (rv != NS_CONTENT_ATTR_HAS_VALUE)
|
||||
return NS_OK;
|
||||
NS_ASSERTION(builder != nsnull, "null ptr");
|
||||
if (! builder)
|
||||
continue;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> tmplDOMEle;
|
||||
rv = GetElementById(tmplID, getter_AddRefs(tmplDOMEle));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = builder->CloseContainer(aElement);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "error closing container");
|
||||
// XXX ignore error code?
|
||||
|
||||
nsCOMPtr<nsIContent> tmpl = do_QueryInterface(tmplDOMEle);
|
||||
if (! tmpl)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIContent> tmplParent;
|
||||
rv = tmpl->GetParent(*getter_AddRefs(tmplParent));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
NS_ASSERTION(tmplParent != nsnull, "template node has no parent");
|
||||
if (! tmplParent)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIAtom> tmplParentTag;
|
||||
rv = tmplParent->GetTag(*getter_AddRefs(tmplParentTag));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIContent> childcontainer;
|
||||
if ((tmplParentTag.get() == kRuleAtom) || (tmplParentTag.get() == kTemplateAtom)) {
|
||||
childcontainer = dont_QueryInterface(aElement);
|
||||
NS_RELEASE(builder);
|
||||
}
|
||||
else {
|
||||
rv = nsRDFContentUtils::FindChildByTag(aElement,
|
||||
kNameSpaceID_XUL,
|
||||
tmplParentTag,
|
||||
getter_AddRefs(childcontainer));
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (rv == NS_RDF_NO_VALUE) {
|
||||
// No tag; must've already been closed
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
PRInt32 count;
|
||||
rv = childcontainer->ChildCount(count);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get count of the parent's children");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
while (--count >= 0) {
|
||||
nsCOMPtr<nsIContent> child;
|
||||
rv = childcontainer->ChildAt(count, *getter_AddRefs(child));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = childcontainer->RemoveChildAt(count, PR_TRUE);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "error removing child");
|
||||
|
||||
do {
|
||||
// If it's _not_ a XUL element, then we want to blow it and
|
||||
// all of its kids out of the XUL document's
|
||||
// resource-to-element map.
|
||||
nsCOMPtr<nsIRDFResource> resource;
|
||||
rv = nsRDFContentUtils::GetElementResource(child, getter_AddRefs(resource));
|
||||
if (NS_FAILED(rv)) break;
|
||||
|
||||
PRBool isXULElement;
|
||||
rv = mDocumentDataSource->HasAssertion(resource, kRDF_instanceOf, kXUL_element, PR_TRUE, &isXULElement);
|
||||
if (NS_FAILED(rv)) break;
|
||||
|
||||
if (! isXULElement)
|
||||
break;
|
||||
|
||||
rv = child->SetDocument(nsnull, PR_TRUE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
} while (0);
|
||||
}
|
||||
|
||||
// Clear the container-contents-generated attribute so that the next time we
|
||||
// come back, we'll regenerate the kids we just killed.
|
||||
rv = aElement->UnsetAttribute(kNameSpaceID_None,
|
||||
kContainerContentsGeneratedAtom,
|
||||
PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// This is a _total_ hack to make sure that any XUL we blow away
|
||||
// gets rebuilt.
|
||||
rv = childcontainer->UnsetAttribute(kNameSpaceID_None,
|
||||
kXULContentsGeneratedAtom,
|
||||
PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = childcontainer->SetAttribute(kNameSpaceID_None,
|
||||
kLazyContentAtom,
|
||||
"true",
|
||||
PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
XULDocumentImpl::RemoveAndRebuildGeneratedChildren(nsIContent* aElement)
|
||||
XULDocumentImpl::RebuildWidgetItem(nsIContent* aElement)
|
||||
{
|
||||
NS_PRECONDITION(aElement != nsnull, "null ptr");
|
||||
if (! aElement)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (! mBuilders)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
PRInt32 count;
|
||||
rv = aElement->ChildCount(count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
while (--count >= 0) {
|
||||
nsCOMPtr<nsIContent> child;
|
||||
rv = aElement->ChildAt(count, *getter_AddRefs(child));
|
||||
#ifdef PR_LOGGING
|
||||
if (PR_LOG_TEST(gXULLog, PR_LOG_DEBUG)) {
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
rv = aElement->GetTag(*getter_AddRefs(tag));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsAutoString tmplID;
|
||||
rv = child->GetAttribute(kNameSpaceID_None, kTemplateAtom, tmplID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
nsAutoString tagStr;
|
||||
tag->ToString(tagStr);
|
||||
|
||||
if (rv != NS_CONTENT_ATTR_HAS_VALUE)
|
||||
PR_LOG(gXULLog, PR_LOG_DEBUG,
|
||||
("xuldoc close-widget-item %s",
|
||||
(const char*) nsCAutoString(tagStr)));
|
||||
}
|
||||
#endif
|
||||
|
||||
PRUint32 cnt = 0;
|
||||
rv = mBuilders->Count(&cnt);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Count failed");
|
||||
for (PRUint32 i = 0; i < cnt; ++i) {
|
||||
// XXX we should QueryInterface() here
|
||||
nsIRDFContentModelBuilder* builder
|
||||
= (nsIRDFContentModelBuilder*) mBuilders->ElementAt(i);
|
||||
|
||||
NS_ASSERTION(builder != nsnull, "null ptr");
|
||||
if (! builder)
|
||||
continue;
|
||||
|
||||
// It's a generated element. Remove it, and set its document
|
||||
// to null so that it'll get knocked out of the XUL doc's
|
||||
// resource-to-element map.
|
||||
rv = aElement->RemoveChildAt(count, PR_TRUE);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "error removing child");
|
||||
rv = builder->RebuildContainer(aElement);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "error rebuilding container");
|
||||
// XXX ignore error code?
|
||||
|
||||
rv = child->SetDocument(nsnull, PR_TRUE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
NS_RELEASE(builder);
|
||||
}
|
||||
|
||||
// Clear the contents-generated attribute so that the next time we
|
||||
// come back, we'll regenerate the kids we just killed.
|
||||
rv = aElement->UnsetAttribute(kNameSpaceID_None,
|
||||
kTemplateContentsGeneratedAtom,
|
||||
PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = aElement->UnsetAttribute(kNameSpaceID_None,
|
||||
kContainerContentsGeneratedAtom,
|
||||
PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = CreateContents(aElement);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -41,38 +41,36 @@
|
|||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMXULDocument.h"
|
||||
#include "nsIDOMXULElement.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIHTMLContent.h"
|
||||
#include "nsIHTMLElementFactory.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsIRDFContentModelBuilder.h"
|
||||
#include "nsIRDFCompositeDataSource.h"
|
||||
#include "nsIRDFContainerUtils.h"
|
||||
#include "nsIRDFContentModelBuilder.h"
|
||||
#include "nsIRDFDocument.h"
|
||||
#include "nsIRDFNode.h"
|
||||
#include "nsIRDFObserver.h"
|
||||
#include "nsIRDFRemoteDataSource.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsITextContent.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsIXULSortService.h"
|
||||
#include "nsLayoutCID.h"
|
||||
#include "nsRDFCID.h"
|
||||
#include "nsRDFContentUtils.h"
|
||||
#include "nsString.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "prlog.h"
|
||||
#include "rdf.h"
|
||||
#include "rdfutil.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsIDOMXULElement.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsIXULSortService.h"
|
||||
#include "nsIHTMLElementFactory.h"
|
||||
#include "nsIHTMLContent.h"
|
||||
#include "nsRDFGenericBuilder.h"
|
||||
#include "prlog.h"
|
||||
#include "nsIRDFRemoteDataSource.h"
|
||||
|
||||
|
||||
// Return values for EnsureElementHasGenericChild()
|
||||
#define NS_RDF_ELEMENT_WAS_CREATED NS_RDF_NO_VALUE
|
||||
#define NS_RDF_ELEMENT_WAS_THERE NS_OK
|
||||
|
||||
|
@ -107,8 +105,252 @@ static NS_DEFINE_CID(kIHTMLElementFactoryIID, NS_IHTML_ELEMENT_FACTORY_IID);
|
|||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class RDFGenericBuilderImpl : public nsIRDFContentModelBuilder,
|
||||
public nsIRDFObserver
|
||||
{
|
||||
public:
|
||||
RDFGenericBuilderImpl();
|
||||
virtual ~RDFGenericBuilderImpl();
|
||||
|
||||
nsresult Init();
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIRDFContentModelBuilder interface
|
||||
NS_IMETHOD SetDocument(nsIRDFDocument* aDocument);
|
||||
NS_IMETHOD SetDataBase(nsIRDFCompositeDataSource* aDataBase);
|
||||
NS_IMETHOD GetDataBase(nsIRDFCompositeDataSource** aDataBase);
|
||||
NS_IMETHOD CreateRootContent(nsIRDFResource* aResource);
|
||||
NS_IMETHOD SetRootContent(nsIContent* aElement);
|
||||
NS_IMETHOD CreateContents(nsIContent* aElement);
|
||||
NS_IMETHOD OpenContainer(nsIContent* aContainer);
|
||||
NS_IMETHOD CloseContainer(nsIContent* aContainer);
|
||||
NS_IMETHOD RebuildContainer(nsIContent* aContainer);
|
||||
NS_IMETHOD CreateElement(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aTag,
|
||||
nsIRDFResource* aResource,
|
||||
nsIContent** aResult);
|
||||
|
||||
// nsIRDFObserver interface
|
||||
NS_IMETHOD OnAssert(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget);
|
||||
|
||||
NS_IMETHOD OnUnassert(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget);
|
||||
|
||||
NS_IMETHOD OnChange(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aOldTarget,
|
||||
nsIRDFNode* aNewTarget);
|
||||
|
||||
NS_IMETHOD OnMove(nsIRDFResource* aOldSource,
|
||||
nsIRDFResource* aNewSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget);
|
||||
|
||||
// Implementation methods
|
||||
nsresult
|
||||
FindTemplate(nsIContent* aElement,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFResource* aChild,
|
||||
nsIContent **theTemplate);
|
||||
|
||||
nsresult
|
||||
IsTemplateRuleMatch(nsIContent* aElement,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFResource* aChild,
|
||||
nsIContent *aRule,
|
||||
PRBool *isMatch);
|
||||
|
||||
PRBool
|
||||
IsIgnoreableAttribute(PRInt32 aNameSpaceID, nsIAtom* aAtom);
|
||||
|
||||
nsresult
|
||||
GetSubstitutionText(nsIRDFResource* aResource,
|
||||
const nsString& aSubstitution,
|
||||
nsString& aResult);
|
||||
|
||||
nsresult
|
||||
BuildContentFromTemplate(nsIContent *aTemplateNode,
|
||||
nsIContent *aRealNode,
|
||||
PRBool aIsUnique,
|
||||
nsIRDFResource* aChild,
|
||||
PRInt32 aNaturalOrderPos,
|
||||
PRBool aNotify);
|
||||
|
||||
nsresult
|
||||
CreateWidgetItem(nsIContent* aElement,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFResource* aChild,
|
||||
PRInt32 aNaturalOrderPos,
|
||||
PRBool aNotify);
|
||||
|
||||
enum eUpdateAction { eSet, eClear };
|
||||
|
||||
#if 0
|
||||
PRBool
|
||||
IsAttributePersisent(nsIContent *element, PRInt32 aNameSpaceID, nsIAtom* aAtom);
|
||||
|
||||
void
|
||||
GetPersistentAttributes(nsIContent *realKid);
|
||||
|
||||
void
|
||||
PersistAttribute(nsIContent *element,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAtom,
|
||||
nsString aValue,
|
||||
eUpdateAction action);
|
||||
|
||||
void
|
||||
PersistProperty(nsIContent *element,
|
||||
nsIRDFResource *aProperty,
|
||||
nsIRDFNode *aTarget,
|
||||
eUpdateAction action);
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
SynchronizeUsingTemplate(nsIContent *aTemplateNode,
|
||||
nsIContent* aRealNode,
|
||||
eUpdateAction aAction,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aValue);
|
||||
|
||||
nsresult
|
||||
RemoveWidgetItem(nsIContent* aElement,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFResource* aValue,
|
||||
PRBool aNotify);
|
||||
|
||||
nsresult
|
||||
CreateContainerContents(nsIContent* aElement, nsIRDFResource* aResource, PRBool aNotify);
|
||||
|
||||
nsresult
|
||||
CreateTemplateContents(nsIContent* aElement, const nsString& aTemplateID);
|
||||
|
||||
nsresult
|
||||
EnsureElementHasGenericChild(nsIContent* aParent,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aTag,
|
||||
PRBool aNotify,
|
||||
nsIContent** aResult);
|
||||
|
||||
PRBool
|
||||
IsContainmentProperty(nsIContent* aElement, nsIRDFResource* aProperty);
|
||||
|
||||
PRBool
|
||||
IsIgnoredProperty(nsIContent* aElement, nsIRDFResource* aProperty);
|
||||
|
||||
PRBool
|
||||
IsContainer(nsIContent* aParentElement, nsIRDFResource* aTargetResource);
|
||||
|
||||
PRBool
|
||||
IsEmpty(nsIContent* aParentElement, nsIRDFResource* aContainer);
|
||||
|
||||
PRBool
|
||||
IsOpen(nsIContent* aElement);
|
||||
|
||||
PRBool
|
||||
IsElementInWidget(nsIContent* aElement);
|
||||
|
||||
PRBool
|
||||
IsResourceElement(nsIContent* aElement);
|
||||
|
||||
nsresult
|
||||
GetDOMNodeResource(nsIDOMNode* aNode, nsIRDFResource** aResource);
|
||||
|
||||
nsresult
|
||||
GetResource(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aNameAtom,
|
||||
nsIRDFResource** aResource);
|
||||
|
||||
nsresult FindInsertionPoint(nsIContent* aElement, nsIContent** aResult);
|
||||
nsresult RemoveGeneratedContent(nsIContent* aElement);
|
||||
nsresult FindFirstGeneratedChild(nsIContent* aElement, PRInt32* aIndex);
|
||||
|
||||
// XXX. Urg. Hack until layout can batch reflows. See bug 10818.
|
||||
PRBool
|
||||
IsTreeWidgetItem(nsIContent* aElement);
|
||||
|
||||
PRBool
|
||||
IsReflowScheduled();
|
||||
|
||||
nsresult
|
||||
ScheduleReflow();
|
||||
|
||||
static void
|
||||
ForceTreeReflow(nsITimer* aTimer, void* aClosure);
|
||||
|
||||
protected:
|
||||
nsIRDFDocument* mDocument; // [WEAK]
|
||||
|
||||
// We are an observer of the composite datasource. The cycle is
|
||||
// broken by out-of-band SetDataBase(nsnull) call when document is
|
||||
// destroyed.
|
||||
nsCOMPtr<nsIRDFCompositeDataSource> mDB;
|
||||
nsCOMPtr<nsIContent> mRoot;
|
||||
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
|
||||
static nsIRDFDataSource *mLocalstore;
|
||||
static PRBool persistLock;
|
||||
|
||||
// pseudo-constants
|
||||
static nsrefcnt gRefCnt;
|
||||
static nsIRDFService* gRDFService;
|
||||
static nsIRDFContainerUtils* gRDFContainerUtils;
|
||||
static nsINameSpaceManager* gNameSpaceManager;
|
||||
static nsIHTMLElementFactory* gHTMLElementFactory;
|
||||
|
||||
static nsIAtom* kContainerAtom;
|
||||
static nsIAtom* kLazyContentAtom;
|
||||
static nsIAtom* kIsContainerAtom;
|
||||
static nsIAtom* kIsEmptyAtom;
|
||||
static nsIAtom* kXULContentsGeneratedAtom;
|
||||
static nsIAtom* kTemplateContentsGeneratedAtom;
|
||||
static nsIAtom* kContainerContentsGeneratedAtom;
|
||||
static nsIAtom* kNaturalOrderPosAtom;
|
||||
static nsIAtom* kIdAtom;
|
||||
static nsIAtom* kPersistAtom;
|
||||
static nsIAtom* kOpenAtom;
|
||||
static nsIAtom* kEmptyAtom;
|
||||
static nsIAtom* kResourceAtom;
|
||||
static nsIAtom* kURIAtom;
|
||||
static nsIAtom* kContainmentAtom;
|
||||
static nsIAtom* kIgnoreAtom;
|
||||
static nsIAtom* kRefAtom;
|
||||
static nsIAtom* kValueAtom;
|
||||
|
||||
static nsIAtom* kTemplateAtom;
|
||||
static nsIAtom* kRuleAtom;
|
||||
static nsIAtom* kTextAtom;
|
||||
static nsIAtom* kPropertyAtom;
|
||||
static nsIAtom* kInstanceOfAtom;
|
||||
|
||||
static nsIAtom* kTreeAtom;
|
||||
static nsIAtom* kTreeChildrenAtom;
|
||||
static nsIAtom* kTreeItemAtom;
|
||||
|
||||
static PRInt32 kNameSpaceID_RDF;
|
||||
static PRInt32 kNameSpaceID_XUL;
|
||||
|
||||
static nsIRDFResource* kNC_Title;
|
||||
static nsIRDFResource* kNC_child;
|
||||
static nsIRDFResource* kNC_Column;
|
||||
static nsIRDFResource* kNC_Folder;
|
||||
static nsIRDFResource* kRDF_child;
|
||||
static nsIRDFResource* kRDF_instanceOf;
|
||||
static nsIRDFResource* kXUL_element;
|
||||
|
||||
static nsIXULSortService* gXULSortService;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsrefcnt RDFGenericBuilderImpl::gRefCnt = 0;
|
||||
nsIXULSortService* RDFGenericBuilderImpl::XULSortService = nsnull;
|
||||
nsIXULSortService* RDFGenericBuilderImpl::gXULSortService = nsnull;
|
||||
|
||||
nsIAtom* RDFGenericBuilderImpl::kContainerAtom;
|
||||
nsIAtom* RDFGenericBuilderImpl::kLazyContentAtom;
|
||||
|
@ -252,7 +494,7 @@ RDFGenericBuilderImpl::~RDFGenericBuilderImpl(void)
|
|||
|
||||
nsServiceManager::ReleaseService(kRDFServiceCID, gRDFService);
|
||||
nsServiceManager::ReleaseService(kRDFContainerUtilsCID, gRDFContainerUtils);
|
||||
nsServiceManager::ReleaseService(kXULSortServiceCID, XULSortService);
|
||||
nsServiceManager::ReleaseService(kXULSortServiceCID, gXULSortService);
|
||||
NS_RELEASE(gNameSpaceManager);
|
||||
NS_IF_RELEASE(gHTMLElementFactory);
|
||||
}
|
||||
|
@ -351,7 +593,7 @@ RDFGenericBuilderImpl::Init()
|
|||
|
||||
rv = nsServiceManager::GetService(kXULSortServiceCID,
|
||||
kIXULSortServiceIID,
|
||||
(nsISupports**) &XULSortService);
|
||||
(nsISupports**) &gXULSortService);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = nsComponentManager::CreateInstance(kHTMLElementFactoryCID,
|
||||
|
@ -475,19 +717,23 @@ RDFGenericBuilderImpl::SetRootContent(nsIContent* aElement)
|
|||
NS_IMETHODIMP
|
||||
RDFGenericBuilderImpl::CreateContents(nsIContent* aElement)
|
||||
{
|
||||
nsresult rv;
|
||||
NS_PRECONDITION(aElement != nsnull, "null ptr");
|
||||
if (! aElement)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// First, make sure that the element is in the right widget -- ours.
|
||||
if (!IsElementInWidget(aElement))
|
||||
return NS_OK;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIRDFResource> resource;
|
||||
rv = nsRDFContentUtils::GetElementRefResource(aElement, getter_AddRefs(resource));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// The element has a resource; that means that it corresponds
|
||||
// to something in the graph, so we need to go to the graph to
|
||||
// create its contents.
|
||||
rv = CreateContainerContents(aElement, resource);
|
||||
rv = CreateContainerContents(aElement, resource, PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
|
@ -505,6 +751,192 @@ RDFGenericBuilderImpl::CreateContents(nsIContent* aElement)
|
|||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFGenericBuilderImpl::OpenContainer(nsIContent* aElement)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// First, make sure that the element is in the right widget -- ours.
|
||||
if (!IsElementInWidget(aElement))
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIRDFResource> resource;
|
||||
rv = nsRDFContentUtils::GetElementRefResource(aElement, getter_AddRefs(resource));
|
||||
|
||||
// If it has no resource, there's nothing that we need to be
|
||||
// concerned about here.
|
||||
if (NS_FAILED(rv))
|
||||
return NS_OK;
|
||||
|
||||
// The element has a resource; that means that it corresponds
|
||||
// to something in the graph, so we need to go to the graph to
|
||||
// create its contents.
|
||||
rv = CreateContainerContents(aElement, resource, PR_TRUE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (rv == NS_RDF_ELEMENT_WAS_CREATED) {
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
rv = aElement->GetTag(*getter_AddRefs(tag));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (tag.get() == kTreeItemAtom) {
|
||||
nsCOMPtr<nsIContent> insertionpoint;
|
||||
rv = FindInsertionPoint(aElement, getter_AddRefs(insertionpoint));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (! insertionpoint) {
|
||||
// No content got built. Bail!
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Find the first element beneath the insertion point that
|
||||
// is generated from a template.
|
||||
PRInt32 indx;
|
||||
rv = FindFirstGeneratedChild(insertionpoint, &indx);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (indx != -1) {
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(mDocument);
|
||||
if (! doc)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
rv = doc->ContentAppended(insertionpoint, indx);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFGenericBuilderImpl::CloseContainer(nsIContent* aElement)
|
||||
{
|
||||
NS_PRECONDITION(aElement != nsnull, "null ptr");
|
||||
if (! aElement)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// First, make sure that the element is in the right widget -- ours.
|
||||
if (!IsElementInWidget(aElement))
|
||||
return NS_OK;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
rv = aElement->GetTag(*getter_AddRefs(tag));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// If it's not a tree, just bail. Keep the content around until
|
||||
// the cows come home.
|
||||
if (tag.get() != kTreeItemAtom)
|
||||
return NS_OK;
|
||||
|
||||
// Find the tag that contains the children so that we can remove
|
||||
// all of the children.
|
||||
//
|
||||
// XXX We do this as a (premature?) optimization so that nodes
|
||||
// which are not being displayed don't hang around taking up
|
||||
// space. Unfortunately, the tree widget currently _relies_ on
|
||||
// this behavior and will break if we don't do it :-(.
|
||||
nsCOMPtr<nsIContent> insertionpoint;
|
||||
rv = FindInsertionPoint(aElement, getter_AddRefs(insertionpoint));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (insertionpoint) {
|
||||
PRInt32 count;
|
||||
rv = insertionpoint->ChildCount(count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = RemoveGeneratedContent(insertionpoint);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
// Clear the contents-generated attribute so that the next time we
|
||||
// come back, we'll regenerate the kids we just killed.
|
||||
rv = aElement->UnsetAttribute(kNameSpaceID_None,
|
||||
kContainerContentsGeneratedAtom,
|
||||
PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// XXX Hack. Setting this attribute forces the RDF element to
|
||||
// remember that it needs to be re-generated next time around.
|
||||
rv = aElement->SetAttribute(kNameSpaceID_None,
|
||||
kLazyContentAtom,
|
||||
"true",
|
||||
PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFGenericBuilderImpl::RebuildContainer(nsIContent* aElement)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// Remove any generated children from this node
|
||||
rv = RemoveGeneratedContent(aElement);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Clear the contents-generated attribute so that the next time we
|
||||
// come back, we'll regenerate the kids we just killed.
|
||||
rv = aElement->UnsetAttribute(kNameSpaceID_None,
|
||||
kContainerContentsGeneratedAtom,
|
||||
PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// XXX Hack. Setting this attribute forces the RDF element to
|
||||
// remember that it needs to be re-generated next time around.
|
||||
rv = aElement->SetAttribute(kNameSpaceID_None,
|
||||
kLazyContentAtom,
|
||||
"true",
|
||||
PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Since we're changing the 'ref' attribute, we'll need to
|
||||
// rebuild content for _this_ resource template, too.
|
||||
rv = aElement->UnsetAttribute(kNameSpaceID_None,
|
||||
kTemplateContentsGeneratedAtom,
|
||||
PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Do it!!!
|
||||
rv = CreateContents(aElement);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Now see where on earth the content was _really_ appended so we
|
||||
// can tell the frames to go reflow themselves. Start with _this_
|
||||
// element.
|
||||
nsCOMPtr<nsIContent> insertionpoint = dont_QueryInterface(aElement);
|
||||
|
||||
PRInt32 indx;
|
||||
rv = FindFirstGeneratedChild(insertionpoint, &indx);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (indx == -1) {
|
||||
// Okay, nothing got inserted directly beneath this node; see
|
||||
// if the it was inserted somewhere _below_ us...
|
||||
rv = FindInsertionPoint(aElement, getter_AddRefs(insertionpoint));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if ((insertionpoint != nsnull) && (insertionpoint.get() != aElement)) {
|
||||
rv = FindFirstGeneratedChild(insertionpoint, &indx);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
|
||||
if (indx != -1) {
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(mDocument);
|
||||
|
||||
rv = doc->ContentAppended(insertionpoint, indx);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFGenericBuilderImpl::CreateElement(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aTag,
|
||||
|
@ -634,27 +1066,19 @@ RDFGenericBuilderImpl::OnAssert(nsIRDFResource* aSource,
|
|||
|
||||
// Okay, it's a "live" element, so go ahead and append the new
|
||||
// child to this node.
|
||||
|
||||
// XXX Bug 10818.
|
||||
PRBool notify = PR_TRUE;
|
||||
if (IsTreeWidgetItem(element)) {
|
||||
if (!IsReflowScheduled()) {
|
||||
rv = ScheduleReflow();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
else {
|
||||
// a reflow has been scheduled. we'll add the
|
||||
// element but won't notify right now.
|
||||
notify = PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
rv = CreateWidgetItem(element, aProperty, resource, 0, notify);
|
||||
rv = CreateWidgetItem(element, aProperty, resource, 0, PR_TRUE);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create widget item");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = element->SetAttribute(kNameSpaceID_None, kEmptyAtom, "false", PR_TRUE);
|
||||
|
||||
// Update the "empty" attribute
|
||||
nsAutoString empty;
|
||||
rv = element->GetAttribute(kNameSpaceID_None, kEmptyAtom, empty);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if ((rv != NS_CONTENT_ATTR_HAS_VALUE) || (! empty.Equals("false"))) {
|
||||
rv = element->SetAttribute(kNameSpaceID_None, kEmptyAtom, "false", PR_TRUE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Either the target of the assertion is not a resource,
|
||||
|
@ -762,8 +1186,14 @@ RDFGenericBuilderImpl::OnUnassert(nsIRDFResource* aSource,
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (numKids == 0) {
|
||||
rv = element->SetAttribute(kNameSpaceID_None, kEmptyAtom, "true", PR_TRUE);
|
||||
nsAutoString empty;
|
||||
rv = element->GetAttribute(kNameSpaceID_None, kEmptyAtom, empty);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if ((rv != NS_CONTENT_ATTR_HAS_VALUE) && (! empty.Equals("true"))) {
|
||||
rv = element->SetAttribute(kNameSpaceID_None, kEmptyAtom, "true", PR_TRUE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1020,7 +1450,7 @@ RDFGenericBuilderImpl::GetPersistentAttributes(nsIContent *element)
|
|||
literal->GetValueConst(&uniLiteral);
|
||||
if (uniLiteral)
|
||||
{
|
||||
rv = element->SetAttribute(nameSpaceID, tag, uniLiteral, PR_TRUE);
|
||||
rv = element->SetAttribute(nameSpaceID, tag, uniLiteral, PR_FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1430,7 +1860,7 @@ RDFGenericBuilderImpl::BuildContentFromTemplate(nsIContent *aTemplateNode,
|
|||
|
||||
nsCOMPtr<nsIContent> realKid;
|
||||
if (aIsUnique) {
|
||||
rv = EnsureElementHasGenericChild(aRealNode, nameSpaceID, tag, getter_AddRefs(realKid));
|
||||
rv = EnsureElementHasGenericChild(aRealNode, nameSpaceID, tag, aNotify, getter_AddRefs(realKid));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (rv == NS_RDF_ELEMENT_WAS_THERE) {
|
||||
|
@ -1489,7 +1919,7 @@ RDFGenericBuilderImpl::BuildContentFromTemplate(nsIContent *aTemplateNode,
|
|||
rv = content->SetText(text.GetUnicode(), text.Length(), PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = aRealNode->AppendChildTo(nsCOMPtr<nsIContent>( do_QueryInterface(content) ), PR_FALSE);
|
||||
rv = aRealNode->AppendChildTo(nsCOMPtr<nsIContent>( do_QueryInterface(content) ), aNotify);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
|
@ -1564,15 +1994,14 @@ RDFGenericBuilderImpl::BuildContentFromTemplate(nsIContent *aTemplateNode,
|
|||
|
||||
// We'll _already_ have added the unique elements.
|
||||
if (! aIsUnique) {
|
||||
// Note: add into tree, but only sort if its a resource element!
|
||||
if ((nsnull != XULSortService) && (isResourceElement)) {
|
||||
rv = XULSortService->InsertContainerNode(aRealNode, realKid, aNotify);
|
||||
if (NS_FAILED(rv)) {
|
||||
aRealNode->AppendChildTo(realKid, aNotify);
|
||||
}
|
||||
// Add into content model, special casing treeitems.
|
||||
if ((nsnull != gXULSortService) && (isResourceElement) && (tag.get() == kTreeItemAtom)) {
|
||||
rv = gXULSortService->InsertContainerNode(aRealNode, realKid, aNotify);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to insert element via sort service");
|
||||
}
|
||||
else {
|
||||
aRealNode->AppendChildTo(realKid, aNotify);
|
||||
rv = aRealNode->AppendChildTo(realKid, aNotify);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to insert element");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1605,12 +2034,8 @@ RDFGenericBuilderImpl::CreateWidgetItem(nsIContent *aElement,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
rv = BuildContentFromTemplate(tmpl,
|
||||
aElement,
|
||||
PR_TRUE,
|
||||
aChild,
|
||||
aNaturalOrderPos,
|
||||
aNotify);
|
||||
rv = BuildContentFromTemplate(tmpl, aElement, PR_TRUE, aChild, aNaturalOrderPos, aNotify);
|
||||
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to build content from template");
|
||||
return rv;
|
||||
}
|
||||
|
@ -1777,7 +2202,7 @@ RDFGenericBuilderImpl::RemoveWidgetItem(nsIContent* aElement,
|
|||
|
||||
|
||||
nsresult
|
||||
RDFGenericBuilderImpl::CreateContainerContents(nsIContent* aElement, nsIRDFResource* aResource)
|
||||
RDFGenericBuilderImpl::CreateContainerContents(nsIContent* aElement, nsIRDFResource* aResource, PRBool aNotify)
|
||||
{
|
||||
// Create the contents of a container by iterating over all of the
|
||||
// "containment" arcs out of the element's resource.
|
||||
|
@ -1801,7 +2226,7 @@ RDFGenericBuilderImpl::CreateContainerContents(nsIContent* aElement, nsIRDFResou
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if ((rv == NS_CONTENT_ATTR_HAS_VALUE) && (attrValue.EqualsIgnoreCase("true")))
|
||||
return NS_OK;
|
||||
return NS_RDF_ELEMENT_WAS_CREATED;
|
||||
|
||||
// Now mark the element's contents as being generated so that
|
||||
// any re-entrant calls don't trigger an infinite recursion.
|
||||
|
@ -1821,11 +2246,6 @@ RDFGenericBuilderImpl::CreateContainerContents(nsIContent* aElement, nsIRDFResou
|
|||
rv = mDB->ArcLabelsOut(aResource, getter_AddRefs(properties));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// rjc - sort
|
||||
nsCOMPtr<nsISupportsArray> tempArray;
|
||||
rv = NS_NewISupportsArray(getter_AddRefs(tempArray));
|
||||
if NS_FAILED(rv) return rv;
|
||||
|
||||
while (1) {
|
||||
PRBool hasMore;
|
||||
rv = properties->HasMoreElements(&hasMore);
|
||||
|
@ -1865,74 +2285,13 @@ RDFGenericBuilderImpl::CreateContainerContents(nsIContent* aElement, nsIRDFResou
|
|||
rv = targets->GetNext(getter_AddRefs(isupportsNext));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIRDFResource> valueResource = do_QueryInterface(isupportsNext);
|
||||
NS_ASSERTION(valueResource != nsnull, "not a resource");
|
||||
if (! valueResource)
|
||||
nsCOMPtr<nsIRDFResource> target = do_QueryInterface(isupportsNext);
|
||||
NS_ASSERTION(target != nsnull, "not a resource");
|
||||
if (! target)
|
||||
continue;
|
||||
|
||||
// XXX hack: always append value resource 1st due to sort
|
||||
// callback implementation
|
||||
tempArray->AppendElement(valueResource);
|
||||
tempArray->AppendElement(property);
|
||||
}
|
||||
}
|
||||
|
||||
PRUint32 numElements;
|
||||
rv = tempArray->Count(&numElements);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (numElements == 0)
|
||||
return NS_OK;
|
||||
|
||||
// Tree widget hackery. To be removed if and when the
|
||||
// reflow lock is exposed. See bug 10818.
|
||||
PRBool istree = IsTreeWidgetItem(aElement);
|
||||
|
||||
{
|
||||
// XXX change to use nsVoidArray?
|
||||
nsIRDFResource** flatArray = new nsIRDFResource*[numElements];
|
||||
if (! flatArray) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// flatten array of resources, sort them, then add as item elements
|
||||
PRUint32 loop;
|
||||
for (loop=0; loop<numElements; loop++)
|
||||
flatArray[loop] = (nsIRDFResource *)tempArray->ElementAt(loop);
|
||||
|
||||
if (XULSortService) {
|
||||
XULSortService->OpenContainer(mDB, aElement, flatArray, numElements/2, 2*sizeof(nsIRDFResource *));
|
||||
}
|
||||
|
||||
// This will insert all of the elements into the
|
||||
// container, but _won't_ bother layout about it.
|
||||
for (loop=0; loop<numElements; loop+=2) {
|
||||
rv = CreateWidgetItem(aElement, flatArray[loop+1], flatArray[loop], loop+1, PR_FALSE);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create widget item");
|
||||
if (NS_FAILED(rv)) break;
|
||||
}
|
||||
|
||||
for (PRInt32 i = PRInt32(numElements) - 1; i >=0; i--) {
|
||||
NS_IF_RELEASE(flatArray[i]);
|
||||
}
|
||||
|
||||
delete [] flatArray;
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
if (istree) {
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(mDocument);
|
||||
if (! doc)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIContent> treechildren;
|
||||
rv = nsRDFContentUtils::FindChildByTag(aElement,
|
||||
kNameSpaceID_XUL,
|
||||
kTreeChildrenAtom,
|
||||
getter_AddRefs(treechildren));
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// _Now_ tell layout that we've mucked with the container. This'll
|
||||
// force a reflow and get the content displayed.
|
||||
rv = doc->ContentAppended(treechildren, 0);
|
||||
rv = CreateWidgetItem(aElement, property, target, -1, aNotify);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create item");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
|
@ -2000,7 +2359,7 @@ RDFGenericBuilderImpl::CreateTemplateContents(nsIContent* aElement, const nsStri
|
|||
element = parent;
|
||||
}
|
||||
|
||||
rv = BuildContentFromTemplate(tmpl, aElement, PR_FALSE, resource, -1, PR_TRUE);
|
||||
rv = BuildContentFromTemplate(tmpl, aElement, PR_FALSE, resource, -1, PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
|
@ -2010,6 +2369,7 @@ nsresult
|
|||
RDFGenericBuilderImpl::EnsureElementHasGenericChild(nsIContent* parent,
|
||||
PRInt32 nameSpaceID,
|
||||
nsIAtom* tag,
|
||||
PRBool aNotify,
|
||||
nsIContent** result)
|
||||
{
|
||||
nsresult rv;
|
||||
|
@ -2026,7 +2386,7 @@ RDFGenericBuilderImpl::EnsureElementHasGenericChild(nsIContent* parent,
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// XXX Note that the notification ensures we won't batch insertions! This could be bad! - Dave
|
||||
rv = parent->AppendChildTo(element, PR_TRUE);
|
||||
rv = parent->AppendChildTo(element, aNotify);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
*result = element;
|
||||
|
@ -2381,6 +2741,109 @@ RDFGenericBuilderImpl::GetResource(PRInt32 aNameSpaceID,
|
|||
}
|
||||
|
||||
|
||||
nsresult
|
||||
RDFGenericBuilderImpl::FindInsertionPoint(nsIContent* aElement, nsIContent** aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// XXX Hack-o-rama. This needs to be fixed to actually grovel over
|
||||
// the template n' stuff.
|
||||
nsCOMPtr<nsIAtom> tag;
|
||||
rv = aElement->GetTag(*getter_AddRefs(tag));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsAutoString tagName;
|
||||
rv = tag->ToString(tagName);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (tagName.Equals("tree") || tagName.Equals("treeitem")) {
|
||||
rv = nsRDFContentUtils::FindChildByTag(aElement, kNameSpaceID_XUL, NS_NewAtom("treechildren"), aResult);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
else if (tagName.Equals("menu")) {
|
||||
rv = nsRDFContentUtils::FindChildByTag(aElement, kNameSpaceID_XUL, NS_NewAtom("menupopup"), aResult);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
else {
|
||||
*aResult = aElement;
|
||||
NS_ADDREF(*aResult);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
RDFGenericBuilderImpl::RemoveGeneratedContent(nsIContent* aElement)
|
||||
{
|
||||
// Remove all the content beneath aElement that has been generated
|
||||
// from a template.
|
||||
|
||||
nsresult rv;
|
||||
|
||||
PRInt32 count;
|
||||
rv = aElement->ChildCount(count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
while (--count >= 0) {
|
||||
nsCOMPtr<nsIContent> child;
|
||||
rv = aElement->ChildAt(count, *getter_AddRefs(child));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsAutoString tmplID;
|
||||
rv = child->GetAttribute(kNameSpaceID_None, kTemplateAtom, tmplID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (rv != NS_CONTENT_ATTR_HAS_VALUE)
|
||||
continue;
|
||||
|
||||
// It's a generated element. Remove it, and set its document
|
||||
// to null so that it'll get knocked out of the XUL doc's
|
||||
// resource-to-element map.
|
||||
rv = aElement->RemoveChildAt(count, PR_TRUE);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "error removing child");
|
||||
|
||||
rv = child->SetDocument(nsnull, PR_TRUE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
RDFGenericBuilderImpl::FindFirstGeneratedChild(nsIContent* aElement, PRInt32* aIndex)
|
||||
{
|
||||
// Find the first kid of aElement that has been generated from a
|
||||
// template.
|
||||
|
||||
nsresult rv;
|
||||
|
||||
PRInt32 count;
|
||||
rv = aElement->ChildCount(count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRInt32 i = 0;
|
||||
while (i < count) {
|
||||
nsCOMPtr<nsIContent> child;
|
||||
rv = aElement->ChildAt(i, *getter_AddRefs(child));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsAutoString tmplID;
|
||||
rv = child->GetAttribute(kNameSpaceID_None, kTemplateAtom, tmplID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (rv == NS_CONTENT_ATTR_HAS_VALUE)
|
||||
break;
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
*aIndex = (i < count) ? i : -1;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
RDFGenericBuilderImpl::IsTreeWidgetItem(nsIContent* aElement)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче