diff --git a/rdf/src/nsRDFDataModel.cpp b/rdf/src/nsRDFDataModel.cpp index f48d0ab3cb3..221ad974581 100644 --- a/rdf/src/nsRDFDataModel.cpp +++ b/rdf/src/nsRDFDataModel.cpp @@ -72,6 +72,7 @@ static NS_DEFINE_IID(kIDataModelIID, NS_IDATAMODEL_IID); NS_IMPL_QUERY_INTERFACE(nsRDFDataModel, kIDataModelIID); //////////////////////////////////////////////////////////////////////// +// nsIDataModel interface NS_IMETHODIMP nsRDFDataModel::InitFromURL(const nsString& url) @@ -134,8 +135,10 @@ nsRDFDataModel::Initialize(const nsString& aUrl) PL_strfree(const_cast(dbstr[0])); RDF_Resource r = RDF_GetResource(mDB, url, PR_TRUE); - if ((mRoot = new nsRDFDataModelItem(*this, r)) != NULL) + if ((mRoot = new nsRDFDataModelItem(*this, r)) != NULL) { mRoot->AddRef(); + mRoot->SetOpenState(PR_TRUE); + } delete url; } diff --git a/rdf/src/nsRDFDataModel.h b/rdf/src/nsRDFDataModel.h index 10dd7b5a5c3..b3d4d2aa861 100644 --- a/rdf/src/nsRDFDataModel.h +++ b/rdf/src/nsRDFDataModel.h @@ -41,8 +41,8 @@ private: nsRDFDataModelItem* mRoot; nsIDMWidget* mWidget; - RDF_Resource mArcProperty; - nsRDFArcType mArcType; + RDF_Resource mArcProperty; + nsRDFArcType mArcType; public: nsRDFDataModel(void); @@ -97,6 +97,9 @@ public: nsRDFArcType GetArcType(void) const { return mArcType; } + + virtual NS_METHOD + CreateItem(RDF_Resource r, nsRDFDataModelItem*& result) = 0; }; #endif // nsRDFDataModel_h__ diff --git a/rdf/src/nsRDFDataModelItem.cpp b/rdf/src/nsRDFDataModelItem.cpp index e6f5fb97f83..faf241519c0 100644 --- a/rdf/src/nsRDFDataModelItem.cpp +++ b/rdf/src/nsRDFDataModelItem.cpp @@ -16,6 +16,7 @@ * Reserved. */ +#include "nsRDFDataModel.h" #include "nsRDFDataModelItem.h" //////////////////////////////////////////////////////////////////////// @@ -33,6 +34,10 @@ nsRDFDataModelItem::nsRDFDataModelItem(nsRDFDataModel& model, RDF_Resource resou nsRDFDataModelItem::~nsRDFDataModelItem(void) { + for (PRUint32 i = 0; i < mChildren.GetSize(); ++i) { + nsRDFDataModelItem* child = static_cast(mChildren[i]); + child->Release(); + } } NS_IMPL_ADDREF(nsRDFDataModelItem); @@ -42,6 +47,7 @@ static NS_DEFINE_IID(kIDMItemIID, NS_IDMITEM_IID); NS_IMPL_QUERY_INTERFACE(nsRDFDataModelItem, kIDMItemIID); //////////////////////////////////////////////////////////////////////// +// nsIDMItem interface NS_IMETHODIMP nsRDFDataModelItem::GetIconImage(nsIImage*& image, nsIImageGroup* group) const @@ -58,6 +64,18 @@ nsRDFDataModelItem::GetOpenState(PRBool& result) const return NS_OK; } +// XXX I assume this is coming... +NS_IMETHODIMP +nsRDFDataModelItem::SetOpenState(PRBool open) +{ + if (open) + Open(); + else + Close(); + + return NS_OK; +} + NS_IMETHODIMP nsRDFDataModelItem::GetChildCount(PRUint32& count) const { @@ -147,12 +165,20 @@ nsRDFDataModelItem::GetSubtreeSize(void) const nsRDFDataModelItem* nsRDFDataModelItem::GetNth(PRUint32 n) const { + // XXX this algorithm sucks: it's O(m*log(n)), where m is the + // branching factor and n is the depth of the tree. We need to + // eventually do something like the old HT did: keep a + // vector. Alternatively, hyatt suggested that is we can keep a + // pointer to the topmost node, m will be kept small. + if (n == 0) return const_cast(this); - PRUint32 upperBound = mChildren.GetUpperBound(); + // iterate through all of the children. since we know the subtree + // height of each child, we can determine a range of indices + // contained within the subtree. PRUint32 firstIndexInSubtree = 1; - for (PRUint32 i = 0; i < upperBound; ++i) { + for (PRUint32 i = 0; i < mChildren.GetSize(); ++i) { nsRDFDataModelItem* child = static_cast(mChildren[i]); @@ -167,3 +193,58 @@ nsRDFDataModelItem::GetNth(PRUint32 n) const PR_ASSERT(0); return NULL; } + + +void +nsRDFDataModelItem::Open(void) +{ + RDF_Cursor cursor; + if (mDataModel.GetArcType() == eRDFArcType_Outbound) { + // Arcs are outbound, that is, from a parent to it's + // child. Find all arcs whose source is "me". + cursor = RDF_GetSources(mDataModel.GetDB(), + GetResource(), + mDataModel.GetArcProperty(), + RDF_RESOURCE_TYPE, + PR_TRUE); + } + else { + // Arcs are inbound, that is, from a child to it's + // parent. Find all arcs whose target is "me". + cursor = RDF_GetTargets(mDataModel.GetDB(), + GetResource(), + mDataModel.GetArcProperty(), + RDF_RESOURCE_TYPE, + PR_TRUE); + } + + if (cursor) { + PRUint32 index = 0; + RDF_Resource r; + while ((r = static_cast(RDF_NextValue(cursor))) != NULL) { + nsRDFDataModelItem* child; + if (NS_FAILED(mDataModel.CreateItem(r, child))) + continue; + + mChildren[index++] = child; + child->mParent = this; + } + RDF_DisposeCursor(cursor); + } + + InvalidateCachedSubtreeSize(); + mOpen = PR_TRUE; +} + + +void +nsRDFDataModelItem::Close(void) +{ + for (PRUint32 i = 0; i < mChildren.GetSize(); ++i) { + nsRDFDataModelItem* child = static_cast(mChildren[i]); + child->Release(); + } + + InvalidateCachedSubtreeSize(); + mOpen = PR_FALSE; +} diff --git a/rdf/src/nsRDFDataModelItem.h b/rdf/src/nsRDFDataModelItem.h index 7c97cd67650..57dcca4ede6 100644 --- a/rdf/src/nsRDFDataModelItem.h +++ b/rdf/src/nsRDFDataModelItem.h @@ -34,7 +34,13 @@ private: PRBool mOpen; nsVector mChildren; nsRDFDataModelItem* mParent; - mutable PRUint32 mCachedSubtreeSize; + + /** + * A cached value for the size of this item's subtree. Zero means "invalid" + * or "unknown", and the next call to GetSubtreeSize() will force it to be + * recomputed. + */ + mutable PRUint32 mCachedSubtreeSize; PRUint32 GetSubtreeSize(void) const; void InvalidateCachedSubtreeSize(void); @@ -63,6 +69,7 @@ public: NS_IMETHOD GetParent(nsIDMItem*& pItem) const; // Setters + NS_IMETHOD SetOpenState(PRBool state); // XXX not there yet... // Methods to query the data model for a specific item displayed within the widget. NS_IMETHOD GetStringPropertyValue(nsString& value, const nsString& itemProperty) const; @@ -82,9 +89,8 @@ public: return mOpen; } - void SetOpenState(PRBool open) { - mOpen = open; - } + void Open(void); + void Close(void); nsRDFDataModelItem* ChildAt(PRUint32 index) const { return static_cast(mChildren[index]); diff --git a/rdf/src/nsRDFToolbarDataModel.cpp b/rdf/src/nsRDFToolbarDataModel.cpp index 462c183be6b..58251052d25 100644 --- a/rdf/src/nsRDFToolbarDataModel.cpp +++ b/rdf/src/nsRDFToolbarDataModel.cpp @@ -17,6 +17,7 @@ */ #include "nsRDFToolbarDataModel.h" +#include "nsRDFToolbarDataModelItem.h" static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_IID(kIDataModelIID, NS_IDATAMODEL_IID); @@ -112,3 +113,18 @@ nsRDFToolbarDataModel::GetIntPropertyValue(PRInt32& value, const nsString& prope //////////////////////////////////////////////////////////////////////// // nsIToolbarDataModel interface + + + +//////////////////////////////////////////////////////////////////////// +// Implementation methods + +NS_METHOD +nsRDFToolbarDataModel::CreateItem(RDF_Resource r, nsRDFDataModelItem*& result) +{ + result = new nsRDFToolbarDataModelItem(*this, r); + if (! result) + return NS_ERROR_OUT_OF_MEMORY; + + return NS_OK; +} diff --git a/rdf/src/nsRDFToolbarDataModel.h b/rdf/src/nsRDFToolbarDataModel.h index 17935b76762..e69de29bb2d 100644 --- a/rdf/src/nsRDFToolbarDataModel.h +++ b/rdf/src/nsRDFToolbarDataModel.h @@ -1,70 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * The contents of this file are subject to the Netscape Public License - * Version 1.0 (the "NPL"); you may not use this file except in - * compliance with the NPL. You may obtain a copy of the NPL at - * http://www.mozilla.org/NPL/ - * - * Software distributed under the NPL is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL - * for the specific language governing rights and limitations under the - * NPL. - * - * The Initial Developer of this code under the NPL is Netscape - * Communications Corporation. Portions created by Netscape are - * Copyright (C) 1998 Netscape Communications Corporation. All Rights - * Reserved. - */ - -#ifndef nsRDFToolbarDataModel_h__ -#define nsRDFToolbarDataModel_h__ - -#include "nsRDFDataModel.h" -#include "nsIToolbarDataModel.h" -#include "rdf.h" - -//////////////////////////////////////////////////////////////////////// - -/** - * An implementation for the Toolbar widget model. - */ -class nsRDFToolbarDataModel : public nsIToolbarDataModel, public nsRDFDataModel { -public: - nsRDFToolbarDataModel(void); - virtual ~nsRDFToolbarDataModel(void); - - //////////////////////////////////////////////////////////////////////// - // nsISupports interface -- delegates to superclass - - NS_IMETHOD_(nsrefcnt) AddRef(void); - NS_IMETHOD_(nsrefcnt) Release(void); - NS_IMETHOD QueryInterface(const nsIID& iid, void** result); - - //////////////////////////////////////////////////////////////////////// - // nsIDataModel interface -- delegates to superclass - - // Initializers - NS_IMETHOD InitFromURL(const nsString& url); - NS_IMETHOD InitFromResource(nsIDMItem* pResource); - - // Inspectors - NS_IMETHOD GetDMWidget(nsIDMWidget*& pWidget) const; - - // Setters - NS_IMETHOD SetDMWidget(nsIDMWidget* pWidget); - - // Methods to query the data model for property values for an entire widget. - NS_IMETHOD GetStringPropertyValue(nsString& value, const nsString& property) const; - NS_IMETHOD GetIntPropertyValue(PRInt32& value, const nsString& property) const; - - //////////////////////////////////////////////////////////////////////// - // nsIToolbarDataModel interface - - - -private: -}; - - - -#endif // nsRDFToolbarDataModel_h__ diff --git a/rdf/src/nsRDFTreeDataModel.cpp b/rdf/src/nsRDFTreeDataModel.cpp index 62c264edab0..add6217a1ac 100644 --- a/rdf/src/nsRDFTreeDataModel.cpp +++ b/rdf/src/nsRDFTreeDataModel.cpp @@ -36,7 +36,7 @@ nsRDFTreeDataModel::nsRDFTreeDataModel(void) nsRDFTreeDataModel::~nsRDFTreeDataModel(void) { - for (PRUint32 i = mColumns.GetUpperBound(); i >= 0; --i) { + for (PRUint32 i = 0; i < mColumns.GetSize(); ++i) { nsRDFTreeColumn* column = static_cast(mColumns[i]); PR_ASSERT(column); @@ -126,7 +126,7 @@ NS_IMETHODIMP nsRDFTreeDataModel::GetVisibleColumnCount(PRUint32& count) const { count = 0; - for (PRInt32 i = mColumns.GetUpperBound(); i >= 0; --i) { + for (PRUint32 i = 0; i < mColumns.GetSize(); ++i) { nsRDFTreeColumn* column = static_cast(mColumns.Get(i)); if (column->IsVisible()) ++count; @@ -170,6 +170,11 @@ nsRDFTreeDataModel::GetNthTreeItem(nsITreeDMItem*& pItem, PRUint32 n) const return NS_ERROR_NOT_IMPLEMENTED; } +#ifdef DYNAMIC_CASTING +#define DYNAMIC_CAST(__type, __pointer) dynamic_cast<__type>(__pointer) +#else +#define DYNAMIC_CAST(__type, __pointer) ((__type)(__pointer)) +#endif NS_IMETHODIMP nsRDFTreeDataModel::GetItemTextForColumn(nsString& nodeText, @@ -182,14 +187,14 @@ nsRDFTreeDataModel::GetItemTextForColumn(nsString& nodeText, // XXX may need to turn off the dynamic_cast stuff... nsRDFTreeDataModelItem* item = - dynamic_cast(pItem); + DYNAMIC_CAST(nsRDFTreeDataModelItem*, pItem); PR_ASSERT(item); if (! item) return NS_ERROR_UNEXPECTED; // XXX nsRDFTreeColumn* column = - dynamic_cast(pColumn); + DYNAMIC_CAST(nsRDFTreeColumn*, pColumn); PR_ASSERT(column); if (! column) @@ -273,3 +278,14 @@ nsRDFTreeDataModel::AddColumn(const nsString& name, RDF_Resource property) nsRDFTreeColumn* column = new nsRDFTreeColumn(*this, name, property); mColumns.Add(column); } + + +NS_METHOD +nsRDFTreeDataModel::CreateItem(RDF_Resource r, nsRDFDataModelItem*& result) +{ + result = new nsRDFTreeDataModelItem(*this, r); + if (! result) + return NS_ERROR_OUT_OF_MEMORY; + + return NS_OK; +} diff --git a/rdf/src/nsRDFTreeDataModel.h b/rdf/src/nsRDFTreeDataModel.h index ecd79a4dfb0..3dd27eb6dfc 100644 --- a/rdf/src/nsRDFTreeDataModel.h +++ b/rdf/src/nsRDFTreeDataModel.h @@ -74,9 +74,13 @@ public: NS_IMETHOD GetItemTextForColumn(nsString& nodeText, nsITreeDMItem* pItem, nsITreeColumn* pColumn) const; //////////////////////////////////////////////////////////////////////// + // Implemantation methods void AddColumn(const nsString& name, RDF_Resource property); + virtual NS_METHOD + CreateItem(RDF_Resource r, nsRDFDataModelItem*& result); + private: nsVector mColumns;