767 lines
18 KiB
Plaintext
767 lines
18 KiB
Plaintext
{*******************************************************}
|
|
{ }
|
|
{ Tocsg.VTUtil }
|
|
{ }
|
|
{ Copyright (C) 2022 kku }
|
|
{ }
|
|
{*******************************************************}
|
|
|
|
unit Tocsg.VTUtil;
|
|
|
|
interface
|
|
|
|
uses
|
|
WinAPi.Windows, VirtualTrees, VirtualTrees.Types, System.Classes, System.SysUtils;
|
|
|
|
type
|
|
TTgVirtualStringTreeHelper = class helper for TBaseVirtualTree
|
|
public
|
|
procedure SortEx(pBeginNode: PVirtualNode; nColumn: TColumnIndex; Direction: TSortDirection; nSortCount: Integer = -1);
|
|
end;
|
|
|
|
function VT_CountTotalNode(vt: TVirtualStringTree): DWORD;
|
|
function VT_CountVisibleNode(vt: TVirtualStringTree): DWORD;
|
|
function VT_CountVisibleChildNode(pNode: PVirtualNode): DWORD;
|
|
function VT_CountVisibleCheckedNode(vt: TVirtualStringTree): DWORD;
|
|
procedure VT_ReverseSelected(vt: TVirtualStringTree);
|
|
procedure VT_CheckAll(var vt: TVirtualStringTree);
|
|
procedure VT_UnCheckAll(var vt: TVirtualStringTree);
|
|
procedure VT_ForceCheckNode(pNode: PVirtualNode);
|
|
procedure VT_ForceUnCheckNode(pNode: PVirtualNode);
|
|
procedure VT_ReverseCheckAll(vt: TVirtualStringTree);
|
|
procedure VT_SetEnalbedNode(vt: TVirtualStringTree; pNode: PVirtualNode; bVal: Boolean);
|
|
function VT_HasDisableNode(vt: TVirtualStringTree; pNode: PVirtualNode): Boolean;
|
|
procedure VT_ExpandAll(vt: TVirtualStringTree; bFlag: Boolean);
|
|
procedure VT_ExpandNodeAll(vt: TVirtualStringTree; pNode: PVirtualNode; bFlag: Boolean);
|
|
function VT_CopyToClipboardSelectedInfo(vt: TVirtualStringTree; nStartColumnIdx: Integer = 1): Integer;
|
|
|
|
function VT_AddChild(vt: TVirtualStringTree; pParent: PVirtualNode = nil): PVirtualNode; inline;
|
|
function VT_AddChildDataN(vt: TVirtualStringTree; out pAddNode: PVirtualNode; pParent: PVirtualNode = nil): Pointer; overload; inline;
|
|
function VT_AddChildData(vt: TVirtualStringTree; pParent: PVirtualNode = nil): Pointer; inline; overload;
|
|
|
|
function VT_HasChildNode(vt: TVirtualStringTree; pParent, pFindNode: PVirtualNode): Boolean;
|
|
|
|
function VT_Get1SelNodeData(vt: TVirtualStringTree): Pointer;
|
|
procedure VT_SortAll(vt: TVirtualStringTree; nColumn: Integer; aDirection: TSortDirection);
|
|
procedure VT_SortNodeChilds(vt: TVirtualStringTree; pNode: PVirtualNode; nColumn: Integer; aDirection: TSortDirection);
|
|
function VT_FindNodeFromPath(vt: TVirtualStringTree; sPath: String; sDelimiter: String = '\'; nColumn: Integer = 0): PVirtualNode;
|
|
procedure VT_SetCheckTypeAllNode(vt: TVirtualStringTree; aCheckType: TCheckType);
|
|
procedure VT_SetFocuceNode(vt: TVirtualStringTree; pNode: PVirtualNode);
|
|
procedure VT_Clear(aVT: TVirtualStringTree);
|
|
|
|
implementation
|
|
|
|
uses
|
|
Vcl.Clipbrd, Tocsg.Safe, Tocsg.Strings;
|
|
|
|
// pBeginNode 부터 nSortCount 수만큼 정렬을 시도한다.
|
|
// 기본 골격은 TBaseVirtualTree >> procedure Sort(Node: PVirtualNode; Column: TColumnIndex; Direction: TSortDirection; DoInit: Boolean = True); virtual;
|
|
procedure TTgVirtualStringTreeHelper.SortEx(pBeginNode: PVirtualNode; nColumn: TColumnIndex; Direction: TSortDirection; nSortCount: Integer = -1);
|
|
|
|
function MergeAscending(A, B: PVirtualNode): PVirtualNode;
|
|
var
|
|
Dummy: TVirtualNode;
|
|
CompareResult: Integer;
|
|
begin
|
|
// This avoids checking for Result = nil in the loops.
|
|
Result := @Dummy;
|
|
while Assigned(A) and Assigned(B) do
|
|
begin
|
|
if OperationCanceled then
|
|
CompareResult := 0
|
|
else
|
|
CompareResult := DoCompare(A, B, nColumn);
|
|
|
|
if CompareResult <= 0 then
|
|
begin
|
|
Result.NextSibling := A;
|
|
Result := A;
|
|
A := A.NextSibling;
|
|
end
|
|
else
|
|
begin
|
|
Result.NextSibling := B;
|
|
Result := B;
|
|
B := B.NextSibling;
|
|
end;
|
|
end;
|
|
|
|
// Just append the list which is not nil (or set end of result list to nil if both lists are nil).
|
|
if Assigned(A) then
|
|
Result.NextSibling := A
|
|
else
|
|
Result.NextSibling := B;
|
|
// return start of the new merged list
|
|
Result := Dummy.NextSibling;
|
|
end;
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
function MergeDescending(A, B: PVirtualNode): PVirtualNode;
|
|
var
|
|
Dummy: TVirtualNode;
|
|
CompareResult: Integer;
|
|
|
|
begin
|
|
// this avoids checking for Result = nil in the loops
|
|
Result := @Dummy;
|
|
while Assigned(A) and Assigned(B) do
|
|
begin
|
|
if OperationCanceled then
|
|
CompareResult := 0
|
|
else
|
|
CompareResult := DoCompare(A, B, nColumn);
|
|
|
|
if CompareResult >= 0 then
|
|
begin
|
|
Result.NextSibling := A;
|
|
Result := A;
|
|
A := A.NextSibling;
|
|
end
|
|
else
|
|
begin
|
|
Result.NextSibling := B;
|
|
Result := B;
|
|
B := B.NextSibling;
|
|
end;
|
|
end;
|
|
|
|
// Just append the list which is not nil (or set end of result list to nil if both lists are nil).
|
|
if Assigned(A) then
|
|
Result.NextSibling := A
|
|
else
|
|
Result.NextSibling := B;
|
|
// Return start of the newly merged list.
|
|
Result := Dummy.NextSibling;
|
|
end;
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
function MergeSortAscending(var Node: PVirtualNode; N: Cardinal): PVirtualNode;
|
|
var
|
|
A, B: PVirtualNode;
|
|
|
|
begin
|
|
if N > 1 then
|
|
begin
|
|
A := MergeSortAscending(Node, N div 2);
|
|
B := MergeSortAscending(Node, (N + 1) div 2);
|
|
Result := MergeAscending(A, B);
|
|
end
|
|
else
|
|
begin
|
|
Result := Node;
|
|
Node := Node.NextSibling;
|
|
Result.NextSibling := nil;
|
|
end;
|
|
end;
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
function MergeSortDescending(var Node: PVirtualNode; N: Cardinal): PVirtualNode;
|
|
|
|
// Sorts the list of nodes given by Node (which must not be nil).
|
|
|
|
var
|
|
A, B: PVirtualNode;
|
|
|
|
begin
|
|
if N > 1 then
|
|
begin
|
|
A := MergeSortDescending(Node, N div 2);
|
|
B := MergeSortDescending(Node, (N + 1) div 2);
|
|
Result := MergeDescending(A, B);
|
|
end
|
|
else
|
|
begin
|
|
Result := Node;
|
|
Node := Node.NextSibling;
|
|
Result.NextSibling := nil;
|
|
end;
|
|
end;
|
|
|
|
//--------------- end local functions ---------------------------------------
|
|
|
|
var
|
|
Run: PVirtualNode;
|
|
Index: Cardinal;
|
|
|
|
i: Integer;
|
|
bBeginFirstChild: Boolean;
|
|
pTempNode,
|
|
pSortCountNextNode,
|
|
pBeginPrevNode: PVirtualNode;
|
|
vtState: TVirtualTreeStates;
|
|
begin
|
|
with Self do
|
|
begin
|
|
InterruptValidation;
|
|
|
|
if tsEditPending in FStates then
|
|
begin
|
|
StopTimer(EditTimer);
|
|
DoStateChange([], [tsEditPending]);
|
|
end;
|
|
|
|
vtState := FStates;
|
|
end;
|
|
|
|
if not (tsEditing in vtState) or DoEndEdit then
|
|
begin
|
|
if pBeginNode = nil then
|
|
exit;
|
|
|
|
if nSortCount = -1 then
|
|
begin
|
|
nSortCount := 0;
|
|
pTempNode := pBeginNode;
|
|
while pTempNode <> nil do
|
|
begin
|
|
Inc(nSortCount);
|
|
pTempNode := pTempNode.NextSibling;
|
|
end;
|
|
pSortCountNextNode := nil;
|
|
end else begin
|
|
pTempNode := pBeginNode;
|
|
for i := 1 to nSortCount do
|
|
begin
|
|
pTempNode := pTempNode.NextSibling;
|
|
if pTempNode = nil then
|
|
begin
|
|
nSortCount := i;
|
|
break;
|
|
end;
|
|
end;
|
|
pSortCountNextNode := pTempNode;
|
|
end;
|
|
|
|
if nSortCount > 1 then
|
|
begin
|
|
bBeginFirstChild := false;
|
|
if pBeginNode.Parent <> nil then
|
|
begin
|
|
if pBeginNode.Parent.FirstChild = pBeginNode then
|
|
bBeginFirstChild := true;
|
|
end;
|
|
|
|
pBeginPrevNode := pBeginNode.PrevSibling;
|
|
Index := pBeginNode.Index;
|
|
|
|
StartOperation(okSortNode);
|
|
try
|
|
// Sort the linked list, check direction flag only once.
|
|
if Direction = sdAscending then
|
|
pTempNode := MergeSortAscending(pBeginNode, nSortCount)
|
|
else
|
|
pTempNode := MergeSortDescending(pBeginNode, nSortCount);
|
|
|
|
if pTempNode.Parent <> nil then
|
|
begin
|
|
if bBeginFirstChild then
|
|
pTempNode.Parent.FirstChild := pTempNode;
|
|
end;
|
|
finally
|
|
EndOperation(okSortNode);
|
|
end;
|
|
|
|
// Consolidate the child list finally.
|
|
Run := pTempNode;
|
|
if pBeginPrevNode <> nil then
|
|
pBeginPrevNode.NextSibling := Run;
|
|
Run.PrevSibling := pBeginPrevNode;
|
|
|
|
repeat
|
|
Run.Index := Index;
|
|
Inc(Index);
|
|
if Run.NextSibling = nil then
|
|
Break;
|
|
Run.NextSibling.PrevSibling := Run;
|
|
Run := Run.NextSibling;
|
|
until False;
|
|
|
|
if pSortCountNextNode <> nil then
|
|
begin
|
|
Run.NextSibling := pSortCountNextNode;
|
|
pSortCountNextNode.PrevSibling := Run;
|
|
end else
|
|
if (Run.Parent <> nil) and (Run.NextSibling = nil) then
|
|
Run.Parent.LastChild := Run;
|
|
|
|
InvalidateCache;
|
|
end;
|
|
|
|
with Self do
|
|
begin
|
|
if FUpdateCount = 0 then
|
|
begin
|
|
ValidateCache;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{ Other }
|
|
|
|
function VT_CountTotalNode(vt: TVirtualStringTree): DWORD;
|
|
var
|
|
pNode: PVirtualNode;
|
|
begin
|
|
Result := 0;
|
|
pNode := vt.GetFirst;
|
|
while pNode <> nil do
|
|
begin
|
|
Inc(Result);
|
|
pNode := vt.GetNext(pNode);
|
|
end;
|
|
end;
|
|
|
|
function VT_CountVisibleNode(vt: TVirtualStringTree): DWORD;
|
|
var
|
|
pNode: PVirtualNode;
|
|
begin
|
|
Result := 0;
|
|
pNode := vt.GetFirst;
|
|
while pNode <> nil do
|
|
begin
|
|
if vt.IsVisible[pNode] then
|
|
Inc(Result);
|
|
pNode := vt.GetNext(pNode);
|
|
end;
|
|
end;
|
|
|
|
function VT_CountVisibleChildNode(pNode: PVirtualNode): DWORD;
|
|
begin
|
|
Result := 0;
|
|
pNode := pNode.FirstChild;
|
|
while pNode <> nil do
|
|
begin
|
|
if vsVisible in pNode.States then
|
|
Inc(Result);
|
|
|
|
pNode := pNode.NextSibling;
|
|
end;
|
|
end;
|
|
|
|
function VT_CountVisibleCheckedNode(vt: TVirtualStringTree): DWORD;
|
|
var
|
|
pNode: PVirtualNode;
|
|
begin
|
|
Result := 0;
|
|
pNode := vt.GetFirst;
|
|
while pNode <> nil do
|
|
begin
|
|
if vt.IsVisible[pNode] and (pNode.CheckState = csCheckedNormal) then
|
|
Inc(Result);
|
|
pNode := vt.GetNext(pNode);
|
|
end;
|
|
end;
|
|
|
|
procedure VT_ReverseSelected(vt: TVirtualStringTree);
|
|
var
|
|
pNode: PVirtualNode;
|
|
begin
|
|
vt.BeginUpdate;
|
|
try
|
|
pNode := vt.GetFirst;
|
|
while pNode <> nil do
|
|
begin
|
|
vt.Selected[pNode] := not vt.Selected[pNode];
|
|
pNode := vt.GetNext(pNode);
|
|
end;
|
|
finally
|
|
vt.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure VT_CheckAll(var vt: TVirtualStringTree);
|
|
var
|
|
pNode: PVirtualNode;
|
|
begin
|
|
vt.BeginUpdate;
|
|
try
|
|
pNode := vt.GetFirst;
|
|
while pNode <> nil do
|
|
begin
|
|
if vt.IsVisible[pNode] and not vt.IsDisabled[pNode] then
|
|
pNode.CheckState := csCheckedNormal;
|
|
pNode := vt.GetNext(pNode, true);
|
|
end;
|
|
finally
|
|
vt.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure VT_UnCheckAll(var vt: TVirtualStringTree);
|
|
var
|
|
pNode: PVirtualNode;
|
|
begin
|
|
vt.BeginUpdate;
|
|
try
|
|
pNode := vt.GetFirst;
|
|
while pNode <> nil do
|
|
begin
|
|
if vt.IsVisible[pNode] and not vt.IsDisabled[pNode] then
|
|
// vt.CheckState[pNode] := csUncheckedNormal;
|
|
pNode.CheckState := csUncheckedNormal;
|
|
pNode := vt.GetNext(pNode, true);
|
|
end;
|
|
finally
|
|
vt.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure VT_ForceCheckNode(pNode: PVirtualNode);
|
|
var
|
|
pChildN: PVirtualNode;
|
|
begin
|
|
pNode.CheckState := csCheckedNormal;
|
|
pChildN := pNode.FirstChild;
|
|
while pChildN <> nil do
|
|
begin
|
|
pChildN.CheckState := csCheckedNormal;
|
|
if pChildN.ChildCount > 0 then
|
|
VT_ForceCheckNode(pChildN);
|
|
pChildN := pChildN.NextSibling;
|
|
end;
|
|
end;
|
|
|
|
procedure VT_ForceUnCheckNode(pNode: PVirtualNode);
|
|
var
|
|
pChildN: PVirtualNode;
|
|
begin
|
|
pNode.CheckState := csUncheckedNormal;
|
|
pChildN := pNode.FirstChild;
|
|
while pChildN <> nil do
|
|
begin
|
|
pChildN.CheckState := csUncheckedNormal;
|
|
if pChildN.ChildCount > 0 then
|
|
VT_ForceCheckNode(pChildN);
|
|
pChildN := pChildN.NextSibling;
|
|
end;
|
|
end;
|
|
|
|
procedure VT_ReverseCheckAll(vt: TVirtualStringTree);
|
|
var
|
|
pNode: PVirtualNode;
|
|
begin
|
|
vt.BeginUpdate;
|
|
try
|
|
pNode := vt.GetFirst;
|
|
while pNode <> nil do
|
|
begin
|
|
if vt.IsVisible[pNode] and not vt.IsDisabled[pNode] then
|
|
begin
|
|
if pNode.CheckState = csCheckedNormal then
|
|
pNode.CheckState := csUncheckedNormal
|
|
else
|
|
if pNode.CheckState = csUncheckedNormal then
|
|
pNode.CheckState := csCheckedNormal;
|
|
end;
|
|
|
|
pNode := vt.GetNext(pNode);
|
|
end;
|
|
finally
|
|
vt.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure VT_SetEnalbedNode(vt: TVirtualStringTree; pNode: PVirtualNode; bVal: Boolean);
|
|
begin
|
|
vt.BeginUpdate;
|
|
try
|
|
vt.IsDisabled[pNode] := not bVal;
|
|
if pNode.ChildCount > 0 then
|
|
begin
|
|
pNode := pNode.FirstChild;
|
|
while pNode <> nil do
|
|
begin
|
|
VT_SetEnalbedNode(vt, pNode, bVal);
|
|
pNode := pNode.NextSibling;
|
|
end;
|
|
end;
|
|
finally
|
|
vt.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
function VT_HasDisableNode(vt: TVirtualStringTree; pNode: PVirtualNode): Boolean;
|
|
|
|
function CheckDisableNode(aNode: PVirtualNode): Boolean;
|
|
begin
|
|
Result := false;
|
|
if vt.IsDisabled[aNode] then
|
|
begin
|
|
Result := true;
|
|
exit;
|
|
end;
|
|
|
|
if aNode.ChildCount > 0 then
|
|
begin
|
|
aNode := aNode.FirstChild;
|
|
while aNode <> nil do
|
|
begin
|
|
Result := CheckDisableNode(aNode);
|
|
if Result then
|
|
exit;
|
|
aNode := aNode.NextSibling;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
vt.BeginUpdate;
|
|
try
|
|
Result := CheckDisableNode(pNode);
|
|
finally
|
|
vt.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure VT_ExpandAll(vt: TVirtualStringTree; bFlag: Boolean);
|
|
var
|
|
pNode: PVirtualNode;
|
|
begin
|
|
vt.BeginUpdate;
|
|
try
|
|
pNode := vt.GetFirst;
|
|
while pNode <> nil do
|
|
begin
|
|
vt.Expanded[pNode] := bFlag;
|
|
pNode := vt.GetNext(pNode);
|
|
end;
|
|
finally
|
|
vt.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure VT_ExpandNodeAll(vt: TVirtualStringTree; pNode: PVirtualNode; bFlag: Boolean);
|
|
begin
|
|
vt.BeginUpdate;
|
|
try
|
|
while pNode <> nil do
|
|
begin
|
|
vt.Expanded[pNode] := bFlag;
|
|
pNode := vt.GetNext(pNode);
|
|
end;
|
|
finally
|
|
vt.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
function VT_CopyToClipboardSelectedInfo(vt: TVirtualStringTree; nStartColumnIdx: Integer = 1): Integer;
|
|
var
|
|
pNode: PVirtualNode;
|
|
sData: String;
|
|
i: Integer;
|
|
cbd: TClipboard;
|
|
begin
|
|
Result := 0;
|
|
pNode := vt.GetFirstSelected;
|
|
if pNode = nil then
|
|
begin
|
|
Result := 1;
|
|
exit;
|
|
end;
|
|
|
|
if vt.SelectedCount > 1000 then
|
|
begin
|
|
Result := 2;
|
|
exit;
|
|
end;
|
|
|
|
if nStartColumnIdx >= vt.Header.Columns.Count then
|
|
nStartColumnIdx := 0;
|
|
|
|
sData := '';
|
|
while pNode <> nil do
|
|
begin
|
|
for i := nStartColumnIdx to vt.Header.Columns.Count - 1 do
|
|
if coVisible in vt.Header.Columns[i].Options then
|
|
begin
|
|
sData := sData + vt.Text[pNode, i] + #9;
|
|
end;
|
|
|
|
sData := sData + #13#10;
|
|
|
|
pNode := vt.GetNextSelected(pNode);
|
|
end;
|
|
|
|
if sData <> '' then
|
|
begin
|
|
Guard(cbd, TClipboard.Create);
|
|
cbd.AsText := sData;
|
|
end else Result := 3;
|
|
end;
|
|
|
|
function VT_AddChild(vt: TVirtualStringTree; pParent: PVirtualNode = nil): PVirtualNode; inline;
|
|
begin
|
|
Result := vt.AddChild(pParent);
|
|
Include(Result.States, vsInitialized);
|
|
end;
|
|
|
|
function VT_AddChildDataN(vt: TVirtualStringTree; out pAddNode: PVirtualNode; pParent: PVirtualNode = nil): Pointer; inline;
|
|
begin
|
|
pAddNode := vt.AddChild(pParent);
|
|
Include(pAddNode.States, vsInitialized);
|
|
Result := vt.GetNodeData(pAddNode);
|
|
end;
|
|
|
|
function VT_AddChildData(vt: TVirtualStringTree; pParent: PVirtualNode = nil): Pointer; inline; overload;
|
|
var
|
|
pNode: PVirtualNode;
|
|
begin
|
|
Result := VT_AddChildDataN(vt, pNode, pParent);
|
|
end;
|
|
|
|
function VT_HasChildNode(vt: TVirtualStringTree; pParent, pFindNode: PVirtualNode): Boolean;
|
|
var
|
|
pNode: PVirtualNode;
|
|
begin
|
|
Result := false;
|
|
|
|
if pParent = nil then
|
|
exit;
|
|
|
|
if pParent = pFindNode then
|
|
begin
|
|
Result := true;
|
|
exit;
|
|
end;
|
|
|
|
pNode := pParent.FirstChild;
|
|
while pNode <> nil do
|
|
begin
|
|
Result := VT_HasChildNode(vt, pNode, pFindNode);
|
|
if Result then
|
|
exit;
|
|
|
|
pNode := pNode.NextSibling;
|
|
end;
|
|
end;
|
|
|
|
function VT_Get1SelNodeData(vt: TVirtualStringTree): Pointer;
|
|
var
|
|
pNode: PVirtualNode;
|
|
begin
|
|
pNode := vt.GetFirstSelected;
|
|
if pNode <> nil then
|
|
Result := vt.GetNodeData(pNode)
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
procedure VT_SortAll(vt: TVirtualStringTree; nColumn: Integer; aDirection: TSortDirection);
|
|
var
|
|
pNode: PVirtualNode;
|
|
begin
|
|
vt.Sort(nil, nColumn, aDirection);
|
|
|
|
pNode := vt.GetFirst;
|
|
while pNode <> nil do
|
|
begin
|
|
if pNode.ChildCount > 0 then
|
|
vt.Sort(pNode, nColumn, aDirection);
|
|
pNode := vt.GetNext(pNode);
|
|
end;
|
|
end;
|
|
|
|
procedure VT_SortNodeChilds(vt: TVirtualStringTree; pNode: PVirtualNode; nColumn: Integer; aDirection: TSortDirection);
|
|
begin
|
|
vt.Sort(pNode, nColumn, aDirection);
|
|
|
|
if pNode = nil then
|
|
pNode := vt.RootNode;
|
|
|
|
pNode := pNode.FirstChild;
|
|
while pNode <> nil do
|
|
begin
|
|
if pNode.ChildCount > 0 then
|
|
VT_SortNodeChilds(vt, pNode, nColumn, aDirection);
|
|
pNode := pNode.NextSibling;
|
|
end;
|
|
end;
|
|
|
|
// 잘 동작하는지 테스트 안됨 22_0119 21:34:10 kku
|
|
// 확인 되면 이거 지워 ㅇㅇ
|
|
function VT_FindNodeFromPath(vt: TVirtualStringTree; sPath: String; sDelimiter: String = '\'; nColumn: Integer = 0): PVirtualNode;
|
|
|
|
function GetMatchTextNode(pNode: PVirtualNode; sMatchText: String): PVirtualNode;
|
|
begin
|
|
Result := nil;
|
|
while pNode <> nil do
|
|
begin
|
|
if CompareText(vt.Text[pNode, nColumn], sMatchText) = 0 then
|
|
begin
|
|
Result := pNode;
|
|
exit;
|
|
end;
|
|
pNode := pNode.NextSibling;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
PathList: TStringList;
|
|
pNode: PVirtualNode;
|
|
i: Integer;
|
|
begin
|
|
Result := nil;
|
|
Guard(PathList, TStringList.Create);
|
|
|
|
if SplitString2(sDelimiter, sPath, PathList) = 0 then
|
|
exit;
|
|
|
|
vt.BeginUpdate;
|
|
try
|
|
pNode := vt.RootNode;
|
|
if pNode = nil then
|
|
exit;
|
|
|
|
for i := 0 to PathList.Count - 1 do
|
|
begin
|
|
Result := GetMatchTextNode(pNode.FirstChild, PathList[i]);
|
|
if Result = nil then
|
|
break;
|
|
end;
|
|
finally
|
|
vt.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure VT_SetCheckTypeAllNode(vt: TVirtualStringTree; aCheckType: TCheckType);
|
|
var
|
|
pNode: PVirtualNode;
|
|
begin
|
|
pNode := vt.GetFirst;
|
|
while pNode <> nil do
|
|
begin
|
|
pNode.CheckType := aCheckType;
|
|
pNode := vt.GetNext(pNode);
|
|
end;
|
|
end;
|
|
|
|
procedure VT_SetFocuceNode(vt: TVirtualStringTree; pNode: PVirtualNode);
|
|
begin
|
|
vt.FocusedNode := nil;
|
|
vt.ClearSelection;
|
|
|
|
vt.FocusedNode := pNode;
|
|
vt.Selected[pNode] := true;
|
|
vt.ScrollIntoView(pNode, true);
|
|
end;
|
|
|
|
procedure VT_Clear(aVT: TVirtualStringTree);
|
|
begin
|
|
with aVT.Header do
|
|
begin
|
|
if SortColumn <> -1 then
|
|
begin
|
|
Columns[SortColumn].Options := Columns[SortColumn].Options + [coParentColor];
|
|
SortColumn := -1;
|
|
end;
|
|
end;
|
|
aVT.Clear;
|
|
end;
|
|
|
|
end.
|