content/xul/templates/src/nsTreeRows.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #ifndef nsTreeRows_h__
     7 #define nsTreeRows_h__
     9 #include "nsCOMPtr.h"
    10 #include "nsTArray.h"
    11 #include "pldhash.h"
    12 #include "nsIXULTemplateResult.h"
    13 #include "nsTemplateMatch.h"
    14 #include "nsIRDFResource.h"
    17 /**
    18  * This class maintains the state of the XUL tree builder's
    19  * rows. It maps a row number to the nsTemplateMatch object that
    20  * populates the row.
    21  */
    22 class nsTreeRows
    23 {
    24 public:
    25     class iterator;
    26     friend class iterator;
    28     enum Direction { eDirection_Forwards = +1, eDirection_Backwards = -1 };
    30     enum ContainerType {
    31         eContainerType_Unknown      =  0,
    32         eContainerType_Noncontainer =  1,
    33         eContainerType_Container    =  2
    34     };
    36     enum ContainerState {
    37         eContainerState_Unknown     =  0,
    38         eContainerState_Open        =  1,
    39         eContainerState_Closed      =  2
    40     };
    42     enum ContainerFill {
    43         eContainerFill_Unknown      =  0,
    44         eContainerFill_Empty        =  1,
    45         eContainerFill_Nonempty     =  2
    46     };
    48     class Subtree;
    50     /**
    51      * A row in the tree. Contains the match that the row
    52      * corresponds to, and a pointer to the row's subtree, if there
    53      * are any.
    54      */
    55     struct Row {
    56         nsTemplateMatch* mMatch;
    57         ContainerType    mContainerType  : 4;
    58         ContainerState   mContainerState : 4;
    59         ContainerFill    mContainerFill  : 4;
    61         Subtree*         mSubtree; // XXX eventually move to hashtable
    62     };
    64     /**
    65      * A subtree in the tree. A subtree contains rows, which may
    66      * contain other subtrees.
    67      */
    68     class Subtree {
    69     protected:
    70         friend class nsTreeRows; // so that it can access members, for now
    72         /**
    73          * The parent subtree; null if we're the root
    74          */
    75         Subtree* mParent;
    77         /**
    78          * The number of immediate children in this subtree
    79          */
    80         int32_t mCount;
    82         /**
    83          * The capacity of the subtree
    84          */
    85         int32_t mCapacity;
    87         /**
    88          * The total number of rows in this subtree, recursively
    89          * including child subtrees.
    90          */
    91         int32_t mSubtreeSize;
    93         /**
    94          * The array of rows in the subtree
    95          */
    96         Row* mRows;
    98     public:
    99         /**
   100          * Creates a subtree with the specified parent.
   101          */
   102         Subtree(Subtree* aParent)
   103             : mParent(aParent),
   104               mCount(0),
   105               mCapacity(0),
   106               mSubtreeSize(0),
   107               mRows(nullptr) {}
   109         ~Subtree();
   111         /**
   112          * Return the number of immediate child rows in the subtree
   113          */
   114         int32_t Count() const { return mCount; }
   116         /**
   117          * Return the number of rows in this subtree, as well as all
   118          * the subtrees it contains.
   119          */
   120         int32_t GetSubtreeSize() const { return mSubtreeSize; }
   122         /**
   123          * Retrieve the immediate child row at the specified index.
   124          */
   125         const Row& operator[](int32_t aIndex) const {
   126             NS_PRECONDITION(aIndex >= 0 && aIndex < mCount, "bad index");
   127             return mRows[aIndex]; }
   129         /**
   130          * Retrieve the immediate row at the specified index.
   131          */
   132         Row& operator[](int32_t aIndex) {
   133             NS_PRECONDITION(aIndex >= 0 && aIndex < mCount, "bad index");
   134             return mRows[aIndex]; }
   136         /**
   137          * Remove all rows from the subtree.
   138          */
   139         void Clear();
   141     protected:
   142         /**
   143          * Insert an immediate child row at the specified index.
   144          */
   145         iterator InsertRowAt(nsTemplateMatch* aMatch, int32_t aIndex);
   147         /**
   148          * Remove an immediate child row from the specified index.
   149          */
   150         void RemoveRowAt(int32_t aChildIndex);
   151     };
   153     friend class Subtree;
   155 protected:
   156     /**
   157      * A link in the path through the view's tree.
   158      */
   159     struct Link {
   160         Subtree* mParent;
   161         int32_t  mChildIndex;
   163         Link&
   164         operator=(const Link& aLink) {
   165             mParent = aLink.mParent;
   166             mChildIndex = aLink.mChildIndex;
   167             return *this; }
   169         bool
   170         operator==(const Link& aLink) const {
   171             return (mParent == aLink.mParent)
   172                 && (mChildIndex == aLink.mChildIndex); }
   174         Subtree* GetParent() { return mParent; }
   175         const Subtree* GetParent() const { return mParent; }
   177         int32_t GetChildIndex() const { return mChildIndex; }
   179         Row& GetRow() { return (*mParent)[mChildIndex]; }
   180         const Row& GetRow() const { return (*mParent)[mChildIndex]; }
   181     };
   183 public:
   184     /**
   185      * An iterator that can be used to traverse the tree view.
   186      */
   187     class iterator {
   188     protected:
   189         int32_t mRowIndex;
   190         nsAutoTArray<Link, 8> mLink;
   192         void Next();
   193         void Prev();
   195         friend class Subtree; // so InsertRowAt can initialize us
   196         friend class nsTreeRows; // so nsTreeRows can initialize us
   198         /**
   199          * Used by operator[]() to initialize an iterator.
   200          */
   201         void Append(Subtree* aParent, int32_t aChildIndex);
   203         /**
   204          * Used by InsertRowAt() to initialize an iterator.
   205          */
   206         void Push(Subtree *aParent, int32_t aChildIndex);
   208         /**
   209          * Used by operator[]() and InsertRowAt() to initialize an iterator.
   210          */
   211         void SetRowIndex(int32_t aRowIndex) { mRowIndex = aRowIndex; }
   213         /**
   214          * Handy accessors to the top element.
   215          */
   216         Link& GetTop() { return mLink[mLink.Length() - 1]; }
   217         const Link& GetTop() const { return mLink[mLink.Length() - 1]; }
   219     public:
   220         iterator() : mRowIndex(-1) {}
   222         iterator(const iterator& aIterator);
   223         iterator& operator=(const iterator& aIterator);
   225         bool operator==(const iterator& aIterator) const;
   227         bool operator!=(const iterator& aIterator) const {
   228             return !aIterator.operator==(*this); }
   230         const Row& operator*() const { return GetTop().GetRow(); }
   231         Row& operator*() { return GetTop().GetRow(); }
   233         const Row* operator->() const { return &(GetTop().GetRow()); }
   234         Row* operator->() { return &(GetTop().GetRow()); }
   236         iterator& operator++() { Next(); return *this; }
   237         iterator operator++(int) { iterator temp(*this); Next(); return temp; }
   238         iterator& operator--() { Prev(); return *this; }
   239         iterator operator--(int) { iterator temp(*this); Prev(); return temp; }
   241         /**
   242          * Return the current parent link
   243          */
   244         Subtree* GetParent() { return GetTop().GetParent(); }
   246         const Subtree* GetParent() const { return GetTop().GetParent(); }
   248         /**
   249          * Return the current child index
   250          */
   251         int32_t GetChildIndex() const { return GetTop().GetChildIndex(); }
   253         /**
   254          * Return the depth of the path the iterator is maintaining
   255          * into the tree.
   256          */
   257         int32_t GetDepth() const { return mLink.Length(); }
   259         /**
   260          * Return the current row index of the iterator
   261          */
   262         int32_t GetRowIndex() const { return mRowIndex; }
   264         /**
   265          * Pop the iterator up a level.
   266          */
   267         iterator& Pop() { mLink.SetLength(GetDepth() - 1); return *this; }
   268     };
   270     /**
   271      * Retrieve the first element in the view
   272      */
   273     iterator First();
   275     /**
   276      * Retrieve (one past) the last element in the view
   277      */
   278     iterator Last();
   280     /**
   281      * Find the row that contains the given resource
   282      */
   283     iterator FindByResource(nsIRDFResource* aResource);
   285     /**
   286      * Find the row that contains the result
   287      */
   288     iterator Find(nsIXULTemplateResult* aResult);
   290     /**
   291      * Retrieve the ith element in the view
   292      */
   293     iterator operator[](int32_t aIndex);
   295     nsTreeRows() : mRoot(nullptr) {}
   296     ~nsTreeRows() {}
   298     /**
   299      * Ensure that a child subtree exists within the specified parent
   300      * at the specified child index within the parent. (In other
   301      * words, create a subtree if one doesn't already exist.)
   302      */
   303     Subtree*
   304     EnsureSubtreeFor(Subtree* aParent, int32_t aChildIndex);
   306     /**
   307      * Ensure that a child subtree exists at the iterator's position.
   308      */
   309     Subtree*
   310     EnsureSubtreeFor(iterator& aIterator) {
   311         return EnsureSubtreeFor(aIterator.GetParent(),
   312                                 aIterator.GetChildIndex()); }
   314     /**
   315      * Get the child subtree for the specified parent at the specified
   316      * child index. Optionally return the child subtree's size. Will
   317      * return `null' if no subtree exists.
   318      */
   319     Subtree*
   320     GetSubtreeFor(const Subtree* aParent,
   321                   int32_t aChildIndex,
   322                   int32_t* aSubtreeSize = nullptr);
   324     /**
   325      * Retrieve the size of the subtree within the specified parent.
   326      */
   327     int32_t
   328     GetSubtreeSizeFor(const Subtree* aParent,
   329                       int32_t aChildIndex) {
   330         int32_t size;
   331         GetSubtreeFor(aParent, aChildIndex, &size);
   332         return size; }
   334     /**
   335      * Retrieve the size of the subtree within the specified parent.
   336      */
   337     int32_t
   338     GetSubtreeSizeFor(const iterator& aIterator) {
   339         int32_t size;
   340         GetSubtreeFor(aIterator.GetParent(), aIterator.GetChildIndex(), &size);
   341         return size; }
   343     /**
   344      * Remove the specified subtree for a row, leaving the row itself
   345      * intact.
   346      */
   347     void
   348     RemoveSubtreeFor(Subtree* aParent, int32_t aChildIndex);
   350     /**
   351      * Remove the specified subtree for a row, leaving the row itself
   352      * intact.
   353      */
   354     void
   355     RemoveSubtreeFor(iterator& aIterator) {
   356         RemoveSubtreeFor(aIterator.GetParent(), aIterator.GetChildIndex()); }
   358     /**
   359      * Remove the specified row from the view
   360      */
   361     int32_t
   362     RemoveRowAt(iterator& aIterator) {
   363         iterator temp = aIterator--;
   364         Subtree* parent = temp.GetParent();
   365         parent->RemoveRowAt(temp.GetChildIndex());
   366         InvalidateCachedRow();
   367         return parent->Count(); }
   369     /**
   370      * Insert a new match into the view
   371      */
   372     iterator
   373     InsertRowAt(nsTemplateMatch* aMatch, Subtree* aSubtree, int32_t aChildIndex) {
   374         InvalidateCachedRow();
   375         return aSubtree->InsertRowAt(aMatch, aChildIndex); }
   377     /**
   378      * Raw access to the rows; e.g., for sorting.
   379      */
   380     Row*
   381     GetRowsFor(Subtree* aSubtree) { return aSubtree->mRows; }
   383     /**
   384      * Remove all of the rows
   385      */
   386     void Clear();
   388     /**
   389      * Return the total number of rows in the tree view.
   390      */
   391     int32_t Count() const { return mRoot.GetSubtreeSize(); }
   393     /**
   394      * Retrieve the root subtree
   395      */
   396     Subtree* GetRoot() { return &mRoot; }
   398     /**
   399      * Set the root resource for the view
   400      */
   401     void SetRootResource(nsIRDFResource* aResource) {
   402         mRootResource = aResource; }
   404     /**
   405      * Retrieve the root resource for the view
   406      */
   407     nsIRDFResource* GetRootResource() {
   408         return mRootResource.get(); }
   410     /**
   411      * Invalidate the cached row; e.g., because the view has changed
   412      * in a way that would corrupt the iterator.
   413      */
   414     void
   415     InvalidateCachedRow() { mLastRow = iterator(); }
   417 protected:
   418     /**
   419      * The root subtree.
   420      */
   421     Subtree mRoot;
   423     /**
   424      * The root resource for the view
   425      */
   426     nsCOMPtr<nsIRDFResource> mRootResource;
   428     /**
   429      * The last row that was asked for by operator[]. By remembering
   430      * this, we can usually avoid the O(n) search through the row
   431      * array to find the row at the specified index.
   432      */
   433     iterator mLastRow;
   434 };
   437 #endif // nsTreeRows_h__

mercurial