📄 tree_util.cpp
字号:
//----------------------------------------------------------------------------
//
// tree_util.cpp
// Chapter 30 - How To - Tree View Component Example
//
// Paul Gustavson
// pgustavson@simventions.com
//
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "tree_util.h"
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <olectl.h> // for the CoCreateGuid call
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void __fastcall MoveUpTree(TTreeNode *item)
{
if (item == NULL)
{
MessageBeep(MB_OK);
return;
}
TNodeAttachMode AttachMode = naInsert;
TTreeNode *ppItem = item->getPrevSibling();
int level = item->Level;
if (ppItem == NULL)
{
MessageBeep(MB_OK);
return;
}
if (ppItem->Level != level)
{
MessageBeep(MB_OK);
return;
}
item->MoveTo(ppItem, AttachMode);
}
//---------------------------------------------------------------------------
int __fastcall FindTreeNodeBasedOnLabel(TTreeNodes *Tree,AnsiString SearchString)
{
TTreeNode *CurItem = Tree->GetFirstNode();
if (CurItem) do
{
AnsiString title = CurItem->Text;
StripParenCount(title);
if (AnsiCompareStr(title,SearchString) == 0)
return CurItem->AbsoluteIndex;
CurItem = CurItem->GetNext();
} while (CurItem);
return -1; // couldn't find it..
}
//---------------------------------------------------------------------------
int __fastcall FindTreeNodeBasedOnID(TTreeNodes *Tree,unsigned int ID)
{
TTreeNode *CurItem = Tree->GetFirstNode();
int count =0;
if (CurItem) do
{
if (CurItem->Data)
{
if (PInfo(CurItem->Data)->ID == ID)
{
return CurItem->AbsoluteIndex;
}
count++;
}
CurItem = CurItem->GetNext();
} while (CurItem);
return -1; // couldn't find it..
}
//---------------------------------------------------------------------------
void __fastcall AddCountToNode(TTreeNodes* tree)
{
tree->BeginUpdate();
TTreeNode *CurItem = tree->GetFirstNode();
while (CurItem) //walk down all the nodes of the tree
{
CurItem->Count;
AnsiString NewName = CurItem->Text;
StripParenCount(NewName);
if (CurItem->Count > 0)
CurItem->Text = NewName + " (" + CurItem->Count + ")";
else
CurItem->Text = NewName;
CurItem = CurItem->GetNext();
}
tree->EndUpdate();
}
//---------------------------------------------------------------------------
bool __fastcall StripParenCount(AnsiString &text)
{
AnsiString NewName;
bool result = true;
int location = text.AnsiPos(" (");
if (location > 0)
{
NewName = text.SubString(1,(location-1));
result = true;
}
else // nothing to strip
{
result = false;
return result;
}
text = NewName;
return result;
}
//---------------------------------------------------------------------------
TInfo::TInfo() // constructor
{
type = 0;
ID = 0;
deleted = false;
Name = "";
}
//---------------------------------------------------------------------------
TPersonalInfo::TPersonalInfo() // constructor
{
FirstName = "";
LastName = "";
DOB = ""; // Date of birth
DOD = ""; // Date of death
BirthPlace = "";
Epitath = "";
Residence = "";
Gender = true; // true = male, false = female
Occupation = "";
Notes = "";
Mother = NULL;
Father = NULL;
}
//---------------------------------------------------------------------------
void TPersonalInfo::DetermineParent(TPersonalInfo* parent)
{
if (!parent)
return;
LastName = parent->LastName;
if (parent->Gender) // parent is male, than fill in father info
Father = parent;
else
Mother = parent;
}
//---------------------------------------------------------------------------
bool __fastcall AddToUndoRedoList(TTreeNodes * Tree, unsigned int ID, TInfo *info, int imageindex, bool deletedflag)
{
// look for items that already have the ID we're going to insert and delete it...
int index = 0;
do
{
index = FindTreeNodeBasedOnID(Tree,ID);
if (index != -1) Tree->Item[index]->Delete();
} while (index > -1);
// okay, now we can add it.
TTreeNode *node = Tree->AddObjectFirst(NULL,info->Name,info);
node->StateIndex = imageindex;
node->ImageIndex = imageindex;
info->deleted = deletedflag;
return (bool)Tree->Count;
}
//---------------------------------------------------------------------------
unsigned int __fastcall GetNewID()
{
GUID guid;
::CoCreateGuid(&guid);
return guid.Data1;
}
//---------------------------------------------------------------------------
void __fastcall ClearAll(TTreeNodes* tree)
{
TTreeNode *CurItem = tree->GetFirstNode();
TInfo *info;
while (CurItem) //walk down all the nodes of the tree and delete data
{
if (CurItem->Data)
{
info = (TInfo*)( CurItem->Data);
delete info;
}
CurItem = CurItem->GetNext();
}
// now that all the data is deleted, the tree can be delete
tree->Clear();
}
//---------------------------------------------------------------------------
void __fastcall ClearDeletedItems(TTreeNodes* tree) // makes soft deletes hard deletes
{
tree->BeginUpdate(); // prevent screen update of tree view
TTreeNode *CurItem = tree->GetFirstNode();
TTreeNode *NextItem;
TInfo *info;
while (CurItem) //walk down all the nodes of the tree and delete appropriate nodes
{
NextItem = CurItem->GetNext(); // keep track of potential next node
if (CurItem->Data)
{
info = (TInfo*)(CurItem->Data);
if (info->deleted)
NextItem = DeleteNode(CurItem,false,false,NULL); // hard delete, no message, no undo list
}
CurItem = NextItem;
}
tree->EndUpdate(); // enabled screen update
}
//---------------------------------------------------------------------------
TTreeNode* __fastcall DeleteNode(TTreeNode *node, bool displaymessage, bool soft, TTreeNodes * undolist)
{
// recursive function
if (!node) return NULL; // no tree node.. get out
TTreeNode *tempnode = NULL;
// take care of children first
int count = node->Count;
while (count > 0) // can't use HasChildren property for soft deletes
{
int response = IDYES;
if (displaymessage)
{
// notify user of branch deletion
response =
Application->MessageBox("Are you sure you wish to delete branch?",
"Node Has Children", MB_YESNO);
}
if (response == IDNO)
{
MessageBeep(MB_OK);
return NULL;
}
else
{
displaymessage = false;
tempnode = node->GetPrevChild(tempnode);
if (tempnode == NULL)
tempnode = node->GetLastChild();
if (tempnode)
DeleteNode(tempnode,false,soft,NULL); // call itself with next child,
//messages are no longer displayed (false), no need for undo list (NULL)
if (!soft)
tempnode = NULL;
}
count--; // decrment children count
}
if (soft) // soft delete (undo support)
{
TInfo * info;
if (node->Data)
info = (TInfo*)(node->Data);
else
{ // better add data in case the user hits undo
// Here's where we add the information to the tree
info = new TPersonalInfo;
info->ID = GetNewID(); // get a unique id
info->Name = node->Text;
node->Data = (void*)info; // now add it as an object to the node
}
info->deleted = true; // mark it for deletion
if (undolist)
AddToUndoRedoList(undolist,info->ID, info, node->ImageIndex,true);
node->OverlayIndex = 0;
return node->GetNext(); // return the next node
}
else // hard delete (no undo support)
{
TTreeNode* nextnode = node->GetNext(); // get the next node before we delete it
if (node->Data)
{
TInfo * info = (TInfo*)(node->Data);
delete info; // delete data
}
node->Delete(); // delete node
return nextnode;
}
}
//---------------------------------------------------------------------------
void __fastcall UndeleteNode(TTreeNode *node) // this is recursive too
{
if (!node) return;
TTreeNode* tempnode = NULL;
int count = node->Count; // check the children
while (count > 0)
{
tempnode = node->GetNextChild(tempnode);
if (tempnode == NULL)
tempnode = node->getFirstChild();
if (tempnode)
UndeleteNode(tempnode);
count--;
}
node->OverlayIndex = -1;
}
//---------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -