More support for column sorting.

This commit is contained in:
rjc%netscape.com 1999-03-07 09:44:38 +00:00
parent 3dbf66b81d
commit a23baf95a7
10 changed files with 787 additions and 231 deletions

View File

@ -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<nsIContent> child;
nsresult rv;
*colIndex = 0;
*sortColIndex = 0;
if (NS_FAILED(rv = tree->ChildCount(numChildren))) return(rv);
for (childIndex=0; childIndex<numChildren; childIndex++)
{
@ -316,11 +391,64 @@ XULSortServiceImpl::GetSortColumnIndex(nsIContent *tree, nsString sortResource,
{
if (colResource == sortResource)
{
nsString trueStr("true");
child->SetAttribute(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<nsIContent> child;
PRBool found = PR_FALSE;
PRInt32 childIndex, numChildren, nameSpaceID;
nsresult rv;
if (NS_FAILED(rv = tree->ChildCount(numChildren))) return(rv);
for (childIndex=0; childIndex<numChildren; childIndex++)
{
if (NS_FAILED(rv = tree->ChildAt(childIndex, *getter_AddRefs(child)))) return(rv);
if (NS_FAILED(rv = child->GetNameSpaceID(nameSpaceID))) return(rv);
if (nameSpaceID == kNameSpaceID_XUL)
{
nsCOMPtr<nsIAtom> 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<nsIAtom> 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<nsIContent> 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; loop<numElements; loop++)
@ -523,12 +768,83 @@ XULSortServiceImpl::SortTreeChildren(nsIContent *container, PRInt32 colIndex, PR
{
container->InsertChildAt((nsIContent *)flatArray[loop+1], numChildren++, PR_TRUE);
}
// recurse on grandchildren
for (loop=0; loop<numElements; loop+=2)
{
container = (nsIContent *)flatArray[loop+1];
PRBool canHaveKids = PR_FALSE;
if (NS_FAILED(rv = container->CanContainChildren(canHaveKids))) continue;
if (canHaveKids == PR_FALSE) continue;
if (NS_FAILED(rv = container->ChildCount(numChildren))) continue;
for (childIndex=0; childIndex<numChildren; childIndex++)
{
if (NS_FAILED(rv = container->ChildAt(childIndex, *getter_AddRefs(child))))
continue;
if (NS_FAILED(rv = child->GetNameSpaceID(nameSpaceID))) continue;
if (nameSpaceID == kNameSpaceID_XUL)
{
nsCOMPtr<nsIAtom> 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);
}

View File

@ -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;
};

View File

@ -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; loop<numElements; loop++)
flatArray[loop] = (nsIRDFResource *)tempArray->ElementAt(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; loop<numElements; loop+=2)
{
if (NS_FAILED(rv = AddTreeRow(aElement,
(nsIRDFResource *)flatArray[loop+1],
(nsIRDFResource *)flatArray[loop])))
if (NS_FAILED(rv = AddTreeRow(aElement, flatArray[loop+1], flatArray[loop], loop+1)))
{
NS_ERROR("unable to create tree row");
}
}
free(flatArray);
delete [] flatArray;
}
}
delete tempArray;
@ -888,7 +812,7 @@ RDFTreeBuilderImpl::OnAssert(nsIRDFResource* aSubject,
contentsGenerated.EqualsIgnoreCase("true")) {
// Okay, it's a "live" element, so go ahead and append the new
// child to this node.
if (NS_FAILED(rv = AddTreeRow(element, aPredicate, resource))) {
if (NS_FAILED(rv = AddTreeRow(element, aPredicate, resource, 0))) {
NS_ERROR("unable to create new tree row");
return rv;
}
@ -1318,7 +1242,8 @@ RDFTreeBuilderImpl::EnsureElementHasGenericChild(nsIContent* parent,
nsresult
RDFTreeBuilderImpl::AddTreeRow(nsIContent* aElement,
nsIRDFResource* aProperty,
nsIRDFResource* aValue)
nsIRDFResource* aValue,
PRInt32 naturalOrderPos)
{
// If it's a tree property, then we need to add the new child
// element to a special "children" element in the parent. The
@ -1446,6 +1371,17 @@ RDFTreeBuilderImpl::AddTreeRow(nsIContent* aElement,
}
treeItem->SetAttribute(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)) {

View File

@ -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<nsIContent> child;
nsresult rv;
*colIndex = 0;
*sortColIndex = 0;
if (NS_FAILED(rv = tree->ChildCount(numChildren))) return(rv);
for (childIndex=0; childIndex<numChildren; childIndex++)
{
@ -316,11 +391,64 @@ XULSortServiceImpl::GetSortColumnIndex(nsIContent *tree, nsString sortResource,
{
if (colResource == sortResource)
{
nsString trueStr("true");
child->SetAttribute(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<nsIContent> child;
PRBool found = PR_FALSE;
PRInt32 childIndex, numChildren, nameSpaceID;
nsresult rv;
if (NS_FAILED(rv = tree->ChildCount(numChildren))) return(rv);
for (childIndex=0; childIndex<numChildren; childIndex++)
{
if (NS_FAILED(rv = tree->ChildAt(childIndex, *getter_AddRefs(child)))) return(rv);
if (NS_FAILED(rv = child->GetNameSpaceID(nameSpaceID))) return(rv);
if (nameSpaceID == kNameSpaceID_XUL)
{
nsCOMPtr<nsIAtom> 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<nsIAtom> 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<nsIContent> 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; loop<numElements; loop++)
@ -523,12 +768,83 @@ XULSortServiceImpl::SortTreeChildren(nsIContent *container, PRInt32 colIndex, PR
{
container->InsertChildAt((nsIContent *)flatArray[loop+1], numChildren++, PR_TRUE);
}
// recurse on grandchildren
for (loop=0; loop<numElements; loop+=2)
{
container = (nsIContent *)flatArray[loop+1];
PRBool canHaveKids = PR_FALSE;
if (NS_FAILED(rv = container->CanContainChildren(canHaveKids))) continue;
if (canHaveKids == PR_FALSE) continue;
if (NS_FAILED(rv = container->ChildCount(numChildren))) continue;
for (childIndex=0; childIndex<numChildren; childIndex++)
{
if (NS_FAILED(rv = container->ChildAt(childIndex, *getter_AddRefs(child))))
continue;
if (NS_FAILED(rv = child->GetNameSpaceID(nameSpaceID))) continue;
if (nameSpaceID == kNameSpaceID_XUL)
{
nsCOMPtr<nsIAtom> 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);
}

View File

@ -8,19 +8,30 @@
<html:script>
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)
</html:script>
<xul:tree datasources="rdf:files rdf:bookmarks rdf:mail">
<xul:treecol rdf:resource="http://home.netscape.com/NC-rdf#Name"/>
<xul:treecol rdf:resource="http://home.netscape.com/NC-rdf#URL"/>
<xul:treecol rdf:resource="http://home.netscape.com/WEB-rdf#LastModifiedDate"/>
<xul:treecol id="NameColumn" rdf:resource="http://home.netscape.com/NC-rdf#Name"/>
<xul:treecol id="URLColumn" rdf:resource="http://home.netscape.com/NC-rdf#URL"/>
<xul:treecol id="LastModColumn" rdf:resource="http://home.netscape.com/WEB-rdf#LastModifiedDate"/>
<xul:treehead>
<xul:treeitem>
<xul:treecell resource='http://home.netscape.com/NC-rdf#Name' onclick="return doSort(this);">Name</xul:treecell>
<xul:treecell resource='http://home.netscape.com/NC-rdf#URL' onclick="return doSort(this);">URL</xul:treecell>
<xul:treecell resource='http://home.netscape.com/WEB-rdf#LastModifiedDate' onclick="return doSort(this);">Last Modified</xul:treecell>
<xul:treecell resource='http://home.netscape.com/NC-rdf#Name' onclick="return doSort('NameColumn');">Name</xul:treecell>
<xul:treecell resource='http://home.netscape.com/NC-rdf#URL' onclick="return doSort('URLColumn');">URL</xul:treecell>
<xul:treecell resource='http://home.netscape.com/WEB-rdf#LastModifiedDate' onclick="return doSort('LastModColumn');">Last Modified</xul:treecell>
</xul:treeitem>
</xul:treehead>

View File

@ -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);
};

View File

@ -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);

View File

@ -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}
};

View File

@ -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");

View File

@ -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: