diff --git a/content/xul/templates/src/nsXULSortService.cpp b/content/xul/templates/src/nsXULSortService.cpp index 2ae8636cbe35..337e16d05917 100644 --- a/content/xul/templates/src/nsXULSortService.cpp +++ b/content/xul/templates/src/nsXULSortService.cpp @@ -20,6 +20,37 @@ This file provides the implementation for the sort service manager. */ +#include "nsCOMPtr.h" +#include "nsCRT.h" +#include "nsIAtom.h" +#include "nsIContent.h" +#include "nsIDOMElement.h" +#include "nsIDOMElementObserver.h" +#include "nsIDOMNode.h" +#include "nsIDOMNodeObserver.h" +#include "nsIDocument.h" +#include "nsINameSpaceManager.h" +#include "nsIRDFContentModelBuilder.h" +#include "nsIRDFCursor.h" +#include "nsIRDFCompositeDataSource.h" +#include "nsIRDFDocument.h" +#include "nsIRDFNode.h" +#include "nsIRDFObserver.h" +#include "nsIRDFService.h" +#include "nsIServiceManager.h" +#include "nsINameSpaceManager.h" +#include "nsIServiceManager.h" +#include "nsISupportsArray.h" +#include "nsIURL.h" +#include "nsLayoutCID.h" +#include "nsRDFCID.h" +#include "nsRDFContentUtils.h" +#include "nsString.h" +#include "rdf.h" +#include "rdfutil.h" + +#include "nsVoidArray.h" +#include "rdf_qsort.h" #include "nsIAtom.h" #include "nsIXULSortService.h" #include "nsString.h" @@ -42,8 +73,11 @@ #include "nsIDOMNode.h" #include "nsIDOMElement.h" -#include "nsIRDFContentModelBuilder.h" +#include "nsIRDFContentModelBuilder.h" +#include "nsIRDFCompositeDataSource.h" +#include "nsIRDFNode.h" +#include "nsIRDFService.h" #include "rdf.h" @@ -62,6 +96,11 @@ static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID); static NS_DEFINE_IID(kIDomNodeIID, NS_IDOMNODE_IID); static NS_DEFINE_IID(kIDomElementIID, NS_IDOMELEMENT_IID); +static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); +static NS_DEFINE_IID(kIRDFServiceIID, NS_IRDFSERVICE_IID); +static NS_DEFINE_IID(kIRDFResourceIID, NS_IRDFRESOURCE_IID); +static NS_DEFINE_IID(kIRDFLiteralIID, NS_IRDFLITERAL_IID); + // XXX This is sure to change. Copied from mozilla/layout/xul/content/src/nsXULAtoms.cpp static const char kXULNameSpaceURI[] = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; @@ -91,16 +130,25 @@ private: static nsIAtom *kTreeItemAtom; static nsIAtom *kResourceAtom; static nsIAtom *kTreeContentsGeneratedAtom; + static nsIAtom *kNameAtom; + static nsIAtom *kSortAtom; + static nsIAtom *kSortDirectionAtom; + static nsIAtom *kIdAtom; + static nsIAtom *kNaturalOrderPosAtom; + static PRInt32 kNameSpaceID_XUL; static PRInt32 kNameSpaceID_RDF; + static nsIRDFService *gRDFService; + nsresult FindTreeElement(nsIContent* aElement,nsIContent** aTreeElement); nsresult FindTreeBodyElement(nsIContent *tree, nsIContent **treeBody); -nsresult GetSortColumnIndex(nsIContent *tree, nsString sortResource, PRInt32 *colIndex); +nsresult GetSortColumnIndex(nsIContent *tree, nsString sortResource, nsString sortDirection, PRInt32 *colIndex); +nsresult GetSortColumnInfo(nsIContent *tree, nsString &sortResource, nsString &sortDirection); nsresult GetTreeCell(nsIContent *node, PRInt32 colIndex, nsIContent **cell); nsresult GetTreeCellValue(nsIContent *node, nsString & value); nsresult RemoveAllChildren(nsIContent *node); -nsresult SortTreeChildren(nsIContent *container, PRInt32 colIndex, PRInt32 indentLevel); +nsresult SortTreeChildren(nsIContent *container, PRInt32 colIndex, nsString sortDirection, PRInt32 indentLevel); nsresult PrintTreeChildren(nsIContent *container, PRInt32 colIndex, PRInt32 indentLevel); public: @@ -111,12 +159,16 @@ public: NS_DECL_ISUPPORTS // nsISortService - NS_IMETHOD DoSort(nsIDOMNode* node, const nsString& sortResource); + NS_IMETHOD DoSort(nsIDOMNode* node, const nsString& sortResource, const nsString& sortDirection); + NS_IMETHOD OpenContainer(nsIRDFCompositeDataSource *db, nsIContent *container, nsIRDFResource **flatArray, + PRInt32 numElements, PRInt32 elementSize); }; nsIXULSortService* XULSortServiceImpl::gXULSortService = nsnull; nsrefcnt XULSortServiceImpl::gRefCnt = 0; +nsIRDFService *XULSortServiceImpl::gRDFService = nsnull; + nsIAtom* XULSortServiceImpl::kTreeAtom; nsIAtom* XULSortServiceImpl::kTreeBodyAtom; nsIAtom* XULSortServiceImpl::kTreeCellAtom; @@ -125,6 +177,12 @@ nsIAtom* XULSortServiceImpl::kTreeColAtom; nsIAtom* XULSortServiceImpl::kTreeItemAtom; nsIAtom* XULSortServiceImpl::kResourceAtom; nsIAtom* XULSortServiceImpl::kTreeContentsGeneratedAtom; +nsIAtom* XULSortServiceImpl::kNameAtom; +nsIAtom* XULSortServiceImpl::kSortAtom; +nsIAtom* XULSortServiceImpl::kSortDirectionAtom; +nsIAtom* XULSortServiceImpl::kIdAtom; +nsIAtom* XULSortServiceImpl::kNaturalOrderPosAtom; + PRInt32 XULSortServiceImpl::kNameSpaceID_XUL; PRInt32 XULSortServiceImpl::kNameSpaceID_RDF; @@ -143,9 +201,19 @@ XULSortServiceImpl::XULSortServiceImpl(void) kTreeItemAtom = NS_NewAtom("treeitem"); kResourceAtom = NS_NewAtom("resource"); kTreeContentsGeneratedAtom = NS_NewAtom("treecontentsgenerated"); + kNameAtom = NS_NewAtom("Name"); + kSortAtom = NS_NewAtom("sortActive"); + kSortDirectionAtom = NS_NewAtom("sortDirection"); + kIdAtom = NS_NewAtom("id"); + kNaturalOrderPosAtom = NS_NewAtom("pos"); nsresult rv; + if (NS_FAILED(rv = nsServiceManager::GetService(kRDFServiceCID, + kIRDFServiceIID, (nsISupports**) &gRDFService))) + { + NS_ERROR("couldn't create rdf service"); + } // Register the XUL and RDF namespaces: these'll just retrieve // the IDs if they've already been registered by someone else. nsINameSpaceManager* mgr; @@ -192,7 +260,14 @@ XULSortServiceImpl::~XULSortServiceImpl(void) NS_RELEASE(kTreeItemAtom); NS_RELEASE(kResourceAtom); NS_RELEASE(kTreeContentsGeneratedAtom); + NS_RELEASE(kNameAtom); + NS_RELEASE(kSortAtom); + NS_RELEASE(kSortDirectionAtom); + NS_RELEASE(kIdAtom); + NS_RELEASE(kNaturalOrderPosAtom); + nsServiceManager::ReleaseService(kRDFServiceCID, gRDFService); + gRDFService = nsnull; nsServiceManager::ReleaseService(kXULSortServiceCID, gXULSortService); gXULSortService = nsnull; } @@ -289,14 +364,14 @@ XULSortServiceImpl::FindTreeBodyElement(nsIContent *tree, nsIContent **treeBody) } nsresult -XULSortServiceImpl::GetSortColumnIndex(nsIContent *tree, nsString sortResource, PRInt32 *colIndex) +XULSortServiceImpl::GetSortColumnIndex(nsIContent *tree, nsString sortResource, nsString sortDirection, PRInt32 *sortColIndex) { PRBool found = PR_FALSE; - PRInt32 childIndex = 0, numChildren = 0, nameSpaceID; + PRInt32 childIndex, colIndex = 0, numChildren, nameSpaceID; nsCOMPtr child; nsresult rv; - *colIndex = 0; + *sortColIndex = 0; if (NS_FAILED(rv = tree->ChildCount(numChildren))) return(rv); for (childIndex=0; childIndexSetAttribute(kNameSpaceID_None, kSortAtom, trueStr, PR_TRUE); + child->SetAttribute(kNameSpaceID_None, kSortDirectionAtom, sortDirection, PR_TRUE); + *sortColIndex = colIndex; found = PR_TRUE; + // Note: don't break, want to set/unset attribs on ALL sort columns + // break; + } + else + { + nsString falseStr("false"); + child->SetAttribute(kNameSpaceID_None, kSortAtom, falseStr, PR_TRUE); + child->SetAttribute(kNameSpaceID_None, kSortDirectionAtom, sortDirection, PR_TRUE); + } + } + ++colIndex; + } + } + } + return((found == PR_TRUE) ? NS_OK : NS_ERROR_FAILURE); +} + +nsresult +XULSortServiceImpl::GetSortColumnInfo(nsIContent *tree, nsString &sortResource, nsString &sortDirection) +{ + nsCOMPtr child; + PRBool found = PR_FALSE; + PRInt32 childIndex, numChildren, nameSpaceID; + nsresult rv; + + if (NS_FAILED(rv = tree->ChildCount(numChildren))) return(rv); + for (childIndex=0; childIndexChildAt(childIndex, *getter_AddRefs(child)))) return(rv); + if (NS_FAILED(rv = child->GetNameSpaceID(nameSpaceID))) return(rv); + if (nameSpaceID == kNameSpaceID_XUL) + { + nsCOMPtr tag; + + if (NS_FAILED(rv = child->GetTag(*getter_AddRefs(tag)))) + return rv; + if (tag.get() == kTreeColAtom) + { + nsString value; + if (NS_OK == child->GetAttribute(kNameSpaceID_None, kSortAtom, value)) + { + if (value.Equals("true")) + { + if (NS_OK == child->GetAttribute(kNameSpaceID_RDF, kResourceAtom, sortResource)) + { + if (NS_OK == child->GetAttribute(kNameSpaceID_None, kSortDirectionAtom, sortDirection)) + { + found = PR_TRUE; + } + } break; } } - ++(*colIndex); } } } @@ -376,17 +504,8 @@ XULSortServiceImpl::GetTreeCellValue(nsIContent *node, nsString & val) { if (NS_FAILED(rv = node->ChildAt(childIndex, *getter_AddRefs(child)))) break;; if (NS_FAILED(rv = child->GetNameSpaceID(nameSpaceID))) break; - if (nameSpaceID == kNameSpaceID_XUL) - { - nsCOMPtr tag; - - if (NS_FAILED(rv = child->GetTag(*getter_AddRefs(tag)))) - return rv; - nsString tagName; - tag->ToString(tagName); - printf("Child #%d: tagName='%s'\n", childIndex, tagName.ToNewCString()); - } - else if (nameSpaceID != kNameSpaceID_XUL) + // XXX is this the correct way to get text? Probably not... + if (nameSpaceID != kNameSpaceID_XUL) { nsITextContent *text = nsnull; if (NS_SUCCEEDED(rv = child->QueryInterface(kITextContentIID, (void **)&text))) @@ -426,13 +545,82 @@ XULSortServiceImpl::RemoveAllChildren(nsIContent *container) } + typedef struct _sortStruct { + nsIRDFCompositeDataSource *db; + nsIRDFResource *sortProperty; PRBool descendingSort; + PRBool naturalOrderSort; } sortStruct, *sortPtr; + +int openSortCallback(const void *data1, const void *data2, void *sortData); int inplaceSortCallback(const void *data1, const void *data2, void *sortData); + + +int +openSortCallback(const void *data1, const void *data2, void *sortData) +{ + int sortOrder = 0; + nsresult rv; + + nsIRDFNode *node1, *node2; + node1 = *(nsIRDFNode **)data1; + node2 = *(nsIRDFNode **)data2; + _sortStruct *sortPtr = (_sortStruct *)sortData; + + nsIRDFResource *res1; + nsIRDFResource *res2; + const PRUnichar *uniStr1 = nsnull; + const PRUnichar *uniStr2 = nsnull; + + if (NS_SUCCEEDED(node1->QueryInterface(kIRDFResourceIID, (void **) &res1))) + { + nsIRDFNode *nodeVal1; + if (NS_SUCCEEDED(rv = sortPtr->db->GetTarget(res1, sortPtr->sortProperty, PR_TRUE, &nodeVal1))) + { + nsIRDFLiteral *literal1; + if (NS_SUCCEEDED(nodeVal1->QueryInterface(kIRDFLiteralIID, (void **) &literal1))) + { + literal1->GetValue(&uniStr1); + } + } + } + if (NS_SUCCEEDED(node2->QueryInterface(kIRDFResourceIID, (void **) &res2))) + { + nsIRDFNode *nodeVal2; + if (NS_SUCCEEDED(rv = sortPtr->db->GetTarget(res2, sortPtr->sortProperty, PR_TRUE, &nodeVal2))) + { + nsIRDFLiteral *literal2; + if (NS_SUCCEEDED(nodeVal2->QueryInterface(kIRDFLiteralIID, (void **) &literal2))) + { + literal2->GetValue(&uniStr2); + } + } + } + if ((uniStr1 != nsnull) && (uniStr2 != nsnull)) + { + nsAutoString str1(uniStr1), str2(uniStr2); + sortOrder = (int)str1.Compare(str2, PR_TRUE); + if (sortPtr->descendingSort == PR_TRUE) + { + sortOrder = -sortOrder; + } + } + else if ((uniStr1 != nsnull) && (uniStr2 == nsnull)) + { + sortOrder = -1; + } + else + { + sortOrder = 1; + } + return(sortOrder); +} + + int inplaceSortCallback(const void *data1, const void *data2, void *sortData) { @@ -452,14 +640,30 @@ inplaceSortCallback(const void *data1, const void *data2, void *sortData) return(sortOrder); } + + nsresult -XULSortServiceImpl::SortTreeChildren(nsIContent *container, PRInt32 colIndex, PRInt32 indentLevel) +XULSortServiceImpl::SortTreeChildren(nsIContent *container, PRInt32 colIndex, nsString sortDirection, PRInt32 indentLevel) { PRInt32 childIndex = 0, numChildren = 0, nameSpaceID; nsCOMPtr child; nsresult rv; nsVoidArray *childArray; + _sortStruct sortInfo; + + if (sortDirection.Equals("natural")) + { + sortInfo.naturalOrderSort = PR_TRUE; + sortInfo.descendingSort = PR_FALSE; + } + else + { + sortInfo.naturalOrderSort = PR_FALSE;; + if (sortDirection.Equals("ascending")) sortInfo.descendingSort = PR_FALSE; + else if (sortDirection.Equals("descending")) sortInfo.descendingSort = PR_TRUE; + } + if (NS_FAILED(rv = container->ChildCount(numChildren))) return(rv); if ((childArray = new nsVoidArray()) == nsnull) return (NS_ERROR_OUT_OF_MEMORY); @@ -474,8 +678,9 @@ XULSortServiceImpl::SortTreeChildren(nsIContent *container, PRInt32 colIndex, PR if (NS_FAILED(rv = child->GetTag(*getter_AddRefs(tag)))) return rv; if (tag.get() == kTreeItemAtom) { + PRBool found = PR_FALSE; nsIContent *cell; - if (NS_SUCCEEDED(rv = GetTreeCell(child, colIndex, &cell))) + if ((indentLevel == 0) && (NS_SUCCEEDED(rv = GetTreeCell(child, colIndex, &cell)))) { if (cell) { @@ -484,11 +689,55 @@ XULSortServiceImpl::SortTreeChildren(nsIContent *container, PRInt32 colIndex, PR { // hack: always append cell value 1st as // that's what sort callback expects - childArray->AppendElement(val.ToNewCString()); - childArray->AppendElement(child); + + if (sortInfo.naturalOrderSort == PR_TRUE) + { + // ??????????????????? + + // XXX: note memory leak! + childArray->AppendElement(val.ToNewCString()); + childArray->AppendElement(child); + } + else + { + // XXX: note memory leak! + childArray->AppendElement(val.ToNewCString()); + childArray->AppendElement(child); + } + found = PR_TRUE; } } } + if (found == PR_FALSE) + { + // hack: always append cell value 1st as + // that's what sort callback expects + + PRBool foundValue = PR_FALSE; + if (sortInfo.naturalOrderSort == PR_TRUE) + { + nsString pos; + if (NS_OK == child->GetAttribute(kNameSpaceID_None, kNaturalOrderPosAtom, pos)) + { + // XXX: note memory leak! + childArray->AppendElement(pos.ToNewCString()); + childArray->AppendElement(child); + foundValue = PR_TRUE; + } + } + if (foundValue == PR_FALSE) + { + nsString name; + if (NS_OK == child->GetAttribute(kNameSpaceID_None, kNameAtom, name)) + { + // XXX: note memory leak! + childArray->AppendElement(name.ToNewCString()); + childArray->AppendElement(child); + foundValue = PR_TRUE; + } + } + found = PR_TRUE; + } } } } @@ -498,10 +747,6 @@ XULSortServiceImpl::SortTreeChildren(nsIContent *container, PRInt32 colIndex, PR nsIContent ** flatArray = new nsIContent*[numElements]; if (flatArray) { - _sortStruct sortInfo; - - sortInfo.descendingSort = PR_TRUE; - // flatten array of resources, sort them, then add as tree elements unsigned long loop; for (loop=0; loopInsertChildAt((nsIContent *)flatArray[loop+1], numChildren++, PR_TRUE); } + + // recurse on grandchildren + + for (loop=0; loopCanContainChildren(canHaveKids))) continue; + if (canHaveKids == PR_FALSE) continue; + + if (NS_FAILED(rv = container->ChildCount(numChildren))) continue; + for (childIndex=0; childIndexChildAt(childIndex, *getter_AddRefs(child)))) + continue; + if (NS_FAILED(rv = child->GetNameSpaceID(nameSpaceID))) continue; + if (nameSpaceID == kNameSpaceID_XUL) + { + nsCOMPtr tag; + if (NS_FAILED(rv = child->GetTag(*getter_AddRefs(tag)))) + continue; + if (tag.get() == kTreeChildrenAtom) + { + SortTreeChildren(child, colIndex, sortDirection, indentLevel+1); + } + } + } + } + delete [] flatArray; + flatArray = nsnull; } } - delete(childArray); - return(rv); + return(NS_OK); } + + +NS_IMETHODIMP +XULSortServiceImpl::OpenContainer(nsIRDFCompositeDataSource *db, nsIContent *container, + nsIRDFResource **flatArray, PRInt32 numElements, PRInt32 elementSize) +{ + nsresult rv; + nsIContent *treeNode; + nsString sortResource, sortDirection; + _sortStruct sortInfo; + + // get sorting info (property to sort on, direction to sort, etc) + + if (NS_FAILED(rv = FindTreeElement(container, &treeNode))) return(rv); + + sortInfo.db = db; + if (NS_FAILED(rv = GetSortColumnInfo(treeNode, sortResource, sortDirection))) return(rv); + char *uri = sortResource.ToNewCString(); + if (NS_FAILED(rv = gRDFService->GetResource(uri, &sortInfo.sortProperty))) return(rv); + delete [] uri; + if (sortDirection.Equals("natural")) + { + sortInfo.naturalOrderSort = PR_TRUE; + sortInfo.descendingSort = PR_FALSE; + // no need to sort for natural order + } + else + { + sortInfo.naturalOrderSort = PR_FALSE; + if (sortDirection.Equals("descending")) + sortInfo.descendingSort = PR_TRUE; + else + sortInfo.descendingSort = PR_FALSE; + rdf_qsort((void *)flatArray, numElements, elementSize, openSortCallback, (void *)&sortInfo); + } + + return(NS_OK); +} + + + nsresult XULSortServiceImpl::PrintTreeChildren(nsIContent *container, PRInt32 colIndex, PRInt32 indentLevel) { @@ -605,38 +921,22 @@ XULSortServiceImpl::PrintTreeChildren(nsIContent *container, PRInt32 colIndex, P } NS_IMETHODIMP -XULSortServiceImpl::DoSort(nsIDOMNode* node, const nsString& sortResource) +XULSortServiceImpl::DoSort(nsIDOMNode* node, const nsString& sortResource, + const nsString& sortDirection) { - printf("XULSortServiceImpl::DoSort entered!!!\n"); - - PRInt32 childIndex, colIndex, numChildren, treeBodyIndex; - nsIContent *child, *contentNode, *treeNode, *treeBody, *treeParent; + PRInt32 colIndex, treeBodyIndex; + nsIContent *contentNode, *treeNode, *treeBody, *treeParent; nsresult rv; if (NS_FAILED(rv = node->QueryInterface(kIContentIID, (void**)&contentNode))) return(rv); - printf("Success converting dom node to content node.\n"); - if (NS_FAILED(rv = FindTreeElement(contentNode, &treeNode))) return(rv); - printf("found tree element\n"); - - if (NS_FAILED(rv = GetSortColumnIndex(treeNode, sortResource, &colIndex))) return(rv); - printf("Sort column index is %d.\n", (int)colIndex); - + if (NS_FAILED(rv = GetSortColumnIndex(treeNode, sortResource, sortDirection, &colIndex))) return(rv); if (NS_FAILED(rv = FindTreeBodyElement(treeNode, &treeBody))) return(rv); - printf("Found tree body.\n"); - if (NS_FAILED(rv = treeBody->GetParent(treeParent))) return(rv); - printf("Found tree parent.\n"); - if (NS_FAILED(rv = treeParent->IndexOf(treeBody, treeBodyIndex))) return(rv); - printf("Found index of tree body in tree parent.\n"); - if (NS_FAILED(rv = treeParent->RemoveChildAt(treeBodyIndex, PR_TRUE))) return(rv); - printf("Removed tree body from parent.\n"); - - if (NS_SUCCEEDED(rv = SortTreeChildren(treeBody, colIndex, 0))) + if (NS_SUCCEEDED(rv = SortTreeChildren(treeBody, colIndex, sortDirection, 0))) { - printf("Tree sorted.\n"); } if (NS_SUCCEEDED(rv = treeBody->UnsetAttribute(kNameSpaceID_None, @@ -649,17 +949,18 @@ XULSortServiceImpl::DoSort(nsIDOMNode* node, const nsString& sortResource) } if (NS_FAILED(rv = treeParent->AppendChildTo(treeBody, PR_TRUE))) return(rv); - printf("Added tree body back into parent.\n"); #if 0 if (NS_FAILED(rv = PrintTreeChildren(treeBody, colIndex, 0))) return(rv); - printf("Tree printed.\nDone.\n"); #endif return(NS_OK); } + + nsresult NS_NewXULSortService(nsIXULSortService** mgr) { return XULSortServiceImpl::GetSortService(mgr); } + diff --git a/rdf/content/public/nsIXULSortService.h b/rdf/content/public/nsIXULSortService.h index b0a53228bfa0..b6c54a2d772b 100644 --- a/rdf/content/public/nsIXULSortService.h +++ b/rdf/content/public/nsIXULSortService.h @@ -40,7 +40,9 @@ class nsIXULSortService : public nsISupports { public: static const nsIID& IID() { static nsIID iid = NS_IXULSORTSERVICE_IID; return iid; } - NS_IMETHOD DoSort(nsIDOMNode* node, const nsString& sortResource) = 0; + NS_IMETHOD DoSort(nsIDOMNode* node, const nsString& sortResource, const nsString& sortDirection) = 0; + NS_IMETHOD OpenContainer(nsIRDFCompositeDataSource *db, nsIContent *container, + nsIRDFResource **flatArray, PRInt32 numElements, PRInt32 elementSize) = 0; }; diff --git a/rdf/content/src/nsRDFTreeBuilder.cpp b/rdf/content/src/nsRDFTreeBuilder.cpp index 67718ca07303..061a55d68334 100644 --- a/rdf/content/src/nsRDFTreeBuilder.cpp +++ b/rdf/content/src/nsRDFTreeBuilder.cpp @@ -80,7 +80,7 @@ #include "rdfutil.h" #include "nsVoidArray.h" -#include "rdf_qsort.h" +#include "nsIXULSortService.h" //////////////////////////////////////////////////////////////////////// @@ -107,6 +107,9 @@ static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_CID(kNameSpaceManagerCID, NS_NAMESPACEMANAGER_CID); static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); +static NS_DEFINE_IID(kXULSortServiceCID, NS_XULSORTSERVICE_CID); +static NS_DEFINE_IID(kIXULSortServiceIID, NS_IXULSORTSERVICE_IID); + //////////////////////////////////////////////////////////////////////// class RDFTreeBuilderImpl : public nsIRDFContentModelBuilder, @@ -139,6 +142,7 @@ private: static nsIAtom* kTreeIndentationAtom; static nsIAtom* kTreeItemAtom; static nsIAtom* kContainmentAtom; + static nsIAtom* kNaturalOrderPosAtom; static PRInt32 kNameSpaceID_RDF; static PRInt32 kNameSpaceID_XUL; @@ -201,7 +205,8 @@ public: nsresult AddTreeRow(nsIContent* aTreeItemElement, nsIRDFResource* aProperty, - nsIRDFResource* aValue); + nsIRDFResource* aValue, + PRInt32 naturalOrderPos); nsresult EnsureCell(nsIContent* aTreeItemElement, PRInt32 aIndex, nsIContent** aCellElement); @@ -282,6 +287,7 @@ nsIAtom* RDFTreeBuilderImpl::kTreeIconAtom; nsIAtom* RDFTreeBuilderImpl::kTreeIndentationAtom; nsIAtom* RDFTreeBuilderImpl::kTreeItemAtom; nsIAtom* RDFTreeBuilderImpl::kContainmentAtom; +nsIAtom* RDFTreeBuilderImpl::kNaturalOrderPosAtom; PRInt32 RDFTreeBuilderImpl::kNameSpaceID_RDF; PRInt32 RDFTreeBuilderImpl::kNameSpaceID_XUL; @@ -339,6 +345,7 @@ RDFTreeBuilderImpl::RDFTreeBuilderImpl(void) kTreeIndentationAtom = NS_NewAtom("treeindentation"); kTreeItemAtom = NS_NewAtom("treeitem"); kContainmentAtom = NS_NewAtom("containment"); + kNaturalOrderPosAtom = NS_NewAtom("pos"); nsresult rv; @@ -421,7 +428,7 @@ RDFTreeBuilderImpl::~RDFTreeBuilderImpl(void) NS_RELEASE(kTreeIndentationAtom); NS_RELEASE(kTreeItemAtom); NS_RELEASE(kContainmentAtom); - + NS_RELEASE(kNaturalOrderPosAtom); NS_RELEASE(kNC_Title); NS_RELEASE(kNC_Column); @@ -591,76 +598,6 @@ RDFTreeBuilderImpl::SetRootContent(nsIContent* aElement) } -typedef struct _sortStruct { - nsIRDFCompositeDataSource *db; - nsIRDFResource *sortProperty; - PRBool descendingSort; -} sortStruct, *sortPtr; - - -int rdfSortCallback(const void *data1, const void *data2, void *data); - - -int -rdfSortCallback(const void *data1, const void *data2, void *sortData) -{ - int sortOrder = 0; - nsresult rv; - - nsIRDFNode *node1, *node2; - node1 = *(nsIRDFNode **)data1; - node2 = *(nsIRDFNode **)data2; - _sortStruct *sortPtr = (_sortStruct *)sortData; - - nsIRDFResource *res1; - nsIRDFResource *res2; - const PRUnichar *uniStr1 = nsnull; - const PRUnichar *uniStr2 = nsnull; - - if (NS_SUCCEEDED(node1->QueryInterface(kIRDFResourceIID, (void **) &res1))) - { - nsIRDFNode *nodeVal1; - if (NS_SUCCEEDED(rv = sortPtr->db->GetTarget(res1, sortPtr->sortProperty, PR_TRUE, &nodeVal1))) - { - nsIRDFLiteral *literal1; - if (NS_SUCCEEDED(nodeVal1->QueryInterface(kIRDFLiteralIID, (void **) &literal1))) - { - literal1->GetValue(&uniStr1); - } - } - } - if (NS_SUCCEEDED(node2->QueryInterface(kIRDFResourceIID, (void **) &res2))) - { - nsIRDFNode *nodeVal2; - if (NS_SUCCEEDED(rv = sortPtr->db->GetTarget(res2, sortPtr->sortProperty, PR_TRUE, &nodeVal2))) - { - nsIRDFLiteral *literal2; - if (NS_SUCCEEDED(nodeVal2->QueryInterface(kIRDFLiteralIID, (void **) &literal2))) - { - literal2->GetValue(&uniStr2); - } - } - } - if ((uniStr1 != nsnull) && (uniStr2 != nsnull)) - { - nsAutoString str1(uniStr1), str2(uniStr2); - sortOrder = (int)str1.Compare(str2, PR_TRUE); - if (sortPtr->descendingSort == PR_TRUE) - { - sortOrder = -sortOrder; - } - } - else if ((uniStr1 != nsnull) && (uniStr2 == nsnull)) - { - sortOrder = -1; - } - else - { - sortOrder = 1; - } - return(sortOrder); -} - NS_IMETHODIMP RDFTreeBuilderImpl::CreateContents(nsIContent* aElement) @@ -761,11 +698,6 @@ RDFTreeBuilderImpl::CreateContents(nsIContent* aElement) due to sort callback implementation */ tempArray->AppendElement(valueResource); tempArray->AppendElement(property); -/* if (NS_FAILED(rv = AddTreeRow(aElement, property, valueResource))) { - NS_ERROR("unable to create tree row"); - return rv; - } -*/ } else { if (NS_FAILED(rv = SetCellValue(aElement, property, value))) { @@ -780,41 +712,33 @@ RDFTreeBuilderImpl::CreateContents(nsIContent* aElement) unsigned long numElements = tempArray->Count(); if (numElements > 0) { - nsIRDFResource ** flatArray = (nsIRDFResource **)malloc(numElements * sizeof(void *)); + nsIRDFResource ** flatArray = new nsIRDFResource *[numElements]; if (flatArray) { - _sortStruct sortInfo; - - // get sorting info (property to sort on, direction to sort, etc) - - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - // XXX Note: currently hardcoded; should get from DOM, or... ? - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - - sortInfo.db = mDB; - sortInfo.descendingSort = PR_FALSE; - if (NS_FAILED(rv = gRDFService->GetResource("http://home.netscape.com/NC-rdf#Name", &sortInfo.sortProperty))) - { - NS_ERROR("unable to create gSortProperty resource"); - return rv; - } - // flatten array of resources, sort them, then add as tree elements unsigned long loop; for (loop=0; loopElementAt(loop); - rdf_qsort((void *)flatArray, numElements/2, 2 * sizeof(void *), rdfSortCallback, (void *)&sortInfo); + + nsIXULSortService *gXULSortService = nsnull; + + nsresult rv = nsServiceManager::GetService(kXULSortServiceCID, + kIXULSortServiceIID, (nsISupports**) &gXULSortService); + if (nsnull != gXULSortService) + { + gXULSortService->OpenContainer(mDB, aElement, flatArray, numElements/2, 2*sizeof(nsIRDFResource *)); + nsServiceManager::ReleaseService(kXULSortServiceCID, gXULSortService); + } + for (loop=0; loopSetAttribute(nameSpaceID, tag, s, PR_FALSE); + + if (naturalOrderPos > 0) + { + nsAutoString pos, zero("0");; + pos.Append(naturalOrderPos, 10); + if (pos.Length() < 4) + { + pos.Insert(zero, 0, 4-pos.Length()); + } + treeItem->SetAttribute(kNameSpaceID_None, kNaturalOrderPosAtom, pos, PR_FALSE); + } } if (NS_FAILED(rv) && (rv != NS_ERROR_RDF_CURSOR_EMPTY)) { diff --git a/rdf/content/src/nsXULSortService.cpp b/rdf/content/src/nsXULSortService.cpp index 2ae8636cbe35..337e16d05917 100644 --- a/rdf/content/src/nsXULSortService.cpp +++ b/rdf/content/src/nsXULSortService.cpp @@ -20,6 +20,37 @@ This file provides the implementation for the sort service manager. */ +#include "nsCOMPtr.h" +#include "nsCRT.h" +#include "nsIAtom.h" +#include "nsIContent.h" +#include "nsIDOMElement.h" +#include "nsIDOMElementObserver.h" +#include "nsIDOMNode.h" +#include "nsIDOMNodeObserver.h" +#include "nsIDocument.h" +#include "nsINameSpaceManager.h" +#include "nsIRDFContentModelBuilder.h" +#include "nsIRDFCursor.h" +#include "nsIRDFCompositeDataSource.h" +#include "nsIRDFDocument.h" +#include "nsIRDFNode.h" +#include "nsIRDFObserver.h" +#include "nsIRDFService.h" +#include "nsIServiceManager.h" +#include "nsINameSpaceManager.h" +#include "nsIServiceManager.h" +#include "nsISupportsArray.h" +#include "nsIURL.h" +#include "nsLayoutCID.h" +#include "nsRDFCID.h" +#include "nsRDFContentUtils.h" +#include "nsString.h" +#include "rdf.h" +#include "rdfutil.h" + +#include "nsVoidArray.h" +#include "rdf_qsort.h" #include "nsIAtom.h" #include "nsIXULSortService.h" #include "nsString.h" @@ -42,8 +73,11 @@ #include "nsIDOMNode.h" #include "nsIDOMElement.h" -#include "nsIRDFContentModelBuilder.h" +#include "nsIRDFContentModelBuilder.h" +#include "nsIRDFCompositeDataSource.h" +#include "nsIRDFNode.h" +#include "nsIRDFService.h" #include "rdf.h" @@ -62,6 +96,11 @@ static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID); static NS_DEFINE_IID(kIDomNodeIID, NS_IDOMNODE_IID); static NS_DEFINE_IID(kIDomElementIID, NS_IDOMELEMENT_IID); +static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); +static NS_DEFINE_IID(kIRDFServiceIID, NS_IRDFSERVICE_IID); +static NS_DEFINE_IID(kIRDFResourceIID, NS_IRDFRESOURCE_IID); +static NS_DEFINE_IID(kIRDFLiteralIID, NS_IRDFLITERAL_IID); + // XXX This is sure to change. Copied from mozilla/layout/xul/content/src/nsXULAtoms.cpp static const char kXULNameSpaceURI[] = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; @@ -91,16 +130,25 @@ private: static nsIAtom *kTreeItemAtom; static nsIAtom *kResourceAtom; static nsIAtom *kTreeContentsGeneratedAtom; + static nsIAtom *kNameAtom; + static nsIAtom *kSortAtom; + static nsIAtom *kSortDirectionAtom; + static nsIAtom *kIdAtom; + static nsIAtom *kNaturalOrderPosAtom; + static PRInt32 kNameSpaceID_XUL; static PRInt32 kNameSpaceID_RDF; + static nsIRDFService *gRDFService; + nsresult FindTreeElement(nsIContent* aElement,nsIContent** aTreeElement); nsresult FindTreeBodyElement(nsIContent *tree, nsIContent **treeBody); -nsresult GetSortColumnIndex(nsIContent *tree, nsString sortResource, PRInt32 *colIndex); +nsresult GetSortColumnIndex(nsIContent *tree, nsString sortResource, nsString sortDirection, PRInt32 *colIndex); +nsresult GetSortColumnInfo(nsIContent *tree, nsString &sortResource, nsString &sortDirection); nsresult GetTreeCell(nsIContent *node, PRInt32 colIndex, nsIContent **cell); nsresult GetTreeCellValue(nsIContent *node, nsString & value); nsresult RemoveAllChildren(nsIContent *node); -nsresult SortTreeChildren(nsIContent *container, PRInt32 colIndex, PRInt32 indentLevel); +nsresult SortTreeChildren(nsIContent *container, PRInt32 colIndex, nsString sortDirection, PRInt32 indentLevel); nsresult PrintTreeChildren(nsIContent *container, PRInt32 colIndex, PRInt32 indentLevel); public: @@ -111,12 +159,16 @@ public: NS_DECL_ISUPPORTS // nsISortService - NS_IMETHOD DoSort(nsIDOMNode* node, const nsString& sortResource); + NS_IMETHOD DoSort(nsIDOMNode* node, const nsString& sortResource, const nsString& sortDirection); + NS_IMETHOD OpenContainer(nsIRDFCompositeDataSource *db, nsIContent *container, nsIRDFResource **flatArray, + PRInt32 numElements, PRInt32 elementSize); }; nsIXULSortService* XULSortServiceImpl::gXULSortService = nsnull; nsrefcnt XULSortServiceImpl::gRefCnt = 0; +nsIRDFService *XULSortServiceImpl::gRDFService = nsnull; + nsIAtom* XULSortServiceImpl::kTreeAtom; nsIAtom* XULSortServiceImpl::kTreeBodyAtom; nsIAtom* XULSortServiceImpl::kTreeCellAtom; @@ -125,6 +177,12 @@ nsIAtom* XULSortServiceImpl::kTreeColAtom; nsIAtom* XULSortServiceImpl::kTreeItemAtom; nsIAtom* XULSortServiceImpl::kResourceAtom; nsIAtom* XULSortServiceImpl::kTreeContentsGeneratedAtom; +nsIAtom* XULSortServiceImpl::kNameAtom; +nsIAtom* XULSortServiceImpl::kSortAtom; +nsIAtom* XULSortServiceImpl::kSortDirectionAtom; +nsIAtom* XULSortServiceImpl::kIdAtom; +nsIAtom* XULSortServiceImpl::kNaturalOrderPosAtom; + PRInt32 XULSortServiceImpl::kNameSpaceID_XUL; PRInt32 XULSortServiceImpl::kNameSpaceID_RDF; @@ -143,9 +201,19 @@ XULSortServiceImpl::XULSortServiceImpl(void) kTreeItemAtom = NS_NewAtom("treeitem"); kResourceAtom = NS_NewAtom("resource"); kTreeContentsGeneratedAtom = NS_NewAtom("treecontentsgenerated"); + kNameAtom = NS_NewAtom("Name"); + kSortAtom = NS_NewAtom("sortActive"); + kSortDirectionAtom = NS_NewAtom("sortDirection"); + kIdAtom = NS_NewAtom("id"); + kNaturalOrderPosAtom = NS_NewAtom("pos"); nsresult rv; + if (NS_FAILED(rv = nsServiceManager::GetService(kRDFServiceCID, + kIRDFServiceIID, (nsISupports**) &gRDFService))) + { + NS_ERROR("couldn't create rdf service"); + } // Register the XUL and RDF namespaces: these'll just retrieve // the IDs if they've already been registered by someone else. nsINameSpaceManager* mgr; @@ -192,7 +260,14 @@ XULSortServiceImpl::~XULSortServiceImpl(void) NS_RELEASE(kTreeItemAtom); NS_RELEASE(kResourceAtom); NS_RELEASE(kTreeContentsGeneratedAtom); + NS_RELEASE(kNameAtom); + NS_RELEASE(kSortAtom); + NS_RELEASE(kSortDirectionAtom); + NS_RELEASE(kIdAtom); + NS_RELEASE(kNaturalOrderPosAtom); + nsServiceManager::ReleaseService(kRDFServiceCID, gRDFService); + gRDFService = nsnull; nsServiceManager::ReleaseService(kXULSortServiceCID, gXULSortService); gXULSortService = nsnull; } @@ -289,14 +364,14 @@ XULSortServiceImpl::FindTreeBodyElement(nsIContent *tree, nsIContent **treeBody) } nsresult -XULSortServiceImpl::GetSortColumnIndex(nsIContent *tree, nsString sortResource, PRInt32 *colIndex) +XULSortServiceImpl::GetSortColumnIndex(nsIContent *tree, nsString sortResource, nsString sortDirection, PRInt32 *sortColIndex) { PRBool found = PR_FALSE; - PRInt32 childIndex = 0, numChildren = 0, nameSpaceID; + PRInt32 childIndex, colIndex = 0, numChildren, nameSpaceID; nsCOMPtr child; nsresult rv; - *colIndex = 0; + *sortColIndex = 0; if (NS_FAILED(rv = tree->ChildCount(numChildren))) return(rv); for (childIndex=0; childIndexSetAttribute(kNameSpaceID_None, kSortAtom, trueStr, PR_TRUE); + child->SetAttribute(kNameSpaceID_None, kSortDirectionAtom, sortDirection, PR_TRUE); + *sortColIndex = colIndex; found = PR_TRUE; + // Note: don't break, want to set/unset attribs on ALL sort columns + // break; + } + else + { + nsString falseStr("false"); + child->SetAttribute(kNameSpaceID_None, kSortAtom, falseStr, PR_TRUE); + child->SetAttribute(kNameSpaceID_None, kSortDirectionAtom, sortDirection, PR_TRUE); + } + } + ++colIndex; + } + } + } + return((found == PR_TRUE) ? NS_OK : NS_ERROR_FAILURE); +} + +nsresult +XULSortServiceImpl::GetSortColumnInfo(nsIContent *tree, nsString &sortResource, nsString &sortDirection) +{ + nsCOMPtr child; + PRBool found = PR_FALSE; + PRInt32 childIndex, numChildren, nameSpaceID; + nsresult rv; + + if (NS_FAILED(rv = tree->ChildCount(numChildren))) return(rv); + for (childIndex=0; childIndexChildAt(childIndex, *getter_AddRefs(child)))) return(rv); + if (NS_FAILED(rv = child->GetNameSpaceID(nameSpaceID))) return(rv); + if (nameSpaceID == kNameSpaceID_XUL) + { + nsCOMPtr tag; + + if (NS_FAILED(rv = child->GetTag(*getter_AddRefs(tag)))) + return rv; + if (tag.get() == kTreeColAtom) + { + nsString value; + if (NS_OK == child->GetAttribute(kNameSpaceID_None, kSortAtom, value)) + { + if (value.Equals("true")) + { + if (NS_OK == child->GetAttribute(kNameSpaceID_RDF, kResourceAtom, sortResource)) + { + if (NS_OK == child->GetAttribute(kNameSpaceID_None, kSortDirectionAtom, sortDirection)) + { + found = PR_TRUE; + } + } break; } } - ++(*colIndex); } } } @@ -376,17 +504,8 @@ XULSortServiceImpl::GetTreeCellValue(nsIContent *node, nsString & val) { if (NS_FAILED(rv = node->ChildAt(childIndex, *getter_AddRefs(child)))) break;; if (NS_FAILED(rv = child->GetNameSpaceID(nameSpaceID))) break; - if (nameSpaceID == kNameSpaceID_XUL) - { - nsCOMPtr tag; - - if (NS_FAILED(rv = child->GetTag(*getter_AddRefs(tag)))) - return rv; - nsString tagName; - tag->ToString(tagName); - printf("Child #%d: tagName='%s'\n", childIndex, tagName.ToNewCString()); - } - else if (nameSpaceID != kNameSpaceID_XUL) + // XXX is this the correct way to get text? Probably not... + if (nameSpaceID != kNameSpaceID_XUL) { nsITextContent *text = nsnull; if (NS_SUCCEEDED(rv = child->QueryInterface(kITextContentIID, (void **)&text))) @@ -426,13 +545,82 @@ XULSortServiceImpl::RemoveAllChildren(nsIContent *container) } + typedef struct _sortStruct { + nsIRDFCompositeDataSource *db; + nsIRDFResource *sortProperty; PRBool descendingSort; + PRBool naturalOrderSort; } sortStruct, *sortPtr; + +int openSortCallback(const void *data1, const void *data2, void *sortData); int inplaceSortCallback(const void *data1, const void *data2, void *sortData); + + +int +openSortCallback(const void *data1, const void *data2, void *sortData) +{ + int sortOrder = 0; + nsresult rv; + + nsIRDFNode *node1, *node2; + node1 = *(nsIRDFNode **)data1; + node2 = *(nsIRDFNode **)data2; + _sortStruct *sortPtr = (_sortStruct *)sortData; + + nsIRDFResource *res1; + nsIRDFResource *res2; + const PRUnichar *uniStr1 = nsnull; + const PRUnichar *uniStr2 = nsnull; + + if (NS_SUCCEEDED(node1->QueryInterface(kIRDFResourceIID, (void **) &res1))) + { + nsIRDFNode *nodeVal1; + if (NS_SUCCEEDED(rv = sortPtr->db->GetTarget(res1, sortPtr->sortProperty, PR_TRUE, &nodeVal1))) + { + nsIRDFLiteral *literal1; + if (NS_SUCCEEDED(nodeVal1->QueryInterface(kIRDFLiteralIID, (void **) &literal1))) + { + literal1->GetValue(&uniStr1); + } + } + } + if (NS_SUCCEEDED(node2->QueryInterface(kIRDFResourceIID, (void **) &res2))) + { + nsIRDFNode *nodeVal2; + if (NS_SUCCEEDED(rv = sortPtr->db->GetTarget(res2, sortPtr->sortProperty, PR_TRUE, &nodeVal2))) + { + nsIRDFLiteral *literal2; + if (NS_SUCCEEDED(nodeVal2->QueryInterface(kIRDFLiteralIID, (void **) &literal2))) + { + literal2->GetValue(&uniStr2); + } + } + } + if ((uniStr1 != nsnull) && (uniStr2 != nsnull)) + { + nsAutoString str1(uniStr1), str2(uniStr2); + sortOrder = (int)str1.Compare(str2, PR_TRUE); + if (sortPtr->descendingSort == PR_TRUE) + { + sortOrder = -sortOrder; + } + } + else if ((uniStr1 != nsnull) && (uniStr2 == nsnull)) + { + sortOrder = -1; + } + else + { + sortOrder = 1; + } + return(sortOrder); +} + + int inplaceSortCallback(const void *data1, const void *data2, void *sortData) { @@ -452,14 +640,30 @@ inplaceSortCallback(const void *data1, const void *data2, void *sortData) return(sortOrder); } + + nsresult -XULSortServiceImpl::SortTreeChildren(nsIContent *container, PRInt32 colIndex, PRInt32 indentLevel) +XULSortServiceImpl::SortTreeChildren(nsIContent *container, PRInt32 colIndex, nsString sortDirection, PRInt32 indentLevel) { PRInt32 childIndex = 0, numChildren = 0, nameSpaceID; nsCOMPtr child; nsresult rv; nsVoidArray *childArray; + _sortStruct sortInfo; + + if (sortDirection.Equals("natural")) + { + sortInfo.naturalOrderSort = PR_TRUE; + sortInfo.descendingSort = PR_FALSE; + } + else + { + sortInfo.naturalOrderSort = PR_FALSE;; + if (sortDirection.Equals("ascending")) sortInfo.descendingSort = PR_FALSE; + else if (sortDirection.Equals("descending")) sortInfo.descendingSort = PR_TRUE; + } + if (NS_FAILED(rv = container->ChildCount(numChildren))) return(rv); if ((childArray = new nsVoidArray()) == nsnull) return (NS_ERROR_OUT_OF_MEMORY); @@ -474,8 +678,9 @@ XULSortServiceImpl::SortTreeChildren(nsIContent *container, PRInt32 colIndex, PR if (NS_FAILED(rv = child->GetTag(*getter_AddRefs(tag)))) return rv; if (tag.get() == kTreeItemAtom) { + PRBool found = PR_FALSE; nsIContent *cell; - if (NS_SUCCEEDED(rv = GetTreeCell(child, colIndex, &cell))) + if ((indentLevel == 0) && (NS_SUCCEEDED(rv = GetTreeCell(child, colIndex, &cell)))) { if (cell) { @@ -484,11 +689,55 @@ XULSortServiceImpl::SortTreeChildren(nsIContent *container, PRInt32 colIndex, PR { // hack: always append cell value 1st as // that's what sort callback expects - childArray->AppendElement(val.ToNewCString()); - childArray->AppendElement(child); + + if (sortInfo.naturalOrderSort == PR_TRUE) + { + // ??????????????????? + + // XXX: note memory leak! + childArray->AppendElement(val.ToNewCString()); + childArray->AppendElement(child); + } + else + { + // XXX: note memory leak! + childArray->AppendElement(val.ToNewCString()); + childArray->AppendElement(child); + } + found = PR_TRUE; } } } + if (found == PR_FALSE) + { + // hack: always append cell value 1st as + // that's what sort callback expects + + PRBool foundValue = PR_FALSE; + if (sortInfo.naturalOrderSort == PR_TRUE) + { + nsString pos; + if (NS_OK == child->GetAttribute(kNameSpaceID_None, kNaturalOrderPosAtom, pos)) + { + // XXX: note memory leak! + childArray->AppendElement(pos.ToNewCString()); + childArray->AppendElement(child); + foundValue = PR_TRUE; + } + } + if (foundValue == PR_FALSE) + { + nsString name; + if (NS_OK == child->GetAttribute(kNameSpaceID_None, kNameAtom, name)) + { + // XXX: note memory leak! + childArray->AppendElement(name.ToNewCString()); + childArray->AppendElement(child); + foundValue = PR_TRUE; + } + } + found = PR_TRUE; + } } } } @@ -498,10 +747,6 @@ XULSortServiceImpl::SortTreeChildren(nsIContent *container, PRInt32 colIndex, PR nsIContent ** flatArray = new nsIContent*[numElements]; if (flatArray) { - _sortStruct sortInfo; - - sortInfo.descendingSort = PR_TRUE; - // flatten array of resources, sort them, then add as tree elements unsigned long loop; for (loop=0; loopInsertChildAt((nsIContent *)flatArray[loop+1], numChildren++, PR_TRUE); } + + // recurse on grandchildren + + for (loop=0; loopCanContainChildren(canHaveKids))) continue; + if (canHaveKids == PR_FALSE) continue; + + if (NS_FAILED(rv = container->ChildCount(numChildren))) continue; + for (childIndex=0; childIndexChildAt(childIndex, *getter_AddRefs(child)))) + continue; + if (NS_FAILED(rv = child->GetNameSpaceID(nameSpaceID))) continue; + if (nameSpaceID == kNameSpaceID_XUL) + { + nsCOMPtr tag; + if (NS_FAILED(rv = child->GetTag(*getter_AddRefs(tag)))) + continue; + if (tag.get() == kTreeChildrenAtom) + { + SortTreeChildren(child, colIndex, sortDirection, indentLevel+1); + } + } + } + } + delete [] flatArray; + flatArray = nsnull; } } - delete(childArray); - return(rv); + return(NS_OK); } + + +NS_IMETHODIMP +XULSortServiceImpl::OpenContainer(nsIRDFCompositeDataSource *db, nsIContent *container, + nsIRDFResource **flatArray, PRInt32 numElements, PRInt32 elementSize) +{ + nsresult rv; + nsIContent *treeNode; + nsString sortResource, sortDirection; + _sortStruct sortInfo; + + // get sorting info (property to sort on, direction to sort, etc) + + if (NS_FAILED(rv = FindTreeElement(container, &treeNode))) return(rv); + + sortInfo.db = db; + if (NS_FAILED(rv = GetSortColumnInfo(treeNode, sortResource, sortDirection))) return(rv); + char *uri = sortResource.ToNewCString(); + if (NS_FAILED(rv = gRDFService->GetResource(uri, &sortInfo.sortProperty))) return(rv); + delete [] uri; + if (sortDirection.Equals("natural")) + { + sortInfo.naturalOrderSort = PR_TRUE; + sortInfo.descendingSort = PR_FALSE; + // no need to sort for natural order + } + else + { + sortInfo.naturalOrderSort = PR_FALSE; + if (sortDirection.Equals("descending")) + sortInfo.descendingSort = PR_TRUE; + else + sortInfo.descendingSort = PR_FALSE; + rdf_qsort((void *)flatArray, numElements, elementSize, openSortCallback, (void *)&sortInfo); + } + + return(NS_OK); +} + + + nsresult XULSortServiceImpl::PrintTreeChildren(nsIContent *container, PRInt32 colIndex, PRInt32 indentLevel) { @@ -605,38 +921,22 @@ XULSortServiceImpl::PrintTreeChildren(nsIContent *container, PRInt32 colIndex, P } NS_IMETHODIMP -XULSortServiceImpl::DoSort(nsIDOMNode* node, const nsString& sortResource) +XULSortServiceImpl::DoSort(nsIDOMNode* node, const nsString& sortResource, + const nsString& sortDirection) { - printf("XULSortServiceImpl::DoSort entered!!!\n"); - - PRInt32 childIndex, colIndex, numChildren, treeBodyIndex; - nsIContent *child, *contentNode, *treeNode, *treeBody, *treeParent; + PRInt32 colIndex, treeBodyIndex; + nsIContent *contentNode, *treeNode, *treeBody, *treeParent; nsresult rv; if (NS_FAILED(rv = node->QueryInterface(kIContentIID, (void**)&contentNode))) return(rv); - printf("Success converting dom node to content node.\n"); - if (NS_FAILED(rv = FindTreeElement(contentNode, &treeNode))) return(rv); - printf("found tree element\n"); - - if (NS_FAILED(rv = GetSortColumnIndex(treeNode, sortResource, &colIndex))) return(rv); - printf("Sort column index is %d.\n", (int)colIndex); - + if (NS_FAILED(rv = GetSortColumnIndex(treeNode, sortResource, sortDirection, &colIndex))) return(rv); if (NS_FAILED(rv = FindTreeBodyElement(treeNode, &treeBody))) return(rv); - printf("Found tree body.\n"); - if (NS_FAILED(rv = treeBody->GetParent(treeParent))) return(rv); - printf("Found tree parent.\n"); - if (NS_FAILED(rv = treeParent->IndexOf(treeBody, treeBodyIndex))) return(rv); - printf("Found index of tree body in tree parent.\n"); - if (NS_FAILED(rv = treeParent->RemoveChildAt(treeBodyIndex, PR_TRUE))) return(rv); - printf("Removed tree body from parent.\n"); - - if (NS_SUCCEEDED(rv = SortTreeChildren(treeBody, colIndex, 0))) + if (NS_SUCCEEDED(rv = SortTreeChildren(treeBody, colIndex, sortDirection, 0))) { - printf("Tree sorted.\n"); } if (NS_SUCCEEDED(rv = treeBody->UnsetAttribute(kNameSpaceID_None, @@ -649,17 +949,18 @@ XULSortServiceImpl::DoSort(nsIDOMNode* node, const nsString& sortResource) } if (NS_FAILED(rv = treeParent->AppendChildTo(treeBody, PR_TRUE))) return(rv); - printf("Added tree body back into parent.\n"); #if 0 if (NS_FAILED(rv = PrintTreeChildren(treeBody, colIndex, 0))) return(rv); - printf("Tree printed.\nDone.\n"); #endif return(NS_OK); } + + nsresult NS_NewXULSortService(nsIXULSortService** mgr) { return XULSortServiceImpl::GetSortService(mgr); } + diff --git a/rdf/resources/sidebar.xul b/rdf/resources/sidebar.xul index ffe46c42a397..b3e08551fa6b 100644 --- a/rdf/resources/sidebar.xul +++ b/rdf/resources/sidebar.xul @@ -8,19 +8,30 @@ -function doSort(node) +function doSort(sortColName) { + var node = document.getElementById(sortColName); // determine column resource to sort on var sortResource = node.getAttribute('resource'); if (!node) return(false); - dump("Sort on '" + sortResource + "' column.\n"); + + var sortDirection="ascending"; + var isSortActive = node.getAttribute('sortActive'); + if (isSortActive == "true") + { + var currentDirection = node.getAttribute('sortDirection'); + if (currentDirection == "ascending") + sortDirection = "descending"; + else if (currentDirection == "descending") + sortDirection = "natural"; + else sortDirection = "ascending"; + } + dump("Sort on '" + sortResource + "' column in '" + sortDirection + "' order.\n"); // get RDF Core service var rdfCore = XPAppCoresManager.Find("RDFCore"); if (!rdfCore) { - dump(" *** error: RDFCore not found.\n"); - rdfCore = new RDFCore(); if (!rdfCore) { @@ -38,7 +49,7 @@ function doSort(node) // sort!!! dump("About to sort...\n"); - rdfCore.doSort(node, sortResource, "ascending"); + rdfCore.doSort(node, sortResource, sortDirection); dump("Sort done.\n"); return(false); @@ -47,15 +58,15 @@ function doSort(node) - - - + + + - Name - URL - Last Modified + Name + URL + Last Modified diff --git a/xpfe/AppCores/idl/RDFCore.idl b/xpfe/AppCores/idl/RDFCore.idl index e469cb5d99bd..1c8c0e4eff3f 100644 --- a/xpfe/AppCores/idl/RDFCore.idl +++ b/xpfe/AppCores/idl/RDFCore.idl @@ -6,5 +6,5 @@ interface RDFCore : BaseAppCore void RDFCore(); - void doSort(in Node node, in DOMString sortResource); + void doSort(in Node node, in DOMString sortResource, in DOMString sortDirection); }; diff --git a/xpfe/AppCores/public/nsIDOMRDFCore.h b/xpfe/AppCores/public/nsIDOMRDFCore.h index 474269d065cd..d35ebeba7f14 100644 --- a/xpfe/AppCores/public/nsIDOMRDFCore.h +++ b/xpfe/AppCores/public/nsIDOMRDFCore.h @@ -35,17 +35,17 @@ class nsIDOMRDFCore : public nsIDOMBaseAppCore { public: static const nsIID& GetIID() { static nsIID iid = NS_IDOMRDFCORE_IID; return iid; } - NS_IMETHOD DoSort(nsIDOMNode* aNode, const nsString& aSortResource)=0; + NS_IMETHOD DoSort(nsIDOMNode* aNode, const nsString& aSortResource, const nsString& aSortDirection)=0; }; #define NS_DECL_IDOMRDFCORE \ - NS_IMETHOD DoSort(nsIDOMNode* aNode, const nsString& aSortResource); \ + NS_IMETHOD DoSort(nsIDOMNode* aNode, const nsString& aSortResource, const nsString& aSortDirection); \ #define NS_FORWARD_IDOMRDFCORE(_to) \ - NS_IMETHOD DoSort(nsIDOMNode* aNode, const nsString& aSortResource) { return _to##DoSort(aNode, aSortResource); } \ + NS_IMETHOD DoSort(nsIDOMNode* aNode, const nsString& aSortResource, const nsString& aSortDirection) { return _to##DoSort(aNode, aSortResource, aSortDirection); } \ extern "C" NS_DOM nsresult NS_InitRDFCoreClass(nsIScriptContext *aContext, void **aPrototype); diff --git a/xpfe/AppCores/src/nsJSRDFCore.cpp b/xpfe/AppCores/src/nsJSRDFCore.cpp index a091f54bcc6a..3d55acb3dd64 100644 --- a/xpfe/AppCores/src/nsJSRDFCore.cpp +++ b/xpfe/AppCores/src/nsJSRDFCore.cpp @@ -140,6 +140,7 @@ RDFCoreDoSort(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval JSBool rBool = JS_FALSE; nsIDOMNodePtr b0; nsAutoString b1; + nsAutoString b2; *rval = JSVAL_NULL; @@ -148,7 +149,7 @@ RDFCoreDoSort(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval return JS_TRUE; } - if (argc >= 2) { + if (argc >= 3) { if (JS_FALSE == nsJSUtils::nsConvertJSValToObject((nsISupports **)&b0, kINodeIID, @@ -160,14 +161,16 @@ RDFCoreDoSort(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval nsJSUtils::nsConvertJSValToString(b1, cx, argv[1]); - if (NS_OK != nativeThis->DoSort(b0, b1)) { + nsJSUtils::nsConvertJSValToString(b2, cx, argv[2]); + + if (NS_OK != nativeThis->DoSort(b0, b1, b2)) { return JS_FALSE; } *rval = JSVAL_VOID; } else { - JS_ReportError(cx, "Function doSort requires 2 parameters"); + JS_ReportError(cx, "Function doSort requires 3 parameters"); return JS_FALSE; } @@ -207,7 +210,7 @@ static JSPropertySpec RDFCoreProperties[] = // static JSFunctionSpec RDFCoreMethods[] = { - {"doSort", RDFCoreDoSort, 2}, + {"doSort", RDFCoreDoSort, 3}, {0} }; diff --git a/xpfe/AppCores/src/nsRDFCore.cpp b/xpfe/AppCores/src/nsRDFCore.cpp index d8fdad1c0d5a..c1e96ea8d1e0 100644 --- a/xpfe/AppCores/src/nsRDFCore.cpp +++ b/xpfe/AppCores/src/nsRDFCore.cpp @@ -132,7 +132,8 @@ nsRDFCore::Init(const nsString& aId) } NS_IMETHODIMP -nsRDFCore::DoSort(nsIDOMNode* node, const nsString& sortResource) +nsRDFCore::DoSort(nsIDOMNode* node, const nsString& sortResource, + const nsString &sortDirection) { printf(" ***** nsRDFCore::DoSort entered!!! *****\n"); @@ -146,6 +147,7 @@ nsRDFCore::DoSort(nsIDOMNode* node, const nsString& sortResource) printf("-- Sort \n"); printf("----------------------------\n"); printf("Column: %s \n", sortResource.ToNewCString()); + printf("Direction: %s \n", sortDirection.ToNewCString()); printf("----------------------------\n"); nsIXULSortService *gXULSortService = nsnull; @@ -156,7 +158,7 @@ nsRDFCore::DoSort(nsIDOMNode* node, const nsString& sortResource) { printf("\n******** YES, we got kXULSortServiceCID\n\n"); - gXULSortService->DoSort(node, sortResource); + gXULSortService->DoSort(node, sortResource, sortDirection); nsServiceManager::ReleaseService(kXULSortServiceCID, gXULSortService); } else printf("\n******** unable to obtain kXULSortServiceCID\n\n"); diff --git a/xpfe/AppCores/src/nsRDFCore.h b/xpfe/AppCores/src/nsRDFCore.h index 0269542a6ae6..d018eeed57b2 100644 --- a/xpfe/AppCores/src/nsRDFCore.h +++ b/xpfe/AppCores/src/nsRDFCore.h @@ -49,7 +49,7 @@ class nsRDFCore : public nsBaseAppCore, NS_IMETHOD GetId(nsString& aId) { return nsBaseAppCore::GetId(aId); } NS_IMETHOD SetDocumentCharset(const nsString& aCharset) { return nsBaseAppCore::SetDocumentCharset(aCharset); } - NS_IMETHOD DoSort(nsIDOMNode* node, const nsString& sortResource); + NS_IMETHOD DoSort(nsIDOMNode* node, const nsString& sortResource, const nsString& sortDirection); protected: