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

/////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 1996-2002 Microsoft Corporation
//
// Module Name:
// TreeItem.cpp
//
// Abstract:
// Implementation of the CTreeItem class.
//
// Author:
// David Potter (davidp) May 3, 1996
//
// Revision History:
//
// Notes:
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ConstDef.h"
#include "TreeItem.h"
#include "TreeItem.inl"
#include "TreeView.h"
#include "ListView.h"
#include "ClusDoc.h"
#include "SplitFrm.h"
#include "TraceTag.h"
#include "ExcOper.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// Global Variables
/////////////////////////////////////////////////////////////////////////////
#ifdef _DEBUG
CTraceTag g_tagTreeItemUpdate(_T("UI"), _T("TREE ITEM UPDATE"), 0);
CTraceTag g_tagTreeItemSelect(_T("UI"), _T("TREE ITEM SELECT"), 0);
CTraceTag g_tagTreeItemCreate(_T("Create"), _T("TREE ITEM CREATE"), 0);
CTraceTag g_tagTreeItemDelete(_T("Delete"), _T("TREE ITEM DELETE"), 0);
#endif
/////////////////////////////////////////////////////////////////////////////
// CTreeItemList
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItemList::PtiFromPci
//
// Routine Description:
// Find a tree item in the list by its cluster item.
//
// Arguments:
// pci [IN] Cluster item to search for.
// ppos [OUT] Position of the item in the list.
//
// Return Value:
// pti Tree item corresponding to the cluster item.
//
//--
/////////////////////////////////////////////////////////////////////////////
CTreeItem * CTreeItemList::PtiFromPci(
IN const CClusterItem * pci,
OUT POSITION * ppos // = NULL
) const
{
POSITION posPti;
POSITION posCurPti;
CTreeItem * pti = NULL;
posPti = GetHeadPosition();
while (posPti != NULL)
{
posCurPti = posPti;
pti = GetNext(posPti);
ASSERT_VALID(pti);
if (pti->Pci() == pci)
{
if (ppos != NULL)
*ppos = posCurPti;
break;
} // if: found a match
pti = NULL;
} // while: more resources in the list
return pti;
} //*** CTreeItemList::PtiFromPci()
//***************************************************************************
/////////////////////////////////////////////////////////////////////////////
// CTreeItem
/////////////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNCREATE(CTreeItem, CBaseCmdTarget)
/////////////////////////////////////////////////////////////////////////////
// Message Maps
/////////////////////////////////////////////////////////////////////////////
BEGIN_MESSAGE_MAP(CTreeItem, CBaseCmdTarget)
//{{AFX_MSG_MAP(CTreeItem)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::CTreeItem
//
// Routine Description:
// Default constructor.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CTreeItem::CTreeItem(void)
{
m_ptiParent = NULL;
m_pci = NULL;
m_bWeOwnPci = FALSE;
} //*** CTreeItem::CTreeItem()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::CTreeItem
//
// Routine Description:
// Constructor.
//
// Arguments:
// ptiParent [IN OUT] Parent item for this item.
// pci [IN OUT] Cluster item represented by this tree item.
// bTakeOwnership [IN] TRUE = delete pci when this object is destroyed.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CTreeItem::CTreeItem(
IN OUT CTreeItem * ptiParent,
IN OUT CClusterItem * pci,
IN BOOL bTakeOwnership // = FALSE
)
{
ASSERT_VALID(pci);
m_ptiParent = ptiParent;
m_pci = pci;
m_bWeOwnPci = bTakeOwnership;
m_pci->AddRef();
// Set the column section name. If there is a parent, append our name
// onto the parent's section name.
try
{
if (PtiParent() == NULL)
m_strProfileSection.Format(
REGPARAM_CONNECTIONS _T("\\%s\\%s"),
Pci()->Pdoc()->StrNode(),
Pci()->StrName()
);
else
m_strProfileSection.Format(
_T("%s\\%s"),
PtiParent()->StrProfileSection(),
Pci()->StrName()
);
} // try
catch (CException * pe)
{
// If an error occurs constructing the section name, just ignore it.
pe->Delete();
} // catch: CException
Trace(g_tagTreeItemCreate, _T("CTreeItem() - Creating '%s', parent = '%s', owned = %d"), pci->StrName(), (ptiParent ? ptiParent->Pci()->StrName() : _T("<None>")), bTakeOwnership);
} //*** CTreeItem::CTreeItem(pci)
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::Init
//
// Routine Description:
// Initialize the tree item.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTreeItem::Init(void)
{
} //*** CTreeItem::Init()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::~CTreeItem
//
// Routine Description:
// Destructor.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CTreeItem::~CTreeItem(void)
{
#ifdef _DEBUG
TCHAR szName[1024];
HRESULT hr;
if (Pci() != NULL)
{
hr = StringCchCopyN( szName, RTL_NUMBER_OF( szName ), Pci()->StrName(), Pci()->StrName().GetLength() );
ASSERT( SUCCEEDED( hr ) );
}
else
{
hr = StringCchCopy( szName, RTL_NUMBER_OF( szName ), _T("<Unknown>") );
ASSERT( SUCCEEDED( hr ) );
}
Trace(g_tagTreeItemDelete, _T("~CTreeItem() - Deleting tree item '%s'"), szName);
#endif
// Cleanup this object.
Cleanup();
Trace(g_tagTreeItemDelete, _T("~CTreeItem() - Done deleting tree item '%s'"), szName);
} //*** CTreeItem::~CTreeItem()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::Delete
//
// Routine Description:
// Delete the item. If the item still has references, add it to the
// document's pending delete list.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
// Exceptions Thrown:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTreeItem::Delete(void)
{
// Add a reference so that we don't delete ourselves while
// still doing cleanup.
AddRef();
// Cleanup this object.
Cleanup();
// If there are still references to this object, add it to the delete
// pending list. Check for greater than 1 because we added a reference
// at the beginning of this method.
// if (NReferenceCount() > 1)
// {
// ASSERT(Pdoc()->LpciToBeDeleted().Find(this) == NULL);
// Pdoc()->LpciToBeDeleted().AddTail(this);
// } // if: object still has references to it
// Release the reference we added at the beginning. This will
// cause the object to be deleted if we were the last reference.
Release();
} //*** CTreeItem::Delete()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::Cleanup
//
// Routine Description:
// Cleanup the item.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
// Exceptions Thrown:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTreeItem::Cleanup(void)
{
// Delete our children first.
// NOTE: List items MUST be deleted first since tree items delete
// owned cluster items.
DeleteAllItemData(m_lpliChildren);
DeleteAllItemData(m_lptiChildren);
m_lpliChildren.RemoveAll();
m_lptiChildren.RemoveAll();
// Remove ourself from all views.
RemoveFromAllLists();
// Delete all other lists.
DeleteAllItemData(m_lpcoli);
DeleteAllItemData(m_lptic);
m_lpcoli.RemoveAll();
m_lptic.RemoveAll();
// If we own the cluster item, delete it.
if (m_bWeOwnPci)
{
#ifdef _DEBUG
TCHAR szName[1024];
HRESULT hr;
if (Pci() != NULL)
{
hr = StringCchCopyN( szName, RTL_NUMBER_OF( szName ), Pci()->StrName(), Pci()->StrName().GetLength() );
ASSERT( SUCCEEDED( hr ) );
}
else
{
hr = StringCchCopy( szName, RTL_NUMBER_OF( szName ), _T("<Unknown>") );
ASSERT( SUCCEEDED( hr ) );
}
Trace(g_tagTreeItemDelete, _T("Cleanup --> Deleting cluster item '%s'"), szName);
#endif
delete m_pci;
} // if: we own the cluster item
else if (m_pci != NULL)
m_pci->Release();
m_pci = NULL;
} //*** CTreeItem::Cleanup()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::StrProfileSection
//
// Routine Description:
// Return the profile section name for this item.
//
// Arguments:
// None.
//
// Return Value:
// CString Reference to profile section string.
//
//--
/////////////////////////////////////////////////////////////////////////////
const CString & CTreeItem::StrProfileSection(void)
{
ASSERT_VALID(Pci());
if (Pci() != NULL)
{
// Set the column section name. If there is a parent, append our name
// onto the parent's section name.
try
{
if (PtiParent() == NULL)
{
ASSERT_VALID(Pci()->Pdoc());
m_strProfileSection.Format(
REGPARAM_CONNECTIONS _T("\\%s\\%s"),
Pci()->Pdoc()->StrNode(),
Pci()->StrName()
);
} // if: item has no parent
else
{
m_strProfileSection.Format(
_T("%s\\%s"),
PtiParent()->StrProfileSection(),
Pci()->StrName()
);
} // else: item has a parent
} // try
catch (CException * pe)
{
// If an error occurs constructing the section name, just ignore it.
pe->Delete();
} // catch: CException
} // if: valid cluster item and document
return m_strProfileSection;
} //*** CTreeItem::StrProfileSection()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::PtiAddChildBefore
//
// Routine Description:
// Add a child to the item's list of children following the specified
// item. Also creates an entry in the list of children list items.
//
// Arguments:
// pciOld [IN] Cluster item to follow the new tree item.
// pciNew [IN OUT] Cluster item represented by the new tree item.
// bTakeOwnership [IN] TRUE = delete pci when done, FALSE = don't delete.
//
// Return Value:
// ptiChild The new child item.
//
//--
/////////////////////////////////////////////////////////////////////////////
CTreeItem * CTreeItem::PtiAddChildBefore(
IN const CClusterItem * pciOld,
OUT CClusterItem * pciNew,
IN BOOL bTakeOwnership // = FALSE
)
{
CTreeItem * ptiOldChild;
CTreeItem * ptiNewChild;
CListItem * pliChild;
POSITION posOld;
// If no old was specified, add to the tail.
if (pciOld == NULL)
return PtiAddChild(pciNew, bTakeOwnership);
// Find the old item.
ptiOldChild = LptiChildren().PtiFromPci(pciOld, &posOld);
ASSERT_VALID(ptiOldChild);
// Create a child tree item.
ptiNewChild = new CTreeItem(this, pciNew, bTakeOwnership);
if (ptiNewChild == NULL)
{
ThrowStaticException(GetLastError());
} // if: error allocating the tree item
ASSERT_VALID(ptiNewChild);
ptiNewChild->Init();
// Add the item before the specified item.
VERIFY((m_lptiChildren.InsertBefore(posOld, ptiNewChild)) != NULL);
// Add it to the back of the cluster item's list.
pciNew->AddTreeItem(ptiNewChild);
// Create a list item.
pliChild = PliAddChild(pciNew);
ASSERT_VALID(pliChild);
// Insert the new tree item in all tree controls.
InsertChildInAllTrees(ptiNewChild);
return ptiNewChild;
} //*** CTreeItem::PtiAddChildBefore()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::InsertChildInAllTrees
//
// Routine Description:
// Insert a child item in all tree controls. The child item must have
// already been inserted in the list of child tree items.
//
// Arguments:
// ptiNewChild [IN OUT] Tree item to be inserted.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTreeItem::InsertChildInAllTrees(IN OUT CTreeItem * ptiNewChild)
{
POSITION posPtic;
CTreeItemContext * pticParent;
POSITION posPrevChild;
HTREEITEM htiPrevChild;
CTreeItemContext * pticPrevChild;
CTreeItem * ptiPrevChild;
CTreeItemContext * pticNewChild;
CTreeCtrl * ptc;
CString strName;
ASSERT_VALID(ptiNewChild);
// Find the position of the child being inserted. Then get the address
// of the child before the one being inserted. This requires two calls
// to GetPrev.
VERIFY((posPrevChild = LptiChildren().Find(ptiNewChild)) != NULL); // Get new child pos.
VERIFY((ptiPrevChild = LptiChildren().GetPrev(posPrevChild)) != NULL); // Get pointer to new child.
if (posPrevChild == NULL) // If this is the first child,
{
htiPrevChild = TVI_FIRST; // set the hti to that value.
ptiPrevChild = NULL;
} // if: new child is not the first child
else
{
htiPrevChild = NULL;
ptiPrevChild = LptiChildren().GetPrev(posPrevChild); // Get pointer to prev child.
ASSERT_VALID(ptiPrevChild);
} // else: new child is the first child
// Loop through all the tree item contexts and add this item
// to the tree controls.
posPtic = Lptic().GetHeadPosition();
while (posPtic != NULL)
{
// Get the parent's tree item context.
pticParent = Lptic().GetNext(posPtic);
ASSERT_VALID(pticParent);
// Get the child's tree item context.
if (ptiPrevChild != NULL)
{
pticPrevChild = ptiPrevChild->PticFromFrame(pticParent->m_pframe);
ASSERT_VALID(pticPrevChild);
htiPrevChild = pticPrevChild->m_hti;
} // if: not inserting at beginning of list
// Allocate a new tree item context.
pticNewChild = new CTreeItemContext(pticParent->m_pframe, ptiNewChild, NULL, FALSE /*bExpanded*/);
if (pticNewChild == NULL)
{
ThrowStaticException(GetLastError());
} // if: error allocating the tree item context
ASSERT_VALID(pticNewChild);
pticNewChild->Init();
ptiNewChild->m_lptic.AddTail(pticNewChild);
// Get the name to show in the tree.
ptiNewChild->Pci()->GetTreeName(strName);
// Insert the item in the tree.
ASSERT_VALID(pticParent->m_pframe);
ASSERT_VALID(pticParent->m_pframe->PviewTree());
ptc = &pticParent->m_pframe->PviewTree()->GetTreeCtrl();
VERIFY((pticNewChild->m_hti = ptc->InsertItem(strName, pticParent->m_hti, htiPrevChild)) != NULL);
VERIFY(ptc->SetItemData(pticNewChild->m_hti, (DWORD_PTR) ptiNewChild));
} // while: more tree item contexts in the list
} //*** CTreeItem::InsertChildInAllTrees()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::PtiAddChild(CClusterItem*)
//
// Routine Description:
// Add a child to the item's list of children. Also creates an entry
// in the list of children list items.
//
// Arguments:
// pci [IN OUT] Cluster item represented by the new tree item.
// bTakeOwnership [IN] TRUE = delete pci when done, FALSE = don't delete.
//
// Return Value:
// ptiChild The new child item.
//
//--
/////////////////////////////////////////////////////////////////////////////
CTreeItem * CTreeItem::PtiAddChild(
IN OUT CClusterItem * pci,
IN BOOL bTakeOwnership // = FALSE
)
{
CTreeItem * ptiChild;
CListItem * pliChild;
ASSERT_VALID(pci);
// Create a child tree item.
ptiChild = new CTreeItem(this, pci, bTakeOwnership);
if (ptiChild == NULL)
{
ThrowStaticException(GetLastError());
goto Cleanup;
} // if: error allocating the child tree item
ASSERT_VALID(ptiChild);
ptiChild->Init();
// Add the item to the list of child tree items.
m_lptiChildren.AddTail(ptiChild);
// Add ourselves to the back of the cluster item's list.
pci->AddTreeItem(ptiChild);
// Create a list item.
pliChild = PliAddChild(pci);
ASSERT_VALID(pliChild);
// Insert the new tree item in all tree controls.
InsertChildInAllTrees(ptiChild);
Cleanup:
return ptiChild;
} //*** CTreeItem::PtiAddChild(CClusterItem*)
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::PtiAddChild(CString&)
//
// Routine Description:
// Add a child to the item's list of children. Also creates an entry
// in the list of children list items.
//
// Arguments:
// rstrName [IN] String for the name of the item.
//
// Return Value:
// ptiChild The new child item.
//
//--
/////////////////////////////////////////////////////////////////////////////
CTreeItem * CTreeItem::PtiAddChild(IN const CString & rstrName)
{
CClusterItem * pci;
CTreeItem * ptiChild;
// Create the cluster item.
pci = new CClusterItem(&rstrName);
if (pci == NULL)
{
ThrowStaticException(GetLastError());
} // if: error allocating the cluster item
ASSERT_VALID(pci);
// Add the cluster item to our list of children.
ptiChild = PtiAddChild(pci, TRUE /*bTakeOwnership*/);
ASSERT_VALID(ptiChild);
return ptiChild;
} //*** CTreeItem::PtiAddChild(CString&)
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::PtiAddChild(IDS)
//
// Routine Description:
// Add a child to the item's list of children. Also creates an entry
// in the list of children list items.
//
// Arguments:
// idsName [IN] String resource ID for the name of the item.
//
// Return Value:
// ptiChild The new child item.
//
//--
/////////////////////////////////////////////////////////////////////////////
CTreeItem * CTreeItem::PtiAddChild(IN IDS idsName)
{
CString strName;
ASSERT(idsName != 0);
strName.LoadString(idsName);
return PtiAddChild(strName);
} //*** CTreeItem::PtiAddChild(IDS)
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::PliAddChild
//
// Routine Description:
// Add a child to the item's list of children list items.
//
// Arguments:
// pci [IN OUT] Cluster item represented by the list item.
//
// Return Value:
// pliChild The new child item.
//
//--
/////////////////////////////////////////////////////////////////////////////
CListItem * CTreeItem::PliAddChild(IN OUT CClusterItem * pci)
{
CListItem * pliChild;
ASSERT_VALID(pci);
// Create a list item.
pliChild = new CListItem(pci, this);
if (pliChild == NULL)
{
ThrowStaticException(GetLastError());
} // if: error allocating the list item
ASSERT_VALID(pliChild);
// Add the list item to the list of child list items.
m_lpliChildren.AddTail(pliChild);
// Add the list item to the cluster item's list.
pci->AddListItem(pliChild);
// Add the list item to any list views.
{
POSITION posPtic;
CTreeItemContext * ptic;
int ili;
posPtic = Lptic().GetHeadPosition();
while (posPtic != NULL)
{
ptic = Lptic().GetNext(posPtic);
ASSERT_VALID(ptic);
if (ptic->m_pframe->PviewTree()->HtiSelected() == ptic->m_hti)
{
ASSERT_VALID(ptic->m_pframe);
VERIFY((ili = pliChild->IliInsertInList(ptic->m_pframe->PviewList())) != -1);
} // if: currently showing children in list view
} // while: item is showing in more views
} // Add the list item to any list views
return pliChild;
} //*** CTreeItem::PliAddChild()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::RemoveItem
//
// Routine Description:
// Remove the item from the tree.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTreeItem::RemoveItem(void)
{
ASSERT_VALID(PtiParent());
PtiParent()->RemoveChild(Pci());
} //*** CTreeItem::RemoveItem()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::RemoveChild
//
// Routine Description:
// Remove a child from the item's list of children list items.
//
// Arguments:
// pci [IN OUT] Cluster item represented by the list item.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTreeItem::RemoveChild(IN OUT CClusterItem * pci)
{
ASSERT_VALID(pci);
// Remove the item from the list of list items.
{
CListItem * pliChild;
POSITION posPli;
pliChild = PliChildFromPci(pci);
if (pliChild != NULL)
{
pliChild->RemoveFromAllLists();
posPli = LpliChildren().Find(pliChild);
ASSERT(posPli != NULL);
m_lpliChildren.RemoveAt(posPli);
Trace(g_tagTreeItemDelete, _T("RemoveChild() - Deleting child list item '%s' from '%s' - %d left"), pliChild->Pci()->StrName(), Pci()->StrName(), LpliChildren().GetCount());
delete pliChild;
} // if: child lives in the list
} // Remove the item from the list of list items
// Remove the item from the list of tree items.
{
CTreeItem * ptiChild;
CTreeItem * ptiChildChild;
POSITION posPti;
ULONG nReferenceCount;
ptiChild = PtiChildFromPci(pci);
if (ptiChild != NULL)
{
// Remove the children of this child.
{
posPti = ptiChild->LptiChildren().GetHeadPosition();
while (posPti != NULL)
{
ptiChildChild = ptiChild->LptiChildren().GetNext(posPti);
ASSERT_VALID(ptiChildChild);
ptiChildChild->RemoveItem();
} // while: more items in the list
} // Remove the children of this child
posPti = LptiChildren().Find(ptiChild);
ASSERT(posPti != NULL);
nReferenceCount = ptiChild->NReferenceCount();
m_lptiChildren.RemoveAt(posPti);
Trace(g_tagTreeItemDelete, _T("RemoveChild() - Deleting child tree item '%s' from '%s' - %d left"), ptiChild->Pci()->StrName(), Pci()->StrName(), LptiChildren().GetCount());
if (nReferenceCount > 1)
{
ptiChild->AddRef();
ptiChild->RemoveFromAllLists();
ptiChild->Release();
} // if: child not deleted yet
} // if: child lives in the tree
} // Remove the item from the list of tree items
} //*** CTreeItem::RemoveChild()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::PtiChildFromName
//
// Routine Description:
// Find a child tree item from its name.
//
// Arguments:
// rstrName [IN] Name of the item.
// ppos [OUT] Position of the item in the list.
//
// Return Value:
// ptiChild Child item corresponding to the specified name.
//
//--
/////////////////////////////////////////////////////////////////////////////
CTreeItem * CTreeItem::PtiChildFromName(
IN const CString & rstrName,
OUT POSITION * ppos // = NULL
) const
{
POSITION posPtiChild;
POSITION posCurPtiChild;
CTreeItem * ptiChild = NULL;
// Loop through each child item to find the specified item.
posPtiChild = LptiChildren().GetHeadPosition();
while (posPtiChild != NULL)
{
posCurPtiChild = posPtiChild;
ptiChild = LptiChildren().GetNext(posPtiChild);
ASSERT_VALID(ptiChild);
if (ptiChild->StrName() == rstrName)
{
if (ppos != NULL)
*ppos = posCurPtiChild;
break;
} // if: found a match
} // while: more children of this tree item
return ptiChild;
} //*** CTreeItem::PtiChildFromName(CString&)
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::PtiChildFromName
//
// Routine Description:
// Find a child tree item from its name.
//
// Arguments:
// idsName [IN] ID of the name of the item.
// ppos [OUT] Position of the item in the list.
//
// Return Value:
// ptiChild Child item corresponding to the specified name.
//
//--
/////////////////////////////////////////////////////////////////////////////
CTreeItem * CTreeItem::PtiChildFromName(
IN IDS idsName,
OUT POSITION * ppos // = NULL
) const
{
CString strName;
VERIFY(strName.LoadString(idsName));
return PtiChildFromName(strName, ppos);
} //*** CTreeItem::PtiChildFromName(IDS)
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::PtiChildFromPci
//
// Routine Description:
// Find a child tree item from its cluster item.
//
// Arguments:
// pci [IN] Cluster item to search for.
//
// Return Value:
// ptiChild Child item corresponding to the specified cluster item.
//
//--
/////////////////////////////////////////////////////////////////////////////
CTreeItem * CTreeItem::PtiChildFromPci(IN const CClusterItem * pci) const
{
POSITION posPtiChild;
CTreeItem * ptiChild = NULL;
ASSERT_VALID(pci);
// Loop through each child item to find the specified item.
posPtiChild = LptiChildren().GetHeadPosition();
while (posPtiChild != NULL)
{
ptiChild = LptiChildren().GetNext(posPtiChild);
ASSERT_VALID(ptiChild);
if (ptiChild->Pci() == pci)
break;
} // while: more children of this tree item
return ptiChild;
} //*** CTreeItem::PtiChildFromPci()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::PliChildFromPci
//
// Routine Description:
// Find a child list item from its cluster item.
//
// Arguments:
// pci [IN] Cluster item to search for.
//
// Return Value:
// pliChild Child item corresponding to the specified cluster item.
//
//--
/////////////////////////////////////////////////////////////////////////////
CListItem * CTreeItem::PliChildFromPci(IN const CClusterItem * pci) const
{
POSITION posPliChild;
CListItem * pliChild = NULL;
// Loop through each child item to find the specified item.
posPliChild = LpliChildren().GetHeadPosition();
while (posPliChild != NULL)
{
pliChild = LpliChildren().GetNext(posPliChild);
ASSERT_VALID(pliChild);
if (pliChild->Pci() == pci)
break;
} // while: more children of this tree item
return pliChild;
} //*** CTreeItem::PliChildFromPci()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::HtiInsertInTree
//
// Routine Description:
// Insert the item in a tree under the specified parent.
//
// Arguments:
// pctv [IN OUT] Cluster tree view in which item is displayed.
//
// Return Value:
// m_hti Handle of the new item in the tree.
//
//--
/////////////////////////////////////////////////////////////////////////////
HTREEITEM CTreeItem::HtiInsertInTree(
IN OUT CClusterTreeView * pctv
)
{
CTreeItemContext * ptic;
HTREEITEM htiParent;
CSplitterFrame * pframe;
ASSERT_VALID(pctv);
ASSERT_VALID(Pci());
// Get the frame pointer.
pframe = (CSplitterFrame *) pctv->GetParent()->GetParent();
ASSERT_VALID(pframe);
// Get the tree item context for this item.
// If it doesn't exist yet, create one.
ptic = PticFromView(pctv);
if (ptic == NULL)
{
// Create the new tree item context.
ptic = new CTreeItemContext(pframe, this, NULL, FALSE /*bExpanded*/);
if (ptic == NULL)
{
ThrowStaticException(GetLastError());
} // if: error allcoating the tree item context
ASSERT_VALID(ptic);
ptic->Init();
m_lptic.AddTail(ptic);
} // if: no entry found
// Get our parent's handle.
if (PtiParent() != NULL)
{
CTreeItemContext * pticParent;
pticParent = PtiParent()->PticFromFrame(pframe);
ASSERT_VALID(pticParent);
htiParent = pticParent->m_hti;
} // if: parent specified
else
htiParent = NULL;
// Insert the item in the tree.
{
CTreeCtrl * ptc;
CString strName;
ASSERT_VALID(pframe->PviewTree());
Pci()->GetTreeName(strName);
ptc = &pframe->PviewTree()->GetTreeCtrl();
VERIFY((ptic->m_hti = ptc->InsertItem(strName, htiParent)) != NULL);
VERIFY(ptc->SetItemData(ptic->m_hti, (DWORD_PTR) this));
} // Insert the item in the tree
UpdateState();
return ptic->m_hti;
} //*** CTreeItem::HtiInsertInTree()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::RemoveFromAllLists
//
// Routine Description:
// Remove this item from all lists.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTreeItem::RemoveFromAllLists(void)
{
if (Pci() != NULL)
{
ASSERT_VALID(Pci());
// Loop through each view and remove the item from the list.
{
POSITION posPtic;
POSITION posPticPrev;
CTreeItemContext * ptic;
CTreeCtrl * ptc;
CClusterListView * pviewList;
posPtic = Lptic().GetHeadPosition();
while (posPtic != NULL)
{
// Get the next tree item context list entry.
posPticPrev = posPtic;
ptic = Lptic().GetNext(posPtic);
ASSERT_VALID(ptic);
// Get the tree control and list view from the frame.
ASSERT_VALID(ptic->m_pframe);
ptc = &ptic->m_pframe->PviewTree()->GetTreeCtrl();
pviewList = ptic->m_pframe->PviewList();
// If this tree item is the parent of the list control items,
// refresh the list control with no selection.
if (pviewList->PtiParent() == this)
pviewList->Refresh(NULL);
// Delete the item from the tree control and the list.
VERIFY(ptc->DeleteItem(ptic->m_hti));
m_lptic.RemoveAt(posPticPrev);
delete ptic;
} // while: more lists
} // Loop through each view and remove the item from the list
// Remove ourselves from the cluster item's list.
Pci()->RemoveTreeItem(this);
} // if: valid cluster item pointer
} //*** CTreeItem::RemoveFromAllLists()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::Select
//
// Routine Description:
// Select this item in the specified tree view. This causes the
// children of this item to be displayed in a list view.
//
// Arguments:
// pctv [IN OUT] Tree view in which item was selected.
// bSelectInTree [IN] TRUE = select in tree control also.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTreeItem::Select(IN OUT CClusterTreeView * pctv, IN BOOL bSelectInTree)
{
CTreeItemContext * ptic;
ASSERT_VALID(pctv);
// Get the tree item context.
ptic = PticFromView(pctv);
ASSERT_VALID(ptic);
Trace(g_tagTreeItemSelect, _T("'%s' selected"), Pci()->StrName());
// Select the item in the tree control.
if (bSelectInTree)
ptic->m_pframe->PviewTree()->GetTreeCtrl().Select(ptic->m_hti, TVGN_CARET);
// Refresh the list control.
ASSERT_VALID(ptic->m_pframe);
ASSERT_VALID(ptic->m_pframe->PviewList());
ptic->m_pframe->PviewList()->Refresh(this);
} //*** CTreeItem::Select()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::PreRemoveFromFrameWithChildren
//
// Routine Description:
// Cleanup an item and all its children.
//
// Arguments:
// pframe [IN OUT] Frame window item is being removed from.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTreeItem::PreRemoveFromFrameWithChildren(IN OUT CSplitterFrame * pframe)
{
POSITION posChild;
CTreeItem * ptiChild;
ASSERT_VALID(this);
// Cleanup all child items.
posChild = LptiChildren().GetHeadPosition();
while (posChild != NULL)
{
ptiChild = LptiChildren().GetNext(posChild);
ASSERT_VALID(ptiChild);
ptiChild->PreRemoveFromFrameWithChildren(pframe);
} // while: more items in the list
// Cleanup this item.
PreRemoveFromFrame(pframe);
} //*** CTreeItem::PreRemoveFromFrameWithChildren()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::PreRemoveFromFrame
//
// Routine Description:
// Prepare to remove the item from a tree.
//
// Arguments:
// pframe [IN OUT] Frame window item is being removed from.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTreeItem::PreRemoveFromFrame(IN OUT CSplitterFrame * pframe)
{
CTreeItemContext * ptic;
POSITION posPtic;
ASSERT_VALID(pframe);
// Find the view in our list.
ptic = PticFromFrame(pframe);
if (ptic == NULL)
return;
ASSERT_VALID(ptic);
VERIFY((posPtic = Lptic().Find(ptic)) != NULL);
// Remove the view from the list.
m_lptic.RemoveAt(posPtic);
// Delete the context item.
delete ptic;
} //*** CTreeItem::PreRemoveFromFrame(pframe)
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::PticFromFrame
//
// Routine Description:
// Find a tree item context from a frame.
//
// Arguments:
// pframe [IN] Frame to search on.
//
// Return Value:
// ptic Found context, or NULL if not found.
//
//--
/////////////////////////////////////////////////////////////////////////////
CTreeItemContext * CTreeItem::PticFromFrame(IN const CSplitterFrame * pframe) const
{
POSITION posPtic;
CTreeItemContext * ptic;
ASSERT_VALID(pframe);
posPtic = Lptic().GetHeadPosition();
while (posPtic != NULL)
{
ptic = Lptic().GetNext(posPtic);
ASSERT_VALID(ptic);
if (ptic->m_pframe == pframe)
return ptic;
} // while: more items in the list
return NULL;
} //*** CTreeItem::PticFromFrame()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::PticFromView
//
// Routine Description:
// Find a tree item context from a tree view.
//
// Arguments:
// pctv [IN] Tree view to search on.
//
// Return Value:
// ptic Found context, or NULL if not found.
//
//--
/////////////////////////////////////////////////////////////////////////////
CTreeItemContext * CTreeItem::PticFromView(IN const CClusterTreeView * pctv) const
{
POSITION posPtic;
CTreeItemContext * ptic;
ASSERT_VALID(pctv);
posPtic = Lptic().GetHeadPosition();
while (posPtic != NULL)
{
ptic = Lptic().GetNext(posPtic);
ASSERT_VALID(ptic);
ASSERT_VALID(ptic->m_pframe);
if (ptic->m_pframe->PviewTree() == pctv)
return ptic;
} // while: more items in the list
return NULL;
} //*** CTreeItem::PticFromView(CClusterTreeView*)
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::PticFromView
//
// Routine Description:
// Find a tree item context from a list view.
//
// Arguments:
// pclv [IN] List view to search on.
//
// Return Value:
// ptic Found context, or NULL if not found.
//
//--
/////////////////////////////////////////////////////////////////////////////
CTreeItemContext * CTreeItem::PticFromView(IN const CClusterListView * pclv) const
{
POSITION posPtic;
CTreeItemContext * ptic;
ASSERT_VALID(pclv);
posPtic = Lptic().GetHeadPosition();
while (posPtic != NULL)
{
ptic = Lptic().GetNext(posPtic);
ASSERT_VALID(ptic);
ASSERT_VALID(ptic->m_pframe);
if (ptic->m_pframe->PviewList() == pclv)
return ptic;
} // while: more items in the list
return NULL;
} //*** CTreeItem::PticFromView(CClusterListView*)
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::HtiFromView
//
// Routine Description:
// Find a tree item handle from a view.
//
// Arguments:
// pctv [IN] View to search on.
//
// Return Value:
// hti Found tree item handle, or NULL if not found.
//
//--
/////////////////////////////////////////////////////////////////////////////
HTREEITEM CTreeItem::HtiFromView(IN const CClusterTreeView * pctv) const
{
CTreeItemContext * ptic;
HTREEITEM hti = NULL;
ASSERT_VALID(pctv);
ptic = PticFromView(pctv);
if (ptic != NULL)
hti = ptic->m_hti;
return hti;
} //*** CTreeItem::HtiFromView()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::PcoliAddColumn
//
// Routine Description:
// Add a column to the list of column header items.
//
// Arguments:
// rstrText [IN] Reference to the text of the column.
// idsColumnID [IN] ID of the column to identify the data.
// nDefaultWidth [IN] Default width of the column.
// nWidth [IN] Actual width of the column.
//
// Return Value:
// pcoli Column item added to the list.
//
//--
/////////////////////////////////////////////////////////////////////////////
CColumnItem * CTreeItem::PcoliAddColumn(
IN const CString & rstrText,
IN IDS idsColumnID,
IN int nDefaultWidth,
IN int nWidth
)
{
CColumnItem * pcoli;
pcoli = new CColumnItem(rstrText, idsColumnID, nDefaultWidth, nWidth);
if (pcoli == NULL)
{
ThrowStaticException(GetLastError());
} // if: error allocating the column item
m_lpcoli.AddTail(pcoli);
return pcoli;
} //*** CTreeItem::PcoliAddColumn(CString&)
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::PcoliAddColumn
//
// Routine Description:
// Add a column to the list of column header items.
//
// Arguments:
// idsText [IN] String resource ID for the text of the column.
// Also used as the column ID.
// nDefaultWidth [IN] Default width of the column.
// nWidth [IN] Actual width of the column.
//
// Return Value:
// pcoli Column item added to the list.
//
//--
/////////////////////////////////////////////////////////////////////////////
CColumnItem * CTreeItem::PcoliAddColumn(IN IDS idsText, IN int nDefaultWidth, IN int nWidth)
{
CString strText;
strText.LoadString(idsText);
return PcoliAddColumn(strText, idsText, nDefaultWidth, nWidth);
} //*** CTreeItem::PcoliAddColumn(IDS)
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::BSelectItem
//
// Routine Description:
// Select the item in the specified tree control.
//
// Arguments:
// pctv [IN OUT] Cluster tree view in which to select the item.
//
// Return Value:
// TRUE Item was selected successfully.
// FALSE Item not selected.
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL CTreeItem::BSelectItem(IN OUT CClusterTreeView * pctv)
{
HTREEITEM hti;
ASSERT_VALID(pctv);
VERIFY((hti = HtiFromView(pctv)) != NULL);
return (pctv->GetTreeCtrl().SelectItem(hti) != 0);
} //*** CTreeItem::BSelectItem()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::SelectInAllViews
//
// Routine Description:
// Select this item in all views in which it is being displayed. This
// causes the children of this item to be displayed in a list view.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTreeItem::SelectInAllViews(void)
{
POSITION posPtic;
CTreeItemContext * ptic;
posPtic = Lptic().GetHeadPosition();
while (posPtic != NULL)
{
// Get the next tree item context list entry.
ptic = Lptic().GetNext(posPtic);
ASSERT_VALID(ptic);
// Select the item in this list.
ASSERT_VALID(ptic->m_pframe);
BSelectItem(ptic->m_pframe->PviewTree());
ptic->m_pframe->PviewTree()->SetFocus();
} // while: more items in the list
} //*** CTreeItem::SelectInAllViews()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::BExpand
//
// Routine Description:
// Expand the item in the specified tree control.
//
// Arguments:
// pctv [IN OUT] Cluster tree view in which to expand the item.
// nCode [IN] Flag indicating the type of action to be taken.
//
// Return Value:
// TRUE Item was expanded successfully.
// FALSE Item not expanded.
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL CTreeItem::BExpand(IN OUT CClusterTreeView * pctv, IN UINT nCode)
{
CTreeItemContext * ptic;
ASSERT_VALID(pctv);
ASSERT(nCode != 0);
ptic = PticFromView(pctv);
ASSERT_VALID(ptic);
if (nCode == TVE_EXPAND)
ptic->m_bExpanded = TRUE;
else
ptic->m_bExpanded = FALSE;
return (pctv->GetTreeCtrl().Expand(ptic->m_hti, nCode) != 0);
} //*** CTreeItem::BExpand()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::ExpandInAllViews
//
// Routine Description:
// Expand the item in all views in which it is displayed.
//
// Arguments:
// nCode [IN] Flag indicating the type of action to be taken.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTreeItem::ExpandInAllViews(IN UINT nCode)
{
POSITION posPtic;
CTreeItemContext * ptic;
ASSERT(nCode != 0);
posPtic = Lptic().GetHeadPosition();
while (posPtic != NULL)
{
// Get the next tree item context list entry.
ptic = Lptic().GetNext(posPtic);
ASSERT_VALID(ptic);
// Select the item in this list.
ASSERT_VALID(ptic->m_pframe);
BExpand(ptic->m_pframe->PviewTree(), nCode);
} // while: more items in the list
} //*** CTreeItem::ExpandInAllViews()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::SetExpandedState
//
// Routine Description:
// Save the expanded state of the item in the specified view.
//
// Arguments:
// pctv [IN] Tree view in which expanded state is being saved.
// bExpanded [IN] TRUE = item is expanded in the specified view.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTreeItem::SetExpandedState(
IN const CClusterTreeView * pctv,
IN BOOL bExpanded
)
{
CTreeItemContext * ptic;
ASSERT_VALID(pctv);
ptic = PticFromView(pctv);
ASSERT_VALID(ptic);
ptic->m_bExpanded = bExpanded;
} //*** CTreeItem::SetExpandedState()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::BShouldBeExpanded
//
// Routine Description:
// Returns whether the item should be expanded in the specified tree
// view based on the user's profile.
//
// Arguments:
// pctv [IN] Tree view in which expanded state is being saved.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL CTreeItem::BShouldBeExpanded(IN const CClusterTreeView * pctv) const
{
CTreeItemContext * ptic;
ASSERT_VALID(pctv);
ptic = PticFromView(pctv);
ASSERT_VALID(ptic);
return ptic->m_bExpanded;
} //*** CTreeItem::BShouldBeExpanded()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::UpdateState
//
// Routine Description:
// Update the current state of the item.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTreeItem::UpdateState(void)
{
ASSERT_VALID(this);
ASSERT_VALID(Pci());
// Ask the item to update its state.
if (Pci() != NULL)
Pci()->UpdateState();
} //*** CTreeItem::UpdateState()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::UpdateAllStatesInTree
//
// Routine Description:
// Update the current state of the item.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTreeItem::UpdateAllStatesInTree(void)
{
POSITION posPti;
CTreeItem * ptiChild;
UpdateState();
posPti = LptiChildren().GetHeadPosition();
while (posPti != NULL)
{
ptiChild = LptiChildren().GetNext(posPti);
ASSERT_VALID(ptiChild);
ptiChild->UpdateAllStatesInTree();
} // while: more children
} //*** CTreeItem::UpdateAllStatesInTree()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::UpdateUIState
//
// Routine Description:
// Update the current UI state of the item.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTreeItem::UpdateUIState(void)
{
POSITION posPtic;
CTreeItemContext * ptic;
UINT nMask;
UINT nImage;
#ifdef _DISPLAY_STATE_TEXT_IN_TREE
CString strText;
#endif
ASSERT_VALID(Pci());
// Loop through the views and update the state on each one.
posPtic = Lptic().GetHeadPosition();
while (posPtic != NULL)
{
ptic = Lptic().GetNext(posPtic);
ASSERT_VALID(ptic);
// Set the images that are displayed for the item.
ASSERT_VALID(ptic->m_pframe);
ASSERT_VALID(ptic->m_pframe->PviewTree());
nMask = TVIF_TEXT;
if (Pci() == NULL)
{
#ifdef _DISPLAY_STATE_TEXT_IN_TREE
strText = StrName();
#endif
nImage = 0;
} // if: invalid cluster item
else
{
nMask |= TVIF_IMAGE | TVIF_SELECTEDIMAGE;
#ifdef _DISPLAY_STATE_TEXT_IN_TREE
Pci()->GetTreeName(strText);
#endif
nImage = Pci()->IimgState();
} // else: valid cluster item
#ifdef _DISPLAY_STATE_TEXT_IN_TREE
Trace(g_tagTreeItemUpdate, _T("Updating item '%s' (pci name = '%s')"), strText, Pci()->StrName());
#else
Trace(g_tagTreeItemUpdate, _T("Updating item '%s' (pci name = '%s')"), StrName(), Pci()->StrName());
#endif
ptic->m_pframe->PviewTree()->GetTreeCtrl().SetItem(
ptic->m_hti, // hItem
nMask, // nMask
#ifdef _DISPLAY_STATE_TEXT_IN_TREE
strText, // lpszItem
#else
StrName(), // lpszItem
#endif
nImage, // nImage
nImage, // nSelectedImage
0, // nState
0, // nStatemask
NULL // lParam
);
} // while: more view
} //*** CTreeItem::UpdateUIState()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::OnCmdMsg
//
// Routine Description:
// Processes command messages. Attempts to pass them on to a selected
// item first.
//
// Arguments:
// nID [IN] Command ID.
// nCode [IN] Notification code.
// pExtra [IN OUT] Used according to the value of nCode.
// pHandlerInfo [OUT] ???
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL CTreeItem::OnCmdMsg(
UINT nID,
int nCode,
void * pExtra,
AFX_CMDHANDLERINFO * pHandlerInfo
)
{
if (Pci() != NULL)
{
// Give the cluster item a chance to handle the message.
if (Pci()->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
return TRUE;
} // if: valid cluster item
return CBaseCmdTarget::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
} //*** CTreeItem::OnCmdMsg()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::OpenChild
//
// Routine Description:
// Open the specified child item.
//
// Arguments:
// pti [IN OUT] Child tree item to open.
// pframe [IN OUT] Frame in which to open the item.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTreeItem::OpenChild(
IN OUT CTreeItem * pti,
IN OUT CSplitterFrame * pframe
)
{
CTreeItemContext * ptic;
ASSERT_VALID(pti);
ASSERT_VALID(pframe);
// Find the tree item context for the frame.
ptic = PticFromFrame(pframe);
ASSERT_VALID(ptic);
// Expand the parent item and then select the child item.
if (pframe->PviewTree()->GetTreeCtrl().Expand(ptic->m_hti, TVE_EXPAND))
pti->Select(pframe->PviewTree(), TRUE /*bSelectInTree*/);
} //*** CTreeItem::OpenChild()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItem::EditLabel
//
// Routine Description:
// Processes the ID_FILE_RENAME menu command.
//
// Arguments:
// pctv [IN OUT] Cluster tree view item is being edited in.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTreeItem::EditLabel(IN OUT CClusterTreeView * pctv)
{
HTREEITEM hti;
ASSERT_VALID(pctv);
ASSERT_VALID(Pci());
ASSERT(Pci()->BCanBeEdited());
hti = HtiFromView(pctv);
ASSERT(hti != NULL);
pctv->GetTreeCtrl().EditLabel(hti);
} //*** CTreeItem::EditLabel()
//***************************************************************************
/////////////////////////////////////////////////////////////////////////////
// CTreeItemContext
/////////////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNCREATE(CTreeItemContext, CObject)
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItemContext::Init
//
// Routine Description:
// Initialize the tree item context.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTreeItemContext::Init(void)
{
BOOL bExpanded;
UINT cbColumnInfo;
CString strValueName;
ASSERT_VALID(m_pti);
ASSERT(m_pti->StrProfileSection().GetLength() > 0);
ASSERT(m_prgnColumnInfo == NULL);
try
{
// Read the expanded state.
m_pframe->ConstructProfileValueName(strValueName, REGPARAM_EXPANDED);
bExpanded = AfxGetApp()->GetProfileInt(
m_pti->StrProfileSection(),
strValueName,
m_bExpanded
);
if (bExpanded)
m_bExpanded = bExpanded;
// Read the column information.
m_pframe->ConstructProfileValueName(strValueName, REGPARAM_COLUMNS);
AfxGetApp()->GetProfileBinary(
m_pti->StrProfileSection(),
strValueName,
(BYTE **) &m_prgnColumnInfo,
&cbColumnInfo
);
} // try
catch (CException * pe)
{
pe->Delete();
} // catch: CException
} //*** CTreeItemContext::Init()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItemContext::SaveProfileInfo
//
// Routine Description:
// Save state information to the user's profile. This includes column
// widths and positions as well as whether the tree item was expanded
// or not.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CTreeItemContext::SaveProfileInfo(void)
{
CString strValueName;
try
{
ASSERT_VALID(m_pti);
ASSERT(m_pti->StrProfileSection().GetLength() > 0);
// Save expansion info to the user's profile.
m_pframe->ConstructProfileValueName(strValueName, REGPARAM_EXPANDED);
AfxGetApp()->WriteProfileInt(
m_pti->StrProfileSection(),
strValueName,
m_bExpanded
);
if (m_prgnColumnInfo != NULL)
{
// Save column info to the user's profile.
m_pframe->ConstructProfileValueName(strValueName, REGPARAM_COLUMNS);
AfxGetApp()->WriteProfileBinary(
m_pti->StrProfileSection(),
strValueName,
(PBYTE) m_prgnColumnInfo,
((m_prgnColumnInfo[0] * 2) + 1) * sizeof(DWORD)
);
} // if: there is column info
} // try
catch (CException * pe)
{
pe->Delete();
} // catch: CException
} //*** CTreeItemContext::SaveProfileInfo()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItemContext::PrgnColumnInfo
//
// Routine Description:
// Return the column info. If it doesn't exist or isn't the right
// size, allocate one.
//
// Arguments:
// None.
//
// Return Value:
// prgnColumnInfo The column info array.
//
//--
/////////////////////////////////////////////////////////////////////////////
DWORD * CTreeItemContext::PrgnColumnInfo(void)
{
DWORD cColumns;
ASSERT_VALID(m_pti);
cColumns = (DWORD)m_pti->Lpcoli().GetCount();
if ((m_prgnColumnInfo == NULL)
|| (cColumns != m_prgnColumnInfo[0]))
{
DWORD cnColumnInfo = (cColumns * 2) + 1;
delete [] m_prgnColumnInfo;
m_prgnColumnInfo = new DWORD[cnColumnInfo];
if (m_prgnColumnInfo == NULL)
{
ThrowStaticException(GetLastError());
} // if: error allocating column info array
//
// Initialize the column info array
//
{
DWORD inColumnInfo;
// The first entry is the number of columns.
m_prgnColumnInfo[0] = cColumns;
// The second set of entries is the width of each column.
{
POSITION pos;
CColumnItem * pcoli;
inColumnInfo = 1;
pos = m_pti->Lpcoli().GetHeadPosition();
while (pos != NULL)
{
pcoli = m_pti->Lpcoli().GetNext(pos);
ASSERT_VALID(pcoli);
ASSERT(inColumnInfo <= cColumns);
m_prgnColumnInfo[inColumnInfo++] = pcoli->NWidth();
} // while: more items in the list
} // The second set of entries is the width of each column
// The third set of entries is the order of the columns.
{
DWORD * prgnColumnInfo = &m_prgnColumnInfo[inColumnInfo];
for (inColumnInfo = 0 ; inColumnInfo < cColumns ; inColumnInfo++)
prgnColumnInfo[inColumnInfo] = inColumnInfo;
} // The third set of entries is the order of the columns
} // Initialize the column info array
} // if: column info array doesn't exist or is wrong size
return m_prgnColumnInfo;
} //*** CTreeItemContext::PrgnColumnInfo()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CTreeItemContext::BIsExpanded
//
// Routine Description:
// Return the EXPANDED state of the item in this tree view.
//
// Arguments:
// None.
//
// Return Value:
// TRUE Item is expanded.
// FALSE Item is not expanded.
//
//--
/////////////////////////////////////////////////////////////////////////////
BOOL CTreeItemContext::BIsExpanded(void) const
{
ASSERT_VALID(this);
ASSERT_VALID(m_pframe);
ASSERT_VALID(m_pframe->PviewTree());
ASSERT(m_hti != NULL);
return (m_pframe->PviewTree()->GetTreeCtrl().GetItemState(m_hti, TVIS_EXPANDED) == TVIS_EXPANDED);
} //*** CTreeItemContext::BIsExpanded()
//***************************************************************************
/////////////////////////////////////////////////////////////////////////////
// Global Functions
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//++
//
// DestructElements
//
// Routine Description:
// Destroys CTreeItem* elements.
//
// Arguments:
// pElements Array of pointers to elements to destruct.
// nCount Number of elements to destruct.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
template<>
void AFXAPI DestructElements(CTreeItem ** pElements, INT_PTR nCount)
{
ASSERT(nCount == 0 ||
AfxIsValidAddress(pElements, nCount * sizeof(CTreeItem *)));
// call the destructor(s)
for (; nCount--; pElements++)
{
ASSERT_VALID(*pElements);
(*pElements)->Release();
} // for: each item in the array
} //*** DestructElements(CTreeItem**)
/////////////////////////////////////////////////////////////////////////////
//++
//
// DeleteAllItemData
//
// Routine Description:
// Deletes all item data in a CList.
//
// Arguments:
// rlp [IN OUT] Reference to the list whose data is to be deleted.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void DeleteAllItemData(IN OUT CTreeItemList & rlp)
{
POSITION pos;
CTreeItem * pti;
// Delete all the items in the Contained list.
pos = rlp.GetHeadPosition();
while (pos != NULL)
{
pti = rlp.GetNext(pos);
ASSERT_VALID(pti);
// Trace(g_tagTreeItemDelete, _T("DeleteAllItemData(rlpti) - Deleting tree item '%s'"), pti->Pci()->StrName());
pti->Delete();
} // while: more items in the list
} //*** DeleteAllItemData()
/////////////////////////////////////////////////////////////////////////////
//++
//
// DeleteAllItemData
//
// Routine Description:
// Deletes all item data in a CList.
//
// Arguments:
// rlp [IN OUT] Reference to the list whose data is to be deleted.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void DeleteAllItemData(IN OUT CTreeItemContextList & rlp)
{
POSITION pos;
CTreeItemContext * ptic;
// Delete all the items in the Contained list.
pos = rlp.GetHeadPosition();
while (pos != NULL)
{
ptic = rlp.GetNext(pos);
ASSERT_VALID(ptic);
delete ptic;
} // while: more items in the list
} //*** DeleteAllItemData()