unit TreeViewTools;
interface
uses SysUtils, ComCtrls, Classes;
type
TNodesToPathListTyp = (ntpl_DataNil, ntpl_DataAssigned, ntpl_DataAll);
TArrayOfString =
array of String;
{<--- Funktion, die aus einem Node (mit Parents) ein PathStr bildet --->}
function GetNodePath(aNode:TTreeNode; WithTailingDelimiter: Boolean):
String;
{<--- Trägt kompletten Pfad der Parent-Nodes eines TreeView in eine StringList --->}
procedure NodesToPathList(aTreeView: TTreeView; aStringList: TStrings; WithTailingDelimiter: Boolean;
DataTyp : TNodesToPathListTyp = ntpl_DataAll);
{<--- Findet einen Node durch Angabe des Pfadnamen --->}
function FindNodebyPath(aTreeView: TTreeView; aPath: AnsiString): TTreeNode;
{<--- Prüft, ob in einem TreeZweig ein Node.Text bereits exitiert --->}
function NodeTextExistsInTwig(aTreeView: TTreeView; aParentNode: TTreeNode; aText :
String): Boolean;
{<--- Gibt ein unique NodeText zurück, entweder für Zweig oder ganzen Baum --->}
function GetUniqueNodeText(aTreeView: TTreeView; aParentNode: TTreeNode;
aNodeText :
String; OnlyInTwig : Boolean = True):
String;
implementation
(***************************************************************************
Funktion, die aus einem Node (mit Parents) ein PathStr bildet
Achtung! aNode-Pointer wird innerhalb verändert
***************************************************************************)
// himitsu: umgeschrieben, weniger .Parent und übersichtlicher
function GetNodePath(aNode:TTreeNode; WithTailingDelimiter: Boolean):
String;
begin
Result := '
';
while Assigned(aNode)
do begin
Result := aNode.Text + '
\' + Result;
aNode := aNode.Parent;
end;
if not WithTailingDelimiter
then Delete(Result, Length(Result), 1);
end;
(*
function GetNodePath(aNode:TTreeNode; WithDelimiter: Boolean): String;
begin
if Assigned(aNode) then begin
if WithDelimiter then Result := aNode.Text +'\'
else Result := aNode.Text;
aNode := aNode.Parent;
while assigned(aNode) do begin
Result := aNode.text + '\' + Result;
aNode := aNode.Parent;
end;
end else Result := ''; // himitsu : Zuweisung nur wenn nötig
end;
*)
(***************************************************************************
Trägt kompletten Pfad der Parent-Nodes eines TreeView in eine StringList,
die DataTyp erfüllen.
Der Basis-Node selbst wird in Objects gespeichert
***************************************************************************)
procedure NodesToPathList(aTreeView: TTreeView; aStringList: TStrings; WithTailingDelimiter: Boolean;
DataTyp : TNodesToPathListTyp = ntpl_DataAll);
var
i : Integer;
guilty : Boolean;
begin
with aTreeView
do begin
for i := 0
to Items.Count-1
do begin
// Node ist gültig zum Eintrag in die Liste?
case DataTyp
of
ntpl_DataNil : guilty := Items[i].Data =
NIL;
ntpl_DataAssigned : guilty := Items[i].Data <>
NIL;
else
guilty := True;
// ntpl_DataAll
end;
// Pfad zusammenbauen
if guilty
then
aStringList.AddObject(GetNodePath(Items[i], WithTailingDelimiter),Items[i]);
end;
end;
end;
(***************************************************************************
Findet einen Node durch Angabe des Pfadnamen
Achtung! aPath-Wert wird innerhalb verändert
Dank an himitsu @ Delphi-Praxis
***************************************************************************)
Function FindNodeByPath(aTreeView: TTreeView; aPath:
String): TTreeNode;
Var
Path: TArrayOfString;
i, i2: Integer;
Begin
Result :=
nil;
if aPath='
'
then exit;
//Path := Mixed.Explode('\', ExcludeTrailingBackslash(aPath));
aPath := IncludeTrailingBackslash(aPath);
while aPath <> '
'
do begin
i2 := Pos('
\', aPath);
// himitsu: lokale Variable
i := Length(Path);
// statt mehrfacher Funktionsaufruf
SetLength(Path, i+1);
Path[i] := Copy(aPath, 1, i2-1);
Delete(aPath, 1, i2);
end;
Result := aTreeView.Items.GetFirstNode;
i := 0;
While Assigned(Result)
do Begin
//If CompareStr(Result.Text,Path[i])=0 Then Begin
if Result.Text = Path[i]
Then Begin
If i < High(Path)
Then Begin
Inc(i);
Result := Result.getFirstChild;
End Else Exit;
End Else Result := Result.getNextSibling;
End;
End;
(***************************************************************************
Prüft, ob in einem TreeZweig ein Node.Text bereits exitiert
ist kein Zweig ausgewählt, prüft es die erste Ebene
***************************************************************************)
function NodeTextExistsInTwig(aTreeView: TTreeView; aParentNode: TTreeNode; aText :
String): Boolean;
var
aNode : TTreeNode;
begin
Result := False;
aText := AnsiUpperCase(aText);
// himitsu: späterer Mehrfachaufruf verhindern
aNode :=
NIL;
// richtigen FirstNode ermitteln
if Assigned(aParentNode)
then aNode := aParentNode.GetFirstChild
else if Assigned(aTreeView)
then aNode := aTreeView.TopItem;
// StartNode und SchwesterNodes prüfen
while Assigned(aNode)
do begin
if AnsiUpperCase(aNode.Text) = aText
then begin
Result := True;
Exit;
// Break ginge auch, nächste aNode-Zuweisung würde verworfen
end;
aNode := aNode.getNextSibling;
end;
end;
(***************************************************************************
Prüft, ob ein NodeText schon existiert (entweder im Zweig oder ganzen Baum)
und gibt einen UniqueNamen zurück, erweitert um [x]
Die erste Ebene wird dabei wie ein Zweig (von Root) behandelt
***************************************************************************)
function GetUniqueNodeText(aTreeView: TTreeView; aParentNode: TTreeNode;
aNodeText :
String; OnlyInTwig : Boolean = True):
String;
var
i : Integer;
sl : TStringList;
begin
Result := aNodeText;
{<--- Prüft nur einen Zweig bzw. erste Ebene --->}
if OnlyInTwig
then begin
i := 0;
while NodeTextExistsInTwig(aTreeView, aParentNode, Result)
do begin
inc(i);
Result := aNodeText+'
['+IntToStr(i)+'
]';
end;
{<--- Prüft alle Nodes --->}
end else begin
sl := TStringList.Create;
try
// Namen sammeln, damit Items nicht x-mal durchlaufen werden muss
// Aufwand relativiert sich bei großen Bäumen
for i := 0
to aTreeView.Items.Count-1
do
if Pos(AnsiUpperCase(aNodeText), AnsiUpperCase(aTreeView.Items[i].text)) > 0
then
sl.Add(AnsiUpperCase(aTreeView.Items[i].text));
// Prüfen und gg. erweitern
i := 0;
while sl.IndexOf(AnsiUpperCase(Result)) >= 0
do begin
inc(i);
Result := aNodeText+'
['+IntToStr(i)+'
]';
end;
finally
sl.Free;
end;
end;
end;
end.