1999-05-13 12:25:12 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
1999-03-06 02:51:41 +03:00
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Netscape Public License
|
|
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
|
|
* http://www.mozilla.org/NPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* NPL.
|
|
|
|
*
|
|
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
|
|
* Communications Corporation. Portions created by Netscape are
|
|
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
|
|
* Reserved.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
This file provides the implementation for the sort service manager.
|
|
|
|
*/
|
|
|
|
|
1999-03-07 12:44:38 +03:00
|
|
|
#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 "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"
|
1999-03-29 23:52:54 +04:00
|
|
|
#include "nsXPIDLString.h"
|
1999-03-07 12:44:38 +03:00
|
|
|
#include "rdf.h"
|
|
|
|
#include "rdfutil.h"
|
|
|
|
|
|
|
|
#include "nsVoidArray.h"
|
1999-04-14 07:28:49 +04:00
|
|
|
#include "nsQuickSort.h"
|
1999-03-06 02:51:41 +03:00
|
|
|
#include "nsIAtom.h"
|
|
|
|
#include "nsIXULSortService.h"
|
|
|
|
#include "nsString.h"
|
|
|
|
#include "plhash.h"
|
|
|
|
#include "plstr.h"
|
|
|
|
#include "prlog.h"
|
|
|
|
|
1999-05-18 02:43:47 +04:00
|
|
|
#include "nsICollation.h"
|
|
|
|
#include "nsCollationCID.h"
|
|
|
|
|
1999-03-06 02:51:41 +03:00
|
|
|
#include "nsCOMPtr.h"
|
|
|
|
#include "nsIServiceManager.h"
|
|
|
|
#include "nsINameSpaceManager.h"
|
|
|
|
#include "nsLayoutCID.h"
|
|
|
|
#include "nsRDFCID.h"
|
|
|
|
|
|
|
|
#include "nsIContent.h"
|
1999-05-06 23:28:22 +04:00
|
|
|
#include "nsIDOMText.h"
|
1999-03-06 02:51:41 +03:00
|
|
|
|
|
|
|
#include "nsVoidArray.h"
|
|
|
|
|
|
|
|
#include "nsIDOMNode.h"
|
|
|
|
#include "nsIDOMElement.h"
|
|
|
|
|
1999-03-07 12:44:38 +03:00
|
|
|
#include "nsIRDFContentModelBuilder.h"
|
|
|
|
#include "nsIRDFCompositeDataSource.h"
|
|
|
|
#include "nsIRDFNode.h"
|
|
|
|
#include "nsIRDFService.h"
|
1999-03-06 02:51:41 +03:00
|
|
|
#include "rdf.h"
|
|
|
|
|
1999-03-11 15:01:47 +03:00
|
|
|
#include "nsIDOMXULTreeElement.h"
|
|
|
|
#include "nsIDOMXULElement.h"
|
|
|
|
|
1999-03-06 02:51:41 +03:00
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
static NS_DEFINE_IID(kXULSortServiceCID, NS_XULSORTSERVICE_CID);
|
|
|
|
static NS_DEFINE_IID(kIXULSortServiceIID, NS_IXULSORTSERVICE_IID);
|
|
|
|
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
|
|
|
|
|
|
|
static NS_DEFINE_CID(kNameSpaceManagerCID, NS_NAMESPACEMANAGER_CID);
|
|
|
|
static NS_DEFINE_IID(kINameSpaceManagerIID, NS_INAMESPACEMANAGER_IID);
|
|
|
|
|
|
|
|
static NS_DEFINE_IID(kIContentIID, NS_ICONTENT_IID);
|
1999-05-06 23:28:22 +04:00
|
|
|
static NS_DEFINE_IID(kIDOMTextIID, NS_IDOMTEXT_IID);
|
1999-03-06 02:51:41 +03:00
|
|
|
|
|
|
|
static NS_DEFINE_IID(kIDomNodeIID, NS_IDOMNODE_IID);
|
|
|
|
static NS_DEFINE_IID(kIDomElementIID, NS_IDOMELEMENT_IID);
|
|
|
|
|
1999-03-07 12:44:38 +03:00
|
|
|
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);
|
|
|
|
|
1999-03-11 15:01:47 +03:00
|
|
|
static NS_DEFINE_IID(kIDomXulTreeElementIID, NS_IDOMXULTREEELEMENT_IID);
|
|
|
|
static NS_DEFINE_IID(kIDomXulElementIID, NS_IDOMXULELEMENT_IID);
|
|
|
|
|
1999-05-18 02:43:47 +04:00
|
|
|
static NS_DEFINE_CID(kCollationFactoryCID, NS_COLLATIONFACTORY_CID);
|
|
|
|
static NS_DEFINE_IID(kICollationFactoryIID, NS_ICOLLATIONFACTORY_IID);
|
|
|
|
|
1999-03-06 02:51:41 +03:00
|
|
|
// 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";
|
|
|
|
DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, child);
|
1999-03-19 04:52:18 +03:00
|
|
|
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Name);
|
1999-04-27 06:28:12 +04:00
|
|
|
DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, BookmarkSeparator);
|
1999-03-06 02:51:41 +03:00
|
|
|
|
1999-03-10 10:07:10 +03:00
|
|
|
|
|
|
|
typedef struct _sortStruct {
|
1999-03-19 04:52:18 +03:00
|
|
|
nsIRDFService *rdfService;
|
1999-03-10 10:07:10 +03:00
|
|
|
nsIRDFCompositeDataSource *db;
|
|
|
|
nsIRDFResource *sortProperty;
|
1999-03-11 15:01:47 +03:00
|
|
|
PRInt32 colIndex;
|
|
|
|
nsIAtom *kNaturalOrderPosAtom;
|
|
|
|
nsIAtom *kTreeCellAtom;
|
|
|
|
PRInt32 kNameSpaceID_XUL;
|
1999-03-10 10:07:10 +03:00
|
|
|
PRBool descendingSort;
|
|
|
|
PRBool naturalOrderSort;
|
|
|
|
} sortStruct, *sortPtr;
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-05-13 12:25:12 +04:00
|
|
|
int openSortCallback(const void *data1, const void *data2, void *privateData);
|
|
|
|
int inplaceSortCallback(const void *data1, const void *data2, void *privateData);
|
1999-03-11 15:01:47 +03:00
|
|
|
|
1999-03-10 10:07:10 +03:00
|
|
|
|
|
|
|
|
1999-03-06 02:51:41 +03:00
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// ServiceImpl
|
|
|
|
//
|
|
|
|
// This is the sort service.
|
|
|
|
//
|
|
|
|
class XULSortServiceImpl : public nsIXULSortService
|
|
|
|
{
|
|
|
|
protected:
|
|
|
|
XULSortServiceImpl(void);
|
|
|
|
virtual ~XULSortServiceImpl(void);
|
|
|
|
|
1999-05-18 02:43:47 +04:00
|
|
|
static nsIXULSortService *gXULSortService;
|
|
|
|
static nsICollation *collationService;
|
1999-03-06 02:51:41 +03:00
|
|
|
|
|
|
|
private:
|
|
|
|
static nsrefcnt gRefCnt;
|
|
|
|
static nsIAtom *kTreeAtom;
|
|
|
|
static nsIAtom *kTreeBodyAtom;
|
|
|
|
static nsIAtom *kTreeCellAtom;
|
|
|
|
static nsIAtom *kTreeChildrenAtom;
|
|
|
|
static nsIAtom *kTreeColAtom;
|
|
|
|
static nsIAtom *kTreeItemAtom;
|
|
|
|
static nsIAtom *kResourceAtom;
|
|
|
|
static nsIAtom *kTreeContentsGeneratedAtom;
|
1999-03-07 12:44:38 +03:00
|
|
|
static nsIAtom *kNameAtom;
|
|
|
|
static nsIAtom *kSortAtom;
|
|
|
|
static nsIAtom *kSortDirectionAtom;
|
|
|
|
static nsIAtom *kIdAtom;
|
|
|
|
static nsIAtom *kNaturalOrderPosAtom;
|
1999-04-27 06:28:12 +04:00
|
|
|
static nsIAtom *kRDF_type;
|
|
|
|
|
|
|
|
static nsIRDFResource *kNC_Name;
|
1999-03-07 12:44:38 +03:00
|
|
|
|
1999-03-06 02:51:41 +03:00
|
|
|
static PRInt32 kNameSpaceID_XUL;
|
|
|
|
static PRInt32 kNameSpaceID_RDF;
|
|
|
|
|
1999-03-07 12:44:38 +03:00
|
|
|
static nsIRDFService *gRDFService;
|
|
|
|
|
1999-03-06 02:51:41 +03:00
|
|
|
nsresult FindTreeElement(nsIContent* aElement,nsIContent** aTreeElement);
|
|
|
|
nsresult FindTreeBodyElement(nsIContent *tree, nsIContent **treeBody);
|
1999-03-10 11:11:28 +03:00
|
|
|
nsresult GetSortColumnIndex(nsIContent *tree, const nsString&sortResource, const nsString& sortDirection, PRInt32 *colIndex);
|
1999-03-07 12:44:38 +03:00
|
|
|
nsresult GetSortColumnInfo(nsIContent *tree, nsString &sortResource, nsString &sortDirection);
|
1999-03-06 02:51:41 +03:00
|
|
|
nsresult GetTreeCell(nsIContent *node, PRInt32 colIndex, nsIContent **cell);
|
|
|
|
nsresult GetTreeCellValue(nsIContent *node, nsString & value);
|
1999-03-06 03:11:14 +03:00
|
|
|
nsresult RemoveAllChildren(nsIContent *node);
|
1999-03-10 10:07:10 +03:00
|
|
|
nsresult SortTreeChildren(nsIContent *container, PRInt32 colIndex, sortPtr sortInfo, PRInt32 indentLevel);
|
1999-03-06 02:51:41 +03:00
|
|
|
nsresult PrintTreeChildren(nsIContent *container, PRInt32 colIndex, PRInt32 indentLevel);
|
|
|
|
|
1999-05-18 10:19:04 +04:00
|
|
|
static nsresult GetResourceValue(nsIRDFResource *res1, nsIRDFResource *sortProperty, sortPtr sortInfo, nsString &cellVal1, PRBool &isCollationKey);
|
1999-05-13 20:57:59 +04:00
|
|
|
static nsresult GetNodeValue(nsIContent *node1, nsIRDFResource *sortProperty, sortPtr sortInfo, nsString &cellVal1, PRBool &isCollationKey);
|
|
|
|
static nsresult GetTreeCell(sortPtr sortInfo, nsIContent *node, PRInt32 cellIndex, nsIContent **cell);
|
|
|
|
static nsresult GetTreeCellValue(sortPtr sortInfo, nsIContent *node, nsString & val);
|
1999-05-13 12:25:12 +04:00
|
|
|
|
1999-03-06 02:51:41 +03:00
|
|
|
public:
|
|
|
|
|
|
|
|
static nsresult GetSortService(nsIXULSortService** result);
|
|
|
|
|
1999-05-13 20:57:59 +04:00
|
|
|
static nsresult ImplaceSort(nsIContent *node1, nsIContent *node2, sortPtr sortInfo, PRInt32 *sortOrder);
|
|
|
|
static nsresult OpenSort(nsIRDFNode *node1, nsIRDFNode *node2, sortPtr sortInfo, PRInt32 *theSortOrder);
|
1999-05-13 12:25:12 +04:00
|
|
|
|
1999-03-06 02:51:41 +03:00
|
|
|
// nsISupports
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
|
|
|
|
// nsISortService
|
1999-03-07 12:44:38 +03:00
|
|
|
NS_IMETHOD DoSort(nsIDOMNode* node, const nsString& sortResource, const nsString& sortDirection);
|
|
|
|
NS_IMETHOD OpenContainer(nsIRDFCompositeDataSource *db, nsIContent *container, nsIRDFResource **flatArray,
|
|
|
|
PRInt32 numElements, PRInt32 elementSize);
|
1999-04-21 00:26:13 +04:00
|
|
|
NS_IMETHOD InsertContainerNode(nsIContent *container, nsIContent *node);
|
1999-03-06 02:51:41 +03:00
|
|
|
};
|
|
|
|
|
1999-05-18 02:43:47 +04:00
|
|
|
nsIXULSortService *XULSortServiceImpl::gXULSortService = nsnull;
|
|
|
|
nsICollation *XULSortServiceImpl::collationService = nsnull;
|
1999-03-06 02:51:41 +03:00
|
|
|
nsrefcnt XULSortServiceImpl::gRefCnt = 0;
|
|
|
|
|
1999-03-07 12:44:38 +03:00
|
|
|
nsIRDFService *XULSortServiceImpl::gRDFService = nsnull;
|
|
|
|
|
1999-03-06 02:51:41 +03:00
|
|
|
nsIAtom* XULSortServiceImpl::kTreeAtom;
|
|
|
|
nsIAtom* XULSortServiceImpl::kTreeBodyAtom;
|
|
|
|
nsIAtom* XULSortServiceImpl::kTreeCellAtom;
|
|
|
|
nsIAtom* XULSortServiceImpl::kTreeChildrenAtom;
|
|
|
|
nsIAtom* XULSortServiceImpl::kTreeColAtom;
|
|
|
|
nsIAtom* XULSortServiceImpl::kTreeItemAtom;
|
|
|
|
nsIAtom* XULSortServiceImpl::kResourceAtom;
|
|
|
|
nsIAtom* XULSortServiceImpl::kTreeContentsGeneratedAtom;
|
1999-03-07 12:44:38 +03:00
|
|
|
nsIAtom* XULSortServiceImpl::kNameAtom;
|
|
|
|
nsIAtom* XULSortServiceImpl::kSortAtom;
|
|
|
|
nsIAtom* XULSortServiceImpl::kSortDirectionAtom;
|
|
|
|
nsIAtom* XULSortServiceImpl::kIdAtom;
|
|
|
|
nsIAtom* XULSortServiceImpl::kNaturalOrderPosAtom;
|
1999-04-27 06:28:12 +04:00
|
|
|
nsIAtom* XULSortServiceImpl::kRDF_type;
|
|
|
|
|
|
|
|
nsIRDFResource *XULSortServiceImpl::kNC_Name;
|
1999-03-07 12:44:38 +03:00
|
|
|
|
1999-03-06 02:51:41 +03:00
|
|
|
PRInt32 XULSortServiceImpl::kNameSpaceID_XUL;
|
|
|
|
PRInt32 XULSortServiceImpl::kNameSpaceID_RDF;
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
1999-03-11 15:01:47 +03:00
|
|
|
|
|
|
|
|
1999-03-06 02:51:41 +03:00
|
|
|
XULSortServiceImpl::XULSortServiceImpl(void)
|
|
|
|
{
|
|
|
|
NS_INIT_REFCNT();
|
|
|
|
if (gRefCnt == 0)
|
|
|
|
{
|
|
|
|
kTreeAtom = NS_NewAtom("tree");
|
|
|
|
kTreeBodyAtom = NS_NewAtom("treebody");
|
|
|
|
kTreeCellAtom = NS_NewAtom("treecell");
|
|
|
|
kTreeChildrenAtom = NS_NewAtom("treechildren");
|
|
|
|
kTreeColAtom = NS_NewAtom("treecol");
|
|
|
|
kTreeItemAtom = NS_NewAtom("treeitem");
|
|
|
|
kResourceAtom = NS_NewAtom("resource");
|
|
|
|
kTreeContentsGeneratedAtom = NS_NewAtom("treecontentsgenerated");
|
1999-03-07 12:44:38 +03:00
|
|
|
kNameAtom = NS_NewAtom("Name");
|
|
|
|
kSortAtom = NS_NewAtom("sortActive");
|
|
|
|
kSortDirectionAtom = NS_NewAtom("sortDirection");
|
|
|
|
kIdAtom = NS_NewAtom("id");
|
|
|
|
kNaturalOrderPosAtom = NS_NewAtom("pos");
|
1999-04-27 06:28:12 +04:00
|
|
|
kRDF_type = NS_NewAtom("type");
|
1999-03-06 02:51:41 +03:00
|
|
|
|
|
|
|
nsresult rv;
|
|
|
|
|
1999-03-07 12:44:38 +03:00
|
|
|
if (NS_FAILED(rv = nsServiceManager::GetService(kRDFServiceCID,
|
|
|
|
kIRDFServiceIID, (nsISupports**) &gRDFService)))
|
|
|
|
{
|
|
|
|
NS_ERROR("couldn't create rdf service");
|
|
|
|
}
|
1999-04-27 06:28:12 +04:00
|
|
|
|
1999-05-18 02:43:47 +04:00
|
|
|
nsICollationFactory *colFactory;
|
|
|
|
if (NS_SUCCEEDED(rv = nsComponentManager::CreateInstance(kCollationFactoryCID, NULL,
|
|
|
|
kICollationFactoryIID, (void**) &colFactory)))
|
|
|
|
{
|
|
|
|
// Temporary: pass null until bug#3867 is fixed
|
|
|
|
if (NS_FAILED(rv = colFactory->CreateCollation(nsnull/*locale*/, &collationService)))
|
|
|
|
{
|
|
|
|
NS_ERROR("couldn't create collation instance");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NS_ERROR("couldn't create instance of collation factory");
|
|
|
|
}
|
|
|
|
|
1999-04-27 06:28:12 +04:00
|
|
|
gRDFService->GetResource(kURINC_Name, &kNC_Name);
|
|
|
|
|
1999-03-06 02:51:41 +03:00
|
|
|
// Register the XUL and RDF namespaces: these'll just retrieve
|
|
|
|
// the IDs if they've already been registered by someone else.
|
|
|
|
nsINameSpaceManager* mgr;
|
1999-03-09 12:44:27 +03:00
|
|
|
if (NS_SUCCEEDED(rv = nsComponentManager::CreateInstance(kNameSpaceManagerCID,
|
1999-03-06 02:51:41 +03:00
|
|
|
nsnull,
|
|
|
|
kINameSpaceManagerIID,
|
|
|
|
(void**) &mgr)))
|
|
|
|
{
|
|
|
|
|
|
|
|
// 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";
|
|
|
|
|
|
|
|
static const char kRDFNameSpaceURI[]
|
|
|
|
= RDF_NAMESPACE_URI;
|
|
|
|
|
|
|
|
rv = mgr->RegisterNameSpace(kXULNameSpaceURI, kNameSpaceID_XUL);
|
|
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to register XUL namespace");
|
|
|
|
|
|
|
|
rv = mgr->RegisterNameSpace(kRDFNameSpaceURI, kNameSpaceID_RDF);
|
|
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to register RDF namespace");
|
|
|
|
|
|
|
|
NS_RELEASE(mgr);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NS_ERROR("couldn't create namepsace manager");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
++gRefCnt;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-03-11 15:01:47 +03:00
|
|
|
|
1999-03-06 02:51:41 +03:00
|
|
|
XULSortServiceImpl::~XULSortServiceImpl(void)
|
|
|
|
{
|
|
|
|
--gRefCnt;
|
|
|
|
if (gRefCnt == 0)
|
|
|
|
{
|
|
|
|
NS_RELEASE(kTreeAtom);
|
|
|
|
NS_RELEASE(kTreeBodyAtom);
|
|
|
|
NS_RELEASE(kTreeCellAtom);
|
|
|
|
NS_RELEASE(kTreeChildrenAtom);
|
|
|
|
NS_RELEASE(kTreeColAtom);
|
|
|
|
NS_RELEASE(kTreeItemAtom);
|
|
|
|
NS_RELEASE(kResourceAtom);
|
|
|
|
NS_RELEASE(kTreeContentsGeneratedAtom);
|
1999-03-07 12:44:38 +03:00
|
|
|
NS_RELEASE(kNameAtom);
|
|
|
|
NS_RELEASE(kSortAtom);
|
|
|
|
NS_RELEASE(kSortDirectionAtom);
|
|
|
|
NS_RELEASE(kIdAtom);
|
|
|
|
NS_RELEASE(kNaturalOrderPosAtom);
|
1999-04-27 06:28:12 +04:00
|
|
|
NS_RELEASE(kRDF_type);
|
|
|
|
|
|
|
|
NS_RELEASE(kNC_Name);
|
1999-03-07 12:44:38 +03:00
|
|
|
|
1999-05-18 02:43:47 +04:00
|
|
|
if (collationService)
|
|
|
|
{
|
|
|
|
NS_RELEASE(collationService);
|
|
|
|
collationService = nsnull;
|
|
|
|
}
|
|
|
|
if (gRDFService)
|
|
|
|
{
|
|
|
|
nsServiceManager::ReleaseService(kRDFServiceCID, gRDFService);
|
|
|
|
gRDFService = nsnull;
|
|
|
|
}
|
|
|
|
if (gXULSortService)
|
|
|
|
{
|
|
|
|
nsServiceManager::ReleaseService(kXULSortServiceCID, gXULSortService);
|
|
|
|
gXULSortService = nsnull;
|
|
|
|
}
|
1999-03-06 02:51:41 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-03-11 15:01:47 +03:00
|
|
|
|
1999-03-06 02:51:41 +03:00
|
|
|
nsresult
|
|
|
|
XULSortServiceImpl::GetSortService(nsIXULSortService** mgr)
|
|
|
|
{
|
|
|
|
if (! gXULSortService) {
|
|
|
|
gXULSortService = new XULSortServiceImpl();
|
|
|
|
if (! gXULSortService)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_ADDREF(gXULSortService);
|
|
|
|
*mgr = gXULSortService;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-05-13 12:25:12 +04:00
|
|
|
NS_IMPL_ISUPPORTS(XULSortServiceImpl, nsIXULSortService::GetIID());
|
|
|
|
|
|
|
|
/*
|
1999-03-06 02:51:41 +03:00
|
|
|
NS_IMETHODIMP_(nsrefcnt)
|
|
|
|
XULSortServiceImpl::AddRef(void)
|
|
|
|
{
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
1999-03-11 15:01:47 +03:00
|
|
|
|
|
|
|
|
1999-03-06 02:51:41 +03:00
|
|
|
NS_IMETHODIMP_(nsrefcnt)
|
|
|
|
XULSortServiceImpl::Release(void)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-03-11 15:01:47 +03:00
|
|
|
|
1999-03-06 02:51:41 +03:00
|
|
|
NS_IMPL_QUERY_INTERFACE(XULSortServiceImpl, kIXULSortServiceIID);
|
1999-05-13 12:25:12 +04:00
|
|
|
*/
|
1999-03-06 02:51:41 +03:00
|
|
|
|
1999-03-11 15:01:47 +03:00
|
|
|
|
1999-03-06 02:51:41 +03:00
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
1999-03-11 15:01:47 +03:00
|
|
|
|
|
|
|
|
1999-03-06 02:51:41 +03:00
|
|
|
nsresult
|
|
|
|
XULSortServiceImpl::FindTreeElement(nsIContent *aElement, nsIContent **aTreeElement)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsIContent> element(do_QueryInterface(aElement));
|
|
|
|
|
|
|
|
while (element)
|
|
|
|
{
|
|
|
|
PRInt32 nameSpaceID;
|
|
|
|
if (NS_FAILED(rv = element->GetNameSpaceID(nameSpaceID))) return rv;
|
|
|
|
if (nameSpaceID == kNameSpaceID_XUL)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIAtom> tag;
|
|
|
|
if (NS_FAILED(rv = element->GetTag(*getter_AddRefs(tag)))) return rv;
|
|
|
|
if (tag.get() == kTreeAtom)
|
|
|
|
{
|
|
|
|
*aTreeElement = element;
|
|
|
|
NS_ADDREF(*aTreeElement);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
nsCOMPtr<nsIContent> parent;
|
|
|
|
element->GetParent(*getter_AddRefs(parent));
|
|
|
|
element = parent;
|
|
|
|
}
|
|
|
|
return(NS_ERROR_FAILURE);
|
|
|
|
}
|
|
|
|
|
1999-03-11 15:01:47 +03:00
|
|
|
|
|
|
|
|
1999-03-06 02:51:41 +03:00
|
|
|
nsresult
|
|
|
|
XULSortServiceImpl::FindTreeBodyElement(nsIContent *tree, nsIContent **treeBody)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIContent> child;
|
|
|
|
PRInt32 childIndex = 0, numChildren = 0, 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() == kTreeBodyAtom)
|
|
|
|
{
|
|
|
|
*treeBody = child;
|
|
|
|
NS_ADDREF(*treeBody);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return(NS_ERROR_FAILURE);
|
|
|
|
}
|
|
|
|
|
1999-03-11 15:01:47 +03:00
|
|
|
|
|
|
|
|
1999-03-06 02:51:41 +03:00
|
|
|
nsresult
|
1999-03-10 11:11:28 +03:00
|
|
|
XULSortServiceImpl::GetSortColumnIndex(nsIContent *tree, const nsString& sortResource, const nsString& sortDirection, PRInt32 *sortColIndex)
|
1999-03-06 02:51:41 +03:00
|
|
|
{
|
|
|
|
PRBool found = PR_FALSE;
|
1999-03-07 12:44:38 +03:00
|
|
|
PRInt32 childIndex, colIndex = 0, numChildren, nameSpaceID;
|
1999-03-06 02:51:41 +03:00
|
|
|
nsCOMPtr<nsIContent> child;
|
|
|
|
nsresult rv;
|
|
|
|
|
1999-03-07 12:44:38 +03:00
|
|
|
*sortColIndex = 0;
|
1999-03-06 02:51:41 +03:00
|
|
|
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 colResource;
|
|
|
|
|
|
|
|
if (NS_OK == child->GetAttribute(kNameSpaceID_RDF, kResourceAtom, colResource))
|
|
|
|
{
|
|
|
|
if (colResource == sortResource)
|
|
|
|
{
|
1999-03-07 12:44:38 +03:00
|
|
|
nsString trueStr("true");
|
|
|
|
child->SetAttribute(kNameSpaceID_None, kSortAtom, trueStr, PR_TRUE);
|
|
|
|
child->SetAttribute(kNameSpaceID_None, kSortDirectionAtom, sortDirection, PR_TRUE);
|
|
|
|
*sortColIndex = colIndex;
|
1999-03-06 02:51:41 +03:00
|
|
|
found = PR_TRUE;
|
1999-03-07 12:44:38 +03:00
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
|
1999-03-11 15:01:47 +03:00
|
|
|
|
|
|
|
|
1999-03-07 12:44:38 +03:00
|
|
|
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))
|
|
|
|
{
|
1999-03-10 12:41:07 +03:00
|
|
|
if (value.EqualsIgnoreCase("true"))
|
1999-03-07 12:44:38 +03:00
|
|
|
{
|
|
|
|
if (NS_OK == child->GetAttribute(kNameSpaceID_RDF, kResourceAtom, sortResource))
|
|
|
|
{
|
|
|
|
if (NS_OK == child->GetAttribute(kNameSpaceID_None, kSortDirectionAtom, sortDirection))
|
|
|
|
{
|
|
|
|
found = PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
1999-03-06 02:51:41 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return((found == PR_TRUE) ? NS_OK : NS_ERROR_FAILURE);
|
|
|
|
}
|
|
|
|
|
1999-03-11 15:01:47 +03:00
|
|
|
|
|
|
|
|
1999-03-06 02:51:41 +03:00
|
|
|
nsresult
|
1999-05-13 12:25:12 +04:00
|
|
|
XULSortServiceImpl::GetTreeCell(sortPtr sortInfo, nsIContent *node, PRInt32 cellIndex, nsIContent **cell)
|
1999-03-06 02:51:41 +03:00
|
|
|
{
|
|
|
|
PRBool found = PR_FALSE;
|
|
|
|
PRInt32 childIndex = 0, numChildren = 0, nameSpaceID;
|
|
|
|
nsCOMPtr<nsIContent> child;
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
if (NS_FAILED(rv = node->ChildCount(numChildren))) return(rv);
|
|
|
|
|
|
|
|
for (childIndex=0; childIndex<numChildren; childIndex++)
|
|
|
|
{
|
1999-03-11 15:01:47 +03:00
|
|
|
if (NS_FAILED(rv = node->ChildAt(childIndex, *getter_AddRefs(child)))) break;
|
1999-03-06 02:51:41 +03:00
|
|
|
if (NS_FAILED(rv = child->GetNameSpaceID(nameSpaceID))) break;
|
1999-03-11 15:01:47 +03:00
|
|
|
if (nameSpaceID == sortInfo->kNameSpaceID_XUL)
|
1999-03-06 02:51:41 +03:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIAtom> tag;
|
|
|
|
if (NS_FAILED(rv = child->GetTag(*getter_AddRefs(tag)))) return rv;
|
1999-03-11 15:01:47 +03:00
|
|
|
if (tag.get() == sortInfo->kTreeCellAtom)
|
1999-03-06 02:51:41 +03:00
|
|
|
{
|
|
|
|
if (cellIndex == 0)
|
|
|
|
{
|
|
|
|
found = PR_TRUE;
|
|
|
|
*cell = child;
|
|
|
|
NS_ADDREF(*cell);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
--cellIndex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return((found == PR_TRUE) ? NS_OK : NS_ERROR_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-03-11 15:01:47 +03:00
|
|
|
|
1999-03-06 02:51:41 +03:00
|
|
|
nsresult
|
1999-05-13 12:25:12 +04:00
|
|
|
XULSortServiceImpl::GetTreeCellValue(sortPtr sortInfo, nsIContent *node, nsString & val)
|
1999-03-06 02:51:41 +03:00
|
|
|
{
|
|
|
|
PRBool found = PR_FALSE;
|
|
|
|
PRInt32 childIndex = 0, numChildren = 0, nameSpaceID;
|
|
|
|
nsCOMPtr<nsIContent> child;
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
if (NS_FAILED(rv = node->ChildCount(numChildren))) return(rv);
|
|
|
|
|
|
|
|
for (childIndex=0; childIndex<numChildren; childIndex++)
|
|
|
|
{
|
1999-05-06 23:28:22 +04:00
|
|
|
if (NS_FAILED(rv = node->ChildAt(childIndex, *getter_AddRefs(child))))
|
|
|
|
break;
|
|
|
|
if (NS_FAILED(rv = child->GetNameSpaceID(nameSpaceID)))
|
|
|
|
break;
|
1999-03-11 15:01:47 +03:00
|
|
|
if (nameSpaceID != sortInfo->kNameSpaceID_XUL)
|
1999-03-06 02:51:41 +03:00
|
|
|
{
|
1999-05-06 23:28:22 +04:00
|
|
|
// Get text using the DOM
|
|
|
|
nsCOMPtr<nsIDOMText> domText;
|
|
|
|
rv = child->QueryInterface(kIDOMTextIID, getter_AddRefs(domText));
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
break;
|
|
|
|
val.Truncate();
|
|
|
|
domText->GetData(val);
|
1999-05-07 09:17:30 +04:00
|
|
|
found = PR_TRUE;
|
1999-05-06 23:28:22 +04:00
|
|
|
break;
|
1999-03-06 02:51:41 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return((found == PR_TRUE) ? NS_OK : NS_ERROR_FAILURE);
|
|
|
|
}
|
|
|
|
|
1999-03-11 15:01:47 +03:00
|
|
|
|
|
|
|
|
1999-03-06 02:51:41 +03:00
|
|
|
nsresult
|
1999-03-06 03:11:14 +03:00
|
|
|
XULSortServiceImpl::RemoveAllChildren(nsIContent *container)
|
1999-03-06 02:51:41 +03:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIContent> child;
|
|
|
|
PRInt32 childIndex, numChildren;
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
if (NS_FAILED(rv = container->ChildCount(numChildren))) return(rv);
|
|
|
|
if (numChildren == 0) return(NS_OK);
|
|
|
|
|
|
|
|
for (childIndex=numChildren-1; childIndex >= 0; childIndex--)
|
|
|
|
{
|
|
|
|
if (NS_FAILED(rv = container->ChildAt(childIndex, *getter_AddRefs(child)))) break;
|
1999-03-18 23:46:02 +03:00
|
|
|
container->RemoveChildAt(childIndex, PR_FALSE);
|
1999-03-06 02:51:41 +03:00
|
|
|
}
|
|
|
|
return(rv);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-03-07 12:44:38 +03:00
|
|
|
|
1999-05-13 12:25:12 +04:00
|
|
|
nsresult
|
|
|
|
XULSortServiceImpl::OpenSort(nsIRDFNode *node1, nsIRDFNode *node2, sortPtr sortInfo, PRInt32 *theSortOrder)
|
1999-03-07 12:44:38 +03:00
|
|
|
{
|
1999-05-18 10:19:04 +04:00
|
|
|
nsAutoString cellVal1(""), cellVal2("");
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
PRBool isCollationKey1 = PR_FALSE, isCollationKey2 = PR_FALSE;
|
|
|
|
PRInt32 sortOrder = 0;
|
1999-03-07 12:44:38 +03:00
|
|
|
|
1999-05-13 12:25:12 +04:00
|
|
|
nsCOMPtr<nsIRDFResource> res1 = do_QueryInterface(node1);
|
|
|
|
if (res1)
|
1999-03-07 12:44:38 +03:00
|
|
|
{
|
1999-05-18 10:19:04 +04:00
|
|
|
rv = GetResourceValue(res1, sortInfo->sortProperty, sortInfo, cellVal1, isCollationKey1);
|
1999-03-07 12:44:38 +03:00
|
|
|
}
|
1999-05-13 12:25:12 +04:00
|
|
|
nsCOMPtr<nsIRDFResource> res2 = do_QueryInterface(node2);
|
|
|
|
if (res2)
|
1999-03-07 12:44:38 +03:00
|
|
|
{
|
1999-05-18 10:19:04 +04:00
|
|
|
rv = GetResourceValue(res2, sortInfo->sortProperty, sortInfo, cellVal2, isCollationKey2);
|
1999-03-07 12:44:38 +03:00
|
|
|
}
|
1999-05-13 12:25:12 +04:00
|
|
|
|
1999-05-18 10:19:04 +04:00
|
|
|
if ((isCollationKey1 == PR_TRUE) && (isCollationKey2 == PR_FALSE))
|
|
|
|
{
|
|
|
|
sortOrder = -1;
|
|
|
|
}
|
|
|
|
else if ((isCollationKey1 == PR_FALSE) && (isCollationKey2 == PR_TRUE))
|
|
|
|
{
|
|
|
|
sortOrder = 1;
|
|
|
|
}
|
|
|
|
else if (isCollationKey1 == PR_TRUE && isCollationKey2 == PR_TRUE)
|
1999-03-07 12:44:38 +03:00
|
|
|
{
|
1999-05-18 10:19:04 +04:00
|
|
|
// sort collation keys
|
|
|
|
if (collationService)
|
1999-03-07 12:44:38 +03:00
|
|
|
{
|
1999-05-18 10:19:04 +04:00
|
|
|
collationService->CompareSortKey(cellVal1, cellVal2, &sortOrder);
|
1999-03-07 12:44:38 +03:00
|
|
|
}
|
|
|
|
}
|
1999-05-18 10:19:04 +04:00
|
|
|
else
|
1999-03-07 12:44:38 +03:00
|
|
|
{
|
1999-05-18 10:19:04 +04:00
|
|
|
// neither is a collation key, fallback to a string comparison
|
|
|
|
sortOrder = (PRInt32)cellVal1.Compare(cellVal2, PR_TRUE);
|
1999-03-07 12:44:38 +03:00
|
|
|
}
|
1999-05-18 10:19:04 +04:00
|
|
|
|
|
|
|
if (sortInfo->descendingSort == PR_TRUE)
|
1999-03-07 12:44:38 +03:00
|
|
|
{
|
1999-05-18 10:19:04 +04:00
|
|
|
// descending sort is being imposed, so reverse the sort order
|
|
|
|
sortOrder = -sortOrder;
|
1999-03-07 12:44:38 +03:00
|
|
|
}
|
1999-05-13 12:25:12 +04:00
|
|
|
|
|
|
|
*theSortOrder = sortOrder;
|
1999-05-18 10:19:04 +04:00
|
|
|
return(rv);
|
1999-05-13 12:25:12 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
openSortCallback(const void *data1, const void *data2, void *privateData)
|
|
|
|
{
|
|
|
|
/// Note: openSortCallback is a small C callback stub for NS_QuickSort
|
|
|
|
|
|
|
|
_sortStruct *sortInfo = (_sortStruct *)privateData;
|
|
|
|
nsIRDFNode *node1 = *(nsIRDFNode **)data1;
|
|
|
|
nsIRDFNode *node2 = *(nsIRDFNode **)data2;
|
|
|
|
PRInt32 sortOrder = 0;
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
if (nsnull != sortInfo)
|
|
|
|
{
|
1999-05-18 02:43:47 +04:00
|
|
|
rv = XULSortServiceImpl::OpenSort(node1, node2, sortInfo, &sortOrder);
|
1999-05-13 12:25:12 +04:00
|
|
|
}
|
1999-03-07 12:44:38 +03:00
|
|
|
return(sortOrder);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-03-11 15:01:47 +03:00
|
|
|
|
1999-03-19 04:52:18 +03:00
|
|
|
nsresult
|
1999-05-18 10:19:04 +04:00
|
|
|
XULSortServiceImpl::GetResourceValue(nsIRDFResource *res1, nsIRDFResource *sortProperty, sortPtr sortInfo,
|
1999-05-13 12:25:12 +04:00
|
|
|
nsString &cellVal1, PRBool &isCollationKey)
|
1999-03-19 04:52:18 +03:00
|
|
|
{
|
1999-05-18 10:19:04 +04:00
|
|
|
nsresult rv = NS_OK;
|
1999-03-19 04:52:18 +03:00
|
|
|
|
|
|
|
cellVal1 = "";
|
1999-05-13 12:25:12 +04:00
|
|
|
isCollationKey = PR_FALSE;
|
|
|
|
|
|
|
|
if ((sortInfo->naturalOrderSort == PR_FALSE) && (sortInfo->sortProperty))
|
1999-03-19 04:52:18 +03:00
|
|
|
{
|
1999-05-13 12:25:12 +04:00
|
|
|
nsCOMPtr<nsIRDFNode> target1;
|
|
|
|
nsXPIDLCString sortPropertyURI;
|
|
|
|
sortInfo->sortProperty->GetValue( getter_Copies(sortPropertyURI) );
|
1999-05-13 12:29:56 +04:00
|
|
|
if ((sortPropertyURI) && (res1))
|
1999-03-19 04:52:18 +03:00
|
|
|
{
|
1999-05-13 12:25:12 +04:00
|
|
|
// for any given property, first ask the graph for its value with "?collation=true" appended
|
|
|
|
// to indicate that if there is a collation key available for this value, we want it
|
1999-03-19 04:52:18 +03:00
|
|
|
|
1999-05-13 12:25:12 +04:00
|
|
|
nsAutoString modSortProperty(sortPropertyURI);
|
|
|
|
modSortProperty += "?collation=true";
|
|
|
|
char *collationSortProp = modSortProperty.ToNewCString();
|
|
|
|
if (collationSortProp)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIRDFResource> modSortRes;
|
|
|
|
if (NS_SUCCEEDED(sortInfo->rdfService->GetResource(collationSortProp,
|
|
|
|
getter_AddRefs(modSortRes))) && (modSortRes))
|
1999-03-19 04:52:18 +03:00
|
|
|
{
|
1999-05-13 12:25:12 +04:00
|
|
|
if (NS_SUCCEEDED(rv = (sortInfo->db)->GetTarget(res1, modSortRes,
|
|
|
|
PR_TRUE, getter_AddRefs(target1))) && (rv != NS_RDF_NO_VALUE))
|
1999-03-19 04:52:18 +03:00
|
|
|
{
|
1999-05-13 12:25:12 +04:00
|
|
|
nsCOMPtr<nsIRDFLiteral> literal1 = do_QueryInterface(target1);
|
|
|
|
if (literal1)
|
1999-03-19 04:52:18 +03:00
|
|
|
{
|
1999-05-13 12:25:12 +04:00
|
|
|
nsXPIDLString uniStr1;
|
|
|
|
literal1->GetValue( getter_Copies(uniStr1) );
|
|
|
|
cellVal1 = uniStr1;
|
|
|
|
if (cellVal1.Length() > 0)
|
1999-03-19 04:52:18 +03:00
|
|
|
{
|
1999-05-13 12:25:12 +04:00
|
|
|
isCollationKey = PR_TRUE;
|
1999-03-19 04:52:18 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-05-13 12:25:12 +04:00
|
|
|
delete []collationSortProp;
|
|
|
|
}
|
|
|
|
if (cellVal1.Length() == 0)
|
|
|
|
{
|
|
|
|
// if no collation key, ask the graph for its value with "?sort=true" appended
|
|
|
|
// to indicate that if there is any distinction between its display value and sorting
|
|
|
|
// value, we want the sorting value (so that, for example, a mail datasource could strip
|
|
|
|
// off a "Re:" on a mail message subject)
|
|
|
|
modSortProperty = sortPropertyURI;
|
|
|
|
modSortProperty += "?sort=true";
|
|
|
|
char *sortProp = modSortProperty.ToNewCString();
|
|
|
|
if (sortProp)
|
1999-03-19 04:52:18 +03:00
|
|
|
{
|
1999-05-13 12:25:12 +04:00
|
|
|
nsCOMPtr<nsIRDFResource> modSortRes;
|
|
|
|
if (NS_SUCCEEDED(sortInfo->rdfService->GetResource(sortProp,
|
|
|
|
getter_AddRefs(modSortRes))) && (modSortRes))
|
1999-03-19 04:52:18 +03:00
|
|
|
{
|
1999-05-13 12:25:12 +04:00
|
|
|
if (NS_SUCCEEDED(rv = (sortInfo->db)->GetTarget(res1, modSortRes,
|
|
|
|
PR_TRUE, getter_AddRefs(target1))) && (rv != NS_RDF_NO_VALUE))
|
1999-03-19 04:52:18 +03:00
|
|
|
{
|
1999-05-13 12:25:12 +04:00
|
|
|
nsCOMPtr<nsIRDFLiteral> literal1 = do_QueryInterface(target1);
|
|
|
|
if (literal1)
|
1999-03-19 04:52:18 +03:00
|
|
|
{
|
1999-05-13 12:25:12 +04:00
|
|
|
nsXPIDLString uniStr1;
|
|
|
|
literal1->GetValue( getter_Copies(uniStr1) );
|
|
|
|
cellVal1 = uniStr1;
|
1999-03-19 04:52:18 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-05-13 12:25:12 +04:00
|
|
|
delete []sortProp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (cellVal1.Length() == 0)
|
|
|
|
{
|
|
|
|
// if no collation key and no special sorting value, just get the property value
|
1999-05-13 12:29:56 +04:00
|
|
|
if ((res1) && (NS_SUCCEEDED(rv = (sortInfo->db)->GetTarget(res1, sortProperty,
|
1999-05-13 12:25:12 +04:00
|
|
|
PR_TRUE, getter_AddRefs(target1))) && (rv != NS_RDF_NO_VALUE)))
|
|
|
|
{
|
|
|
|
nsIRDFLiteral *literal1;
|
|
|
|
if (NS_SUCCEEDED(target1->QueryInterface(kIRDFLiteralIID, (void **) &literal1)))
|
|
|
|
{
|
|
|
|
nsXPIDLString uniStr1;
|
|
|
|
literal1->GetValue( getter_Copies(uniStr1) );
|
|
|
|
cellVal1 = uniStr1;
|
|
|
|
NS_RELEASE(literal1);
|
1999-03-19 04:52:18 +03:00
|
|
|
}
|
|
|
|
}
|
1999-05-18 10:19:04 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return(rv);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
XULSortServiceImpl::GetNodeValue(nsIContent *node1, nsIRDFResource *sortProperty, sortPtr sortInfo,
|
|
|
|
nsString &cellVal1, PRBool &isCollationKey)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
cellVal1 = "";
|
|
|
|
isCollationKey = PR_FALSE;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMXULElement> dom1 = do_QueryInterface(node1);
|
|
|
|
if (!dom1) return(NS_ERROR_FAILURE);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIRDFResource> res1 = do_QueryInterface(dom1);
|
|
|
|
// Note: don't check for res1 QI failure here. It only succeeds for RDF nodes,
|
|
|
|
// but for XUL nodes it will failure; in the failure case, the code below gets
|
|
|
|
// the cell's text value straight from the DOM
|
|
|
|
|
|
|
|
if ((sortInfo->naturalOrderSort == PR_FALSE) && (sortInfo->sortProperty))
|
|
|
|
{
|
|
|
|
rv = GetResourceValue(res1, sortProperty, sortInfo, cellVal1, isCollationKey);
|
|
|
|
if (cellVal1.Length() == 0)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIContent> cell1;
|
|
|
|
if (NS_SUCCEEDED(rv = GetTreeCell(sortInfo, node1, sortInfo->colIndex,
|
|
|
|
getter_AddRefs(cell1))) && (cell1))
|
1999-03-19 04:52:18 +03:00
|
|
|
{
|
1999-05-18 10:19:04 +04:00
|
|
|
rv = GetTreeCellValue(sortInfo, cell1, cellVal1);
|
1999-03-19 04:52:18 +03:00
|
|
|
}
|
|
|
|
}
|
1999-05-13 12:25:12 +04:00
|
|
|
}
|
|
|
|
else if (sortInfo->naturalOrderSort == PR_TRUE)
|
|
|
|
{
|
|
|
|
rv = node1->GetAttribute(kNameSpaceID_None, sortInfo->kNaturalOrderPosAtom, cellVal1);
|
1999-03-19 04:52:18 +03:00
|
|
|
}
|
|
|
|
return(rv);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-05-13 12:25:12 +04:00
|
|
|
nsresult
|
|
|
|
XULSortServiceImpl::ImplaceSort(nsIContent *node1, nsIContent *node2, sortPtr sortInfo, PRInt32 *theSortOrder)
|
1999-03-06 02:51:41 +03:00
|
|
|
{
|
1999-03-11 15:01:47 +03:00
|
|
|
nsAutoString cellVal1(""), cellVal2("");
|
1999-05-13 12:25:12 +04:00
|
|
|
PRBool isCollationKey1 = PR_FALSE, isCollationKey2 = PR_FALSE;
|
|
|
|
PRInt32 sortOrder = 0;
|
1999-03-11 15:01:47 +03:00
|
|
|
nsresult rv;
|
1999-03-19 04:52:18 +03:00
|
|
|
|
1999-05-13 12:25:12 +04:00
|
|
|
GetNodeValue(node1, sortInfo->sortProperty, sortInfo, cellVal1, isCollationKey1);
|
1999-05-18 10:19:04 +04:00
|
|
|
GetNodeValue(node2, sortInfo->sortProperty, sortInfo, cellVal2, isCollationKey2);
|
|
|
|
if ((cellVal1.Length() == 0) && (cellVal2.Length() == 0))
|
1999-03-19 04:52:18 +03:00
|
|
|
{
|
1999-05-13 12:25:12 +04:00
|
|
|
nsCOMPtr<nsIRDFResource> name1;
|
|
|
|
sortInfo->rdfService->GetResource(kURINC_Name, getter_AddRefs(name1));
|
|
|
|
if (name1)
|
1999-03-19 04:52:18 +03:00
|
|
|
{
|
1999-05-13 12:25:12 +04:00
|
|
|
rv = GetNodeValue(node1, name1, sortInfo, cellVal1, isCollationKey1);
|
1999-03-19 04:52:18 +03:00
|
|
|
}
|
1999-05-13 12:25:12 +04:00
|
|
|
nsCOMPtr<nsIRDFResource> name2;
|
|
|
|
sortInfo->rdfService->GetResource(kURINC_Name, getter_AddRefs(name2));
|
|
|
|
if (name2)
|
1999-03-19 04:52:18 +03:00
|
|
|
{
|
1999-05-13 12:25:12 +04:00
|
|
|
rv = GetNodeValue(node2, name2, sortInfo, cellVal2, isCollationKey2);
|
1999-03-19 04:52:18 +03:00
|
|
|
}
|
|
|
|
}
|
1999-05-13 12:25:12 +04:00
|
|
|
|
|
|
|
if ((isCollationKey1 == PR_TRUE) && (isCollationKey2 == PR_FALSE))
|
1999-05-18 10:19:04 +04:00
|
|
|
{
|
1999-05-13 12:25:12 +04:00
|
|
|
sortOrder = -1;
|
1999-05-18 10:19:04 +04:00
|
|
|
}
|
1999-05-13 12:25:12 +04:00
|
|
|
else if ((isCollationKey1 == PR_FALSE) && (isCollationKey2 == PR_TRUE))
|
1999-05-18 10:19:04 +04:00
|
|
|
{
|
1999-05-13 12:25:12 +04:00
|
|
|
sortOrder = 1;
|
1999-05-18 10:19:04 +04:00
|
|
|
}
|
1999-05-13 12:25:12 +04:00
|
|
|
else if (isCollationKey1 == PR_TRUE && isCollationKey2 == PR_TRUE)
|
|
|
|
{
|
1999-05-18 02:43:47 +04:00
|
|
|
// sort collation keys
|
|
|
|
if (collationService)
|
|
|
|
{
|
|
|
|
collationService->CompareSortKey(cellVal1, cellVal2, &sortOrder);
|
|
|
|
}
|
1999-05-13 12:25:12 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// neither is a collation key, fallback to a string comparison
|
|
|
|
sortOrder = (PRInt32)cellVal1.Compare(cellVal2, PR_TRUE);
|
|
|
|
}
|
|
|
|
|
1999-03-19 04:52:18 +03:00
|
|
|
if (sortInfo->descendingSort == PR_TRUE)
|
|
|
|
{
|
1999-05-13 12:25:12 +04:00
|
|
|
// descending sort is being imposed, so reverse the sort order
|
1999-03-19 04:52:18 +03:00
|
|
|
sortOrder = -sortOrder;
|
|
|
|
}
|
1999-05-13 12:25:12 +04:00
|
|
|
|
|
|
|
*theSortOrder = sortOrder;
|
|
|
|
return(NS_OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
inplaceSortCallback(const void *data1, const void *data2, void *privateData)
|
|
|
|
{
|
|
|
|
/// Note: inplaceSortCallback is a small C callback stub for NS_QuickSort
|
|
|
|
|
|
|
|
_sortStruct *sortInfo = (_sortStruct *)privateData;
|
|
|
|
nsIContent *node1 = *(nsIContent **)data1;
|
|
|
|
nsIContent *node2 = *(nsIContent **)data2;
|
|
|
|
PRInt32 sortOrder = 0;
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
if (nsnull != sortInfo)
|
|
|
|
{
|
1999-05-18 02:43:47 +04:00
|
|
|
rv = XULSortServiceImpl::ImplaceSort(node1, node2, sortInfo, &sortOrder);
|
1999-05-13 12:25:12 +04:00
|
|
|
}
|
1999-03-19 04:52:18 +03:00
|
|
|
return(sortOrder);
|
1999-03-06 02:51:41 +03:00
|
|
|
}
|
|
|
|
|
1999-03-07 12:44:38 +03:00
|
|
|
|
|
|
|
|
1999-03-06 02:51:41 +03:00
|
|
|
nsresult
|
1999-03-10 10:07:10 +03:00
|
|
|
XULSortServiceImpl::SortTreeChildren(nsIContent *container, PRInt32 colIndex, sortPtr sortInfo, PRInt32 indentLevel)
|
1999-03-06 02:51:41 +03:00
|
|
|
{
|
|
|
|
PRInt32 childIndex = 0, numChildren = 0, nameSpaceID;
|
|
|
|
nsCOMPtr<nsIContent> child;
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
if (NS_FAILED(rv = container->ChildCount(numChildren))) return(rv);
|
|
|
|
|
1999-04-27 05:48:37 +04:00
|
|
|
nsCOMPtr<nsISupportsArray> childArray;
|
|
|
|
rv = NS_NewISupportsArray(getter_AddRefs(childArray));
|
|
|
|
if (NS_FAILED(rv)) return(rv);
|
1999-03-06 02:51:41 +03:00
|
|
|
|
|
|
|
for (childIndex=0; childIndex<numChildren; childIndex++)
|
|
|
|
{
|
|
|
|
if (NS_FAILED(rv = container->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;
|
|
|
|
if (tag.get() == kTreeItemAtom)
|
|
|
|
{
|
1999-03-11 15:01:47 +03:00
|
|
|
childArray->AppendElement(child);
|
|
|
|
|
|
|
|
// if no pos is specified, set one
|
|
|
|
nsAutoString pos;
|
|
|
|
if (NS_OK != child->GetAttribute(kNameSpaceID_None, kNaturalOrderPosAtom, pos))
|
1999-03-06 02:51:41 +03:00
|
|
|
{
|
1999-03-11 15:01:47 +03:00
|
|
|
nsAutoString zero("0000");
|
|
|
|
pos = "";
|
|
|
|
pos.Append(childIndex+1, 10);
|
|
|
|
if (pos.Length() < 4)
|
1999-03-06 02:51:41 +03:00
|
|
|
{
|
1999-03-11 15:01:47 +03:00
|
|
|
pos.Insert(zero, 0, 4-pos.Length());
|
1999-03-07 12:44:38 +03:00
|
|
|
}
|
1999-03-11 15:01:47 +03:00
|
|
|
child->SetAttribute(kNameSpaceID_None, kNaturalOrderPosAtom, pos, PR_FALSE);
|
1999-03-06 02:51:41 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-05-13 08:56:04 +04:00
|
|
|
PRUint32 cnt = 0;
|
1999-05-13 12:25:12 +04:00
|
|
|
rv = childArray->Count(&cnt);
|
|
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "Count failed");
|
|
|
|
unsigned long numElements = cnt;
|
1999-03-11 15:01:47 +03:00
|
|
|
if (numElements > 0)
|
1999-03-06 02:51:41 +03:00
|
|
|
{
|
1999-03-06 07:12:56 +03:00
|
|
|
nsIContent ** flatArray = new nsIContent*[numElements];
|
1999-03-06 02:51:41 +03:00
|
|
|
if (flatArray)
|
|
|
|
{
|
|
|
|
// flatten array of resources, sort them, then add as tree elements
|
|
|
|
unsigned long loop;
|
|
|
|
for (loop=0; loop<numElements; loop++)
|
1999-03-11 15:01:47 +03:00
|
|
|
{
|
1999-03-06 02:51:41 +03:00
|
|
|
flatArray[loop] = (nsIContent *)childArray->ElementAt(loop);
|
1999-03-11 15:01:47 +03:00
|
|
|
}
|
|
|
|
|
1999-04-27 06:28:12 +04:00
|
|
|
/* smart sorting (sort within separators) on name column */
|
|
|
|
if (sortInfo->sortProperty == kNC_Name)
|
|
|
|
{
|
|
|
|
PRInt32 startIndex=0;
|
|
|
|
for (loop=0; loop<numElements; loop++)
|
|
|
|
{
|
|
|
|
nsAutoString type;
|
|
|
|
if (NS_OK == flatArray[loop]->GetAttribute(kNameSpaceID_None, kRDF_type, type))
|
|
|
|
{
|
|
|
|
if (type.EqualsIgnoreCase(kURINC_BookmarkSeparator))
|
|
|
|
{
|
|
|
|
if (loop > startIndex+1)
|
|
|
|
{
|
1999-05-10 10:47:04 +04:00
|
|
|
NS_QuickSort((void *)&flatArray[startIndex], loop-startIndex, sizeof(nsIContent *),
|
1999-04-27 06:28:12 +04:00
|
|
|
inplaceSortCallback, (void *)sortInfo);
|
|
|
|
startIndex = loop+1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (loop > startIndex+1)
|
|
|
|
{
|
1999-05-10 10:47:04 +04:00
|
|
|
NS_QuickSort((void *)&flatArray[startIndex], loop-startIndex, sizeof(nsIContent *),
|
1999-04-27 06:28:12 +04:00
|
|
|
inplaceSortCallback, (void *)sortInfo);
|
|
|
|
startIndex = loop+1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1999-05-10 10:47:04 +04:00
|
|
|
NS_QuickSort((void *)flatArray, numElements, sizeof(nsIContent *),
|
1999-04-27 06:28:12 +04:00
|
|
|
inplaceSortCallback, (void *)sortInfo);
|
|
|
|
}
|
1999-03-06 02:51:41 +03:00
|
|
|
|
1999-03-06 03:11:14 +03:00
|
|
|
RemoveAllChildren(container);
|
1999-03-06 02:51:41 +03:00
|
|
|
if (NS_FAILED(rv = container->UnsetAttribute(kNameSpaceID_None,
|
|
|
|
kTreeContentsGeneratedAtom,
|
|
|
|
PR_FALSE)))
|
|
|
|
{
|
|
|
|
printf("unable to clear contents-generated attribute\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
// insert sorted children
|
|
|
|
numChildren = 0;
|
1999-03-11 15:01:47 +03:00
|
|
|
for (loop=0; loop<numElements; loop++)
|
1999-03-06 02:51:41 +03:00
|
|
|
{
|
1999-03-18 23:46:02 +03:00
|
|
|
container->InsertChildAt((nsIContent *)flatArray[loop], numChildren++, PR_FALSE);
|
1999-03-06 02:51:41 +03:00
|
|
|
}
|
1999-03-07 12:44:38 +03:00
|
|
|
|
|
|
|
// recurse on grandchildren
|
1999-03-11 15:01:47 +03:00
|
|
|
for (loop=0; loop<numElements; loop++)
|
1999-03-07 12:44:38 +03:00
|
|
|
{
|
1999-03-11 15:01:47 +03:00
|
|
|
container = (nsIContent *)flatArray[loop];
|
1999-03-07 12:44:38 +03:00
|
|
|
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)
|
|
|
|
{
|
1999-03-10 10:07:10 +03:00
|
|
|
SortTreeChildren(child, colIndex, sortInfo, indentLevel+1);
|
1999-03-07 12:44:38 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-03-11 15:01:47 +03:00
|
|
|
|
1999-03-07 12:44:38 +03:00
|
|
|
delete [] flatArray;
|
|
|
|
flatArray = nsnull;
|
1999-03-06 02:51:41 +03:00
|
|
|
}
|
|
|
|
}
|
1999-05-13 12:25:12 +04:00
|
|
|
rv = childArray->Count(&cnt);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
for (int i = cnt - 1; i >= 0; i--)
|
|
|
|
{
|
|
|
|
childArray->RemoveElementAt(i);
|
|
|
|
}
|
1999-03-07 12:44:38 +03:00
|
|
|
return(NS_OK);
|
1999-03-06 02:51:41 +03:00
|
|
|
}
|
|
|
|
|
1999-03-07 12:44:38 +03:00
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
XULSortServiceImpl::OpenContainer(nsIRDFCompositeDataSource *db, nsIContent *container,
|
|
|
|
nsIRDFResource **flatArray, PRInt32 numElements, PRInt32 elementSize)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
nsString sortResource, sortDirection;
|
|
|
|
_sortStruct sortInfo;
|
|
|
|
|
|
|
|
// get sorting info (property to sort on, direction to sort, etc)
|
|
|
|
|
1999-04-28 11:03:11 +04:00
|
|
|
nsCOMPtr<nsIContent> treeNode;
|
|
|
|
if (NS_FAILED(rv = FindTreeElement(container, getter_AddRefs(treeNode)))) return(rv);
|
1999-03-07 12:44:38 +03:00
|
|
|
|
1999-03-19 04:52:18 +03:00
|
|
|
sortInfo.rdfService = gRDFService;
|
1999-03-07 12:44:38 +03:00
|
|
|
sortInfo.db = db;
|
1999-03-11 15:01:47 +03:00
|
|
|
|
|
|
|
sortInfo.kNaturalOrderPosAtom = kNaturalOrderPosAtom;
|
|
|
|
sortInfo.kTreeCellAtom = kTreeCellAtom;
|
|
|
|
sortInfo.kNameSpaceID_XUL = kNameSpaceID_XUL;
|
|
|
|
|
1999-03-07 12:44:38 +03:00
|
|
|
if (NS_FAILED(rv = GetSortColumnInfo(treeNode, sortResource, sortDirection))) return(rv);
|
|
|
|
char *uri = sortResource.ToNewCString();
|
1999-03-11 15:01:47 +03:00
|
|
|
if (uri)
|
|
|
|
{
|
|
|
|
rv = gRDFService->GetResource(uri, &sortInfo.sortProperty);
|
|
|
|
delete [] uri;
|
|
|
|
if (NS_FAILED(rv)) return(rv);
|
|
|
|
}
|
1999-05-13 12:25:12 +04:00
|
|
|
|
1999-03-10 12:41:07 +03:00
|
|
|
if (sortDirection.EqualsIgnoreCase("natural"))
|
1999-03-07 12:44:38 +03:00
|
|
|
{
|
|
|
|
sortInfo.naturalOrderSort = PR_TRUE;
|
|
|
|
sortInfo.descendingSort = PR_FALSE;
|
|
|
|
// no need to sort for natural order
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sortInfo.naturalOrderSort = PR_FALSE;
|
1999-03-10 12:41:07 +03:00
|
|
|
if (sortDirection.EqualsIgnoreCase("descending"))
|
1999-03-07 12:44:38 +03:00
|
|
|
sortInfo.descendingSort = PR_TRUE;
|
|
|
|
else
|
|
|
|
sortInfo.descendingSort = PR_FALSE;
|
1999-05-10 10:47:04 +04:00
|
|
|
NS_QuickSort((void *)flatArray, numElements, elementSize, openSortCallback, (void *)&sortInfo);
|
1999-04-21 00:26:13 +04:00
|
|
|
}
|
|
|
|
return(NS_OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
XULSortServiceImpl::InsertContainerNode(nsIContent *container, nsIContent *node)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
nsString sortResource, sortDirection;
|
|
|
|
_sortStruct sortInfo;
|
|
|
|
|
|
|
|
// get sorting info (property to sort on, direction to sort, etc)
|
|
|
|
|
1999-04-28 11:03:11 +04:00
|
|
|
nsCOMPtr<nsIContent> treeNode;
|
|
|
|
if (NS_FAILED(rv = FindTreeElement(container, getter_AddRefs(treeNode)))) return(rv);
|
1999-04-21 00:26:13 +04:00
|
|
|
|
|
|
|
// get composite db for tree
|
|
|
|
nsIDOMXULTreeElement *domXulTree;
|
|
|
|
sortInfo.rdfService = gRDFService;
|
|
|
|
sortInfo.db = nsnull;
|
1999-04-28 10:23:21 +04:00
|
|
|
|
1999-05-13 12:25:12 +04:00
|
|
|
// Maintain an nsCOMPtr to _here_ to the composite datasource so
|
|
|
|
// that we're sure that we'll hold a reference to it (and actually
|
|
|
|
// release that reference when the stack frame goes away).
|
|
|
|
nsCOMPtr<nsIRDFCompositeDataSource> cds;
|
1999-04-21 00:26:13 +04:00
|
|
|
if (NS_SUCCEEDED(rv = treeNode->QueryInterface(kIDomXulTreeElementIID, (void**)&domXulTree)))
|
|
|
|
{
|
1999-04-28 10:23:21 +04:00
|
|
|
if (NS_SUCCEEDED(rv = domXulTree->GetDatabase(getter_AddRefs(cds))))
|
1999-04-21 00:26:13 +04:00
|
|
|
{
|
1999-04-28 10:23:21 +04:00
|
|
|
sortInfo.db = cds;
|
1999-04-21 00:26:13 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sortInfo.kNaturalOrderPosAtom = kNaturalOrderPosAtom;
|
|
|
|
sortInfo.kTreeCellAtom = kTreeCellAtom;
|
|
|
|
sortInfo.kNameSpaceID_XUL = kNameSpaceID_XUL;
|
|
|
|
|
1999-04-21 02:14:38 +04:00
|
|
|
PRBool childAdded = PR_FALSE;
|
|
|
|
if (NS_SUCCEEDED(rv = GetSortColumnInfo(treeNode, sortResource, sortDirection)))
|
1999-04-21 00:26:13 +04:00
|
|
|
{
|
1999-04-21 02:14:38 +04:00
|
|
|
char *uri = sortResource.ToNewCString();
|
|
|
|
if (uri)
|
|
|
|
{
|
|
|
|
rv = gRDFService->GetResource(uri, &sortInfo.sortProperty);
|
|
|
|
delete [] uri;
|
|
|
|
if (NS_FAILED(rv)) return(rv);
|
|
|
|
}
|
|
|
|
if (sortDirection.EqualsIgnoreCase("natural"))
|
|
|
|
{
|
|
|
|
sortInfo.naturalOrderSort = PR_TRUE;
|
1999-04-21 00:26:13 +04:00
|
|
|
sortInfo.descendingSort = PR_FALSE;
|
1999-04-21 02:14:38 +04:00
|
|
|
// no need to sort for natural order
|
|
|
|
container->AppendChildTo(node, PR_TRUE);
|
|
|
|
}
|
|
|
|
else
|
1999-04-21 00:26:13 +04:00
|
|
|
{
|
1999-04-21 02:14:38 +04:00
|
|
|
sortInfo.naturalOrderSort = PR_FALSE;
|
|
|
|
if (sortDirection.EqualsIgnoreCase("descending"))
|
|
|
|
sortInfo.descendingSort = PR_TRUE;
|
|
|
|
else
|
|
|
|
sortInfo.descendingSort = PR_FALSE;
|
|
|
|
|
|
|
|
// figure out where to insert the node when a sort order is being imposed
|
|
|
|
PRInt32 childIndex = 0, numChildren = 0, nameSpaceID;
|
|
|
|
nsCOMPtr<nsIContent> child;
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
if (NS_FAILED(rv = container->ChildCount(numChildren))) return(rv);
|
|
|
|
for (childIndex=0; childIndex<numChildren; childIndex++)
|
1999-04-21 00:26:13 +04:00
|
|
|
{
|
1999-04-21 02:14:38 +04:00
|
|
|
if (NS_FAILED(rv = container->ChildAt(childIndex, *getter_AddRefs(child)))) return(rv);
|
|
|
|
if (NS_FAILED(rv = child->GetNameSpaceID(nameSpaceID))) return(rv);
|
|
|
|
if (nameSpaceID == kNameSpaceID_XUL)
|
1999-04-21 00:26:13 +04:00
|
|
|
{
|
1999-04-21 02:14:38 +04:00
|
|
|
nsIContent *theChild = child.get();
|
|
|
|
PRInt32 sortVal = inplaceSortCallback(&node, &theChild, &sortInfo);
|
|
|
|
if (sortVal <= 0)
|
|
|
|
{
|
|
|
|
container->InsertChildAt(node, childIndex, PR_TRUE);
|
|
|
|
childAdded = PR_TRUE;
|
|
|
|
break;
|
|
|
|
}
|
1999-04-21 00:26:13 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-04-21 02:14:38 +04:00
|
|
|
}
|
|
|
|
if (childAdded == PR_FALSE)
|
|
|
|
{
|
|
|
|
container->AppendChildTo(node, PR_TRUE);
|
1999-03-07 12:44:38 +03:00
|
|
|
}
|
|
|
|
return(NS_OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1999-03-06 02:51:41 +03:00
|
|
|
nsresult
|
|
|
|
XULSortServiceImpl::PrintTreeChildren(nsIContent *container, PRInt32 colIndex, PRInt32 indentLevel)
|
|
|
|
{
|
|
|
|
PRInt32 childIndex = 0, numChildren = 0, nameSpaceID;
|
|
|
|
nsCOMPtr<nsIContent> child;
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
if (NS_FAILED(rv = container->ChildCount(numChildren))) return(rv);
|
|
|
|
for (childIndex=0; childIndex<numChildren; childIndex++)
|
|
|
|
{
|
|
|
|
if (NS_FAILED(rv = container->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;
|
|
|
|
nsString tagName;
|
|
|
|
tag->ToString(tagName);
|
|
|
|
for (PRInt32 indentLoop=0; indentLoop<indentLevel; indentLoop++) printf(" ");
|
|
|
|
printf("Child #%d: tagName='%s'\n", childIndex, tagName.ToNewCString());
|
|
|
|
|
|
|
|
PRInt32 attribIndex, numAttribs;
|
|
|
|
child->GetAttributeCount(numAttribs);
|
1999-03-06 07:12:56 +03:00
|
|
|
for (attribIndex = 0; attribIndex < numAttribs; attribIndex++)
|
1999-03-06 02:51:41 +03:00
|
|
|
{
|
|
|
|
PRInt32 attribNameSpaceID;
|
|
|
|
nsCOMPtr<nsIAtom> attribAtom;
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv = child->GetAttributeNameAt(attribIndex, attribNameSpaceID,
|
|
|
|
*getter_AddRefs(attribAtom))))
|
|
|
|
{
|
|
|
|
nsString attribName, attribValue;
|
|
|
|
attribAtom->ToString(attribName);
|
|
|
|
rv = child->GetAttribute(attribNameSpaceID, attribAtom, attribValue);
|
|
|
|
if (rv == NS_CONTENT_ATTR_HAS_VALUE)
|
|
|
|
{
|
|
|
|
for (PRInt32 indentLoop=0; indentLoop<indentLevel; indentLoop++) printf(" ");
|
|
|
|
printf("Attrib #%d: name='%s' value='%s'\n", attribIndex,
|
|
|
|
attribName.ToNewCString(),
|
|
|
|
attribValue.ToNewCString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ((tag.get() == kTreeItemAtom) || (tag.get() == kTreeChildrenAtom) || (tag.get() == kTreeCellAtom))
|
|
|
|
{
|
|
|
|
PrintTreeChildren(child, colIndex, indentLevel+1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (PRInt32 loop=0; loop<indentLevel; loop++) printf(" ");
|
|
|
|
printf("(Non-XUL node) ");
|
1999-05-13 12:25:12 +04:00
|
|
|
nsCOMPtr<nsIDOMText> text;
|
|
|
|
rv = child->QueryInterface(kIDOMTextIID, getter_AddRefs(text));
|
1999-05-06 23:28:22 +04:00
|
|
|
if (NS_SUCCEEDED(rv))
|
1999-03-06 02:51:41 +03:00
|
|
|
{
|
|
|
|
for (PRInt32 indentLoop=0; indentLoop<indentLevel; indentLoop++) printf(" ");
|
1999-05-06 23:28:22 +04:00
|
|
|
printf("(kIDOMTextIID) ");
|
|
|
|
|
1999-05-13 12:25:12 +04:00
|
|
|
nsAutoString val;
|
|
|
|
text->GetData(val);
|
|
|
|
if (val.Length())
|
|
|
|
{
|
|
|
|
printf("value='");
|
|
|
|
fputs(val, stdout);
|
|
|
|
printf("'");
|
1999-03-06 02:51:41 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return(NS_OK);
|
|
|
|
}
|
|
|
|
|
1999-03-10 10:07:10 +03:00
|
|
|
|
|
|
|
|
1999-03-06 02:51:41 +03:00
|
|
|
NS_IMETHODIMP
|
1999-03-07 12:44:38 +03:00
|
|
|
XULSortServiceImpl::DoSort(nsIDOMNode* node, const nsString& sortResource,
|
|
|
|
const nsString& sortDirection)
|
1999-03-06 02:51:41 +03:00
|
|
|
{
|
1999-03-07 12:44:38 +03:00
|
|
|
PRInt32 colIndex, treeBodyIndex;
|
1999-03-06 02:51:41 +03:00
|
|
|
nsresult rv;
|
1999-03-10 10:07:10 +03:00
|
|
|
_sortStruct sortInfo;
|
1999-03-06 02:51:41 +03:00
|
|
|
|
1999-03-11 15:01:47 +03:00
|
|
|
// get tree node
|
1999-04-28 11:03:11 +04:00
|
|
|
nsCOMPtr<nsIContent> contentNode = do_QueryInterface(node);
|
|
|
|
if (!contentNode) return(NS_ERROR_FAILURE);
|
|
|
|
nsCOMPtr<nsIContent> treeNode;
|
|
|
|
if (NS_FAILED(rv = FindTreeElement(contentNode, getter_AddRefs(treeNode)))) return(rv);
|
1999-03-10 10:07:10 +03:00
|
|
|
|
1999-03-11 15:01:47 +03:00
|
|
|
// get composite db for tree
|
1999-03-19 04:52:18 +03:00
|
|
|
sortInfo.rdfService = gRDFService;
|
1999-03-10 10:07:10 +03:00
|
|
|
sortInfo.db = nsnull;
|
1999-04-28 11:03:11 +04:00
|
|
|
nsCOMPtr<nsIDOMXULTreeElement> domXulTree = do_QueryInterface(treeNode);
|
|
|
|
if (!domXulTree) return(NS_ERROR_FAILURE);
|
|
|
|
nsCOMPtr<nsIRDFCompositeDataSource> cds;
|
|
|
|
if (NS_SUCCEEDED(rv = domXulTree->GetDatabase(getter_AddRefs(cds))))
|
1999-03-11 15:01:47 +03:00
|
|
|
{
|
1999-04-28 11:03:11 +04:00
|
|
|
sortInfo.db = cds;
|
1999-03-11 15:01:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
sortInfo.kNaturalOrderPosAtom = kNaturalOrderPosAtom;
|
|
|
|
sortInfo.kTreeCellAtom = kTreeCellAtom;
|
|
|
|
sortInfo.kNameSpaceID_XUL = kNameSpaceID_XUL;
|
|
|
|
|
|
|
|
char *uri = sortResource.ToNewCString();
|
|
|
|
if (uri)
|
1999-03-10 10:07:10 +03:00
|
|
|
{
|
1999-03-10 12:41:07 +03:00
|
|
|
rv = gRDFService->GetResource(uri, &sortInfo.sortProperty);
|
1999-03-10 10:07:10 +03:00
|
|
|
delete [] uri;
|
1999-03-10 12:41:07 +03:00
|
|
|
if (NS_FAILED(rv)) return(rv);
|
1999-03-10 10:07:10 +03:00
|
|
|
}
|
1999-03-11 15:01:47 +03:00
|
|
|
|
|
|
|
// determine new sort resource and direction to use
|
1999-03-10 12:41:07 +03:00
|
|
|
if (sortDirection.EqualsIgnoreCase("natural"))
|
1999-03-10 10:07:10 +03:00
|
|
|
{
|
|
|
|
sortInfo.naturalOrderSort = PR_TRUE;
|
|
|
|
sortInfo.descendingSort = PR_FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1999-03-11 15:01:47 +03:00
|
|
|
sortInfo.naturalOrderSort = PR_FALSE;
|
1999-03-10 12:41:07 +03:00
|
|
|
if (sortDirection.EqualsIgnoreCase("ascending")) sortInfo.descendingSort = PR_FALSE;
|
|
|
|
else if (sortDirection.EqualsIgnoreCase("descending")) sortInfo.descendingSort = PR_TRUE;
|
1999-03-10 10:07:10 +03:00
|
|
|
}
|
|
|
|
|
1999-03-18 23:46:02 +03:00
|
|
|
// get index of sort column, find tree body, and sort. The sort
|
1999-05-13 12:25:12 +04:00
|
|
|
// _won't_ send any notifications, so we won't trigger any reflows...
|
1999-03-07 12:44:38 +03:00
|
|
|
if (NS_FAILED(rv = GetSortColumnIndex(treeNode, sortResource, sortDirection, &colIndex))) return(rv);
|
1999-03-11 15:01:47 +03:00
|
|
|
sortInfo.colIndex = colIndex;
|
1999-04-28 11:03:11 +04:00
|
|
|
nsCOMPtr<nsIContent> treeBody;
|
|
|
|
if (NS_FAILED(rv = FindTreeBodyElement(treeNode, getter_AddRefs(treeBody)))) return(rv);
|
1999-03-10 10:07:10 +03:00
|
|
|
if (NS_SUCCEEDED(rv = SortTreeChildren(treeBody, colIndex, &sortInfo, 0)))
|
1999-03-06 03:11:14 +03:00
|
|
|
{
|
|
|
|
}
|
1999-03-06 02:51:41 +03:00
|
|
|
|
1999-05-13 12:25:12 +04:00
|
|
|
// Now remove the treebody and re-insert it to force the frames to be rebuilt.
|
1999-04-28 11:03:11 +04:00
|
|
|
nsCOMPtr<nsIContent> treeParent;
|
|
|
|
if (NS_FAILED(rv = treeBody->GetParent(*getter_AddRefs(treeParent)))) return(rv);
|
1999-03-18 23:46:02 +03:00
|
|
|
if (NS_FAILED(rv = treeParent->IndexOf(treeBody, treeBodyIndex))) return(rv);
|
|
|
|
if (NS_FAILED(rv = treeParent->RemoveChildAt(treeBodyIndex, PR_TRUE))) return(rv);
|
|
|
|
|
1999-05-13 12:25:12 +04:00
|
|
|
if (NS_SUCCEEDED(rv = treeBody->UnsetAttribute(kNameSpaceID_None,
|
1999-03-06 03:11:14 +03:00
|
|
|
kTreeContentsGeneratedAtom,PR_FALSE)))
|
|
|
|
{
|
1999-03-06 02:51:41 +03:00
|
|
|
}
|
1999-03-06 03:11:14 +03:00
|
|
|
if (NS_SUCCEEDED(rv = treeParent->UnsetAttribute(kNameSpaceID_None,
|
|
|
|
kTreeContentsGeneratedAtom,PR_FALSE)))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_FAILED(rv = treeParent->AppendChildTo(treeBody, PR_TRUE))) return(rv);
|
1999-03-06 02:51:41 +03:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
if (NS_FAILED(rv = PrintTreeChildren(treeBody, colIndex, 0))) return(rv);
|
|
|
|
#endif
|
|
|
|
return(NS_OK);
|
|
|
|
}
|
|
|
|
|
1999-03-07 12:44:38 +03:00
|
|
|
|
|
|
|
|
1999-03-06 02:51:41 +03:00
|
|
|
nsresult
|
|
|
|
NS_NewXULSortService(nsIXULSortService** mgr)
|
|
|
|
{
|
|
|
|
return XULSortServiceImpl::GetSortService(mgr);
|
|
|
|
}
|