soui 5.0.0.1
Soui5 Doc
 
Loading...
Searching...
No Matches
STree.h
Go to the documentation of this file.
1/**
2 * @file STree.h
3 * @brief Tree template for general data types
4 * @version v1.0
5 * @author SOUI team
6 * @date 2014-07-13
7 *
8 * @details This class provides a tree structure for general data types.
9 * Version history:
10 * - 1.0 2003-10-24: Initial implementation
11 * - 2.0 2004-12-29: Added two traversal interfaces, fixed memory release issues
12 * - 2.1 2006-10-17: Added hChildLast to speed up data insertion
13 * - 2.2 2008-10-16: Fixed an issue in a traversal interface
14 * - 2.3 2011-10-17: Changed data release interface from callback to virtual function
15 */
16
17#ifndef __STREE__H__
18#define __STREE__H__
19
20#ifndef SASSERT
21#define SASSERT(x)
22#endif
23
24// typedef ULONG_PTR HSTREEITEM;
25#ifdef _WIN64
26#define STVN_ROOT ((HSTREENODE)(ULONG_PTR)0xFFFF000000000000) /**< STVN_ROOT */
27#define STVN_FIRST ((HSTREENODE)(ULONG_PTR)0xFFFF000000000001) /**< STVN_FIRST */
28#define STVN_LAST ((HSTREENODE)(ULONG_PTR)0xFFFF000000000002) /**< STVN_LAST */
29#define STVL_ROOT ((PSTREELINK)(ULONG_PTR)0xFFFF000000000000)
30#else
31#define STVN_ROOT ((HSTREENODE)(ULONG_PTR)0xFFFF0000) /**< STVN_ROOT */
32#define STVN_FIRST ((HSTREENODE)(ULONG_PTR)0xFFFF0001) /**< STVN_FIRST */
33#define STVN_LAST ((HSTREENODE)(ULONG_PTR)0xFFFF0002) /**< STVN_LAST */
34#define STVL_ROOT ((PSTREELINK)(ULONG_PTR)0xFFFF0000)
35#endif
36
37#ifndef STVI_ROOT
38#ifdef _WIN64
39#define STVI_ROOT ((HSTREEITEM)0xFFFF000000000000) /**< STVI_ROOT */
40#define STVI_FIRST ((HSTREEITEM)0xFFFF000000000001) /**< STVI_FIRST */
41#define STVI_LAST ((HSTREEITEM)0xFFFF000000000002) /**< STVI_LAST */
42#else
43#define STVI_ROOT ((HSTREEITEM)0xFFFF0000) /**< STVI_ROOT */
44#define STVI_FIRST ((HSTREEITEM)0xFFFF0001) /**< STVI_FIRST */
45#define STVI_LAST ((HSTREEITEM)0xFFFF0002) /**< STVI_LAST */
46#endif
47#endif // STVI_ROOT
48
49/**
50 * @class CSTree
51 * @brief Template class for a tree structure
52 *
53 * @details This template class provides a tree structure for general data types.
54 */
55template <class T>
56class CSTree {
57 /**
58 * @struct _STREENODE
59 * @brief Node structure
60 *
61 * @details Structure representing a node in the tree.
62 */
63 typedef struct _STREENODE
64 {
65 struct _STREENODE *hParent; /**< Parent node */
66 struct _STREENODE *hChildFirst; /**< First child node */
67 struct _STREENODE *hChildLast; /**< Last child node */
68 struct _STREENODE *hPrevSibling; /**< Previous sibling node */
69 struct _STREENODE *hNextSibling; /**< Next sibling node */
70 T data; /**< Data stored in the node */
71 } STREENODE, *HSTREENODE;
72
73 /**
74 * @struct _STREELINK
75 * @brief Tree node link structure
76 *
77 * @details Structure used to link tree nodes.
78 */
79 typedef struct _STREELINK
80 {
81 HSTREENODE hParent; /**< Parent node */
82 HSTREENODE hChildFirst; /**< First child node */
83 HSTREENODE hChildLast; /**< Last child node */
84 HSTREENODE hPrevSibling; /**< Previous sibling node */
85 HSTREENODE hNextSibling; /**< Next sibling node */
86 } STREELINK, *PSTREELINK;
87
88 /**
89 * @typedef CBTRAVERSING
90 * @brief Callback function for tree traversal
91 *
92 * @details Prototype for the callback function used in tree traversal.
93 * @param T *: Current node data
94 * @param LPARAM: Additional parameter for the callback
95 * @return FALSE to continue traversal, TRUE to interrupt traversal
96 */
97 typedef BOOL (*CBTRAVERSING)(T *, LPARAM);
98
99 public:
100 struct IDataFreer
101 {
102 virtual void OnDataFree(T &data) = 0;
103 };
104
105 public:
106 /**
107 * @brief Constructor
108 */
110 : m_hRootFirst(NULL)
111 , m_hRootLast(NULL)
112 , m_dataFreer(NULL)
113 {
114 }
115
116 /**
117 * @brief Destructor
118 */
119 virtual ~CSTree()
120 {
122 }
123
124 /**
125 * @brief Delete all items in the tree
126 */
128 {
129 if (m_hRootFirst)
130 {
131 FreeNode(STVN_ROOT);
132 m_hRootFirst = NULL;
133 m_hRootLast = NULL;
134 }
135 }
136
137 /**
138 * @brief Get the next sibling item
139 * @param HSTREEITEM hItem: Node handle
140 * @return HSTREEITEM: Next sibling node handle
141 */
142 static HSTREEITEM GetNextSiblingItem(HSTREEITEM hItem)
143 {
144 PSTREELINK pLink = (PSTREELINK)hItem;
145 SASSERT(pLink && pLink != STVL_ROOT);
146 return (HSTREEITEM)pLink->hNextSibling;
147 }
148
149 /**
150 * @brief Get the previous sibling item
151 * @param HSTREEITEM hItem: Node handle
152 * @return HSTREEITEM: Previous sibling node handle
153 */
154 static HSTREEITEM GetPrevSiblingItem(HSTREEITEM hItem)
155 {
156 PSTREELINK pLink = (PSTREELINK)hItem;
157 SASSERT(pLink && pLink != STVL_ROOT);
158 return (HSTREEITEM)pLink->hPrevSibling;
159 }
160
161 /**
162 * @brief Get the parent item
163 * @param HSTREEITEM hItem: Node handle
164 * @return HSTREEITEM: Parent node handle
165 */
166 static HSTREEITEM GetParentItem(HSTREEITEM hItem)
167 {
168 PSTREELINK pLink = (PSTREELINK)hItem;
169 SASSERT(pLink && pLink != STVL_ROOT);
170 return (HSTREEITEM)pLink->hParent;
171 }
172
173 /**
174 * @brief Get the level of the item
175 * @param HSTREEITEM hItem: Node handle
176 * @return int: Level of the node
177 */
178 static int GetItemLevel(HSTREEITEM hItem)
179 {
180 int nRet = -1;
181 if (hItem == STVI_ROOT)
182 hItem = 0;
183 while (hItem)
184 {
185 nRet++;
186 hItem = GetParentItem(hItem);
187 }
188 return nRet;
189 }
190
191 /**
192 * @brief Get the root item of the specified node
193 * @param HSTREEITEM hItem: Current node handle
194 * @return HSTREEITEM: Root node handle
195 */
196 static HSTREEITEM GetRootItem(HSTREEITEM hItem)
197 {
198 HSTREEITEM hParent = hItem;
199 while (GetParentItem(hParent))
200 {
201 hParent = GetParentItem(hParent);
202 }
203 return hParent;
204 }
205
206 /**
207 * @brief Get the child item
208 * @param HSTREEITEM hItem: Node handle
209 * @param BOOL bFirst: Whether to get the first child
210 * @return HSTREEITEM: Child node handle
211 */
212 HSTREEITEM GetChildItem(HSTREEITEM hItem, BOOL bFirst = TRUE) const
213 {
214 HSTREENODE hsNode = (HSTREENODE)hItem;
215 SASSERT(hsNode);
216 if (hsNode == STVN_ROOT)
217 {
218 if (bFirst)
219 return (HSTREEITEM)m_hRootFirst;
220 else
221 return (HSTREEITEM)m_hRootLast;
222 }
223 else
224 {
225 if (bFirst)
226 return (HSTREEITEM)hsNode->hChildFirst;
227 else
228 return (HSTREEITEM)hsNode->hChildLast;
229 }
230 }
231
232 /**
233 * @brief Get the number of children
234 * @param HSTREEITEM hItem: Node handle
235 * @return int: Number of child nodes
236 */
237 int GetChildrenCount(HSTREEITEM hItem) const
238 {
239 int nRet = 0;
240 HSTREEITEM hChild = GetChildItem(hItem);
241 while (hChild)
242 {
243 nRet++;
244 hChild = GetNextSiblingItem(hChild);
245 }
246 return nRet;
247 }
248
249 /**
250 * @brief Delete an item
251 * @param HSTREEITEM hItem: Node handle
252 */
253 virtual void DeleteItem(HSTREEITEM hItem)
254 {
255 HSTREENODE hsNode = (HSTREENODE)hItem;
256 SASSERT(hsNode);
257 if (hsNode == STVN_ROOT)
258 {
259 FreeNode(STVN_ROOT);
260 m_hRootFirst = NULL;
261 m_hRootLast = NULL;
262 return;
263 }
264 STREENODE nodeCopy = *hsNode;
265 BOOL bRootFirst = hsNode == m_hRootFirst;
266 BOOL bRootLast = hsNode == m_hRootLast;
267 FreeNode(hsNode);
268
269 if (nodeCopy.hPrevSibling) // has prevsibling
270 nodeCopy.hPrevSibling->hNextSibling = nodeCopy.hNextSibling;
271 else if (nodeCopy.hParent) // parent's first child
272 nodeCopy.hParent->hChildFirst = nodeCopy.hNextSibling;
273 if (nodeCopy.hNextSibling) // update next sibling's previous sibling
274 nodeCopy.hNextSibling->hPrevSibling = nodeCopy.hPrevSibling;
275 else if (nodeCopy.hParent) // parent's last child
276 nodeCopy.hParent->hChildLast = nodeCopy.hPrevSibling;
277 // update root item
278 if (bRootFirst)
279 m_hRootFirst = nodeCopy.hNextSibling;
280 if (bRootLast)
281 m_hRootLast = nodeCopy.hPrevSibling;
282 }
283
284 /**
285 * @brief Delete an item and its branch
286 * @param HSTREEITEM hItem: Node handle
287 * @return BOOL: TRUE if successful, FALSE otherwise
288 */
289 BOOL DeleteItemEx(HSTREEITEM hItem)
290 {
291 if (GetChildItem(hItem))
292 return FALSE;
293 while (hItem && !GetChildItem(hItem))
294 {
295 HSTREEITEM hParent = GetParentItem(hItem);
296 DeleteItem(hItem);
297 hItem = hParent;
298 }
299 return TRUE;
300 }
301
302 /**
303 * @brief Get the item data
304 * @param HSTREEITEM hItem: Node handle
305 * @return T: Data stored in the node
306 */
307 static T GetItem(HSTREEITEM hItem)
308 {
309 SASSERT(hItem != STVI_ROOT);
310 HSTREENODE hsNode = (HSTREENODE)hItem;
311 SASSERT(hsNode);
312 return hsNode->data;
313 }
314
315 /**
316 * @brief Get the item data reference
317 * @param HSTREEITEM hItem: Node handle
318 * @return T&: Reference to data stored in the node
319 */
320 static T &GetItemRef(HSTREEITEM hItem)
321 {
322 SASSERT(hItem != STVI_ROOT);
323 HSTREENODE hsNode = (HSTREENODE)hItem;
324 SASSERT(hsNode);
325 return hsNode->data;
326 }
327
328 /**
329 * @brief Get the item data pointer
330 * @param HSTREEITEM hItem: Node handle
331 * @return T*: Pointer to data stored in the node
332 */
333 static T *GetItemPt(HSTREEITEM hItem)
334 {
335 SASSERT(hItem != STVI_ROOT);
336 HSTREENODE hsNode = (HSTREENODE)hItem;
337 SASSERT(hsNode);
338 return &hsNode->data;
339 }
340
341 /**
342 * @brief Insert a new item
343 * @param const T &data: Data to insert
344 * @param HSTREEITEM hParent: Parent node handle
345 * @param HSTREEITEM hInsertAfter: Insert after this node
346 * @return HSTREEITEM: Handle of the inserted node
347 */
348 HSTREEITEM InsertItem(const T &data, HSTREEITEM hParent = STVI_ROOT, HSTREEITEM hInsertAfter = STVI_LAST)
349 {
350 HSTREENODE hParentNode = (HSTREENODE)hParent;
351 HSTREENODE hInsertAfterNode = (HSTREENODE)hInsertAfter;
352 if (hParentNode == STVN_ROOT)
353 hParentNode = NULL;
354 SASSERT(hInsertAfter);
355 if (hInsertAfterNode != STVN_FIRST && hInsertAfterNode != STVN_LAST)
356 {
357 if (hInsertAfterNode->hParent != hParentNode)
358 return 0;
359 if (hInsertAfterNode->hNextSibling == NULL)
360 hInsertAfterNode = STVN_LAST;
361 }
362
363 HSTREENODE hInserted = new STREENODE;
364 hInserted->data = data;
365 hInserted->hParent = hParentNode;
366 hInserted->hChildFirst = NULL;
367 hInserted->hChildLast = NULL;
368
369 if (hInsertAfterNode == STVN_FIRST)
370 {
371 hInserted->hPrevSibling = NULL;
372 if (hParentNode == NULL) // root
373 {
374 hInserted->hNextSibling = m_hRootFirst;
375 if (m_hRootFirst)
376 m_hRootFirst->hPrevSibling = hInserted;
377 m_hRootFirst = hInserted;
378 if (m_hRootLast == NULL)
379 m_hRootLast = hInserted;
380 }
381 else // has parent
382 {
383 hInserted->hNextSibling = hParentNode->hChildFirst;
384 if (hInserted->hNextSibling)
385 {
386 hInserted->hNextSibling->hPrevSibling = hInserted;
387 hParentNode->hChildFirst = hInserted;
388 }
389 else
390 {
391 hParentNode->hChildLast = hParentNode->hChildFirst = hInserted;
392 }
393 }
394 }
395 else if (hInsertAfterNode == STVN_LAST)
396 {
397 hInserted->hNextSibling = NULL;
398 if (hParentNode == NULL) // root
399 {
400 hInserted->hPrevSibling = m_hRootLast;
401 if (m_hRootLast)
402 m_hRootLast->hNextSibling = hInserted;
403 m_hRootLast = hInserted;
404 if (!m_hRootFirst)
405 m_hRootFirst = hInserted;
406 }
407 else
408 {
409 hInserted->hPrevSibling = hParentNode->hChildLast;
410 if (hParentNode->hChildLast)
411 {
412 hInserted->hPrevSibling->hNextSibling = hInserted;
413 hParentNode->hChildLast = hInserted;
414 }
415 else
416 {
417 hParentNode->hChildLast = hParentNode->hChildFirst = hInserted;
418 }
419 }
420 }
421 else
422 {
423 HSTREENODE hNextSibling = hInsertAfterNode->hNextSibling;
424 hInserted->hPrevSibling = hInsertAfterNode;
425 hInserted->hNextSibling = hNextSibling;
426 hNextSibling->hPrevSibling = hInsertAfterNode->hNextSibling = hInserted;
427 }
428 return (HSTREEITEM)hInserted;
429 }
430
431 /**
432 * @brief Traverse the tree recursively
433 * @param HSTREEITEM hItem: Starting node handle
434 * @param CBTRAVERSING funTraversing: Callback function
435 * @param LPARAM lParam: Additional parameter for the callback
436 * @return HSTREEITEM: Handle of the node where traversal stopped
437 */
438 HSTREEITEM TraversingRecursion(HSTREEITEM hItem, CBTRAVERSING funTraversing, LPARAM lParam)
439 {
440 SASSERT(hItem);
441 if (hItem != STVI_ROOT)
442 {
443 if (funTraversing(GetItemPt(hItem), lParam))
444 return hItem;
445 }
446 HSTREEITEM hChild = GetChildItem(hItem);
447 while (hChild)
448 {
449 HSTREEITEM hTmp = GetChildItem(hChild);
450 if (hTmp)
451 {
452 HSTREEITEM hRet = TraversingRecursion(hTmp, funTraversing, lParam);
453 if (hRet)
454 return hRet;
455 }
456 else
457 {
458 if (funTraversing(GetItemPt(hChild), lParam))
459 return hChild;
460 }
461 hChild = GetNextSiblingItem(hChild);
462 }
463 return NULL;
464 }
465
466 /**
467 * @brief Traverse the tree in sequence
468 * @param HSTREEITEM hItem: Starting node handle
469 * @param CBTRAVERSING funTraversing: Callback function
470 * @param LPARAM lParam: Additional parameter for the callback
471 * @return HSTREEITEM: Handle of the node where traversal stopped
472 *
473 * @details Traverses the tree in sequence starting from the specified node.
474 * If the callback function returns TRUE, the traversal stops and the current node is returned.
475 * Otherwise, it continues to the next node.
476 */
477 HSTREEITEM TraversingSequence(HSTREEITEM hItem, CBTRAVERSING funTraversing, LPARAM lParam)
478 {
479 if (!m_hRootFirst)
480 return NULL;
481 if (hItem != STVI_ROOT)
482 {
483 if (funTraversing(GetItemPt(hItem), lParam))
484 return hItem;
485 }
486 HSTREEITEM hNext = GetNextItem(hItem);
487 while (hNext)
488 {
489 if (funTraversing(GetItemPt(hNext), lParam))
490 return hNext;
491 hNext = GetNextItem(hNext);
492 }
493 return NULL;
494 }
495
496 /**
497 * @brief Get the root item
498 * @param BOOL bFirst: Whether to get the first root item (default is TRUE)
499 * @return HSTREEITEM: Handle of the root item
500 *
501 * @details Returns the root item of the tree. If `bFirst` is TRUE, it returns the first root item;
502 * otherwise, it returns the last root item.
503 */
504 HSTREEITEM GetRootItem(BOOL bFirst = TRUE)
505 {
506 return (HSTREEITEM)(bFirst ? m_hRootFirst : m_hRootLast);
507 }
508
509 /**
510 * @brief Get the number of descendants of a node
511 * @param HSTREEITEM hItem: Starting node handle
512 * @return int: Number of descendant nodes
513 *
514 * @details Recursively counts the number of descendant nodes starting from the specified node.
515 */
516 int GetDesendants(HSTREEITEM hItem)
517 {
518 int nRet = 0;
519 HSTREEITEM hChild = GetChildItem(hItem);
520 while (hChild)
521 {
522 nRet += 1 + GetDesendants(hChild);
523 hChild = GetNextSiblingItem(hChild);
524 }
525 return nRet;
526 }
527
528 /**
529 * @brief Get the next item in the tree
530 * @param HSTREEITEM hItem: Current node handle
531 * @return HSTREEITEM: Handle of the next node
532 *
533 * @details Returns the next node in the tree. The traversal order is:
534 * - First child of the current node
535 * - Next sibling of the current node
536 * - Next sibling of the parent node, if no children or siblings are available
537 */
538 HSTREEITEM GetNextItem(HSTREEITEM hItem) const
539 {
540 if (hItem == STVI_ROOT)
541 return (HSTREEITEM)m_hRootFirst;
542
543 HSTREEITEM hRet = GetChildItem(hItem);
544 if (hRet)
545 return hRet;
546 HSTREEITEM hParent = hItem;
547 while (hParent)
548 {
549 hRet = GetNextSiblingItem(hParent);
550 if (hRet)
551 return hRet;
552 hParent = GetParentItem(hParent);
553 }
554 return 0;
555 }
556
557 /**
558 * @brief Get the next item in the tree with level relationship
559 * @param HSTREEITEM hItem: Current node handle
560 * @param int &nLevel: Level relationship between the current node and the returned node
561 * @return HSTREEITEM: Handle of the next node
562 *
563 * @details Returns the next node in the tree and sets the level relationship:
564 * - 1: Parent-child relationship
565 * - 0: Sibling relationship
566 * - -n: Child to parent's sibling relationship
567 */
568 HSTREEITEM GetNextItem(HSTREEITEM hItem, int &nLevel) const
569 {
570 if (hItem == STVI_ROOT)
571 {
572 nLevel = 1;
573 return (HSTREEITEM)m_hRootFirst;
574 }
575
576 HSTREEITEM hRet = GetChildItem(hItem);
577 if (hRet)
578 {
579 nLevel = 1;
580 return hRet;
581 }
582 HSTREEITEM hParent = hItem;
583 nLevel = 0;
584 while (hParent)
585 {
586 hRet = GetNextSiblingItem(hParent);
587 if (hRet)
588 return hRet;
589 nLevel--;
590 hParent = GetParentItem(hParent);
591 }
592 return NULL;
593 }
594
595 /**
596 * @brief Sort the children of a node
597 * @param HSTREEITEM hItem: Node handle
598 * @param int(__cdecl *funSort)(void *, const void *, const void *): Comparison function
599 * @param void *pCtx: Context for the comparison function
600 *
601 * @details Sorts the children of the specified node using the provided comparison function.
602 * The comparison function should have the signature `int(__cdecl *)(void *, const void *, const void *)`.
603 */
604 void SortChildren(HSTREEITEM hItem, int(__cdecl *funSort)(void *, const void *, const void *), void *pCtx)
605 {
606 int nChilds = GetChildrenCount(hItem);
607 if (nChilds > 1)
608 {
609 HSTREEITEM *pChilds = new HSTREEITEM[nChilds];
610 HSTREEITEM hChild = GetChildItem(hItem);
611 pChilds[0] = hChild;
612 for (int i = 1; i < nChilds; i++)
613 {
614 hChild = GetNextSiblingItem(hChild);
615 pChilds[i] = hChild;
616 }
617 // Call qsort to sort the children
618 qsort_s(pChilds, nChilds, sizeof(HSTREEITEM), funSort, pCtx);
619 // Reorganize the linked list
620 for (int i = 0; i < nChilds - 1; i++)
621 {
622 HSTREENODE node = (HSTREENODE)pChilds[i];
623 node->hNextSibling = (HSTREENODE)pChilds[i + 1];
624 }
625 for (int i = 1; i < nChilds; i++)
626 {
627 HSTREENODE node = (HSTREENODE)pChilds[i];
628 node->hPrevSibling = (HSTREENODE)pChilds[i - 1];
629 }
630 HSTREENODE node = (HSTREENODE)pChilds[0];
631 node->hPrevSibling = NULL;
632 node = (HSTREENODE)pChilds[nChilds - 1];
633 node->hNextSibling = NULL;
634 if (hItem != STVI_ROOT)
635 {
636 HSTREENODE parent = (HSTREENODE)hItem;
637 parent->hChildFirst = (HSTREENODE)pChilds[0];
638 parent->hChildLast = (HSTREENODE)pChilds[nChilds - 1];
639 }
640 else
641 {
642 m_hRootFirst = (HSTREENODE)pChilds[0];
643 m_hRootLast = (HSTREENODE)pChilds[nChilds - 1];
644 }
645 delete[] pChilds;
646 }
647 // Sort children recursively
648 HSTREEITEM hChild = GetChildItem(hItem);
649 while (hChild)
650 {
651 HSTREENODE node = (HSTREENODE)hChild;
652 if (node->hChildFirst && node->hChildLast && node->hChildFirst != node->hChildLast)
653 {
654 SortChildren(hChild, funSort, pCtx);
655 }
656 hChild = GetNextSiblingItem(hChild);
657 }
658 }
659
660 /**
661 * @brief Set the data freer callback
662 * @param IDataFreer *cbFree: Data freer callback object
663 *
664 * @details Sets the callback object for freeing node data.
665 */
666 void SetDataFreer(IDataFreer *cbFree)
667 {
668 m_dataFreer = cbFree;
669 }
670
671 private:
672 /**
673 * @fn void FreeNode(HSTREENODE hsNode)
674 * @brief Recursively frees all child nodes of the given node using post-order traversal.
675 *
676 * @param HSTREENODE hsNode: The current node to free.
677 *
678 * @details This function uses post-order traversal to ensure that all child nodes are freed before the parent node.
679 * It iterates through all child nodes, recursively calling itself on each child. After freeing all children,
680 * it calls `OnNodeFree` to release any associated data and then deletes the node itself.
681 */
682 void FreeNode(HSTREENODE hsNode)
683 {
684 SASSERT(hsNode);
685 HSTREENODE hSibling = (HSTREENODE)GetChildItem((HSTREEITEM)hsNode);
686 while (hSibling)
687 {
688 HSTREENODE hNextSibling = hSibling->hNextSibling;
689 FreeNode(hSibling);
690 hSibling = hNextSibling;
691 }
692 if (hsNode != STVN_ROOT)
693 {
694 OnNodeFree(hsNode->data);
695 delete hsNode;
696 }
697 }
698
699 protected:
700 /**
701 * @fn virtual void OnNodeFree(T &data)
702 * @brief Virtual function to handle the freeing of node data.
703 *
704 * @param T &data: Reference to the data stored in the node.
705 *
706 * @details This function is intended to be overridden in derived classes to implement specific data cleanup logic.
707 * If a data freer callback (`m_dataFreer`) is set, it will call the callback's `OnDataFree` method to handle
708 * the data cleanup.
709 */
710 virtual void OnNodeFree(T &data)
711 {
712 if (m_dataFreer)
713 m_dataFreer->OnDataFree(data);
714 }
715 IDataFreer *m_dataFreer; /**< Pointer to an object implementing the `IDataFreer` interface for custom data cleanup. */
716 HSTREENODE m_hRootFirst; /**< Pointer to the first root node of the tree. */
717 HSTREENODE m_hRootLast; /**< Pointer to the last root node of the tree. */
718};
719
720#endif // __STREE__H__
#define STVI_ROOT
Definition STree.h:43
#define STVN_FIRST
Definition STree.h:32
#define STVN_ROOT
Definition STree.h:31
#define STVN_LAST
Definition STree.h:33
#define STVI_LAST
Definition STree.h:45
static T GetItem(HSTREEITEM hItem)
Get the item data.
Definition STree.h:307
virtual void OnNodeFree(T &data)
Virtual function to handle the freeing of node data.
Definition STree.h:710
HSTREEITEM GetChildItem(HSTREEITEM hItem, BOOL bFirst=TRUE) const
Get the child item.
Definition STree.h:212
HSTREEITEM TraversingRecursion(HSTREEITEM hItem, CBTRAVERSING funTraversing, LPARAM lParam)
Traverse the tree recursively.
Definition STree.h:438
static HSTREEITEM GetParentItem(HSTREEITEM hItem)
Get the parent item.
Definition STree.h:166
void SetDataFreer(IDataFreer *cbFree)
Set the data freer callback.
Definition STree.h:666
HSTREEITEM GetNextItem(HSTREEITEM hItem) const
Get the next item in the tree.
Definition STree.h:538
virtual ~CSTree()
Destructor.
Definition STree.h:119
virtual void DeleteItem(HSTREEITEM hItem)
Delete an item.
Definition STree.h:253
int GetChildrenCount(HSTREEITEM hItem) const
Get the number of children.
Definition STree.h:237
HSTREEITEM GetNextItem(HSTREEITEM hItem, int &nLevel) const
Get the next item in the tree with level relationship.
Definition STree.h:568
static int GetItemLevel(HSTREEITEM hItem)
Get the level of the item.
Definition STree.h:178
HSTREEITEM InsertItem(const T &data, HSTREEITEM hParent=((HSTREEITEM) 0xFFFF0000), HSTREEITEM hInsertAfter=((HSTREEITEM) 0xFFFF0002))
Insert a new item.
Definition STree.h:348
void DeleteAllItems()
Delete all items in the tree.
Definition STree.h:127
HSTREEITEM TraversingSequence(HSTREEITEM hItem, CBTRAVERSING funTraversing, LPARAM lParam)
Traverse the tree in sequence.
Definition STree.h:477
static HSTREEITEM GetNextSiblingItem(HSTREEITEM hItem)
Get the next sibling item.
Definition STree.h:142
BOOL DeleteItemEx(HSTREEITEM hItem)
Delete an item and its branch.
Definition STree.h:289
IDataFreer * m_dataFreer
Definition STree.h:715
CSTree()
Constructor.
Definition STree.h:109
static T * GetItemPt(HSTREEITEM hItem)
Get the item data pointer.
Definition STree.h:333
static T & GetItemRef(HSTREEITEM hItem)
Get the item data reference.
Definition STree.h:320
static HSTREEITEM GetPrevSiblingItem(HSTREEITEM hItem)
Get the previous sibling item.
Definition STree.h:154
static HSTREEITEM GetRootItem(HSTREEITEM hItem)
Get the root item of the specified node.
Definition STree.h:196
HSTREENODE m_hRootLast
Definition STree.h:717
HSTREENODE m_hRootFirst
Definition STree.h:716
void SortChildren(HSTREEITEM hItem, int(__cdecl *funSort)(void *, const void *, const void *), void *pCtx)
Sort the children of a node.
Definition STree.h:604
int GetDesendants(HSTREEITEM hItem)
Get the number of descendants of a node.
Definition STree.h:516
HSTREEITEM GetRootItem(BOOL bFirst=TRUE)
Get the root item.
Definition STree.h:504