Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2217 lines
54 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1996-1999 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // TreeItem.cpp
  7. //
  8. // Abstract:
  9. // Implementation of the CTreeItem class.
  10. //
  11. // Author:
  12. // David Potter (davidp) May 3, 1996
  13. //
  14. // Revision History:
  15. //
  16. // Notes:
  17. //
  18. /////////////////////////////////////////////////////////////////////////////
  19. #include "stdafx.h"
  20. #include "ConstDef.h"
  21. #include "TreeItem.h"
  22. #include "TreeItem.inl"
  23. #include "TreeView.h"
  24. #include "ListView.h"
  25. #include "ClusDoc.h"
  26. #include "SplitFrm.h"
  27. #include "TraceTag.h"
  28. #include "ExcOper.h"
  29. #ifdef _DEBUG
  30. #define new DEBUG_NEW
  31. #undef THIS_FILE
  32. static char THIS_FILE[] = __FILE__;
  33. #endif
  34. /////////////////////////////////////////////////////////////////////////////
  35. // Global Variables
  36. /////////////////////////////////////////////////////////////////////////////
  37. #ifdef _DEBUG
  38. CTraceTag g_tagTreeItemUpdate(_T("UI"), _T("TREE ITEM UPDATE"), 0);
  39. CTraceTag g_tagTreeItemSelect(_T("UI"), _T("TREE ITEM SELECT"), 0);
  40. CTraceTag g_tagTreeItemCreate(_T("Create"), _T("TREE ITEM CREATE"), 0);
  41. CTraceTag g_tagTreeItemDelete(_T("Delete"), _T("TREE ITEM DELETE"), 0);
  42. #endif
  43. /////////////////////////////////////////////////////////////////////////////
  44. // CTreeItemList
  45. /////////////////////////////////////////////////////////////////////////////
  46. /////////////////////////////////////////////////////////////////////////////
  47. //++
  48. //
  49. // CTreeItemList::PtiFromPci
  50. //
  51. // Routine Description:
  52. // Find a tree item in the list by its cluster item.
  53. //
  54. // Arguments:
  55. // pci [IN] Cluster item to search for.
  56. // ppos [OUT] Position of the item in the list.
  57. //
  58. // Return Value:
  59. // pti Tree item corresponding to the cluster item.
  60. //
  61. //--
  62. /////////////////////////////////////////////////////////////////////////////
  63. CTreeItem * CTreeItemList::PtiFromPci(
  64. IN const CClusterItem * pci,
  65. OUT POSITION * ppos // = NULL
  66. ) const
  67. {
  68. POSITION posPti;
  69. POSITION posCurPti;
  70. CTreeItem * pti = NULL;
  71. posPti = GetHeadPosition();
  72. while (posPti != NULL)
  73. {
  74. posCurPti = posPti;
  75. pti = GetNext(posPti);
  76. ASSERT_VALID(pti);
  77. if (pti->Pci() == pci)
  78. {
  79. if (ppos != NULL)
  80. *ppos = posCurPti;
  81. break;
  82. } // if: found a match
  83. pti = NULL;
  84. } // while: more resources in the list
  85. return pti;
  86. } //*** CTreeItemList::PtiFromPci()
  87. //***************************************************************************
  88. /////////////////////////////////////////////////////////////////////////////
  89. // CTreeItem
  90. /////////////////////////////////////////////////////////////////////////////
  91. IMPLEMENT_DYNCREATE(CTreeItem, CBaseCmdTarget)
  92. /////////////////////////////////////////////////////////////////////////////
  93. // Message Maps
  94. /////////////////////////////////////////////////////////////////////////////
  95. BEGIN_MESSAGE_MAP(CTreeItem, CBaseCmdTarget)
  96. //{{AFX_MSG_MAP(CTreeItem)
  97. //}}AFX_MSG_MAP
  98. END_MESSAGE_MAP()
  99. /////////////////////////////////////////////////////////////////////////////
  100. //++
  101. //
  102. // CTreeItem::CTreeItem
  103. //
  104. // Routine Description:
  105. // Default constructor.
  106. //
  107. // Arguments:
  108. // None.
  109. //
  110. // Return Value:
  111. // None.
  112. //
  113. //--
  114. /////////////////////////////////////////////////////////////////////////////
  115. CTreeItem::CTreeItem(void)
  116. {
  117. m_ptiParent = NULL;
  118. m_pci = NULL;
  119. m_bWeOwnPci = FALSE;
  120. } //*** CTreeItem::CTreeItem()
  121. /////////////////////////////////////////////////////////////////////////////
  122. //++
  123. //
  124. // CTreeItem::CTreeItem
  125. //
  126. // Routine Description:
  127. // Constructor.
  128. //
  129. // Arguments:
  130. // ptiParent [IN OUT] Parent item for this item.
  131. // pci [IN OUT] Cluster item represented by this tree item.
  132. // bTakeOwnership [IN] TRUE = delete pci when this object is destroyed.
  133. //
  134. // Return Value:
  135. // None.
  136. //
  137. //--
  138. /////////////////////////////////////////////////////////////////////////////
  139. CTreeItem::CTreeItem(
  140. IN OUT CTreeItem * ptiParent,
  141. IN OUT CClusterItem * pci,
  142. IN BOOL bTakeOwnership // = FALSE
  143. )
  144. {
  145. ASSERT_VALID(pci);
  146. m_ptiParent = ptiParent;
  147. m_pci = pci;
  148. m_bWeOwnPci = bTakeOwnership;
  149. m_pci->AddRef();
  150. // Set the column section name. If there is a parent, append our name
  151. // onto the parent's section name.
  152. try
  153. {
  154. if (PtiParent() == NULL)
  155. m_strProfileSection.Format(
  156. REGPARAM_CONNECTIONS _T("\\%s\\%s"),
  157. Pci()->Pdoc()->StrNode(),
  158. Pci()->StrName()
  159. );
  160. else
  161. m_strProfileSection.Format(
  162. _T("%s\\%s"),
  163. PtiParent()->StrProfileSection(),
  164. Pci()->StrName()
  165. );
  166. } // try
  167. catch (CException * pe)
  168. {
  169. // If an error occurs constructing the section name, just ignore it.
  170. pe->Delete();
  171. } // catch: CException
  172. Trace(g_tagTreeItemCreate, _T("CTreeItem() - Creating '%s', parent = '%s', owned = %d"), pci->StrName(), (ptiParent ? ptiParent->Pci()->StrName() : _T("<None>")), bTakeOwnership);
  173. } //*** CTreeItem::CTreeItem(pci)
  174. /////////////////////////////////////////////////////////////////////////////
  175. //++
  176. //
  177. // CTreeItem::Init
  178. //
  179. // Routine Description:
  180. // Initialize the tree item.
  181. //
  182. // Arguments:
  183. // None.
  184. //
  185. // Return Value:
  186. // None.
  187. //
  188. //--
  189. /////////////////////////////////////////////////////////////////////////////
  190. void CTreeItem::Init(void)
  191. {
  192. } //*** CTreeItem::Init()
  193. /////////////////////////////////////////////////////////////////////////////
  194. //++
  195. //
  196. // CTreeItem::~CTreeItem
  197. //
  198. // Routine Description:
  199. // Destructor.
  200. //
  201. // Arguments:
  202. // None.
  203. //
  204. // Return Value:
  205. // None.
  206. //
  207. //--
  208. /////////////////////////////////////////////////////////////////////////////
  209. CTreeItem::~CTreeItem(void)
  210. {
  211. #ifdef _DEBUG
  212. TCHAR szName[1024];
  213. if (Pci() != NULL)
  214. _tcsncpy(szName, Pci()->StrName(), (sizeof(szName) / sizeof(TCHAR)) - 1);
  215. else
  216. _tcscpy(szName, _T("<Unknown>"));
  217. Trace(g_tagTreeItemDelete, _T("~CTreeItem() - Deleting tree item '%s'"), szName);
  218. #endif
  219. // Cleanup this object.
  220. Cleanup();
  221. Trace(g_tagTreeItemDelete, _T("~CTreeItem() - Done deleting tree item '%s'"), szName);
  222. } //*** CTreeItem::~CTreeItem()
  223. /////////////////////////////////////////////////////////////////////////////
  224. //++
  225. //
  226. // CTreeItem::Delete
  227. //
  228. // Routine Description:
  229. // Delete the item. If the item still has references, add it to the
  230. // document's pending delete list.
  231. //
  232. // Arguments:
  233. // None.
  234. //
  235. // Return Value:
  236. // None.
  237. //
  238. // Exceptions Thrown:
  239. // None.
  240. //
  241. //--
  242. /////////////////////////////////////////////////////////////////////////////
  243. void CTreeItem::Delete(void)
  244. {
  245. // Add a reference so that we don't delete ourselves while
  246. // still doing cleanup.
  247. AddRef();
  248. // Cleanup this object.
  249. Cleanup();
  250. // If there are still references to this object, add it to the delete
  251. // pending list. Check for greater than 1 because we added a reference
  252. // at the beginning of this method.
  253. // if (NReferenceCount() > 1)
  254. // {
  255. // ASSERT(Pdoc()->LpciToBeDeleted().Find(this) == NULL);
  256. // Pdoc()->LpciToBeDeleted().AddTail(this);
  257. // } // if: object still has references to it
  258. // Release the reference we added at the beginning. This will
  259. // cause the object to be deleted if we were the last reference.
  260. Release();
  261. } //*** CTreeItem::Delete()
  262. /////////////////////////////////////////////////////////////////////////////
  263. //++
  264. //
  265. // CTreeItem::Cleanup
  266. //
  267. // Routine Description:
  268. // Cleanup the item.
  269. //
  270. // Arguments:
  271. // None.
  272. //
  273. // Return Value:
  274. // None.
  275. //
  276. // Exceptions Thrown:
  277. // None.
  278. //
  279. //--
  280. /////////////////////////////////////////////////////////////////////////////
  281. void CTreeItem::Cleanup(void)
  282. {
  283. // Delete our children first.
  284. // NOTE: List items MUST be deleted first since tree items delete
  285. // owned cluster items.
  286. DeleteAllItemData(m_lpliChildren);
  287. DeleteAllItemData(m_lptiChildren);
  288. m_lpliChildren.RemoveAll();
  289. m_lptiChildren.RemoveAll();
  290. // Remove ourself from all views.
  291. RemoveFromAllLists();
  292. // Delete all other lists.
  293. DeleteAllItemData(m_lpcoli);
  294. DeleteAllItemData(m_lptic);
  295. m_lpcoli.RemoveAll();
  296. m_lptic.RemoveAll();
  297. // If we own the cluster item, delete it.
  298. if (m_bWeOwnPci)
  299. {
  300. #ifdef _DEBUG
  301. TCHAR szName[1024];
  302. if (Pci() != NULL)
  303. _tcsncpy(szName, Pci()->StrName(), (sizeof(szName) / sizeof(TCHAR)) - 1);
  304. else
  305. _tcscpy(szName, _T("<Unknown>"));
  306. Trace(g_tagTreeItemDelete, _T("Cleanup --> Deleting cluster item '%s'"), szName);
  307. #endif
  308. delete m_pci;
  309. } // if: we own the cluster item
  310. else if (m_pci != NULL)
  311. m_pci->Release();
  312. m_pci = NULL;
  313. } //*** CTreeItem::Cleanup()
  314. /////////////////////////////////////////////////////////////////////////////
  315. //++
  316. //
  317. // CTreeItem::StrProfileSection
  318. //
  319. // Routine Description:
  320. // Return the profile section name for this item.
  321. //
  322. // Arguments:
  323. // None.
  324. //
  325. // Return Value:
  326. // CString Reference to profile section string.
  327. //
  328. //--
  329. /////////////////////////////////////////////////////////////////////////////
  330. const CString & CTreeItem::StrProfileSection(void)
  331. {
  332. ASSERT_VALID(Pci());
  333. if (Pci() != NULL)
  334. {
  335. // Set the column section name. If there is a parent, append our name
  336. // onto the parent's section name.
  337. try
  338. {
  339. if (PtiParent() == NULL)
  340. {
  341. ASSERT_VALID(Pci()->Pdoc());
  342. m_strProfileSection.Format(
  343. REGPARAM_CONNECTIONS _T("\\%s\\%s"),
  344. Pci()->Pdoc()->StrNode(),
  345. Pci()->StrName()
  346. );
  347. } // if: item has no parent
  348. else
  349. {
  350. m_strProfileSection.Format(
  351. _T("%s\\%s"),
  352. PtiParent()->StrProfileSection(),
  353. Pci()->StrName()
  354. );
  355. } // else: item has a parent
  356. } // try
  357. catch (CException * pe)
  358. {
  359. // If an error occurs constructing the section name, just ignore it.
  360. pe->Delete();
  361. } // catch: CException
  362. } // if: valid cluster item and document
  363. return m_strProfileSection;
  364. } //*** CTreeItem::StrProfileSection()
  365. /////////////////////////////////////////////////////////////////////////////
  366. //++
  367. //
  368. // CTreeItem::PtiAddChildBefore
  369. //
  370. // Routine Description:
  371. // Add a child to the item's list of children following the specified
  372. // item. Also creates an entry in the list of children list items.
  373. //
  374. // Arguments:
  375. // pciOld [IN] Cluster item to follow the new tree item.
  376. // pciNew [IN OUT] Cluster item represented by the new tree item.
  377. // bTakeOwnership [IN] TRUE = delete pci when done, FALSE = don't delete.
  378. //
  379. // Return Value:
  380. // ptiChild The new child item.
  381. //
  382. //--
  383. /////////////////////////////////////////////////////////////////////////////
  384. CTreeItem * CTreeItem::PtiAddChildBefore(
  385. IN const CClusterItem * pciOld,
  386. OUT CClusterItem * pciNew,
  387. IN BOOL bTakeOwnership // = FALSE
  388. )
  389. {
  390. CTreeItem * ptiOldChild;
  391. CTreeItem * ptiNewChild;
  392. CListItem * pliChild;
  393. POSITION posOld;
  394. // If no old was specified, add to the tail.
  395. if (pciOld == NULL)
  396. return PtiAddChild(pciNew, bTakeOwnership);
  397. // Find the old item.
  398. ptiOldChild = LptiChildren().PtiFromPci(pciOld, &posOld);
  399. ASSERT_VALID(ptiOldChild);
  400. // Create a child tree item.
  401. ptiNewChild = new CTreeItem(this, pciNew, bTakeOwnership);
  402. if (ptiNewChild == NULL)
  403. {
  404. ThrowStaticException(GetLastError());
  405. } // if: error allocating the tree item
  406. ASSERT_VALID(ptiNewChild);
  407. ptiNewChild->Init();
  408. // Add the item before the specified item.
  409. VERIFY((m_lptiChildren.InsertBefore(posOld, ptiNewChild)) != NULL);
  410. // Add it to the back of the cluster item's list.
  411. pciNew->AddTreeItem(ptiNewChild);
  412. // Create a list item.
  413. pliChild = PliAddChild(pciNew);
  414. ASSERT_VALID(pliChild);
  415. // Insert the new tree item in all tree controls.
  416. InsertChildInAllTrees(ptiNewChild);
  417. return ptiNewChild;
  418. } //*** CTreeItem::PtiAddChildBefore()
  419. /////////////////////////////////////////////////////////////////////////////
  420. //++
  421. //
  422. // CTreeItem::InsertChildInAllTrees
  423. //
  424. // Routine Description:
  425. // Insert a child item in all tree controls. The child item must have
  426. // already been inserted in the list of child tree items.
  427. //
  428. // Arguments:
  429. // ptiNewChild [IN OUT] Tree item to be inserted.
  430. //
  431. // Return Value:
  432. // None.
  433. //
  434. //--
  435. /////////////////////////////////////////////////////////////////////////////
  436. void CTreeItem::InsertChildInAllTrees(IN OUT CTreeItem * ptiNewChild)
  437. {
  438. POSITION posPtic;
  439. CTreeItemContext * pticParent;
  440. POSITION posPrevChild;
  441. HTREEITEM htiPrevChild;
  442. CTreeItemContext * pticPrevChild;
  443. CTreeItem * ptiPrevChild;
  444. CTreeItemContext * pticNewChild;
  445. CTreeCtrl * ptc;
  446. CString strName;
  447. ASSERT_VALID(ptiNewChild);
  448. // Find the position of the child being inserted. Then get the address
  449. // of the child before the one being inserted. This requires two calls
  450. // to GetPrev.
  451. VERIFY((posPrevChild = LptiChildren().Find(ptiNewChild)) != NULL); // Get new child pos.
  452. VERIFY((ptiPrevChild = LptiChildren().GetPrev(posPrevChild)) != NULL); // Get pointer to new child.
  453. if (posPrevChild == NULL) // If this is the first child,
  454. {
  455. htiPrevChild = TVI_FIRST; // set the hti to that value.
  456. ptiPrevChild = NULL;
  457. } // if: new child is not the first child
  458. else
  459. {
  460. htiPrevChild = NULL;
  461. ptiPrevChild = LptiChildren().GetPrev(posPrevChild); // Get pointer to prev child.
  462. ASSERT_VALID(ptiPrevChild);
  463. } // else: new child is the first child
  464. // Loop through all the tree item contexts and add this item
  465. // to the tree controls.
  466. posPtic = Lptic().GetHeadPosition();
  467. while (posPtic != NULL)
  468. {
  469. // Get the parent's tree item context.
  470. pticParent = Lptic().GetNext(posPtic);
  471. ASSERT_VALID(pticParent);
  472. // Get the child's tree item context.
  473. if (ptiPrevChild != NULL)
  474. {
  475. pticPrevChild = ptiPrevChild->PticFromFrame(pticParent->m_pframe);
  476. ASSERT_VALID(pticPrevChild);
  477. htiPrevChild = pticPrevChild->m_hti;
  478. } // if: not inserting at beginning of list
  479. // Allocate a new tree item context.
  480. pticNewChild = new CTreeItemContext(pticParent->m_pframe, ptiNewChild, NULL, FALSE /*bExpanded*/);
  481. if (pticNewChild == NULL)
  482. {
  483. ThrowStaticException(GetLastError());
  484. } // if: error allocating the tree item context
  485. ASSERT_VALID(pticNewChild);
  486. pticNewChild->Init();
  487. ptiNewChild->m_lptic.AddTail(pticNewChild);
  488. // Get the name to show in the tree.
  489. ptiNewChild->Pci()->GetTreeName(strName);
  490. // Insert the item in the tree.
  491. ASSERT_VALID(pticParent->m_pframe);
  492. ASSERT_VALID(pticParent->m_pframe->PviewTree());
  493. ptc = &pticParent->m_pframe->PviewTree()->GetTreeCtrl();
  494. VERIFY((pticNewChild->m_hti = ptc->InsertItem(strName, pticParent->m_hti, htiPrevChild)) != NULL);
  495. VERIFY(ptc->SetItemData(pticNewChild->m_hti, (DWORD_PTR) ptiNewChild));
  496. } // while: more tree item contexts in the list
  497. } //*** CTreeItem::InsertChildInAllTrees()
  498. /////////////////////////////////////////////////////////////////////////////
  499. //++
  500. //
  501. // CTreeItem::PtiAddChild(CClusterItem*)
  502. //
  503. // Routine Description:
  504. // Add a child to the item's list of children. Also creates an entry
  505. // in the list of children list items.
  506. //
  507. // Arguments:
  508. // pci [IN OUT] Cluster item represented by the new tree item.
  509. // bTakeOwnership [IN] TRUE = delete pci when done, FALSE = don't delete.
  510. //
  511. // Return Value:
  512. // ptiChild The new child item.
  513. //
  514. //--
  515. /////////////////////////////////////////////////////////////////////////////
  516. CTreeItem * CTreeItem::PtiAddChild(
  517. IN OUT CClusterItem * pci,
  518. IN BOOL bTakeOwnership // = FALSE
  519. )
  520. {
  521. CTreeItem * ptiChild;
  522. CListItem * pliChild;
  523. ASSERT_VALID(pci);
  524. // Create a child tree item.
  525. ptiChild = new CTreeItem(this, pci, bTakeOwnership);
  526. if (ptiChild == NULL)
  527. {
  528. ThrowStaticException(GetLastError());
  529. } // if: error allocating the child tree item
  530. ASSERT_VALID(ptiChild);
  531. ptiChild->Init();
  532. // Add the item to the list of child tree items.
  533. m_lptiChildren.AddTail(ptiChild);
  534. // Add ourselves to the back of the cluster item's list.
  535. pci->AddTreeItem(ptiChild);
  536. // Create a list item.
  537. pliChild = PliAddChild(pci);
  538. ASSERT_VALID(pliChild);
  539. // Insert the new tree item in all tree controls.
  540. InsertChildInAllTrees(ptiChild);
  541. return ptiChild;
  542. } //*** CTreeItem::PtiAddChild(CClusterItem*)
  543. /////////////////////////////////////////////////////////////////////////////
  544. //++
  545. //
  546. // CTreeItem::PtiAddChild(CString&)
  547. //
  548. // Routine Description:
  549. // Add a child to the item's list of children. Also creates an entry
  550. // in the list of children list items.
  551. //
  552. // Arguments:
  553. // rstrName [IN] String for the name of the item.
  554. //
  555. // Return Value:
  556. // ptiChild The new child item.
  557. //
  558. //--
  559. /////////////////////////////////////////////////////////////////////////////
  560. CTreeItem * CTreeItem::PtiAddChild(IN const CString & rstrName)
  561. {
  562. CClusterItem * pci;
  563. CTreeItem * ptiChild;
  564. // Create the cluster item.
  565. pci = new CClusterItem(&rstrName);
  566. if (pci == NULL)
  567. {
  568. ThrowStaticException(GetLastError());
  569. } // if: error allocating the cluster item
  570. ASSERT_VALID(pci);
  571. // Add the cluster item to our list of children.
  572. ptiChild = PtiAddChild(pci, TRUE /*bTakeOwnership*/);
  573. ASSERT_VALID(ptiChild);
  574. return ptiChild;
  575. } //*** CTreeItem::PtiAddChild(CString&)
  576. /////////////////////////////////////////////////////////////////////////////
  577. //++
  578. //
  579. // CTreeItem::PtiAddChild(IDS)
  580. //
  581. // Routine Description:
  582. // Add a child to the item's list of children. Also creates an entry
  583. // in the list of children list items.
  584. //
  585. // Arguments:
  586. // idsName [IN] String resource ID for the name of the item.
  587. //
  588. // Return Value:
  589. // ptiChild The new child item.
  590. //
  591. //--
  592. /////////////////////////////////////////////////////////////////////////////
  593. CTreeItem * CTreeItem::PtiAddChild(IN IDS idsName)
  594. {
  595. CString strName;
  596. ASSERT(idsName != 0);
  597. strName.LoadString(idsName);
  598. return PtiAddChild(strName);
  599. } //*** CTreeItem::PtiAddChild(IDS)
  600. /////////////////////////////////////////////////////////////////////////////
  601. //++
  602. //
  603. // CTreeItem::PliAddChild
  604. //
  605. // Routine Description:
  606. // Add a child to the item's list of children list items.
  607. //
  608. // Arguments:
  609. // pci [IN OUT] Cluster item represented by the list item.
  610. //
  611. // Return Value:
  612. // pliChild The new child item.
  613. //
  614. //--
  615. /////////////////////////////////////////////////////////////////////////////
  616. CListItem * CTreeItem::PliAddChild(IN OUT CClusterItem * pci)
  617. {
  618. CListItem * pliChild;
  619. ASSERT_VALID(pci);
  620. // Create a list item.
  621. pliChild = new CListItem(pci, this);
  622. if (pliChild == NULL)
  623. {
  624. ThrowStaticException(GetLastError());
  625. } // if: error allocating the list item
  626. ASSERT_VALID(pliChild);
  627. // Add the list item to the list of child list items.
  628. m_lpliChildren.AddTail(pliChild);
  629. // Add the list item to the cluster item's list.
  630. pci->AddListItem(pliChild);
  631. // Add the list item to any list views.
  632. {
  633. POSITION posPtic;
  634. CTreeItemContext * ptic;
  635. int ili;
  636. posPtic = Lptic().GetHeadPosition();
  637. while (posPtic != NULL)
  638. {
  639. ptic = Lptic().GetNext(posPtic);
  640. ASSERT_VALID(ptic);
  641. if (ptic->m_pframe->PviewTree()->HtiSelected() == ptic->m_hti)
  642. {
  643. ASSERT_VALID(ptic->m_pframe);
  644. VERIFY((ili = pliChild->IliInsertInList(ptic->m_pframe->PviewList())) != -1);
  645. } // if: currently showing children in list view
  646. } // while: item is showing in more views
  647. } // Add the list item to any list views
  648. return pliChild;
  649. } //*** CTreeItem::PliAddChild()
  650. /////////////////////////////////////////////////////////////////////////////
  651. //++
  652. //
  653. // CTreeItem::RemoveItem
  654. //
  655. // Routine Description:
  656. // Remove the item from the tree.
  657. //
  658. // Arguments:
  659. // None.
  660. //
  661. // Return Value:
  662. // None.
  663. //
  664. //--
  665. /////////////////////////////////////////////////////////////////////////////
  666. void CTreeItem::RemoveItem(void)
  667. {
  668. ASSERT_VALID(PtiParent());
  669. PtiParent()->RemoveChild(Pci());
  670. } //*** CTreeItem::RemoveItem()
  671. /////////////////////////////////////////////////////////////////////////////
  672. //++
  673. //
  674. // CTreeItem::RemoveChild
  675. //
  676. // Routine Description:
  677. // Remove a child from the item's list of children list items.
  678. //
  679. // Arguments:
  680. // pci [IN OUT] Cluster item represented by the list item.
  681. //
  682. // Return Value:
  683. // None.
  684. //
  685. //--
  686. /////////////////////////////////////////////////////////////////////////////
  687. void CTreeItem::RemoveChild(IN OUT CClusterItem * pci)
  688. {
  689. ASSERT_VALID(pci);
  690. // Remove the item from the list of list items.
  691. {
  692. CListItem * pliChild;
  693. POSITION posPli;
  694. pliChild = PliChildFromPci(pci);
  695. if (pliChild != NULL)
  696. {
  697. pliChild->RemoveFromAllLists();
  698. posPli = LpliChildren().Find(pliChild);
  699. ASSERT(posPli != NULL);
  700. m_lpliChildren.RemoveAt(posPli);
  701. Trace(g_tagTreeItemDelete, _T("RemoveChild() - Deleting child list item '%s' from '%s' - %d left"), pliChild->Pci()->StrName(), Pci()->StrName(), LpliChildren().GetCount());
  702. delete pliChild;
  703. } // if: child lives in the list
  704. } // Remove the item from the list of list items
  705. // Remove the item from the list of tree items.
  706. {
  707. CTreeItem * ptiChild;
  708. CTreeItem * ptiChildChild;
  709. POSITION posPti;
  710. ULONG nReferenceCount;
  711. ptiChild = PtiChildFromPci(pci);
  712. if (ptiChild != NULL)
  713. {
  714. // Remove the children of this child.
  715. {
  716. posPti = ptiChild->LptiChildren().GetHeadPosition();
  717. while (posPti != NULL)
  718. {
  719. ptiChildChild = ptiChild->LptiChildren().GetNext(posPti);
  720. ASSERT_VALID(ptiChildChild);
  721. ptiChildChild->RemoveItem();
  722. } // while: more items in the list
  723. } // Remove the children of this child
  724. posPti = LptiChildren().Find(ptiChild);
  725. ASSERT(posPti != NULL);
  726. nReferenceCount = ptiChild->NReferenceCount();
  727. m_lptiChildren.RemoveAt(posPti);
  728. Trace(g_tagTreeItemDelete, _T("RemoveChild() - Deleting child tree item '%s' from '%s' - %d left"), ptiChild->Pci()->StrName(), Pci()->StrName(), LptiChildren().GetCount());
  729. if (nReferenceCount > 1)
  730. {
  731. ptiChild->AddRef();
  732. ptiChild->RemoveFromAllLists();
  733. ptiChild->Release();
  734. } // if: child not deleted yet
  735. } // if: child lives in the tree
  736. } // Remove the item from the list of tree items
  737. } //*** CTreeItem::RemoveChild()
  738. /////////////////////////////////////////////////////////////////////////////
  739. //++
  740. //
  741. // CTreeItem::PtiChildFromName
  742. //
  743. // Routine Description:
  744. // Find a child tree item from its name.
  745. //
  746. // Arguments:
  747. // rstrName [IN] Name of the item.
  748. // ppos [OUT] Position of the item in the list.
  749. //
  750. // Return Value:
  751. // ptiChild Child item corresponding to the specified name.
  752. //
  753. //--
  754. /////////////////////////////////////////////////////////////////////////////
  755. CTreeItem * CTreeItem::PtiChildFromName(
  756. IN const CString & rstrName,
  757. OUT POSITION * ppos // = NULL
  758. ) const
  759. {
  760. POSITION posPtiChild;
  761. POSITION posCurPtiChild;
  762. CTreeItem * ptiChild = NULL;
  763. // Loop through each child item to find the specified item.
  764. posPtiChild = LptiChildren().GetHeadPosition();
  765. while (posPtiChild != NULL)
  766. {
  767. posCurPtiChild = posPtiChild;
  768. ptiChild = LptiChildren().GetNext(posPtiChild);
  769. ASSERT_VALID(ptiChild);
  770. if (ptiChild->StrName() == rstrName)
  771. {
  772. if (ppos != NULL)
  773. *ppos = posCurPtiChild;
  774. break;
  775. } // if: found a match
  776. } // while: more children of this tree item
  777. return ptiChild;
  778. } //*** CTreeItem::PtiChildFromName(CString&)
  779. /////////////////////////////////////////////////////////////////////////////
  780. //++
  781. //
  782. // CTreeItem::PtiChildFromName
  783. //
  784. // Routine Description:
  785. // Find a child tree item from its name.
  786. //
  787. // Arguments:
  788. // idsName [IN] ID of the name of the item.
  789. // ppos [OUT] Position of the item in the list.
  790. //
  791. // Return Value:
  792. // ptiChild Child item corresponding to the specified name.
  793. //
  794. //--
  795. /////////////////////////////////////////////////////////////////////////////
  796. CTreeItem * CTreeItem::PtiChildFromName(
  797. IN IDS idsName,
  798. OUT POSITION * ppos // = NULL
  799. ) const
  800. {
  801. CString strName;
  802. VERIFY(strName.LoadString(idsName));
  803. return PtiChildFromName(strName, ppos);
  804. } //*** CTreeItem::PtiChildFromName(IDS)
  805. /////////////////////////////////////////////////////////////////////////////
  806. //++
  807. //
  808. // CTreeItem::PtiChildFromPci
  809. //
  810. // Routine Description:
  811. // Find a child tree item from its cluster item.
  812. //
  813. // Arguments:
  814. // pci [IN] Cluster item to search for.
  815. //
  816. // Return Value:
  817. // ptiChild Child item corresponding to the specified cluster item.
  818. //
  819. //--
  820. /////////////////////////////////////////////////////////////////////////////
  821. CTreeItem * CTreeItem::PtiChildFromPci(IN const CClusterItem * pci) const
  822. {
  823. POSITION posPtiChild;
  824. CTreeItem * ptiChild = NULL;
  825. ASSERT_VALID(pci);
  826. // Loop through each child item to find the specified item.
  827. posPtiChild = LptiChildren().GetHeadPosition();
  828. while (posPtiChild != NULL)
  829. {
  830. ptiChild = LptiChildren().GetNext(posPtiChild);
  831. ASSERT_VALID(ptiChild);
  832. if (ptiChild->Pci() == pci)
  833. break;
  834. } // while: more children of this tree item
  835. return ptiChild;
  836. } //*** CTreeItem::PtiChildFromPci()
  837. /////////////////////////////////////////////////////////////////////////////
  838. //++
  839. //
  840. // CTreeItem::PliChildFromPci
  841. //
  842. // Routine Description:
  843. // Find a child list item from its cluster item.
  844. //
  845. // Arguments:
  846. // pci [IN] Cluster item to search for.
  847. //
  848. // Return Value:
  849. // pliChild Child item corresponding to the specified cluster item.
  850. //
  851. //--
  852. /////////////////////////////////////////////////////////////////////////////
  853. CListItem * CTreeItem::PliChildFromPci(IN const CClusterItem * pci) const
  854. {
  855. POSITION posPliChild;
  856. CListItem * pliChild = NULL;
  857. // Loop through each child item to find the specified item.
  858. posPliChild = LpliChildren().GetHeadPosition();
  859. while (posPliChild != NULL)
  860. {
  861. pliChild = LpliChildren().GetNext(posPliChild);
  862. ASSERT_VALID(pliChild);
  863. if (pliChild->Pci() == pci)
  864. break;
  865. } // while: more children of this tree item
  866. return pliChild;
  867. } //*** CTreeItem::PliChildFromPci()
  868. /////////////////////////////////////////////////////////////////////////////
  869. //++
  870. //
  871. // CTreeItem::HtiInsertInTree
  872. //
  873. // Routine Description:
  874. // Insert the item in a tree under the specified parent.
  875. //
  876. // Arguments:
  877. // pctv [IN OUT] Cluster tree view in which item is displayed.
  878. //
  879. // Return Value:
  880. // m_hti Handle of the new item in the tree.
  881. //
  882. //--
  883. /////////////////////////////////////////////////////////////////////////////
  884. HTREEITEM CTreeItem::HtiInsertInTree(
  885. IN OUT CClusterTreeView * pctv
  886. )
  887. {
  888. CTreeItemContext * ptic;
  889. HTREEITEM htiParent;
  890. CSplitterFrame * pframe;
  891. ASSERT_VALID(pctv);
  892. ASSERT_VALID(Pci());
  893. // Get the frame pointer.
  894. pframe = (CSplitterFrame *) pctv->GetParent()->GetParent();
  895. ASSERT_VALID(pframe);
  896. // Get the tree item context for this item.
  897. // If it doesn't exist yet, create one.
  898. ptic = PticFromView(pctv);
  899. if (ptic == NULL)
  900. {
  901. // Create the new tree item context.
  902. ptic = new CTreeItemContext(pframe, this, NULL, FALSE /*bExpanded*/);
  903. if (ptic == NULL)
  904. {
  905. ThrowStaticException(GetLastError());
  906. } // if: error allcoating the tree item context
  907. ASSERT_VALID(ptic);
  908. ptic->Init();
  909. m_lptic.AddTail(ptic);
  910. } // if: no entry found
  911. // Get our parent's handle.
  912. if (PtiParent() != NULL)
  913. {
  914. CTreeItemContext * pticParent;
  915. pticParent = PtiParent()->PticFromFrame(pframe);
  916. ASSERT_VALID(pticParent);
  917. htiParent = pticParent->m_hti;
  918. } // if: parent specified
  919. else
  920. htiParent = NULL;
  921. // Insert the item in the tree.
  922. {
  923. CTreeCtrl * ptc;
  924. CString strName;
  925. ASSERT_VALID(pframe->PviewTree());
  926. Pci()->GetTreeName(strName);
  927. ptc = &pframe->PviewTree()->GetTreeCtrl();
  928. VERIFY((ptic->m_hti = ptc->InsertItem(strName, htiParent)) != NULL);
  929. VERIFY(ptc->SetItemData(ptic->m_hti, (DWORD_PTR) this));
  930. } // Insert the item in the tree
  931. UpdateState();
  932. return ptic->m_hti;
  933. } //*** CTreeItem::HtiInsertInTree()
  934. /////////////////////////////////////////////////////////////////////////////
  935. //++
  936. //
  937. // CTreeItem::RemoveFromAllLists
  938. //
  939. // Routine Description:
  940. // Remove this item from all lists.
  941. //
  942. // Arguments:
  943. // None.
  944. //
  945. // Return Value:
  946. // None.
  947. //
  948. //--
  949. /////////////////////////////////////////////////////////////////////////////
  950. void CTreeItem::RemoveFromAllLists(void)
  951. {
  952. if (Pci() != NULL)
  953. {
  954. ASSERT_VALID(Pci());
  955. // Loop through each view and remove the item from the list.
  956. {
  957. POSITION posPtic;
  958. POSITION posPticPrev;
  959. CTreeItemContext * ptic;
  960. CTreeCtrl * ptc;
  961. CClusterListView * pviewList;
  962. posPtic = Lptic().GetHeadPosition();
  963. while (posPtic != NULL)
  964. {
  965. // Get the next tree item context list entry.
  966. posPticPrev = posPtic;
  967. ptic = Lptic().GetNext(posPtic);
  968. ASSERT_VALID(ptic);
  969. // Get the tree control and list view from the frame.
  970. ASSERT_VALID(ptic->m_pframe);
  971. ptc = &ptic->m_pframe->PviewTree()->GetTreeCtrl();
  972. pviewList = ptic->m_pframe->PviewList();
  973. // If this tree item is the parent of the list control items,
  974. // refresh the list control with no selection.
  975. if (pviewList->PtiParent() == this)
  976. pviewList->Refresh(NULL);
  977. // Delete the item from the tree control and the list.
  978. VERIFY(ptc->DeleteItem(ptic->m_hti));
  979. m_lptic.RemoveAt(posPticPrev);
  980. delete ptic;
  981. } // while: more lists
  982. } // Loop through each view and remove the item from the list
  983. // Remove ourselves from the cluster item's list.
  984. Pci()->RemoveTreeItem(this);
  985. } // if: valid cluster item pointer
  986. } //*** CTreeItem::RemoveFromAllLists()
  987. /////////////////////////////////////////////////////////////////////////////
  988. //++
  989. //
  990. // CTreeItem::Select
  991. //
  992. // Routine Description:
  993. // Select this item in the specified tree view. This causes the
  994. // children of this item to be displayed in a list view.
  995. //
  996. // Arguments:
  997. // pctv [IN OUT] Tree view in which item was selected.
  998. // bSelectInTree [IN] TRUE = select in tree control also.
  999. //
  1000. // Return Value:
  1001. // None.
  1002. //
  1003. //--
  1004. /////////////////////////////////////////////////////////////////////////////
  1005. void CTreeItem::Select(IN OUT CClusterTreeView * pctv, IN BOOL bSelectInTree)
  1006. {
  1007. CTreeItemContext * ptic;
  1008. ASSERT_VALID(pctv);
  1009. // Get the tree item context.
  1010. ptic = PticFromView(pctv);
  1011. ASSERT_VALID(ptic);
  1012. Trace(g_tagTreeItemSelect, _T("'%s' selected"), Pci()->StrName());
  1013. // Select the item in the tree control.
  1014. if (bSelectInTree)
  1015. ptic->m_pframe->PviewTree()->GetTreeCtrl().Select(ptic->m_hti, TVGN_CARET);
  1016. // Refresh the list control.
  1017. ASSERT_VALID(ptic->m_pframe);
  1018. ASSERT_VALID(ptic->m_pframe->PviewList());
  1019. ptic->m_pframe->PviewList()->Refresh(this);
  1020. } //*** CTreeItem::Select()
  1021. /////////////////////////////////////////////////////////////////////////////
  1022. //++
  1023. //
  1024. // CTreeItem::PreRemoveFromFrameWithChildren
  1025. //
  1026. // Routine Description:
  1027. // Cleanup an item and all its children.
  1028. //
  1029. // Arguments:
  1030. // pframe [IN OUT] Frame window item is being removed from.
  1031. //
  1032. // Return Value:
  1033. // None.
  1034. //
  1035. //--
  1036. /////////////////////////////////////////////////////////////////////////////
  1037. void CTreeItem::PreRemoveFromFrameWithChildren(IN OUT CSplitterFrame * pframe)
  1038. {
  1039. POSITION posChild;
  1040. CTreeItem * ptiChild;
  1041. ASSERT_VALID(this);
  1042. // Cleanup all child items.
  1043. posChild = LptiChildren().GetHeadPosition();
  1044. while (posChild != NULL)
  1045. {
  1046. ptiChild = LptiChildren().GetNext(posChild);
  1047. ASSERT_VALID(ptiChild);
  1048. ptiChild->PreRemoveFromFrameWithChildren(pframe);
  1049. } // while: more items in the list
  1050. // Cleanup this item.
  1051. PreRemoveFromFrame(pframe);
  1052. } //*** CTreeItem::PreRemoveFromFrameWithChildren()
  1053. /////////////////////////////////////////////////////////////////////////////
  1054. //++
  1055. //
  1056. // CTreeItem::PreRemoveFromFrame
  1057. //
  1058. // Routine Description:
  1059. // Prepare to remove the item from a tree.
  1060. //
  1061. // Arguments:
  1062. // pframe [IN OUT] Frame window item is being removed from.
  1063. //
  1064. // Return Value:
  1065. // None.
  1066. //
  1067. //--
  1068. /////////////////////////////////////////////////////////////////////////////
  1069. void CTreeItem::PreRemoveFromFrame(IN OUT CSplitterFrame * pframe)
  1070. {
  1071. CTreeItemContext * ptic;
  1072. POSITION posPtic;
  1073. ASSERT_VALID(pframe);
  1074. // Find the view in our list.
  1075. ptic = PticFromFrame(pframe);
  1076. if (ptic == NULL)
  1077. return;
  1078. ASSERT_VALID(ptic);
  1079. VERIFY((posPtic = Lptic().Find(ptic)) != NULL);
  1080. // Remove the view from the list.
  1081. m_lptic.RemoveAt(posPtic);
  1082. // Delete the context item.
  1083. delete ptic;
  1084. } //*** CTreeItem::PreRemoveFromFrame(pframe)
  1085. /////////////////////////////////////////////////////////////////////////////
  1086. //++
  1087. //
  1088. // CTreeItem::PticFromFrame
  1089. //
  1090. // Routine Description:
  1091. // Find a tree item context from a frame.
  1092. //
  1093. // Arguments:
  1094. // pframe [IN] Frame to search on.
  1095. //
  1096. // Return Value:
  1097. // ptic Found context, or NULL if not found.
  1098. //
  1099. //--
  1100. /////////////////////////////////////////////////////////////////////////////
  1101. CTreeItemContext * CTreeItem::PticFromFrame(IN const CSplitterFrame * pframe) const
  1102. {
  1103. POSITION posPtic;
  1104. CTreeItemContext * ptic;
  1105. ASSERT_VALID(pframe);
  1106. posPtic = Lptic().GetHeadPosition();
  1107. while (posPtic != NULL)
  1108. {
  1109. ptic = Lptic().GetNext(posPtic);
  1110. ASSERT_VALID(ptic);
  1111. if (ptic->m_pframe == pframe)
  1112. return ptic;
  1113. } // while: more items in the list
  1114. return NULL;
  1115. } //*** CTreeItem::PticFromFrame()
  1116. /////////////////////////////////////////////////////////////////////////////
  1117. //++
  1118. //
  1119. // CTreeItem::PticFromView
  1120. //
  1121. // Routine Description:
  1122. // Find a tree item context from a tree view.
  1123. //
  1124. // Arguments:
  1125. // pctv [IN] Tree view to search on.
  1126. //
  1127. // Return Value:
  1128. // ptic Found context, or NULL if not found.
  1129. //
  1130. //--
  1131. /////////////////////////////////////////////////////////////////////////////
  1132. CTreeItemContext * CTreeItem::PticFromView(IN const CClusterTreeView * pctv) const
  1133. {
  1134. POSITION posPtic;
  1135. CTreeItemContext * ptic;
  1136. ASSERT_VALID(pctv);
  1137. posPtic = Lptic().GetHeadPosition();
  1138. while (posPtic != NULL)
  1139. {
  1140. ptic = Lptic().GetNext(posPtic);
  1141. ASSERT_VALID(ptic);
  1142. ASSERT_VALID(ptic->m_pframe);
  1143. if (ptic->m_pframe->PviewTree() == pctv)
  1144. return ptic;
  1145. } // while: more items in the list
  1146. return NULL;
  1147. } //*** CTreeItem::PticFromView(CClusterTreeView*)
  1148. /////////////////////////////////////////////////////////////////////////////
  1149. //++
  1150. //
  1151. // CTreeItem::PticFromView
  1152. //
  1153. // Routine Description:
  1154. // Find a tree item context from a list view.
  1155. //
  1156. // Arguments:
  1157. // pclv [IN] List view to search on.
  1158. //
  1159. // Return Value:
  1160. // ptic Found context, or NULL if not found.
  1161. //
  1162. //--
  1163. /////////////////////////////////////////////////////////////////////////////
  1164. CTreeItemContext * CTreeItem::PticFromView(IN const CClusterListView * pclv) const
  1165. {
  1166. POSITION posPtic;
  1167. CTreeItemContext * ptic;
  1168. ASSERT_VALID(pclv);
  1169. posPtic = Lptic().GetHeadPosition();
  1170. while (posPtic != NULL)
  1171. {
  1172. ptic = Lptic().GetNext(posPtic);
  1173. ASSERT_VALID(ptic);
  1174. ASSERT_VALID(ptic->m_pframe);
  1175. if (ptic->m_pframe->PviewList() == pclv)
  1176. return ptic;
  1177. } // while: more items in the list
  1178. return NULL;
  1179. } //*** CTreeItem::PticFromView(CClusterListView*)
  1180. /////////////////////////////////////////////////////////////////////////////
  1181. //++
  1182. //
  1183. // CTreeItem::HtiFromView
  1184. //
  1185. // Routine Description:
  1186. // Find a tree item handle from a view.
  1187. //
  1188. // Arguments:
  1189. // pctv [IN] View to search on.
  1190. //
  1191. // Return Value:
  1192. // hti Found tree item handle, or NULL if not found.
  1193. //
  1194. //--
  1195. /////////////////////////////////////////////////////////////////////////////
  1196. HTREEITEM CTreeItem::HtiFromView(IN const CClusterTreeView * pctv) const
  1197. {
  1198. CTreeItemContext * ptic;
  1199. HTREEITEM hti = NULL;
  1200. ASSERT_VALID(pctv);
  1201. ptic = PticFromView(pctv);
  1202. if (ptic != NULL)
  1203. hti = ptic->m_hti;
  1204. return hti;
  1205. } //*** CTreeItem::HtiFromView()
  1206. /////////////////////////////////////////////////////////////////////////////
  1207. //++
  1208. //
  1209. // CTreeItem::PcoliAddColumn
  1210. //
  1211. // Routine Description:
  1212. // Add a column to the list of column header items.
  1213. //
  1214. // Arguments:
  1215. // rstrText [IN] Reference to the text of the column.
  1216. // idsColumnID [IN] ID of the column to identify the data.
  1217. // nDefaultWidth [IN] Default width of the column.
  1218. // nWidth [IN] Actual width of the column.
  1219. //
  1220. // Return Value:
  1221. // pcoli Column item added to the list.
  1222. //
  1223. //--
  1224. /////////////////////////////////////////////////////////////////////////////
  1225. CColumnItem * CTreeItem::PcoliAddColumn(
  1226. IN const CString & rstrText,
  1227. IN IDS idsColumnID,
  1228. IN int nDefaultWidth,
  1229. IN int nWidth
  1230. )
  1231. {
  1232. CColumnItem * pcoli;
  1233. pcoli = new CColumnItem(rstrText, idsColumnID, nDefaultWidth, nWidth);
  1234. if (pcoli == NULL)
  1235. {
  1236. ThrowStaticException(GetLastError());
  1237. } // if: error allocating the column item
  1238. m_lpcoli.AddTail(pcoli);
  1239. return pcoli;
  1240. } //*** CTreeItem::PcoliAddColumn(CString&)
  1241. /////////////////////////////////////////////////////////////////////////////
  1242. //++
  1243. //
  1244. // CTreeItem::PcoliAddColumn
  1245. //
  1246. // Routine Description:
  1247. // Add a column to the list of column header items.
  1248. //
  1249. // Arguments:
  1250. // idsText [IN] String resource ID for the text of the column.
  1251. // Also used as the column ID.
  1252. // nDefaultWidth [IN] Default width of the column.
  1253. // nWidth [IN] Actual width of the column.
  1254. //
  1255. // Return Value:
  1256. // pcoli Column item added to the list.
  1257. //
  1258. //--
  1259. /////////////////////////////////////////////////////////////////////////////
  1260. CColumnItem * CTreeItem::PcoliAddColumn(IN IDS idsText, IN int nDefaultWidth, IN int nWidth)
  1261. {
  1262. CString strText;
  1263. strText.LoadString(idsText);
  1264. return PcoliAddColumn(strText, idsText, nDefaultWidth, nWidth);
  1265. } //*** CTreeItem::PcoliAddColumn(IDS)
  1266. /////////////////////////////////////////////////////////////////////////////
  1267. //++
  1268. //
  1269. // CTreeItem::BSelectItem
  1270. //
  1271. // Routine Description:
  1272. // Select the item in the specified tree control.
  1273. //
  1274. // Arguments:
  1275. // pctv [IN OUT] Cluster tree view in which to select the item.
  1276. //
  1277. // Return Value:
  1278. // TRUE Item was selected successfully.
  1279. // FALSE Item not selected.
  1280. //
  1281. //--
  1282. /////////////////////////////////////////////////////////////////////////////
  1283. BOOL CTreeItem::BSelectItem(IN OUT CClusterTreeView * pctv)
  1284. {
  1285. HTREEITEM hti;
  1286. ASSERT_VALID(pctv);
  1287. VERIFY((hti = HtiFromView(pctv)) != NULL);
  1288. return (pctv->GetTreeCtrl().SelectItem(hti) != 0);
  1289. } //*** CTreeItem::BSelectItem()
  1290. /////////////////////////////////////////////////////////////////////////////
  1291. //++
  1292. //
  1293. // CTreeItem::SelectInAllViews
  1294. //
  1295. // Routine Description:
  1296. // Select this item in all views in which it is being displayed. This
  1297. // causes the children of this item to be displayed in a list view.
  1298. //
  1299. // Arguments:
  1300. // None.
  1301. //
  1302. // Return Value:
  1303. // None.
  1304. //
  1305. //--
  1306. /////////////////////////////////////////////////////////////////////////////
  1307. void CTreeItem::SelectInAllViews(void)
  1308. {
  1309. POSITION posPtic;
  1310. CTreeItemContext * ptic;
  1311. posPtic = Lptic().GetHeadPosition();
  1312. while (posPtic != NULL)
  1313. {
  1314. // Get the next tree item context list entry.
  1315. ptic = Lptic().GetNext(posPtic);
  1316. ASSERT_VALID(ptic);
  1317. // Select the item in this list.
  1318. ASSERT_VALID(ptic->m_pframe);
  1319. BSelectItem(ptic->m_pframe->PviewTree());
  1320. ptic->m_pframe->PviewTree()->SetFocus();
  1321. } // while: more items in the list
  1322. } //*** CTreeItem::SelectInAllViews()
  1323. /////////////////////////////////////////////////////////////////////////////
  1324. //++
  1325. //
  1326. // CTreeItem::BExpand
  1327. //
  1328. // Routine Description:
  1329. // Expand the item in the specified tree control.
  1330. //
  1331. // Arguments:
  1332. // pctv [IN OUT] Cluster tree view in which to expand the item.
  1333. // nCode [IN] Flag indicating the type of action to be taken.
  1334. //
  1335. // Return Value:
  1336. // TRUE Item was expanded successfully.
  1337. // FALSE Item not expanded.
  1338. //
  1339. //--
  1340. /////////////////////////////////////////////////////////////////////////////
  1341. BOOL CTreeItem::BExpand(IN OUT CClusterTreeView * pctv, IN UINT nCode)
  1342. {
  1343. CTreeItemContext * ptic;
  1344. ASSERT_VALID(pctv);
  1345. ASSERT(nCode != 0);
  1346. ptic = PticFromView(pctv);
  1347. ASSERT_VALID(ptic);
  1348. if (nCode == TVE_EXPAND)
  1349. ptic->m_bExpanded = TRUE;
  1350. else
  1351. ptic->m_bExpanded = FALSE;
  1352. return (pctv->GetTreeCtrl().Expand(ptic->m_hti, nCode) != 0);
  1353. } //*** CTreeItem::BExpand()
  1354. /////////////////////////////////////////////////////////////////////////////
  1355. //++
  1356. //
  1357. // CTreeItem::ExpandInAllViews
  1358. //
  1359. // Routine Description:
  1360. // Expand the item in all views in which it is displayed.
  1361. //
  1362. // Arguments:
  1363. // nCode [IN] Flag indicating the type of action to be taken.
  1364. //
  1365. // Return Value:
  1366. // None.
  1367. //
  1368. //--
  1369. /////////////////////////////////////////////////////////////////////////////
  1370. void CTreeItem::ExpandInAllViews(IN UINT nCode)
  1371. {
  1372. POSITION posPtic;
  1373. CTreeItemContext * ptic;
  1374. ASSERT(nCode != 0);
  1375. posPtic = Lptic().GetHeadPosition();
  1376. while (posPtic != NULL)
  1377. {
  1378. // Get the next tree item context list entry.
  1379. ptic = Lptic().GetNext(posPtic);
  1380. ASSERT_VALID(ptic);
  1381. // Select the item in this list.
  1382. ASSERT_VALID(ptic->m_pframe);
  1383. BExpand(ptic->m_pframe->PviewTree(), nCode);
  1384. } // while: more items in the list
  1385. } //*** CTreeItem::ExpandInAllViews()
  1386. /////////////////////////////////////////////////////////////////////////////
  1387. //++
  1388. //
  1389. // CTreeItem::SetExpandedState
  1390. //
  1391. // Routine Description:
  1392. // Save the expanded state of the item in the specified view.
  1393. //
  1394. // Arguments:
  1395. // pctv [IN] Tree view in which expanded state is being saved.
  1396. // bExpanded [IN] TRUE = item is expanded in the specified view.
  1397. //
  1398. // Return Value:
  1399. // None.
  1400. //
  1401. //--
  1402. /////////////////////////////////////////////////////////////////////////////
  1403. void CTreeItem::SetExpandedState(
  1404. IN const CClusterTreeView * pctv,
  1405. IN BOOL bExpanded
  1406. )
  1407. {
  1408. CTreeItemContext * ptic;
  1409. ASSERT_VALID(pctv);
  1410. ptic = PticFromView(pctv);
  1411. ASSERT_VALID(ptic);
  1412. ptic->m_bExpanded = bExpanded;
  1413. } //*** CTreeItem::SetExpandedState()
  1414. /////////////////////////////////////////////////////////////////////////////
  1415. //++
  1416. //
  1417. // CTreeItem::BShouldBeExpanded
  1418. //
  1419. // Routine Description:
  1420. // Returns whether the item should be expanded in the specified tree
  1421. // view based on the user's profile.
  1422. //
  1423. // Arguments:
  1424. // pctv [IN] Tree view in which expanded state is being saved.
  1425. //
  1426. // Return Value:
  1427. // None.
  1428. //
  1429. //--
  1430. /////////////////////////////////////////////////////////////////////////////
  1431. BOOL CTreeItem::BShouldBeExpanded(IN const CClusterTreeView * pctv) const
  1432. {
  1433. CTreeItemContext * ptic;
  1434. ASSERT_VALID(pctv);
  1435. ptic = PticFromView(pctv);
  1436. ASSERT_VALID(ptic);
  1437. return ptic->m_bExpanded;
  1438. } //*** CTreeItem::BShouldBeExpanded()
  1439. /////////////////////////////////////////////////////////////////////////////
  1440. //++
  1441. //
  1442. // CTreeItem::UpdateState
  1443. //
  1444. // Routine Description:
  1445. // Update the current state of the item.
  1446. //
  1447. // Arguments:
  1448. // None.
  1449. //
  1450. // Return Value:
  1451. // None.
  1452. //
  1453. //--
  1454. /////////////////////////////////////////////////////////////////////////////
  1455. void CTreeItem::UpdateState(void)
  1456. {
  1457. ASSERT_VALID(this);
  1458. ASSERT_VALID(Pci());
  1459. // Ask the item to update its state.
  1460. if (Pci() != NULL)
  1461. Pci()->UpdateState();
  1462. } //*** CTreeItem::UpdateState()
  1463. /////////////////////////////////////////////////////////////////////////////
  1464. //++
  1465. //
  1466. // CTreeItem::UpdateAllStatesInTree
  1467. //
  1468. // Routine Description:
  1469. // Update the current state of the item.
  1470. //
  1471. // Arguments:
  1472. // None.
  1473. //
  1474. // Return Value:
  1475. // None.
  1476. //
  1477. //--
  1478. /////////////////////////////////////////////////////////////////////////////
  1479. void CTreeItem::UpdateAllStatesInTree(void)
  1480. {
  1481. POSITION posPti;
  1482. CTreeItem * ptiChild;
  1483. UpdateState();
  1484. posPti = LptiChildren().GetHeadPosition();
  1485. while (posPti != NULL)
  1486. {
  1487. ptiChild = LptiChildren().GetNext(posPti);
  1488. ASSERT_VALID(ptiChild);
  1489. ptiChild->UpdateAllStatesInTree();
  1490. } // while: more children
  1491. } //*** CTreeItem::UpdateAllStatesInTree()
  1492. /////////////////////////////////////////////////////////////////////////////
  1493. //++
  1494. //
  1495. // CTreeItem::UpdateUIState
  1496. //
  1497. // Routine Description:
  1498. // Update the current UI state of the item.
  1499. //
  1500. // Arguments:
  1501. // None.
  1502. //
  1503. // Return Value:
  1504. // None.
  1505. //
  1506. //--
  1507. /////////////////////////////////////////////////////////////////////////////
  1508. void CTreeItem::UpdateUIState(void)
  1509. {
  1510. POSITION posPtic;
  1511. CTreeItemContext * ptic;
  1512. UINT nMask;
  1513. UINT nImage;
  1514. #ifdef _DISPLAY_STATE_TEXT_IN_TREE
  1515. CString strText;
  1516. #endif
  1517. ASSERT_VALID(Pci());
  1518. // Loop through the views and update the state on each one.
  1519. posPtic = Lptic().GetHeadPosition();
  1520. while (posPtic != NULL)
  1521. {
  1522. ptic = Lptic().GetNext(posPtic);
  1523. ASSERT_VALID(ptic);
  1524. // Set the images that are displayed for the item.
  1525. ASSERT_VALID(ptic->m_pframe);
  1526. ASSERT_VALID(ptic->m_pframe->PviewTree());
  1527. nMask = TVIF_TEXT;
  1528. if (Pci() == NULL)
  1529. {
  1530. #ifdef _DISPLAY_STATE_TEXT_IN_TREE
  1531. strText = StrName();
  1532. #endif
  1533. nImage = 0;
  1534. } // if: invalid cluster item
  1535. else
  1536. {
  1537. nMask |= TVIF_IMAGE | TVIF_SELECTEDIMAGE;
  1538. #ifdef _DISPLAY_STATE_TEXT_IN_TREE
  1539. Pci()->GetTreeName(strText);
  1540. #endif
  1541. nImage = Pci()->IimgState();
  1542. } // else: valid cluster item
  1543. #ifdef _DISPLAY_STATE_TEXT_IN_TREE
  1544. Trace(g_tagTreeItemUpdate, _T("Updating item '%s' (pci name = '%s')"), strText, Pci()->StrName());
  1545. #else
  1546. Trace(g_tagTreeItemUpdate, _T("Updating item '%s' (pci name = '%s')"), StrName(), Pci()->StrName());
  1547. #endif
  1548. ptic->m_pframe->PviewTree()->GetTreeCtrl().SetItem(
  1549. ptic->m_hti, // hItem
  1550. nMask, // nMask
  1551. #ifdef _DISPLAY_STATE_TEXT_IN_TREE
  1552. strText, // lpszItem
  1553. #else
  1554. StrName(), // lpszItem
  1555. #endif
  1556. nImage, // nImage
  1557. nImage, // nSelectedImage
  1558. 0, // nState
  1559. 0, // nStatemask
  1560. NULL // lParam
  1561. );
  1562. } // while: more view
  1563. } //*** CTreeItem::UpdateUIState()
  1564. /////////////////////////////////////////////////////////////////////////////
  1565. //++
  1566. //
  1567. // CTreeItem::OnCmdMsg
  1568. //
  1569. // Routine Description:
  1570. // Processes command messages. Attempts to pass them on to a selected
  1571. // item first.
  1572. //
  1573. // Arguments:
  1574. // nID [IN] Command ID.
  1575. // nCode [IN] Notification code.
  1576. // pExtra [IN OUT] Used according to the value of nCode.
  1577. // pHandlerInfo [OUT] ???
  1578. //
  1579. // Return Value:
  1580. // None.
  1581. //
  1582. //--
  1583. /////////////////////////////////////////////////////////////////////////////
  1584. BOOL CTreeItem::OnCmdMsg(
  1585. UINT nID,
  1586. int nCode,
  1587. void * pExtra,
  1588. AFX_CMDHANDLERINFO * pHandlerInfo
  1589. )
  1590. {
  1591. if (Pci() != NULL)
  1592. {
  1593. // Give the cluster item a chance to handle the message.
  1594. if (Pci()->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
  1595. return TRUE;
  1596. } // if: valid cluster item
  1597. return CBaseCmdTarget::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
  1598. } //*** CTreeItem::OnCmdMsg()
  1599. /////////////////////////////////////////////////////////////////////////////
  1600. //++
  1601. //
  1602. // CTreeItem::OpenChild
  1603. //
  1604. // Routine Description:
  1605. // Open the specified child item.
  1606. //
  1607. // Arguments:
  1608. // pti [IN OUT] Child tree item to open.
  1609. // pframe [IN OUT] Frame in which to open the item.
  1610. //
  1611. // Return Value:
  1612. // None.
  1613. //
  1614. //--
  1615. /////////////////////////////////////////////////////////////////////////////
  1616. void CTreeItem::OpenChild(
  1617. IN OUT CTreeItem * pti,
  1618. IN OUT CSplitterFrame * pframe
  1619. )
  1620. {
  1621. CTreeItemContext * ptic;
  1622. ASSERT_VALID(pti);
  1623. ASSERT_VALID(pframe);
  1624. // Find the tree item context for the frame.
  1625. ptic = PticFromFrame(pframe);
  1626. ASSERT_VALID(ptic);
  1627. // Expand the parent item and then select the child item.
  1628. if (pframe->PviewTree()->GetTreeCtrl().Expand(ptic->m_hti, TVE_EXPAND))
  1629. pti->Select(pframe->PviewTree(), TRUE /*bSelectInTree*/);
  1630. } //*** CTreeItem::OpenChild()
  1631. /////////////////////////////////////////////////////////////////////////////
  1632. //++
  1633. //
  1634. // CTreeItem::EditLabel
  1635. //
  1636. // Routine Description:
  1637. // Processes the ID_FILE_RENAME menu command.
  1638. //
  1639. // Arguments:
  1640. // pctv [IN OUT] Cluster tree view item is being edited in.
  1641. //
  1642. // Return Value:
  1643. // None.
  1644. //
  1645. //--
  1646. /////////////////////////////////////////////////////////////////////////////
  1647. void CTreeItem::EditLabel(IN OUT CClusterTreeView * pctv)
  1648. {
  1649. HTREEITEM hti;
  1650. ASSERT_VALID(pctv);
  1651. ASSERT_VALID(Pci());
  1652. ASSERT(Pci()->BCanBeEdited());
  1653. hti = HtiFromView(pctv);
  1654. ASSERT(hti != NULL);
  1655. pctv->GetTreeCtrl().EditLabel(hti);
  1656. } //*** CTreeItem::EditLabel()
  1657. //***************************************************************************
  1658. /////////////////////////////////////////////////////////////////////////////
  1659. // CTreeItemContext
  1660. /////////////////////////////////////////////////////////////////////////////
  1661. IMPLEMENT_DYNCREATE(CTreeItemContext, CObject)
  1662. /////////////////////////////////////////////////////////////////////////////
  1663. //++
  1664. //
  1665. // CTreeItemContext::Init
  1666. //
  1667. // Routine Description:
  1668. // Initialize the tree item context.
  1669. //
  1670. // Arguments:
  1671. // None.
  1672. //
  1673. // Return Value:
  1674. // None.
  1675. //
  1676. //--
  1677. /////////////////////////////////////////////////////////////////////////////
  1678. void CTreeItemContext::Init(void)
  1679. {
  1680. BOOL bExpanded;
  1681. UINT cbColumnInfo;
  1682. CString strValueName;
  1683. ASSERT_VALID(m_pti);
  1684. ASSERT(m_pti->StrProfileSection().GetLength() > 0);
  1685. ASSERT(m_prgnColumnInfo == NULL);
  1686. try
  1687. {
  1688. // Read the expanded state.
  1689. m_pframe->ConstructProfileValueName(strValueName, REGPARAM_EXPANDED);
  1690. bExpanded = AfxGetApp()->GetProfileInt(
  1691. m_pti->StrProfileSection(),
  1692. strValueName,
  1693. m_bExpanded
  1694. );
  1695. if (bExpanded)
  1696. m_bExpanded = bExpanded;
  1697. // Read the column information.
  1698. m_pframe->ConstructProfileValueName(strValueName, REGPARAM_COLUMNS);
  1699. AfxGetApp()->GetProfileBinary(
  1700. m_pti->StrProfileSection(),
  1701. strValueName,
  1702. (BYTE **) &m_prgnColumnInfo,
  1703. &cbColumnInfo
  1704. );
  1705. } // try
  1706. catch (CException * pe)
  1707. {
  1708. pe->Delete();
  1709. } // catch: CException
  1710. } //*** CTreeItemContext::Init()
  1711. /////////////////////////////////////////////////////////////////////////////
  1712. //++
  1713. //
  1714. // CTreeItemContext::SaveProfileInfo
  1715. //
  1716. // Routine Description:
  1717. // Save state information to the user's profile. This includes column
  1718. // widths and positions as well as whether the tree item was expanded
  1719. // or not.
  1720. //
  1721. // Arguments:
  1722. // None.
  1723. //
  1724. // Return Value:
  1725. // None.
  1726. //
  1727. //--
  1728. /////////////////////////////////////////////////////////////////////////////
  1729. void CTreeItemContext::SaveProfileInfo(void)
  1730. {
  1731. CString strValueName;
  1732. try
  1733. {
  1734. ASSERT_VALID(m_pti);
  1735. ASSERT(m_pti->StrProfileSection().GetLength() > 0);
  1736. // Save expansion info to the user's profile.
  1737. m_pframe->ConstructProfileValueName(strValueName, REGPARAM_EXPANDED);
  1738. AfxGetApp()->WriteProfileInt(
  1739. m_pti->StrProfileSection(),
  1740. strValueName,
  1741. m_bExpanded
  1742. );
  1743. if (m_prgnColumnInfo != NULL)
  1744. {
  1745. // Save column info to the user's profile.
  1746. m_pframe->ConstructProfileValueName(strValueName, REGPARAM_COLUMNS);
  1747. AfxGetApp()->WriteProfileBinary(
  1748. m_pti->StrProfileSection(),
  1749. strValueName,
  1750. (PBYTE) m_prgnColumnInfo,
  1751. ((m_prgnColumnInfo[0] * 2) + 1) * sizeof(DWORD)
  1752. );
  1753. } // if: there is column info
  1754. } // try
  1755. catch (CException * pe)
  1756. {
  1757. pe->Delete();
  1758. } // catch: CException
  1759. } //*** CTreeItemContext::SaveProfileInfo()
  1760. /////////////////////////////////////////////////////////////////////////////
  1761. //++
  1762. //
  1763. // CTreeItemContext::PrgnColumnInfo
  1764. //
  1765. // Routine Description:
  1766. // Return the column info. If it doesn't exist or isn't the right
  1767. // size, allocate one.
  1768. //
  1769. // Arguments:
  1770. // None.
  1771. //
  1772. // Return Value:
  1773. // prgnColumnInfo The column info array.
  1774. //
  1775. //--
  1776. /////////////////////////////////////////////////////////////////////////////
  1777. DWORD * CTreeItemContext::PrgnColumnInfo(void)
  1778. {
  1779. DWORD cColumns;
  1780. ASSERT_VALID(m_pti);
  1781. cColumns = (DWORD)m_pti->Lpcoli().GetCount();
  1782. if ((m_prgnColumnInfo == NULL)
  1783. || (cColumns != m_prgnColumnInfo[0]))
  1784. {
  1785. DWORD cnColumnInfo = (cColumns * 2) + 1;
  1786. delete [] m_prgnColumnInfo;
  1787. m_prgnColumnInfo = new DWORD[cnColumnInfo];
  1788. if (m_prgnColumnInfo == NULL)
  1789. {
  1790. ThrowStaticException(GetLastError());
  1791. } // if: error allocating column info array
  1792. //
  1793. // Initialize the column info array
  1794. //
  1795. {
  1796. DWORD inColumnInfo;
  1797. // The first entry is the number of columns.
  1798. m_prgnColumnInfo[0] = cColumns;
  1799. // The second set of entries is the width of each column.
  1800. {
  1801. POSITION pos;
  1802. CColumnItem * pcoli;
  1803. inColumnInfo = 1;
  1804. pos = m_pti->Lpcoli().GetHeadPosition();
  1805. while (pos != NULL)
  1806. {
  1807. pcoli = m_pti->Lpcoli().GetNext(pos);
  1808. ASSERT_VALID(pcoli);
  1809. ASSERT(inColumnInfo <= cColumns);
  1810. m_prgnColumnInfo[inColumnInfo++] = pcoli->NWidth();
  1811. } // while: more items in the list
  1812. } // The second set of entries is the width of each column
  1813. // The third set of entries is the order of the columns.
  1814. {
  1815. DWORD * prgnColumnInfo = &m_prgnColumnInfo[inColumnInfo];
  1816. for (inColumnInfo = 0 ; inColumnInfo < cColumns ; inColumnInfo++)
  1817. prgnColumnInfo[inColumnInfo] = inColumnInfo;
  1818. } // The third set of entries is the order of the columns
  1819. } // Initialize the column info array
  1820. } // if: column info array doesn't exist or is wrong size
  1821. return m_prgnColumnInfo;
  1822. } //*** CTreeItemContext::PrgnColumnInfo()
  1823. /////////////////////////////////////////////////////////////////////////////
  1824. //++
  1825. //
  1826. // CTreeItemContext::BIsExpanded
  1827. //
  1828. // Routine Description:
  1829. // Return the EXPANDED state of the item in this tree view.
  1830. //
  1831. // Arguments:
  1832. // None.
  1833. //
  1834. // Return Value:
  1835. // TRUE Item is expanded.
  1836. // FALSE Item is not expanded.
  1837. //
  1838. //--
  1839. /////////////////////////////////////////////////////////////////////////////
  1840. BOOL CTreeItemContext::BIsExpanded(void) const
  1841. {
  1842. ASSERT_VALID(this);
  1843. ASSERT_VALID(m_pframe);
  1844. ASSERT_VALID(m_pframe->PviewTree());
  1845. ASSERT(m_hti != NULL);
  1846. return (m_pframe->PviewTree()->GetTreeCtrl().GetItemState(m_hti, TVIS_EXPANDED) == TVIS_EXPANDED);
  1847. } //*** CTreeItemContext::BIsExpanded()
  1848. //***************************************************************************
  1849. /////////////////////////////////////////////////////////////////////////////
  1850. // Global Functions
  1851. /////////////////////////////////////////////////////////////////////////////
  1852. /////////////////////////////////////////////////////////////////////////////
  1853. //++
  1854. //
  1855. // DestructElements
  1856. //
  1857. // Routine Description:
  1858. // Destroys CTreeItem* elements.
  1859. //
  1860. // Arguments:
  1861. // pElements Array of pointers to elements to destruct.
  1862. // nCount Number of elements to destruct.
  1863. //
  1864. // Return Value:
  1865. // None.
  1866. //
  1867. //--
  1868. /////////////////////////////////////////////////////////////////////////////
  1869. void AFXAPI DestructElements(CTreeItem ** pElements, int nCount)
  1870. {
  1871. ASSERT(nCount == 0 ||
  1872. AfxIsValidAddress(pElements, nCount * sizeof(CTreeItem *)));
  1873. // call the destructor(s)
  1874. for (; nCount--; pElements++)
  1875. {
  1876. ASSERT_VALID(*pElements);
  1877. (*pElements)->Release();
  1878. } // for: each item in the array
  1879. } //*** DestructElements(CTreeItem**)
  1880. /////////////////////////////////////////////////////////////////////////////
  1881. //++
  1882. //
  1883. // DeleteAllItemData
  1884. //
  1885. // Routine Description:
  1886. // Deletes all item data in a CList.
  1887. //
  1888. // Arguments:
  1889. // rlp [IN OUT] Reference to the list whose data is to be deleted.
  1890. //
  1891. // Return Value:
  1892. // None.
  1893. //
  1894. //--
  1895. /////////////////////////////////////////////////////////////////////////////
  1896. void DeleteAllItemData(IN OUT CTreeItemList & rlp)
  1897. {
  1898. POSITION pos;
  1899. CTreeItem * pti;
  1900. // Delete all the items in the Contained list.
  1901. pos = rlp.GetHeadPosition();
  1902. while (pos != NULL)
  1903. {
  1904. pti = rlp.GetNext(pos);
  1905. ASSERT_VALID(pti);
  1906. // Trace(g_tagTreeItemDelete, _T("DeleteAllItemData(rlpti) - Deleting tree item '%s'"), pti->Pci()->StrName());
  1907. pti->Delete();
  1908. } // while: more items in the list
  1909. } //*** DeleteAllItemData()
  1910. /////////////////////////////////////////////////////////////////////////////
  1911. //++
  1912. //
  1913. // DeleteAllItemData
  1914. //
  1915. // Routine Description:
  1916. // Deletes all item data in a CList.
  1917. //
  1918. // Arguments:
  1919. // rlp [IN OUT] Reference to the list whose data is to be deleted.
  1920. //
  1921. // Return Value:
  1922. // None.
  1923. //
  1924. //--
  1925. /////////////////////////////////////////////////////////////////////////////
  1926. void DeleteAllItemData(IN OUT CTreeItemContextList & rlp)
  1927. {
  1928. POSITION pos;
  1929. CTreeItemContext * ptic;
  1930. // Delete all the items in the Contained list.
  1931. pos = rlp.GetHeadPosition();
  1932. while (pos != NULL)
  1933. {
  1934. ptic = rlp.GetNext(pos);
  1935. ASSERT_VALID(ptic);
  1936. delete ptic;
  1937. } // while: more items in the list
  1938. } //*** DeleteAllItemData()