mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Bug 71530. Put the wraps on the RDF outliner for now. Implement 'natural order' sorting. Also, fix off-by-one in the enumerator. r=ben, sr=hyatt
This commit is contained in:
parent
c3df8d612a
commit
c2f73cbddd
@ -345,8 +345,10 @@ nsOutlinerRows::iterator::Next()
|
||||
// If there are no unfinished subtrees in the stack, then this
|
||||
// iterator is exhausted. Leave it in the same state that
|
||||
// Last() does.
|
||||
if (unfinished < 0)
|
||||
if (unfinished < 0) {
|
||||
top.mChildIndex++;
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, we ran off the end of one of the inner
|
||||
// subtrees. Pop up to the next unfinished level in the stack.
|
||||
|
@ -345,8 +345,10 @@ nsOutlinerRows::iterator::Next()
|
||||
// If there are no unfinished subtrees in the stack, then this
|
||||
// iterator is exhausted. Leave it in the same state that
|
||||
// Last() does.
|
||||
if (unfinished < 0)
|
||||
if (unfinished < 0) {
|
||||
top.mChildIndex++;
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, we ran off the end of one of the inner
|
||||
// subtrees. Pop up to the next unfinished level in the stack.
|
||||
|
@ -236,7 +236,7 @@ protected:
|
||||
|
||||
enum Direction {
|
||||
eDirection_Descending = -1,
|
||||
eDirection_None = 0,
|
||||
eDirection_Natural = 0,
|
||||
eDirection_Ascending = +1
|
||||
};
|
||||
|
||||
@ -282,7 +282,7 @@ NS_IMPL_ISUPPORTS_INHERITED2(nsXULOutlinerBuilder, nsXULTemplateBuilder,
|
||||
|
||||
nsXULOutlinerBuilder::nsXULOutlinerBuilder()
|
||||
: mSortVariable(0),
|
||||
mSortDirection(eDirection_None)
|
||||
mSortDirection(eDirection_Natural)
|
||||
{
|
||||
}
|
||||
|
||||
@ -611,7 +611,7 @@ nsXULOutlinerBuilder::CycleHeader(const PRUnichar* aColID, nsIDOMElement* aEleme
|
||||
}
|
||||
else if (dir == NS_LITERAL_STRING("descending")) {
|
||||
dir = NS_LITERAL_STRING("natural");
|
||||
mSortDirection = eDirection_None;
|
||||
mSortDirection = eDirection_Natural;
|
||||
}
|
||||
else {
|
||||
dir = NS_LITERAL_STRING("ascending");
|
||||
@ -796,7 +796,7 @@ nsXULOutlinerBuilder::ReplaceMatch(nsIRDFResource* aMember,
|
||||
// By default, place the new element at the end of the container
|
||||
PRInt32 index = parent->Count();
|
||||
|
||||
if (mSortVariable && mSortDirection != eDirection_None) {
|
||||
if (mSortVariable) {
|
||||
// Figure out where to put the new element by doing an
|
||||
// insertion sort.
|
||||
PRInt32 left = 0;
|
||||
@ -892,7 +892,7 @@ nsXULOutlinerBuilder::GetSortVariables(VariableSet& aVariables)
|
||||
child->GetAttribute(kNameSpaceID_None, nsXULAtoms::sortDirection, dir);
|
||||
|
||||
if (dir == NS_LITERAL_STRING("none"))
|
||||
mSortDirection = eDirection_None;
|
||||
mSortDirection = eDirection_Natural;
|
||||
else if (dir == NS_LITERAL_STRING("descending"))
|
||||
mSortDirection = eDirection_Descending;
|
||||
else
|
||||
@ -1241,7 +1241,7 @@ nsXULOutlinerBuilder::OpenSubtreeOf(nsOutlinerRows::Subtree* aSubtree,
|
||||
}
|
||||
|
||||
// Sort the container.
|
||||
if (mSortVariable && mSortDirection != eDirection_None) {
|
||||
if (mSortVariable) {
|
||||
NS_QuickSort(mRows.GetRowsFor(aSubtree),
|
||||
aSubtree->Count(),
|
||||
sizeof(nsOutlinerRows::Row),
|
||||
@ -1350,6 +1350,60 @@ nsXULOutlinerBuilder::CompareMatches(nsTemplateMatch* aLeft, nsTemplateMatch* aR
|
||||
{
|
||||
PRInt32 result = 0;
|
||||
|
||||
if (mSortDirection == eDirection_Natural) {
|
||||
// If the sort order is ``natural'', then see if the container
|
||||
// is an RDF sequence. If so, we'll try to use the ordinal
|
||||
// properties to determine order.
|
||||
//
|
||||
// XXX the problem with this is, it doesn't always get the
|
||||
// *real* container; e.g.,
|
||||
//
|
||||
// <outlinerrow uri="?uri" />
|
||||
//
|
||||
// <triple subject="?uri"
|
||||
// predicate="http://home.netscape.com/NC-rdf#subheadings"
|
||||
// object="?subheadings" />
|
||||
//
|
||||
// <member container="?subheadings" child="?subheading" />
|
||||
//
|
||||
// In this case mContainerVar is bound to ?uri, not
|
||||
// ?subheadings. (The ``container'' in the template sense !=
|
||||
// container in the RDF sense.)
|
||||
Value val;
|
||||
aLeft->GetAssignmentFor(mConflictSet, mContainerVar, &val);
|
||||
|
||||
nsIRDFResource* container = VALUE_TO_IRDFRESOURCE(val);
|
||||
|
||||
PRBool isSequence = PR_FALSE;
|
||||
gRDFContainerUtils->IsSeq(mDB, container, &isSequence);
|
||||
if (! isSequence)
|
||||
// If it's not an RDF container, then there's no natural
|
||||
// order.
|
||||
return 0;
|
||||
|
||||
// Determine the indices of the left and right elements in the
|
||||
// container.
|
||||
Value left;
|
||||
aLeft->GetAssignmentFor(mConflictSet, mMemberVar, &left);
|
||||
|
||||
PRInt32 lindex;
|
||||
gRDFContainerUtils->IndexOf(mDB, container, VALUE_TO_IRDFNODE(left), &lindex);
|
||||
if (lindex < 0)
|
||||
return 0;
|
||||
|
||||
Value right;
|
||||
aRight->GetAssignmentFor(mConflictSet, mMemberVar, &right);
|
||||
|
||||
PRInt32 rindex;
|
||||
gRDFContainerUtils->IndexOf(mDB, container, VALUE_TO_IRDFNODE(right), &rindex);
|
||||
if (rindex < 0)
|
||||
return 0;
|
||||
|
||||
return rindex - lindex;
|
||||
}
|
||||
|
||||
// If we get here, then an ascending or descending sort order is
|
||||
// imposed.
|
||||
Value leftValue;
|
||||
aLeft->GetAssignmentFor(mConflictSet, mSortVariable, &leftValue);
|
||||
nsIRDFNode* leftNode = VALUE_TO_IRDFNODE(leftValue);
|
||||
|
@ -125,6 +125,7 @@ nsrefcnt nsXULTemplateBuilder::gRefCnt = 0;
|
||||
PRInt32 nsXULTemplateBuilder::kNameSpaceID_RDF;
|
||||
PRInt32 nsXULTemplateBuilder::kNameSpaceID_XUL;
|
||||
nsIRDFService* nsXULTemplateBuilder::gRDFService;
|
||||
nsIRDFContainerUtils* nsXULTemplateBuilder::gRDFContainerUtils;
|
||||
nsINameSpaceManager* nsXULTemplateBuilder::gNameSpaceManager;
|
||||
nsIScriptSecurityManager* nsXULTemplateBuilder::gScriptSecurityManager;
|
||||
nsIPrincipal* nsXULTemplateBuilder::gSystemPrincipal;
|
||||
@ -133,9 +134,6 @@ nsIPrincipal* nsXULTemplateBuilder::gSystemPrincipal;
|
||||
PRLogModuleInfo* gXULTemplateLog;
|
||||
#endif
|
||||
|
||||
static nsIRDFContainerUtils* gRDFContainerUtils;
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// nsXULTempalteBuilder methods
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "nsISecurityCheckedComponent.h"
|
||||
#include "nsIRDFCompositeDataSource.h"
|
||||
#include "nsIRDFContainer.h"
|
||||
#include "nsIRDFContainerUtils.h"
|
||||
#include "nsIRDFDataSource.h"
|
||||
#include "nsIRDFObserver.h"
|
||||
#include "nsIRDFService.h"
|
||||
@ -374,6 +375,7 @@ protected:
|
||||
// pseudo-constants
|
||||
static nsrefcnt gRefCnt;
|
||||
static nsIRDFService* gRDFService;
|
||||
static nsIRDFContainerUtils* gRDFContainerUtils;
|
||||
static nsINameSpaceManager* gNameSpaceManager;
|
||||
static nsIScriptSecurityManager* gScriptSecurityManager;
|
||||
static nsIPrincipal* gSystemPrincipal;
|
||||
|
@ -236,7 +236,7 @@ protected:
|
||||
|
||||
enum Direction {
|
||||
eDirection_Descending = -1,
|
||||
eDirection_None = 0,
|
||||
eDirection_Natural = 0,
|
||||
eDirection_Ascending = +1
|
||||
};
|
||||
|
||||
@ -282,7 +282,7 @@ NS_IMPL_ISUPPORTS_INHERITED2(nsXULOutlinerBuilder, nsXULTemplateBuilder,
|
||||
|
||||
nsXULOutlinerBuilder::nsXULOutlinerBuilder()
|
||||
: mSortVariable(0),
|
||||
mSortDirection(eDirection_None)
|
||||
mSortDirection(eDirection_Natural)
|
||||
{
|
||||
}
|
||||
|
||||
@ -611,7 +611,7 @@ nsXULOutlinerBuilder::CycleHeader(const PRUnichar* aColID, nsIDOMElement* aEleme
|
||||
}
|
||||
else if (dir == NS_LITERAL_STRING("descending")) {
|
||||
dir = NS_LITERAL_STRING("natural");
|
||||
mSortDirection = eDirection_None;
|
||||
mSortDirection = eDirection_Natural;
|
||||
}
|
||||
else {
|
||||
dir = NS_LITERAL_STRING("ascending");
|
||||
@ -796,7 +796,7 @@ nsXULOutlinerBuilder::ReplaceMatch(nsIRDFResource* aMember,
|
||||
// By default, place the new element at the end of the container
|
||||
PRInt32 index = parent->Count();
|
||||
|
||||
if (mSortVariable && mSortDirection != eDirection_None) {
|
||||
if (mSortVariable) {
|
||||
// Figure out where to put the new element by doing an
|
||||
// insertion sort.
|
||||
PRInt32 left = 0;
|
||||
@ -892,7 +892,7 @@ nsXULOutlinerBuilder::GetSortVariables(VariableSet& aVariables)
|
||||
child->GetAttribute(kNameSpaceID_None, nsXULAtoms::sortDirection, dir);
|
||||
|
||||
if (dir == NS_LITERAL_STRING("none"))
|
||||
mSortDirection = eDirection_None;
|
||||
mSortDirection = eDirection_Natural;
|
||||
else if (dir == NS_LITERAL_STRING("descending"))
|
||||
mSortDirection = eDirection_Descending;
|
||||
else
|
||||
@ -1241,7 +1241,7 @@ nsXULOutlinerBuilder::OpenSubtreeOf(nsOutlinerRows::Subtree* aSubtree,
|
||||
}
|
||||
|
||||
// Sort the container.
|
||||
if (mSortVariable && mSortDirection != eDirection_None) {
|
||||
if (mSortVariable) {
|
||||
NS_QuickSort(mRows.GetRowsFor(aSubtree),
|
||||
aSubtree->Count(),
|
||||
sizeof(nsOutlinerRows::Row),
|
||||
@ -1350,6 +1350,60 @@ nsXULOutlinerBuilder::CompareMatches(nsTemplateMatch* aLeft, nsTemplateMatch* aR
|
||||
{
|
||||
PRInt32 result = 0;
|
||||
|
||||
if (mSortDirection == eDirection_Natural) {
|
||||
// If the sort order is ``natural'', then see if the container
|
||||
// is an RDF sequence. If so, we'll try to use the ordinal
|
||||
// properties to determine order.
|
||||
//
|
||||
// XXX the problem with this is, it doesn't always get the
|
||||
// *real* container; e.g.,
|
||||
//
|
||||
// <outlinerrow uri="?uri" />
|
||||
//
|
||||
// <triple subject="?uri"
|
||||
// predicate="http://home.netscape.com/NC-rdf#subheadings"
|
||||
// object="?subheadings" />
|
||||
//
|
||||
// <member container="?subheadings" child="?subheading" />
|
||||
//
|
||||
// In this case mContainerVar is bound to ?uri, not
|
||||
// ?subheadings. (The ``container'' in the template sense !=
|
||||
// container in the RDF sense.)
|
||||
Value val;
|
||||
aLeft->GetAssignmentFor(mConflictSet, mContainerVar, &val);
|
||||
|
||||
nsIRDFResource* container = VALUE_TO_IRDFRESOURCE(val);
|
||||
|
||||
PRBool isSequence = PR_FALSE;
|
||||
gRDFContainerUtils->IsSeq(mDB, container, &isSequence);
|
||||
if (! isSequence)
|
||||
// If it's not an RDF container, then there's no natural
|
||||
// order.
|
||||
return 0;
|
||||
|
||||
// Determine the indices of the left and right elements in the
|
||||
// container.
|
||||
Value left;
|
||||
aLeft->GetAssignmentFor(mConflictSet, mMemberVar, &left);
|
||||
|
||||
PRInt32 lindex;
|
||||
gRDFContainerUtils->IndexOf(mDB, container, VALUE_TO_IRDFNODE(left), &lindex);
|
||||
if (lindex < 0)
|
||||
return 0;
|
||||
|
||||
Value right;
|
||||
aRight->GetAssignmentFor(mConflictSet, mMemberVar, &right);
|
||||
|
||||
PRInt32 rindex;
|
||||
gRDFContainerUtils->IndexOf(mDB, container, VALUE_TO_IRDFNODE(right), &rindex);
|
||||
if (rindex < 0)
|
||||
return 0;
|
||||
|
||||
return rindex - lindex;
|
||||
}
|
||||
|
||||
// If we get here, then an ascending or descending sort order is
|
||||
// imposed.
|
||||
Value leftValue;
|
||||
aLeft->GetAssignmentFor(mConflictSet, mSortVariable, &leftValue);
|
||||
nsIRDFNode* leftNode = VALUE_TO_IRDFNODE(leftValue);
|
||||
|
@ -28,41 +28,69 @@
|
||||
// Container utilities
|
||||
[scriptable, uuid(D4214E91-FB94-11D2-BDD8-00104BDE6048)]
|
||||
interface nsIRDFContainerUtils : nsISupports {
|
||||
// Returns 'true' if the property is an RDF ordinal property.
|
||||
/**
|
||||
* Returns 'true' if the property is an RDF ordinal property.
|
||||
*/
|
||||
boolean IsOrdinalProperty(in nsIRDFResource aProperty);
|
||||
|
||||
// Convert the specified index to an ordinal property.
|
||||
/**
|
||||
* Convert the specified index to an ordinal property.
|
||||
*/
|
||||
nsIRDFResource IndexToOrdinalResource(in long aIndex);
|
||||
|
||||
// Convert the specified ordinal property into an index
|
||||
/**
|
||||
* Convert the specified ordinal property into an index
|
||||
*/
|
||||
long OrdinalResourceToIndex(in nsIRDFResource aOrdinal);
|
||||
|
||||
// Return 'true' if the specified resource is a container
|
||||
/**
|
||||
* Return 'true' if the specified resource is a container
|
||||
*/
|
||||
boolean IsContainer(in nsIRDFDataSource aDataSource, in nsIRDFResource aResource);
|
||||
|
||||
// Return 'true' if the specified resource is a container and it is empty
|
||||
/**
|
||||
* Return 'true' if the specified resource is a container and it is empty
|
||||
*/
|
||||
boolean IsEmpty(in nsIRDFDataSource aDataSource, in nsIRDFResource aResource);
|
||||
|
||||
// Return 'true' if the specified resource is a bag
|
||||
/**
|
||||
* Return 'true' if the specified resource is a bag
|
||||
*/
|
||||
boolean IsBag(in nsIRDFDataSource aDataSource, in nsIRDFResource aResource);
|
||||
|
||||
// Return 'true' if the specified resource is a sequence
|
||||
/**
|
||||
* Return 'true' if the specified resource is a sequence
|
||||
*/
|
||||
boolean IsSeq(in nsIRDFDataSource aDataSource, in nsIRDFResource aResource);
|
||||
|
||||
// Return 'true' if the specified resource is an alternation
|
||||
/**
|
||||
* Return 'true' if the specified resource is an alternation
|
||||
*/
|
||||
boolean IsAlt(in nsIRDFDataSource aDataSource, in nsIRDFResource aResource);
|
||||
|
||||
// Decorates the specified resource appropriately to make it
|
||||
// usable as an empty bag in the specified data source.
|
||||
/**
|
||||
* Decorates the specified resource appropriately to make it
|
||||
* usable as an empty bag in the specified data source.
|
||||
*/
|
||||
nsIRDFContainer MakeBag(in nsIRDFDataSource aDataSource, in nsIRDFResource aResource);
|
||||
|
||||
// Decorates the specified resource appropriately to make it
|
||||
// usable as an empty sequence in the specified data source.
|
||||
/**
|
||||
* Decorates the specified resource appropriately to make it
|
||||
* usable as an empty sequence in the specified data source.
|
||||
*/
|
||||
nsIRDFContainer MakeSeq(in nsIRDFDataSource aDataSource, in nsIRDFResource aResource);
|
||||
|
||||
// Decorates the specified resource appropriately to make it
|
||||
// usable as an empty alternation in the specified data source.
|
||||
/**
|
||||
* Decorates the specified resource appropriately to make it
|
||||
* usable as an empty alternation in the specified data source.
|
||||
*/
|
||||
nsIRDFContainer MakeAlt(in nsIRDFDataSource aDataSource, in nsIRDFResource aResource);
|
||||
|
||||
/**
|
||||
* Retrieve the index of element in the container. Returns -1 if
|
||||
* the element is not in the container.
|
||||
*/
|
||||
long indexOf(in nsIRDFDataSource aDataSource, in nsIRDFResource aContainer, in nsIRDFNode aElement);
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
@ -170,7 +170,7 @@ RDFContainerUtilsImpl::OrdinalResourceToIndex(nsIRDFResource *aOrdinal, PRInt32
|
||||
|
||||
const char *ordinalStr;
|
||||
if (NS_FAILED(aOrdinal->GetValueConst( &ordinalStr )))
|
||||
return PR_FALSE;
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
const char* s = ordinalStr;
|
||||
if (PL_strncmp(s, kRDFNameSpaceURI, sizeof(kRDFNameSpaceURI) - 1) != 0) {
|
||||
@ -469,3 +469,67 @@ RDFContainerUtilsImpl::IsA(nsIRDFDataSource* aDataSource, nsIRDFResource* aResou
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFContainerUtilsImpl::IndexOf(nsIRDFDataSource* aDataSource, nsIRDFResource* aContainer, nsIRDFNode* aElement, PRInt32* aIndex)
|
||||
{
|
||||
// Assume we can't find it.
|
||||
*aIndex = -1;
|
||||
|
||||
// We'll assume that fan-out is much higher than fan-in, so grovel
|
||||
// through the inbound arcs, look for an ordinal resource, and
|
||||
// decode it.
|
||||
nsCOMPtr<nsISimpleEnumerator> arcsIn;
|
||||
aDataSource->ArcLabelsIn(aElement, getter_AddRefs(arcsIn));
|
||||
if (! arcsIn)
|
||||
return NS_OK;
|
||||
|
||||
while (1) {
|
||||
PRBool hasMoreArcs = PR_FALSE;
|
||||
arcsIn->HasMoreElements(&hasMoreArcs);
|
||||
if (! hasMoreArcs)
|
||||
break;
|
||||
|
||||
nsCOMPtr<nsISupports> isupports;
|
||||
arcsIn->GetNext(getter_AddRefs(isupports));
|
||||
if (! isupports)
|
||||
break;
|
||||
|
||||
nsCOMPtr<nsIRDFResource> property =
|
||||
do_QueryInterface(isupports);
|
||||
|
||||
if (! property)
|
||||
continue;
|
||||
|
||||
PRBool isOrdinal;
|
||||
IsOrdinalProperty(property, &isOrdinal);
|
||||
if (! isOrdinal)
|
||||
continue;
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> sources;
|
||||
aDataSource->GetSources(property, aElement, PR_TRUE, getter_AddRefs(sources));
|
||||
if (! sources)
|
||||
continue;
|
||||
|
||||
while (1) {
|
||||
PRBool hasMoreSources = PR_FALSE;
|
||||
sources->HasMoreElements(&hasMoreSources);
|
||||
if (! hasMoreSources)
|
||||
continue;
|
||||
|
||||
nsCOMPtr<nsISupports> isupports2;
|
||||
sources->GetNext(getter_AddRefs(isupports2));
|
||||
if (! isupports2)
|
||||
break;
|
||||
|
||||
nsCOMPtr<nsIRDFResource> source =
|
||||
do_QueryInterface(isupports2);
|
||||
|
||||
if (source == aContainer)
|
||||
// Found it.
|
||||
return OrdinalResourceToIndex(property, aIndex);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user