Back to index

lightning-sunbird  0.9+nobinonly
Public Member Functions | Static Public Member Functions | Protected Member Functions | Static Protected Attributes | Private Member Functions | Static Private Member Functions | Static Private Attributes | Friends
XULSortServiceImpl Class Reference
Inheritance diagram for XULSortServiceImpl:
Inheritance graph
[legend]
Collaboration diagram for XULSortServiceImpl:
Collaboration graph
[legend]

List of all members.

Public Member Functions

void sort (in nsIDOMNode aNode, in AString aSortResource, in AString aSortDirection)
 Sort the contents of the widget containing aNode using aSortResource as the comparison key, and aSortDirection as the direction.
void insertContainerNode (in nsIRDFCompositeDataSource db, in nsRDFSortState sortStatePtr, in nsIContent root, in nsIContent trueParent, in nsIContent container, in nsIContent node, in boolean aNotify)
 Used internally for insertion sorting.

Static Public Member Functions

NS_DECL_ISUPPORTS static
NS_DECL_NSIXULSORTSERVICE
nsresult 
InplaceSort (nsIContent *node1, nsIContent *node2, sortPtr sortInfo, PRInt32 &sortOrder)
static nsresult InplaceSort (contentSortInfo *info1, contentSortInfo *info2, sortPtr sortInfo, PRInt32 &sortOrder)
static nsresult CompareNodes (nsIRDFNode *cellNode1, PRBool isCollationKey1, nsIRDFNode *cellNode2, PRBool isCollationKey2, PRBool &bothValid, PRInt32 &sortOrder)

Protected Member Functions

 XULSortServiceImpl (void)
virtual ~XULSortServiceImpl (void)

Static Protected Attributes

static nsICollationgCollation = nsnull

Private Member Functions

nsresult FindDatabaseElement (nsIContent *aElement, nsIContent **aDatabaseElement)
nsresult FindSortableContainer (nsIContent *tree, nsIContent **treeBody)
nsresult SetSortHints (nsIContent *tree, const nsAString &sortResource, const nsAString &sortDirection, const nsAString &sortResource2, PRBool inbetweenSeparatorSort, PRBool found)
nsresult SetSortColumnHints (nsIContent *content, const nsAString &sortResource, const nsAString &sortDirection)
nsresult GetSortColumnInfo (nsIContent *tree, nsAString &sortResource, nsAString &sortDirection, nsAString &sortResource2, PRBool &inbetweenSeparatorSort)
nsresult SortContainer (nsIContent *container, sortPtr sortInfo, PRBool merelyInvertFlag)
nsresult InvertSortInfo (contentSortInfo **data, PRInt32 numItems)

Static Private Member Functions

static nsresult GetCachedTarget (sortPtr sortInfo, PRBool useCache, nsIRDFResource *aSource, nsIRDFResource *aProperty, PRBool aTruthValue, nsIRDFNode **aResult)
static nsresult GetTarget (contentSortInfo *contentSortInfo, sortPtr sortInfo, PRBool first, PRBool onlyCollationHint, PRBool truthValue, nsIRDFNode **target, PRBool &isCollationKey)
static nsresult GetResourceValue (nsIRDFResource *res1, sortPtr sortInfo, PRBool first, PRBool useCache, PRBool onlyCollationHint, nsIRDFNode **, PRBool &isCollationKey)
static nsresult GetResourceValue (contentSortInfo *contentSortInfo, sortPtr sortInfo, PRBool first, PRBool useCache, PRBool onlyCollationHint, nsIRDFNode **target, PRBool &isCollationKey)
static nsresult GetNodeValue (nsIContent *node1, sortPtr sortInfo, PRBool first, PRBool onlyCollationHint, nsIRDFNode **, PRBool &isCollationKey)
static nsresult GetNodeValue (contentSortInfo *info1, sortPtr sortInfo, PRBool first, PRBool onlyCollationHint, nsIRDFNode **theNode, PRBool &isCollationKey)

Static Private Attributes

static nsrefcnt gRefCnt = 0
static nsStringkTrueStr = nsnull
static nsStringkNaturalStr = nsnull
static nsStringkAscendingStr = nsnull
static nsStringkDescendingStr = nsnull
static nsIRDFServicegRDFService = nsnull
static nsIRDFContainerUtilsgRDFC = nsnull

Friends

nsresult NS_NewXULSortService (nsIXULSortService **mgr)

Detailed Description

Definition at line 148 of file nsXULSortService.cpp.


Constructor & Destructor Documentation

Definition at line 210 of file nsXULSortService.cpp.

{
  if (gRefCnt == 0) {
    kTrueStr = new nsString(NS_LITERAL_STRING("true"));
    kNaturalStr = new nsString(NS_LITERAL_STRING("natural"));
    kAscendingStr = new nsString(NS_LITERAL_STRING("ascending"));
    kDescendingStr = new nsString(NS_LITERAL_STRING("descending"));
 
    nsresult rv = CallGetService(kRDFServiceCID, &gRDFService);

    NS_ASSERTION(NS_SUCCEEDED(rv), "couldn't create rdf service");

    rv = CallGetService(kRDFContainerUtilsCID, &gRDFC);

    NS_ASSERTION(NS_SUCCEEDED(rv), "couldn't create rdf container utils");

    // get a locale service 
    nsCOMPtr<nsILocaleService> localeService = do_GetService(NS_LOCALESERVICE_CONTRACTID, &rv);
    if (NS_SUCCEEDED(rv)) {
      nsCOMPtr<nsILocale>  locale;
      if (NS_SUCCEEDED(rv = localeService->GetApplicationLocale(getter_AddRefs(locale))) && (locale)) {
        nsCOMPtr<nsICollationFactory> colFactory = do_CreateInstance(kCollationFactoryCID);
        if (colFactory) {
          rv = colFactory->CreateCollation(locale, &gCollation);

          NS_ASSERTION(NS_SUCCEEDED(rv), "couldn't create collation instance");
        } else
          NS_ERROR("couldn't create instance of collation factory");
      } else
        NS_ERROR("unable to get application locale");
    } else
      NS_ERROR("couldn't get locale factory");
  }

  ++gRefCnt;
}

Here is the call graph for this function:

XULSortServiceImpl::~XULSortServiceImpl ( void  ) [protected, virtual]

Definition at line 247 of file nsXULSortService.cpp.

                                            {
#ifdef DEBUG_REFS
    --gInstanceCount;
    fprintf(stdout, "%d - RDF: XULSortServiceImpl\n", gInstanceCount);
#endif

  --gRefCnt;
  if (gRefCnt == 0) {
    delete kTrueStr;
    kTrueStr = nsnull;
    delete kAscendingStr;
    kAscendingStr = nsnull;
    delete kDescendingStr;
    kDescendingStr = nsnull;
    delete kNaturalStr;
    kNaturalStr = nsnull;

    NS_IF_RELEASE(gCollation);

    NS_IF_RELEASE(gRDFService);
    NS_IF_RELEASE(gRDFC);
  }
}

Here is the call graph for this function:


Member Function Documentation

nsresult XULSortServiceImpl::CompareNodes ( nsIRDFNode cellNode1,
PRBool  isCollationKey1,
nsIRDFNode cellNode2,
PRBool  isCollationKey2,
PRBool bothValid,
PRInt32 sortOrder 
) [static]

Definition at line 475 of file nsXULSortService.cpp.

{
  bothValid = PR_FALSE;
  sortOrder = 0;

  // First, check for blobs.  This is the preferred way to do a raw key comparison.
  {
    nsCOMPtr<nsIRDFBlob> l = do_QueryInterface(cellNode1);
    if (l)
    {
      nsCOMPtr<nsIRDFBlob> r = do_QueryInterface(cellNode2);
      if (r)
      {
        const PRUint8 *lkey, *rkey;
        PRInt32 llen, rlen;
        l->GetValue(&lkey);
        l->GetLength(&llen);
        r->GetValue(&rkey);
        r->GetLength(&rlen);
        bothValid = PR_TRUE;
        if (gCollation)
          return gCollation->CompareRawSortKey(lkey, llen, rkey, rlen, &sortOrder);
      }
    }
  }

  // Next, literals.  If isCollationKey1 and 2 are both set, do
  // an unsafe raw comparison. (XXX Remove this code someday.)
  {
    nsCOMPtr<nsIRDFLiteral> l = do_QueryInterface(cellNode1);
    if (l)
    {
      nsCOMPtr<nsIRDFLiteral> r = do_QueryInterface(cellNode2);
      if (r)
      {
        const PRUnichar *luni, *runi;
        l->GetValueConst(&luni);
        r->GetValueConst(&runi);
        bothValid = PR_TRUE;
        if (isCollationKey1 && isCollationKey2)
          return gCollation->CompareRawSortKey(NS_REINTERPRET_CAST(const PRUint8*, luni),
                                               nsCRT::strlen(luni)*sizeof(PRUnichar),
                                               NS_REINTERPRET_CAST(const PRUint8*, runi),
                                               nsCRT::strlen(runi)*sizeof(PRUnichar),
                                               &sortOrder);
        else
        {
          nsresult rv = NS_ERROR_FAILURE;
          nsDependentString lstr(luni), rstr(runi);
          if (gCollation)
            rv = gCollation->CompareString(nsICollation::kCollationCaseInSensitive, lstr, rstr, &sortOrder);
          if (NS_FAILED(rv))
            sortOrder = Compare(lstr, rstr, nsCaseInsensitiveStringComparator());
          return NS_OK;
        }
      }
    }
  }

  // Integers.
  {
    nsCOMPtr<nsIRDFInt> l = do_QueryInterface(cellNode1);
    if (l)
    {
      nsCOMPtr<nsIRDFInt> r = do_QueryInterface(cellNode2);
      if (r)
      {
        PRInt32 lint, rint;
        l->GetValue(&lint);
        r->GetValue(&rint);
        bothValid = PR_TRUE;
        sortOrder = 0;
        if (lint < rint)
          sortOrder = -1;
        else if (lint > rint)
          sortOrder = 1;
        return NS_OK;
      }
    }
  }

  // Dates.
  {
    nsCOMPtr<nsIRDFDate> l = do_QueryInterface(cellNode1);
    if (l)
    {
      nsCOMPtr<nsIRDFDate> r = do_QueryInterface(cellNode2);
      if (r)
      {
        PRInt64 ldate, rdate, delta;
        l->GetValue(&ldate);
        r->GetValue(&rdate);
        bothValid = PR_TRUE;
        LL_SUB(delta, ldate, rdate);

        if (LL_IS_ZERO(delta))
          sortOrder = 0;
        else if (LL_GE_ZERO(delta))
          sortOrder = 1;
        else
          sortOrder = -1;
        return NS_OK;
      }
    }
  }

  // Rats.
  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult XULSortServiceImpl::FindDatabaseElement ( nsIContent aElement,
nsIContent **  aDatabaseElement 
) [private]

Definition at line 276 of file nsXULSortService.cpp.

{
  *aDatabaseElement = nsnull;

  // so look from the current node upwards until we find a node with a database
  for (nsIContent* content = aElement; content; content = content->GetParent()) {
    nsCOMPtr<nsIDOMXULElement> element = do_QueryInterface(content);
    nsCOMPtr<nsIRDFCompositeDataSource> db;
    element->GetDatabase(getter_AddRefs(db));
    if (db) {
      NS_ADDREF(*aDatabaseElement = content);
      return NS_OK;
    }
  }

  return NS_ERROR_FAILURE;
}

Here is the call graph for this function:

Definition at line 295 of file nsXULSortService.cpp.

{
  *aContainer = nsnull;

  nsresult rv;

  nsIAtom *tag = aRoot->Tag();

  if (aRoot->IsContentOfType(nsIContent::eXUL)) {
    if (tag == nsXULAtoms::templateAtom) // ignore content within templates
      return NS_OK;    

    if (tag == nsXULAtoms::listbox ||
        tag == nsXULAtoms::treechildren ||
        tag == nsXULAtoms::menupopup) {
      *aContainer = aRoot;
      NS_ADDREF(*aContainer);

      return NS_OK;
    }
  }

  PRUint32 numChildren = aRoot->GetChildCount();

  for (PRUint32 childIndex = 0; childIndex < numChildren; childIndex++) {
    nsIContent *child = aRoot->GetChildAt(childIndex);

    if (child->IsContentOfType(nsIContent::eXUL)) {
      rv = FindSortableContainer(child, aContainer);
      if (*aContainer)
        return rv;
    }
  }

  return NS_ERROR_FAILURE;
}

Here is the call graph for this function:

nsresult XULSortServiceImpl::GetCachedTarget ( sortPtr  sortInfo,
PRBool  useCache,
nsIRDFResource aSource,
nsIRDFResource aProperty,
PRBool  aTruthValue,
nsIRDFNode **  aResult 
) [static, private]

Definition at line 650 of file nsXULSortService.cpp.

{
  nsresult  rv;
  *aResult = nsnull;

  if (!(sortInfo->mInner)) {
    // if we don't have a mInner, create one
    sortInfo->mInner = do_CreateInstance(kRDFInMemoryDataSourceCID, &rv);
    if (NS_FAILED(rv)) return  rv;
  }

  rv = NS_RDF_NO_VALUE;
  if (sortInfo->mInner) {
    if (useCache) {
      // if we do have a mInner, look for the resource in it
      rv = sortInfo->mInner->GetTarget(aSource, aProperty, aTruthValue, aResult);
    } else if (sortInfo->db) {
      // if we don't have a cached value, look it up in the document's DB
      if (NS_SUCCEEDED(rv = (sortInfo->db)->GetTarget(aSource, aProperty, aTruthValue, aResult))
          && (rv != NS_RDF_NO_VALUE))
      {
        // and if we have a value, cache it away in our mInner also (ignore errors)
        sortInfo->mInner->Assert(aSource, aProperty, *aResult, PR_TRUE);
      }
    }
  }
  
  return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult XULSortServiceImpl::GetNodeValue ( nsIContent node1,
sortPtr  sortInfo,
PRBool  first,
PRBool  onlyCollationHint,
nsIRDFNode **  theNode,
PRBool isCollationKey 
) [static, private]

Definition at line 788 of file nsXULSortService.cpp.

{
  nsresult rv;
  nsCOMPtr<nsIRDFResource>  res1;

  *theNode = nsnull;
  isCollationKey = PR_FALSE;

  nsCOMPtr<nsIDOMXULElement>  dom1 = do_QueryInterface(node1);
  if (dom1) {
    if (NS_FAILED(rv = dom1->GetResource(getter_AddRefs(res1))))
      res1 = nsnull;
    // 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
  } else {
    nsCOMPtr<nsIDOMElement>  htmlDom = do_QueryInterface(node1);
    if (htmlDom) {
      nsAutoString htmlID;
      if (NS_SUCCEEDED(rv = node1->GetAttr(kNameSpaceID_None, nsXULAtoms::id, htmlID)) 
          && (rv == NS_CONTENT_ATTR_HAS_VALUE))
      {
        if (NS_FAILED(rv = gRDFService->GetUnicodeResource(htmlID, getter_AddRefs(res1))))
          res1 = nsnull;
      }
    }
    else
    {
      return NS_ERROR_FAILURE;
    }
  }
  
  if ((sortInfo->naturalOrderSort == PR_FALSE) && (sortInfo->sortProperty)) {
    if (res1) {
      rv = GetResourceValue(res1, sortInfo, first, PR_TRUE, onlyCollationHint, theNode, isCollationKey);
      if ((rv == NS_RDF_NO_VALUE) || (!*theNode))
        rv = GetResourceValue(res1, sortInfo, first, PR_FALSE, onlyCollationHint, theNode, isCollationKey);
    }
    else
      rv = NS_RDF_NO_VALUE;

  } else if ((sortInfo->naturalOrderSort == PR_TRUE) && (sortInfo->parentContainer)) {
    nsAutoString    cellPosVal1;

    // check to see if this is a RDF_Seq
    // Note: this code doesn't handle the aggregated Seq case especially well
    if ((res1) && (sortInfo->db))
    {
      nsCOMPtr<nsIRDFResource>  parentResource;
      nsCOMPtr<nsIDOMXULElement>  parentDOMNode = do_QueryInterface(sortInfo->parentContainer);
      if (parentDOMNode)
      {
        if (NS_FAILED(rv = parentDOMNode->GetResource(getter_AddRefs(parentResource))))
        {
          parentResource = nsnull;
        }
      }

      if (parentResource)
      {
        PRInt32 index;
        rv = gRDFC->IndexOf(sortInfo->db, parentResource,
                res1, &index);
        if (index != -1)
        {
          nsCOMPtr<nsIRDFInt> intLit;
          rv = gRDFService->GetIntLiteral(index, getter_AddRefs(intLit));
          CallQueryInterface(intLit, theNode);
          isCollationKey = PR_FALSE;
        }
      }
    }
  }
  return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult XULSortServiceImpl::GetNodeValue ( contentSortInfo info1,
sortPtr  sortInfo,
PRBool  first,
PRBool  onlyCollationHint,
nsIRDFNode **  theNode,
PRBool isCollationKey 
) [static, private]

Definition at line 866 of file nsXULSortService.cpp.

{
  nsresult rv = NS_OK;
  nsCOMPtr<nsIRDFResource>  res1;

  nsIContent *node1 = info1->content;
  *theNode = nsnull;
  isCollationKey = PR_FALSE;

  // determine the rdf resource
  nsCOMPtr<nsIDOMXULElement>  dom1 = do_QueryInterface(node1);
  if (dom1)
    res1 = info1->resource;
  else {
    // If this isn't a XUL element, get its id and fetch the resource directly
    nsCOMPtr<nsIDOMElement>  htmlDom = do_QueryInterface(node1);
    if (htmlDom) {
      nsAutoString htmlID;
      if (NS_SUCCEEDED(rv = node1->GetAttr(kNameSpaceID_None, nsXULAtoms::id, htmlID))
        && (rv == NS_CONTENT_ATTR_HAS_VALUE))
      {
        if (NS_FAILED(rv = gRDFService->GetUnicodeResource(htmlID, getter_AddRefs(res1))))
          res1 = nsnull;
        info1->resource = res1;
      }
    }
    else
      return NS_ERROR_FAILURE;
  }
  
  if ((!sortInfo->naturalOrderSort) && (sortInfo->sortProperty)) {
    if (res1) {
      rv = GetResourceValue(info1, sortInfo, first, PR_TRUE, onlyCollationHint, theNode, isCollationKey);
      if ((rv == NS_RDF_NO_VALUE) || (!*theNode)) {
        rv = GetResourceValue(info1, sortInfo, first, PR_FALSE, onlyCollationHint, theNode, isCollationKey);
      }
    }
    else
      rv = NS_RDF_NO_VALUE;

  } else if ((sortInfo->naturalOrderSort == PR_TRUE) && (sortInfo->parentContainer)) {
    nsAutoString  cellPosVal1;

    // check to see if this is a RDF_Seq
    // Note: this code doesn't handle the aggregated Seq case especially well
    if ((res1) && (sortInfo->db))
    {
      nsCOMPtr<nsIRDFResource>  parentResource;
      nsCOMPtr<nsIDOMXULElement>  parentDOMNode = do_QueryInterface(sortInfo->parentContainer);
      if (parentDOMNode)
      {
        if (NS_FAILED(rv = parentDOMNode->GetResource(getter_AddRefs(parentResource))))
        {
          parentResource = nsnull;
        }
      }

      if (parentResource)
      {
        PRInt32 index;
        rv = gRDFC->IndexOf(sortInfo->db, parentResource,
                res1, &index);
        if (index != -1)
        {
          nsCOMPtr<nsIRDFInt> intLit;
          rv = gRDFService->GetIntLiteral(index, getter_AddRefs(intLit));
          CallQueryInterface(intLit, theNode);
          isCollationKey = PR_FALSE;
        }
      }
    }
  }
  else
    // XXX Is this right?
    rv = NS_ERROR_NULL_POINTER;

  return rv;
}

Here is the call graph for this function:

nsresult XULSortServiceImpl::GetResourceValue ( nsIRDFResource res1,
sortPtr  sortInfo,
PRBool  first,
PRBool  useCache,
PRBool  onlyCollationHint,
nsIRDFNode **  target,
PRBool isCollationKey 
) [static, private]

Definition at line 588 of file nsXULSortService.cpp.

{
  nsresult rv = NS_OK;

  *target = nsnull;
  isCollationKey = PR_FALSE;

  if (res1 && !sortInfo->naturalOrderSort) {
    nsCOMPtr<nsIRDFResource>  modSortRes;

    // 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

    modSortRes = (first) ? sortInfo->sortPropertyColl : sortInfo->sortPropertyColl2;
    if (modSortRes) {
      if (NS_SUCCEEDED(rv = GetCachedTarget(sortInfo, useCache, res1, modSortRes, PR_TRUE, target))
          && (rv != NS_RDF_NO_VALUE))
      {
        isCollationKey = PR_TRUE;
      }
    }
    if (!*target && !onlyCollationHint) {
      // 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)
      modSortRes = first ? sortInfo->sortPropertySort : sortInfo->sortPropertySort2;
      if (modSortRes)
        rv = GetCachedTarget(sortInfo, useCache, res1, modSortRes, PR_TRUE, target);
    }
    if (!*target && !onlyCollationHint) {
      // if no collation key and no special sorting value, just get the property value
      modSortRes = first ? sortInfo->sortProperty : sortInfo->sortProperty2;
      if (modSortRes)
        rv = GetCachedTarget(sortInfo, useCache, res1, modSortRes, PR_TRUE, target);
    }
  }
  
  return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult XULSortServiceImpl::GetResourceValue ( contentSortInfo contentSortInfo,
sortPtr  sortInfo,
PRBool  first,
PRBool  useCache,
PRBool  onlyCollationHint,
nsIRDFNode **  target,
PRBool isCollationKey 
) [static, private]

Definition at line 632 of file nsXULSortService.cpp.

{
  nsresult    rv = NS_OK;

  *target = nsnull;
  isCollationKey = PR_FALSE;

  nsIRDFResource *res1 = contentSortInfo->resource;

  if (res1 && sortInfo->naturalOrderSort == PR_FALSE)
    rv = GetTarget(contentSortInfo, sortInfo, first, onlyCollationHint, PR_TRUE, target, isCollationKey);

  return rv;
}

Here is the call graph for this function:

nsresult XULSortServiceImpl::GetSortColumnInfo ( nsIContent tree,
nsAString &  sortResource,
nsAString &  sortDirection,
nsAString &  sortResource2,
PRBool inbetweenSeparatorSort 
) [private]

Definition at line 418 of file nsXULSortService.cpp.

{
  nsresult rv = NS_ERROR_FAILURE;
  inbetweenSeparatorSort = PR_FALSE;

  nsAutoString value;
  if (NS_SUCCEEDED(rv = tree->GetAttr(kNameSpaceID_None,
                                      nsXULAtoms::sortActive, value))
    && (rv == NS_CONTENT_ATTR_HAS_VALUE))
  {
    if (value.EqualsLiteral("true"))
    {
      if (NS_SUCCEEDED(rv = tree->GetAttr(kNameSpaceID_None,
                                          nsXULAtoms::sortResource,
                                          sortResource))
          && (rv == NS_CONTENT_ATTR_HAS_VALUE))
      {
        if (NS_SUCCEEDED(rv = tree->GetAttr(kNameSpaceID_None,
                                            nsXULAtoms::sortDirection,
                                            sortDirection))
            && (rv == NS_CONTENT_ATTR_HAS_VALUE))
        {
          rv = NS_OK;

          // sort separator flag is optional
          if (NS_SUCCEEDED(rv = tree->GetAttr(kNameSpaceID_None,
                                              nsXULAtoms::sortSeparators,
                                              value)) &&
              (rv == NS_CONTENT_ATTR_HAS_VALUE))
          {
            if (value.EqualsLiteral("true"))
            {
              inbetweenSeparatorSort = PR_TRUE;
            }
          }

          // secondary sort info is optional
          if (NS_FAILED(rv = tree->GetAttr(kNameSpaceID_None,
                                           nsXULAtoms::sortResource2,
                                           sortResource2)) ||
              (rv != NS_CONTENT_ATTR_HAS_VALUE))
          {
            sortResource2.Truncate();
          }
        }
      }
    }
  }
  
  return rv;
}

Here is the call graph for this function:

nsresult XULSortServiceImpl::GetTarget ( contentSortInfo contentSortInfo,
sortPtr  sortInfo,
PRBool  first,
PRBool  onlyCollationHint,
PRBool  truthValue,
nsIRDFNode **  target,
PRBool isCollationKey 
) [static, private]

Definition at line 682 of file nsXULSortService.cpp.

{
  nsresult rv;
  nsIRDFResource *resource = contentSortInfo->resource;

  if (first) {
    if (contentSortInfo->collationNode1) {
      *target = contentSortInfo->collationNode1;
      NS_IF_ADDREF(*target);
    } else if (!contentSortInfo->checkedCollation1
               && NS_SUCCEEDED(rv = (sortInfo->db)->GetTarget(resource, sortInfo->sortPropertyColl, truthValue, target)))
    {
      if (rv != NS_RDF_NO_VALUE)
        contentSortInfo->collationNode1 = *target;
      contentSortInfo->checkedCollation1 = PR_TRUE;
    }
  
    if (*target) {
      isCollationKey = PR_TRUE;
      return NS_OK;
    }

    if (onlyCollationHint == PR_FALSE)
    {
      if (contentSortInfo->sortNode1) {
        *target = contentSortInfo->sortNode1;
        NS_IF_ADDREF(*target);
      } else if (!contentSortInfo->checkedSort1 
                 && NS_SUCCEEDED(rv = (sortInfo->db)->GetTarget(resource, sortInfo->sortPropertySort, truthValue, target)))
      {
        if (rv != NS_RDF_NO_VALUE)
          contentSortInfo->sortNode1 = *target;
        contentSortInfo->checkedSort1 = PR_TRUE;
      }

      if (*target)
        return NS_OK;

      if (contentSortInfo->node1) {
        *target = contentSortInfo->node1;
        NS_IF_ADDREF(*target);
      } else if (!contentSortInfo->checkedNode1 
                 && NS_SUCCEEDED(rv = (sortInfo->db)->GetTarget(resource, sortInfo->sortProperty, truthValue, target)))
      {
        if (rv != NS_RDF_NO_VALUE)
          contentSortInfo->node1 = *target;
        contentSortInfo->checkedNode1 = PR_TRUE;
      }

      if (*target)
        return NS_OK;
    }
  } else {
    if (contentSortInfo->collationNode2) {
      *target = contentSortInfo->collationNode2;
      NS_IF_ADDREF(*target);
    } else if (!contentSortInfo->checkedCollation2
               && NS_SUCCEEDED(rv = (sortInfo->db)->GetTarget(resource, sortInfo->sortPropertyColl2, truthValue, target)))
    {
      if (rv != NS_RDF_NO_VALUE)
        contentSortInfo->collationNode2 = *target;
      contentSortInfo->checkedCollation2 = PR_TRUE;
    }
  
    if (*target) {
      isCollationKey = PR_TRUE;
      return NS_OK;
    }

    if (onlyCollationHint == PR_FALSE) {
      if (contentSortInfo->sortNode2) {
        *target = contentSortInfo->sortNode2;
        NS_IF_ADDREF(*target);
      } else if (!contentSortInfo->checkedSort2
                 && NS_SUCCEEDED(rv = (sortInfo->db)->GetTarget(resource, sortInfo->sortPropertySort2, truthValue, target)))
      {
        if (rv != NS_RDF_NO_VALUE)
          contentSortInfo->sortNode2 = *target;
        contentSortInfo->checkedSort2 = PR_TRUE;
      }

      if (*target)
        return NS_OK;

      if (contentSortInfo->node2) {
        *target = contentSortInfo->node2;
        NS_IF_ADDREF(*target);
      } else if (!contentSortInfo->checkedNode2
                 && NS_SUCCEEDED(rv = (sortInfo->db)->GetTarget(resource, sortInfo->sortProperty2, truthValue, target)))
      {
        if (rv != NS_RDF_NO_VALUE)
          contentSortInfo->node2 = *target;
        contentSortInfo->checkedNode2 = PR_TRUE;
      }

      if (*target)
        return NS_OK;
    }
  }
      
  return NS_RDF_NO_VALUE;
}

Here is the caller graph for this function:

nsresult XULSortServiceImpl::InplaceSort ( nsIContent node1,
nsIContent node2,
sortPtr  sortInfo,
PRInt32 sortOrder 
) [static]

Definition at line 948 of file nsXULSortService.cpp.

{
  PRBool isCollationKey1 = PR_FALSE, isCollationKey2 = PR_FALSE;
  nsresult rv;

  sortOrder = 0;

  nsCOMPtr<nsIRDFNode> cellNode1, cellNode2;

  // rjc: in some cases, the first node is static while the second node changes
  // per comparison; in these circumstances, we can cache the first node
  if ((sortInfo->cacheFirstHint == PR_TRUE) && (sortInfo->cacheFirstNode))
  {
    cellNode1 = sortInfo->cacheFirstNode;
    isCollationKey1 = sortInfo->cacheIsFirstNodeCollationKey;
  }
  else
  {
    GetNodeValue(node1, sortInfo, PR_TRUE, PR_FALSE, getter_AddRefs(cellNode1), isCollationKey1);
    if (sortInfo->cacheFirstHint == PR_TRUE)
    {
      sortInfo->cacheFirstNode = cellNode1;
      sortInfo->cacheIsFirstNodeCollationKey = isCollationKey1;
    }
  }
  GetNodeValue(node2, sortInfo, PR_TRUE, isCollationKey1, getter_AddRefs(cellNode2), isCollationKey2);

  PRBool  bothValid = PR_FALSE;
  rv = CompareNodes(cellNode1, isCollationKey1, cellNode2, isCollationKey2, bothValid, sortOrder);

  if (sortOrder == 0)
  {
    // nodes appear to be equivalent, check for secondary sort criteria
    if (sortInfo->sortProperty2 != nsnull)
    {
      cellNode1 = nsnull;
      cellNode2 = nsnull;
      isCollationKey1 = PR_FALSE;
      isCollationKey2 = PR_FALSE;
      
      GetNodeValue(node1, sortInfo, PR_FALSE, PR_FALSE, getter_AddRefs(cellNode1), isCollationKey1);
      GetNodeValue(node2, sortInfo, PR_FALSE, isCollationKey1, getter_AddRefs(cellNode2), isCollationKey2);

      bothValid = PR_FALSE;
      rv = CompareNodes(cellNode1, isCollationKey1, cellNode2, isCollationKey2, bothValid, sortOrder);
    }
  }

  if ((bothValid == PR_TRUE) && (sortInfo->descendingSort == PR_TRUE))
  {
    // descending sort is being imposed, so reverse the sort order
    sortOrder = -sortOrder;
  }

  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult XULSortServiceImpl::InplaceSort ( contentSortInfo info1,
contentSortInfo info2,
sortPtr  sortInfo,
PRInt32 sortOrder 
) [static]

Definition at line 1006 of file nsXULSortService.cpp.

{
  PRBool isCollationKey1 = PR_FALSE, isCollationKey2 = PR_FALSE;
  nsresult rv;

  sortOrder = 0;

  nsCOMPtr<nsIRDFNode> cellNode1, cellNode2;

  // rjc: in some cases, the first node is static while the second node changes
  // per comparison; in these circumstances, we can cache the first node
  if ((sortInfo->cacheFirstHint == PR_TRUE) && (sortInfo->cacheFirstNode))
  {
    cellNode1 = sortInfo->cacheFirstNode;
    isCollationKey1 = sortInfo->cacheIsFirstNodeCollationKey;
  }
  else
  {
    GetNodeValue(info1, sortInfo, PR_TRUE, PR_FALSE, getter_AddRefs(cellNode1), isCollationKey1);
    if (sortInfo->cacheFirstHint == PR_TRUE)
    {
      sortInfo->cacheFirstNode = cellNode1;
      sortInfo->cacheIsFirstNodeCollationKey = isCollationKey1;
    }
  }
  GetNodeValue(info2, sortInfo, PR_TRUE, isCollationKey1, getter_AddRefs(cellNode2), isCollationKey2);

  PRBool  bothValid = PR_FALSE;
  rv = CompareNodes(cellNode1, isCollationKey1, cellNode2, isCollationKey2, bothValid, sortOrder);

  if (sortOrder == 0) {
    // nodes appear to be equivalent, check for secondary sort criteria
    if (sortInfo->sortProperty2 != nsnull) {
      cellNode1 = nsnull;
      cellNode2 = nsnull;
      isCollationKey1 = PR_FALSE;
      isCollationKey2 = PR_FALSE;
    
      GetNodeValue(info1, sortInfo, PR_FALSE, PR_FALSE, getter_AddRefs(cellNode1), isCollationKey1);
      GetNodeValue(info2, sortInfo, PR_FALSE, isCollationKey1, getter_AddRefs(cellNode2), isCollationKey2);

      bothValid = PR_FALSE;
      rv = CompareNodes(cellNode1, isCollationKey1, cellNode2, isCollationKey2, bothValid, sortOrder);
    }
  }

  if ((bothValid == PR_TRUE) && (sortInfo->descendingSort == PR_TRUE))
  {
    // descending sort is being imposed, so reverse the sort order
    sortOrder = -sortOrder;
  }

  return NS_OK;
}

Here is the call graph for this function:

void nsIXULSortService::insertContainerNode ( in nsIRDFCompositeDataSource  db,
in nsRDFSortState  sortStatePtr,
in nsIContent  root,
in nsIContent  trueParent,
in nsIContent  container,
in nsIContent  node,
in boolean  aNotify 
) [inherited]

Used internally for insertion sorting.

nsresult XULSortServiceImpl::InvertSortInfo ( contentSortInfo **  data,
PRInt32  numItems 
) [private]

Definition at line 1265 of file nsXULSortService.cpp.

{
  if (numItems > 1) {
    PRInt32 upPoint = (numItems + 1)/2, downPoint = (numItems - 2)/2;
    PRInt32 half = numItems/2;
    while (half-- > 0) {
      contentSortInfo *temp = data[downPoint];
      data[downPoint--] = data[upPoint];
      data[upPoint++] = temp;
    }
  }
  return NS_OK;
}

Here is the caller graph for this function:

nsresult XULSortServiceImpl::SetSortColumnHints ( nsIContent content,
const nsAString &  sortResource,
const nsAString &  sortDirection 
) [private]

Definition at line 369 of file nsXULSortService.cpp.

{
  nsresult rv;

  PRUint32 numChildren = content->GetChildCount();

  for (PRUint32 childIndex = 0; childIndex < numChildren; ++childIndex) {
    nsIContent *child = content->GetChildAt(childIndex);

    if (child->IsContentOfType(nsIContent::eXUL)) {
      nsIAtom *tag = child->Tag();

      if (tag == nsXULAtoms::treecols ||
          tag == nsXULAtoms::listcols ||
          tag == nsXULAtoms::listhead) {
        rv = SetSortColumnHints(child, sortResource, sortDirection);
      } else if (tag == nsXULAtoms::treecol ||
                 tag == nsXULAtoms::listcol ||
                 tag == nsXULAtoms::listheader) {
        nsAutoString value;

        if (NS_SUCCEEDED(rv = child->GetAttr(kNameSpaceID_None,
                                             nsXULAtoms::resource, value))
            && rv == NS_CONTENT_ATTR_HAS_VALUE)
        {
          if (value == sortResource) {
            child->SetAttr(kNameSpaceID_None, nsXULAtoms::sortActive,
                           *kTrueStr, PR_TRUE);
            child->SetAttr(kNameSpaceID_None, nsXULAtoms::sortDirection,
                           sortDirection, PR_TRUE);
            // Note: don't break out of loop; want to set/unset
            // attribs on ALL sort columns
          } else {
            child->UnsetAttr(kNameSpaceID_None, nsXULAtoms::sortActive,
                             PR_TRUE);
            child->UnsetAttr(kNameSpaceID_None, nsXULAtoms::sortDirection,
                             PR_TRUE);
          }
        }
      }
    }
  }
  
  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult XULSortServiceImpl::SetSortHints ( nsIContent tree,
const nsAString &  sortResource,
const nsAString &  sortDirection,
const nsAString &  sortResource2,
PRBool  inbetweenSeparatorSort,
PRBool  found 
) [private]

Definition at line 334 of file nsXULSortService.cpp.

{
  if (found) {
    // set hints on tree root node
    tree->SetAttr(kNameSpaceID_None, nsXULAtoms::sortActive, *kTrueStr, PR_FALSE);
    tree->SetAttr(kNameSpaceID_None, nsXULAtoms::sortDirection, sortDirection, PR_FALSE);
    tree->SetAttr(kNameSpaceID_None, nsXULAtoms::sortResource, sortResource, PR_FALSE);

    if (!sortResource2.IsEmpty())
      tree->SetAttr(kNameSpaceID_None, nsXULAtoms::sortResource2, sortResource2, PR_FALSE);
    else
      tree->UnsetAttr(kNameSpaceID_None, nsXULAtoms::sortResource2, PR_FALSE);
  } else {
    tree->UnsetAttr(kNameSpaceID_None, nsXULAtoms::sortActive, PR_FALSE);
    tree->UnsetAttr(kNameSpaceID_None, nsXULAtoms::sortDirection, PR_FALSE);
    tree->UnsetAttr(kNameSpaceID_None, nsXULAtoms::sortResource, PR_FALSE);
    tree->UnsetAttr(kNameSpaceID_None, nsXULAtoms::sortResource2, PR_FALSE);
  }

  // optional hint
  if (inbetweenSeparatorSort == PR_TRUE)
    tree->SetAttr(kNameSpaceID_None, nsXULAtoms::sortSeparators, *kTrueStr, PR_FALSE);
  else
    tree->UnsetAttr(kNameSpaceID_None, nsXULAtoms::sortSeparators, PR_FALSE);

  SetSortColumnHints(tree, sortResource, sortDirection);

  return NS_OK;
}

Here is the call graph for this function:

void nsIXULSortService::sort ( in nsIDOMNode  aNode,
in AString  aSortResource,
in AString  aSortDirection 
) [inherited]

Sort the contents of the widget containing aNode using aSortResource as the comparison key, and aSortDirection as the direction.

Parameters:
aNodeA node in the XUL widget whose children are to be sorted. sort will traverse upwards to find the root node at which to begin the actualy sorting. For optimal results, pass in the root of the widget.
aSortResourceThe RDF resource to be used as the comparison key.
aSortDirectionMay be either natural to return the contents to their natural (unsorted) order, ascending to sort the contents in ascending order, or descending to sort the contents in descending order.
nsresult XULSortServiceImpl::SortContainer ( nsIContent container,
sortPtr  sortInfo,
PRBool  merelyInvertFlag 
) [private]

Definition at line 1114 of file nsXULSortService.cpp.

{
  PRUint32 loop, numElements = 0, currentElement;

  PRUint32 numChildren = container->GetChildCount();
  if (numChildren < 1)
    return NS_OK;

  nsIDocument *doc = container->GetDocument();
  if (!doc)
    return NS_ERROR_UNEXPECTED;

  // Note: This is a straight allocation (not a COMPtr) so we
  // can't return out of this routine until/unless we free it!
  contentSortInfo ** contentSortInfoArray = new contentSortInfo*[numChildren + 1];
  if (!contentSortInfoArray)
    return NS_ERROR_OUT_OF_MEMORY;

  // Note: walk backwards (and add nodes into the array backwards) because
  // we also remove the nodes in this loop [via RemoveChildAt()] and if we
  // were to do this in a forward-looking manner it would be harder
  // (since we also skip over non XUL:treeitem nodes)

  nsresult rv;
  currentElement = numChildren;
  PRUint32 childIndex;
  // childIndex is unsigned, so childIndex >= 0 would always test true
  for (childIndex = numChildren; childIndex > 0; ) {
    --childIndex;
    nsIContent *child = container->GetChildAt(childIndex);

    if (child->IsContentOfType(nsIContent::eXUL)) {
      nsIAtom *tag = child->Tag();

      if (tag == nsXULAtoms::listitem ||
          tag == nsXULAtoms::treeitem ||
          tag == nsXULAtoms::menu ||
          tag == nsXULAtoms::menuitem) {
        --currentElement;

        nsCOMPtr<nsIRDFResource>  resource;
        nsCOMPtr<nsIDOMXULElement> xulElement(do_QueryInterface(child));
        xulElement->GetResource(getter_AddRefs(resource));
        contentSortInfo *contentInfo = CreateContentSortInfo(child, resource);
        if (contentInfo)
          contentSortInfoArray[currentElement] = contentInfo;

        ++numElements;
      }
    }
  }
  
  if (numElements > 0) {
    /* smart sorting (sort within separators) on name column */
    if (sortInfo->inbetweenSeparatorSort) {
      PRUint32 startIndex = currentElement;
      nsAutoString  type;
      for (loop = currentElement; loop < currentElement + numElements;
           ++loop) {
        if (NS_SUCCEEDED(rv = contentSortInfoArray[loop]->content->GetAttr(kNameSpaceID_RDF,
            nsXULAtoms::type, type)) && (rv == NS_CONTENT_ATTR_HAS_VALUE))
        {
          if (type.EqualsASCII(kURINC_BookmarkSeparator)) {
            if (loop > startIndex + 1) {
              if (merelyInvertFlag)
                InvertSortInfo(&contentSortInfoArray[startIndex], loop-startIndex);
              else
                NS_QuickSort((void*)&contentSortInfoArray[startIndex], loop-startIndex,
                             sizeof(contentSortInfo*), testSortCallback, (void*)sortInfo);
              startIndex = loop+1;
            }
          }
        }
      }
      
      if (loop > startIndex+1) {
        if (merelyInvertFlag)
          InvertSortInfo(&contentSortInfoArray[startIndex], loop-startIndex);
        else
          NS_QuickSort((void*)&contentSortInfoArray[startIndex], loop-startIndex,
                       sizeof(contentSortInfo*), testSortCallback, (void*)sortInfo);
        startIndex = loop+1;
      }
    } else {
      if (merelyInvertFlag)
        InvertSortInfo(&contentSortInfoArray[currentElement], numElements);
      else
        NS_QuickSort((void*)(&contentSortInfoArray[currentElement]), numElements,
                     sizeof(contentSortInfo*), testSortCallback, (void*)sortInfo);
    }

    // childIndex is unsigned, so childIndex >= 0 would always test true
    for (childIndex = numChildren; childIndex > 0; )
    {
      --childIndex;
      nsIContent *child = container->GetChildAt(childIndex);

      if (child->IsContentOfType(nsIContent::eXUL)) {
        nsIAtom *tag = child->Tag();

        if (tag == nsXULAtoms::listitem ||
            tag == nsXULAtoms::treeitem ||
            tag == nsXULAtoms::menu ||
            tag == nsXULAtoms::menuitem) {
          // immediately remove the child node, and ignore any errors
          container->RemoveChildAt(childIndex, PR_FALSE);
        }
      }
    }

    // put the items back in sorted order
    nsAutoString value;
    PRUint32 childPos = container->GetChildCount();
    for (loop = currentElement; loop < currentElement + numElements; loop++) {
      contentSortInfo * contentSortInfo = contentSortInfoArray[loop];
      nsIContent *parentNode = (nsIContent *)contentSortInfo->content;
      nsIContent* kid = parentNode;
      container->InsertChildAt(kid, childPos++, PR_FALSE);

      NS_RELEASE(contentSortInfo->content);
      delete contentSortInfo;

      // if it's a container, find its treechildren nodes, and sort those
      if (NS_FAILED(rv = parentNode->GetAttr(kNameSpaceID_None, nsXULAtoms::container, value)) ||
        (rv != NS_CONTENT_ATTR_HAS_VALUE) || !value.EqualsLiteral("true"))
        continue;
        
      numChildren = parentNode->GetChildCount();

      for (childIndex = 0; childIndex < numChildren; childIndex++) {
        nsIContent *child = parentNode->GetChildAt(childIndex);

        nsINodeInfo *ni = child->GetNodeInfo();

        if (ni && (ni->Equals(nsXULAtoms::treechildren, kNameSpaceID_XUL) ||
                   ni->Equals(nsXULAtoms::menupopup, kNameSpaceID_XUL))) {
          sortInfo->parentContainer = parentNode;
          SortContainer(child, sortInfo, merelyInvertFlag);
        }
      }
    }
  }
  
  delete [] contentSortInfoArray;
  contentSortInfoArray = nsnull;

  return NS_OK;
}

Here is the call graph for this function:


Friends And Related Function Documentation

Definition at line 1679 of file nsXULSortService.cpp.

{
  XULSortServiceImpl *sortService = new XULSortServiceImpl();
  if (!sortService)
    return NS_ERROR_OUT_OF_MEMORY;

  *mgr = sortService;
  NS_ADDREF(*mgr);

  return NS_OK;
}

Member Data Documentation

Definition at line 154 of file nsXULSortService.cpp.

Definition at line 166 of file nsXULSortService.cpp.

Definition at line 165 of file nsXULSortService.cpp.

nsrefcnt XULSortServiceImpl::gRefCnt = 0 [static, private]

Definition at line 159 of file nsXULSortService.cpp.

Definition at line 162 of file nsXULSortService.cpp.

Definition at line 163 of file nsXULSortService.cpp.

Definition at line 161 of file nsXULSortService.cpp.

Definition at line 160 of file nsXULSortService.cpp.


The documentation for this class was generated from the following file: