Leaked source code of windows server 2003
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.

2236 lines
63 KiB

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