nsTreeRows.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  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/. */
  5. #ifndef nsTreeRows_h__
  6. #define nsTreeRows_h__
  7. #include "nsCOMPtr.h"
  8. #include "nsTArray.h"
  9. #include "PLDHashTable.h"
  10. #include "nsIXULTemplateResult.h"
  11. #include "nsTemplateMatch.h"
  12. #include "nsIRDFResource.h"
  13. /**
  14. * This class maintains the state of the XUL tree builder's
  15. * rows. It maps a row number to the nsTemplateMatch object that
  16. * populates the row.
  17. */
  18. class nsTreeRows
  19. {
  20. public:
  21. class iterator;
  22. friend class iterator;
  23. enum Direction { eDirection_Forwards = +1, eDirection_Backwards = -1 };
  24. enum ContainerType {
  25. eContainerType_Unknown = 0,
  26. eContainerType_Noncontainer = 1,
  27. eContainerType_Container = 2
  28. };
  29. enum ContainerState {
  30. eContainerState_Unknown = 0,
  31. eContainerState_Open = 1,
  32. eContainerState_Closed = 2
  33. };
  34. enum ContainerFill {
  35. eContainerFill_Unknown = 0,
  36. eContainerFill_Empty = 1,
  37. eContainerFill_Nonempty = 2
  38. };
  39. class Subtree;
  40. /**
  41. * A row in the tree. Contains the match that the row
  42. * corresponds to, and a pointer to the row's subtree, if there
  43. * are any.
  44. */
  45. struct Row {
  46. nsTemplateMatch* mMatch;
  47. ContainerType mContainerType : 4;
  48. ContainerState mContainerState : 4;
  49. ContainerFill mContainerFill : 4;
  50. Subtree* mSubtree; // XXX eventually move to hashtable
  51. };
  52. /**
  53. * A subtree in the tree. A subtree contains rows, which may
  54. * contain other subtrees.
  55. */
  56. class Subtree {
  57. protected:
  58. friend class nsTreeRows; // so that it can access members, for now
  59. /**
  60. * The parent subtree; null if we're the root
  61. */
  62. Subtree* mParent;
  63. /**
  64. * The number of immediate children in this subtree
  65. */
  66. int32_t mCount;
  67. /**
  68. * The capacity of the subtree
  69. */
  70. int32_t mCapacity;
  71. /**
  72. * The total number of rows in this subtree, recursively
  73. * including child subtrees.
  74. */
  75. int32_t mSubtreeSize;
  76. /**
  77. * The array of rows in the subtree
  78. */
  79. Row* mRows;
  80. public:
  81. /**
  82. * Creates a subtree with the specified parent.
  83. */
  84. explicit Subtree(Subtree* aParent)
  85. : mParent(aParent),
  86. mCount(0),
  87. mCapacity(0),
  88. mSubtreeSize(0),
  89. mRows(nullptr) {}
  90. ~Subtree();
  91. /**
  92. * Return the number of immediate child rows in the subtree
  93. */
  94. int32_t Count() const { return mCount; }
  95. /**
  96. * Return the number of rows in this subtree, as well as all
  97. * the subtrees it contains.
  98. */
  99. int32_t GetSubtreeSize() const { return mSubtreeSize; }
  100. /**
  101. * Retrieve the immediate child row at the specified index.
  102. */
  103. const Row& operator[](int32_t aIndex) const {
  104. NS_PRECONDITION(aIndex >= 0 && aIndex < mCount, "bad index");
  105. return mRows[aIndex]; }
  106. /**
  107. * Retrieve the immediate row at the specified index.
  108. */
  109. Row& operator[](int32_t aIndex) {
  110. NS_PRECONDITION(aIndex >= 0 && aIndex < mCount, "bad index");
  111. return mRows[aIndex]; }
  112. /**
  113. * Remove all rows from the subtree.
  114. */
  115. void Clear();
  116. protected:
  117. /**
  118. * Insert an immediate child row at the specified index.
  119. */
  120. iterator InsertRowAt(nsTemplateMatch* aMatch, int32_t aIndex);
  121. /**
  122. * Remove an immediate child row from the specified index.
  123. */
  124. void RemoveRowAt(int32_t aChildIndex);
  125. };
  126. friend class Subtree;
  127. protected:
  128. /**
  129. * A link in the path through the view's tree.
  130. */
  131. struct Link {
  132. Subtree* mParent;
  133. int32_t mChildIndex;
  134. Link&
  135. operator=(const Link& aLink) {
  136. mParent = aLink.mParent;
  137. mChildIndex = aLink.mChildIndex;
  138. return *this; }
  139. bool
  140. operator==(const Link& aLink) const {
  141. return (mParent == aLink.mParent)
  142. && (mChildIndex == aLink.mChildIndex); }
  143. Subtree* GetParent() { return mParent; }
  144. const Subtree* GetParent() const { return mParent; }
  145. int32_t GetChildIndex() const { return mChildIndex; }
  146. Row& GetRow() { return (*mParent)[mChildIndex]; }
  147. const Row& GetRow() const { return (*mParent)[mChildIndex]; }
  148. };
  149. public:
  150. /**
  151. * An iterator that can be used to traverse the tree view.
  152. */
  153. class iterator {
  154. protected:
  155. int32_t mRowIndex;
  156. AutoTArray<Link, 8> mLink;
  157. void Next();
  158. void Prev();
  159. friend class Subtree; // so InsertRowAt can initialize us
  160. friend class nsTreeRows; // so nsTreeRows can initialize us
  161. /**
  162. * Used by operator[]() to initialize an iterator.
  163. */
  164. void Append(Subtree* aParent, int32_t aChildIndex);
  165. /**
  166. * Used by InsertRowAt() to initialize an iterator.
  167. */
  168. void Push(Subtree *aParent, int32_t aChildIndex);
  169. /**
  170. * Used by operator[]() and InsertRowAt() to initialize an iterator.
  171. */
  172. void SetRowIndex(int32_t aRowIndex) { mRowIndex = aRowIndex; }
  173. /**
  174. * Handy accessors to the top element.
  175. */
  176. Link& GetTop() { return mLink[mLink.Length() - 1]; }
  177. const Link& GetTop() const { return mLink[mLink.Length() - 1]; }
  178. public:
  179. iterator() : mRowIndex(-1) {}
  180. iterator(const iterator& aIterator);
  181. iterator& operator=(const iterator& aIterator);
  182. bool operator==(const iterator& aIterator) const;
  183. bool operator!=(const iterator& aIterator) const {
  184. return !aIterator.operator==(*this); }
  185. const Row& operator*() const { return GetTop().GetRow(); }
  186. Row& operator*() { return GetTop().GetRow(); }
  187. const Row* operator->() const { return &(GetTop().GetRow()); }
  188. Row* operator->() { return &(GetTop().GetRow()); }
  189. iterator& operator++() { Next(); return *this; }
  190. iterator operator++(int) { iterator temp(*this); Next(); return temp; }
  191. iterator& operator--() { Prev(); return *this; }
  192. iterator operator--(int) { iterator temp(*this); Prev(); return temp; }
  193. /**
  194. * Return the current parent link
  195. */
  196. Subtree* GetParent() { return GetTop().GetParent(); }
  197. const Subtree* GetParent() const { return GetTop().GetParent(); }
  198. /**
  199. * Return the current child index
  200. */
  201. int32_t GetChildIndex() const { return GetTop().GetChildIndex(); }
  202. /**
  203. * Return the depth of the path the iterator is maintaining
  204. * into the tree.
  205. */
  206. int32_t GetDepth() const { return mLink.Length(); }
  207. /**
  208. * Return the current row index of the iterator
  209. */
  210. int32_t GetRowIndex() const { return mRowIndex; }
  211. /**
  212. * Pop the iterator up a level.
  213. */
  214. iterator& Pop() { mLink.SetLength(GetDepth() - 1); return *this; }
  215. };
  216. /**
  217. * Retrieve the first element in the view
  218. */
  219. iterator First();
  220. /**
  221. * Retrieve (one past) the last element in the view
  222. */
  223. iterator Last();
  224. /**
  225. * Find the row that contains the given resource
  226. */
  227. iterator FindByResource(nsIRDFResource* aResource);
  228. /**
  229. * Find the row that contains the result
  230. */
  231. iterator Find(nsIXULTemplateResult* aResult);
  232. /**
  233. * Retrieve the ith element in the view
  234. */
  235. iterator operator[](int32_t aIndex);
  236. nsTreeRows() : mRoot(nullptr) {}
  237. ~nsTreeRows() {}
  238. /**
  239. * Ensure that a child subtree exists within the specified parent
  240. * at the specified child index within the parent. (In other
  241. * words, create a subtree if one doesn't already exist.)
  242. */
  243. Subtree*
  244. EnsureSubtreeFor(Subtree* aParent, int32_t aChildIndex);
  245. /**
  246. * Ensure that a child subtree exists at the iterator's position.
  247. */
  248. Subtree*
  249. EnsureSubtreeFor(iterator& aIterator) {
  250. return EnsureSubtreeFor(aIterator.GetParent(),
  251. aIterator.GetChildIndex()); }
  252. /**
  253. * Get the child subtree for the specified parent at the specified
  254. * child index. Optionally return the child subtree's size. Will
  255. * return `null' if no subtree exists.
  256. */
  257. Subtree*
  258. GetSubtreeFor(const Subtree* aParent,
  259. int32_t aChildIndex,
  260. int32_t* aSubtreeSize = nullptr);
  261. /**
  262. * Retrieve the size of the subtree within the specified parent.
  263. */
  264. int32_t
  265. GetSubtreeSizeFor(const Subtree* aParent,
  266. int32_t aChildIndex) {
  267. int32_t size;
  268. GetSubtreeFor(aParent, aChildIndex, &size);
  269. return size; }
  270. /**
  271. * Retrieve the size of the subtree within the specified parent.
  272. */
  273. int32_t
  274. GetSubtreeSizeFor(const iterator& aIterator) {
  275. int32_t size;
  276. GetSubtreeFor(aIterator.GetParent(), aIterator.GetChildIndex(), &size);
  277. return size; }
  278. /**
  279. * Remove the specified subtree for a row, leaving the row itself
  280. * intact.
  281. */
  282. void
  283. RemoveSubtreeFor(Subtree* aParent, int32_t aChildIndex);
  284. /**
  285. * Remove the specified subtree for a row, leaving the row itself
  286. * intact.
  287. */
  288. void
  289. RemoveSubtreeFor(iterator& aIterator) {
  290. RemoveSubtreeFor(aIterator.GetParent(), aIterator.GetChildIndex()); }
  291. /**
  292. * Remove the specified row from the view
  293. */
  294. int32_t
  295. RemoveRowAt(iterator& aIterator) {
  296. iterator temp = aIterator--;
  297. Subtree* parent = temp.GetParent();
  298. parent->RemoveRowAt(temp.GetChildIndex());
  299. InvalidateCachedRow();
  300. return parent->Count(); }
  301. /**
  302. * Insert a new match into the view
  303. */
  304. iterator
  305. InsertRowAt(nsTemplateMatch* aMatch, Subtree* aSubtree, int32_t aChildIndex) {
  306. InvalidateCachedRow();
  307. return aSubtree->InsertRowAt(aMatch, aChildIndex); }
  308. /**
  309. * Raw access to the rows; e.g., for sorting.
  310. */
  311. Row*
  312. GetRowsFor(Subtree* aSubtree) { return aSubtree->mRows; }
  313. /**
  314. * Remove all of the rows
  315. */
  316. void Clear();
  317. /**
  318. * Return the total number of rows in the tree view.
  319. */
  320. int32_t Count() const { return mRoot.GetSubtreeSize(); }
  321. /**
  322. * Retrieve the root subtree
  323. */
  324. Subtree* GetRoot() { return &mRoot; }
  325. /**
  326. * Set the root resource for the view
  327. */
  328. void SetRootResource(nsIRDFResource* aResource) {
  329. mRootResource = aResource; }
  330. /**
  331. * Retrieve the root resource for the view
  332. */
  333. nsIRDFResource* GetRootResource() {
  334. return mRootResource.get(); }
  335. /**
  336. * Invalidate the cached row; e.g., because the view has changed
  337. * in a way that would corrupt the iterator.
  338. */
  339. void
  340. InvalidateCachedRow() { mLastRow = iterator(); }
  341. protected:
  342. /**
  343. * The root subtree.
  344. */
  345. Subtree mRoot;
  346. /**
  347. * The root resource for the view
  348. */
  349. nsCOMPtr<nsIRDFResource> mRootResource;
  350. /**
  351. * The last row that was asked for by operator[]. By remembering
  352. * this, we can usually avoid the O(n) search through the row
  353. * array to find the row at the specified index.
  354. */
  355. iterator mLastRow;
  356. };
  357. #endif // nsTreeRows_h__