2,497
社区成员
发帖
与我相关
我的任务
分享
{================ Free TIBXTreeView component for IBX =======================
Igor Ilyinsky, 2001, www.sinn.ru/~mapnn (mapnn@sinn.ru)
==============================================================================
}
unit IBXtrees;
interface
uses ComCtrls, DB, Classes, SysUtils, IBDatabase, IBSQL;
type
PItemRec = ^ItemRec;
ItemRec = record
Id : integer;
Parent: integer;
CCount: integer;
end;
TIBXTreeView=class(TTreeView)
private
IBConnection : TIBDatabase;
IBTransaction : TIBTransaction;
IBTableName : String;
IBSQL : TIBSQL;
procedure BuildNode(Node:TTreeNode);
protected
procedure Delete(Node: TTreeNode); override;
function CanExpand(Node: TTreeNode): Boolean; override;
// Rebuild children for ParentNode
procedure RebuildNode(ParentNode: TTreeNode; Node_Id: integer); virtual;
public
procedure BuildTree(RootName: String);
procedure ClearTree;
//
constructor Create(AOwner:TComponent); override;
destructor Destroy; override;
//
procedure InsertNode(Parent_Id: integer; Name: String);
//
procedure MoveNode(Node_Id, NewParent_Id: integer);
//
procedure RenameNode(Node:TTreeNode; Name: String);
//
procedure DeleteNode(Node:TTreeNode);
//
function GetId(Node: TTreeNode) : Integer;
//
function GetNode(Id: Integer) : TTreeNode;
published
property Database : TIBDatabase read IBConnection write IBConnection;
property Transaction : TIBTransaction read IBTransaction write IBTransaction;
property TableName : string read IBTableName write IBTableName;
end;
procedure Register;
implementation
function TIBXTreeView.GetId(Node: TTreeNode) : Integer;
var R: PItemRec;
begin
R:=PItemRec(Node.Data);
Result := R^.ID;
end;
function TIBXTreeView.GetNode(Id: Integer) : TTreeNode;
var R: PItemRec;
i: integer;
begin
Result:=nil;
i:=0;
While i < Items.Count do begin
R:=PItemRec(Items[i].Data);
if R^.ID = Id then begin
Result := Items[i];
break;
end;
inc(i);
end;
end;
constructor TIBXTreeView.Create(AOwner:TComponent);
begin
inherited Create(AOwner);
IBSQL:=TIBSQL.Create(Self);
end;
procedure TIBXTreeView.Delete(Node: TTreeNode);
begin
inherited Delete(Node);
if Assigned(Node) then
if Assigned(Node.Data) then Dispose(PItemRec(Node.Data));
end;
function TIBXTreeView.CanExpand(Node: TTreeNode): Boolean;
begin
Result:=inherited CanExpand(Node);
if Assigned(Node.Data) then
Items.BeginUpdate;
BuildNode(Node);
Items.EndUpdate;
end;
destructor TIBXTreeView.Destroy;
begin
IBSQL.Free;
inherited;
end;
procedure TIBXTreeView.BuildNode(Node:TTreeNode);
var NewNode: TTreeNode;
R: PItemRec;
begin
if not IBTransaction.inTransaction then IBTransaction.StartTransaction;
IBSQL.Close;
IBSQL.Sql.Text:='select * from '+IBTableName+' where PARENT=:Parent ';
R:=Node.Data;
IBSQL.ParamByName('Parent').asInteger:=R^.Id;
Node.DeleteChildren;
IBSQL.ExecQuery;
while not IBSQL.EOF do
begin
New(R);
R^.Id:=IBSQL.FieldByName('ID').asInteger;
R^.Parent:=IBSQL.FieldByName('PARENT').asInteger;
R^.CCount:=IBSQL.FieldByName('CCOUNT').asInteger;
NewNode:=Items.AddChild(Node,Trim(IBSQL.FieldByName('NAME').asString));
NewNode.Data:=PItemRec(R);
NewNode.HasChildren:=R^.CCount > 0;
if assigned(Images) then begin
NewNode.ImageIndex:=2;
NewNode.SelectedIndex:=3;
end;
IBSQL.Next;
end;
IBSQL.Close;
end;
procedure TIBXTreeView.InsertNode(Parent_Id: integer; Name: String);
var ParentNode: TTreeNode;
begin
if not IBTransaction.inTransaction then IBTransaction.StartTransaction;
IBSQL.Close;
IBSQL.Sql.Text:='insert into '+IBTableName+' (PARENT,NAME) values(:Parent,:Name)';
IBSQL.ParamByName('Parent').asInteger:=Parent_Id;
IBSQL.ParamByName('Name').asString:=Name;
IBSQL.ExecQuery;
IBTransaction.Commit;
ParentNode:=GetNode(Parent_id);
if ParentNode <> nil then RebuildNode(ParentNode, -1); // if parent visible
end;
procedure TIBXTreeView.MoveNode(Node_Id, NewParent_Id: integer);
var Node,NodeParent: TTreeNode;
begin
if Node_Id = NewParent_Id then raise exception.create('Parent Node can not be equal Selected Node!');
if Node_Id = 0 then raise exception.create('Root Node can not be moved!');
if not IBTransaction.inTransaction then IBTransaction.StartTransaction;
IBSQL.Close;
// TEST CICLE NODE
IBSQL.Sql.Text:='select * from GETPARENTS(:Id)';
IBSQL.ParamByName('Id').asInteger:=NewParent_Id;
IBSQL.ExecQuery;
while not IBSQL.EOF do begin
if IBSQL.FieldByName('DID').asInteger = Node_Id then
raise exception.create('Cicle Node!');
IBSQL.Next;
end;
IBSQL.Close;
// UPDATE
IBSQL.Sql.Text:='update '+IBTableName+' set PARENT=:Parent where ID=:ID';
IBSQL.ParamByName('Parent').asInteger:=NewParent_Id;
IBSQL.ParamByName('ID').asInteger:=Node_Id;
IBSQL.ExecQuery;
IBTransaction.Commit;
Node:=GetNode(Node_Id);
if (Node <> nil) and Node.Parent.Expanded then items.delete(Node);
NodeParent:=GetNode(NewParent_Id);
if (NodeParent <> nil) then RebuildNode(NodeParent,Node_Id); // if newparent visible
end;
procedure TIBXTreeView.RenameNode(Node:TTreeNode; Name: String);
var R: PItemRec;
begin
if Node.Parent = nil then raise exception.create('Root Node can not be renamed!');
if not IBTransaction.inTransaction then IBTransaction.StartTransaction;
IBSQL.Close;
IBSQL.Sql.Text:='update '+IBTableName+' set NAME=:Name where ID=:ID';
R:=Node.Data;
IBSQL.ParamByName('ID').asInteger:=R^.ID;
IBSQL.ParamByName('Name').asString:=Name;
IBSQL.ExecQuery;
IBTransaction.Commit;
RebuildNode(Node.Parent,R^.ID);
end;
procedure TIBXTreeView.DeleteNode(Node:TTreeNode);
var R: PItemRec;
begin
if Node.Parent = nil then raise exception.create('Root Node can not be deleted!');
if Node.HasChildren then raise exception.Create('This Node has Children!');
if not IBTransaction.inTransaction then IBTransaction.StartTransaction;
IBSQL.Close;
IBSQL.Sql.Text:='delete from '+IBTableName+' where ID=:ID';
R:=PItemRec(Node.Data);
IBSQL.ParamByName('ID').asInteger:=R^.ID;
IBSQL.ExecQuery;
IBTransaction.Commit;
RebuildNode(Node.Parent,-1);
end;
procedure TIBXTreeView.BuildTree(RootName: String);
var RootNode: TTreeNode;
R: PItemRec;
begin
IBSQL.Database:=IBConnection;
IBSQL.Transaction:=IBTransaction;
if (not assigned(IBConnection)) or (not assigned(IBTransaction)) or (IBTableName = '') then
raise exception.create('IBConnection,IBTransaction or IBTableName is not defined!');
items.BeginUpdate;
ClearTree;
RootNode:=items.Add(nil, RootName); { Add a root node }
if assigned(Images) then begin
RootNode.ImageIndex:=0;
RootNode.SelectedIndex:=1;
end;
new(r);
r^.id:=0; // id root = 0 !!!
RootNode.Data:=r;
BuildNode(RootNode);
RootNode.Expand(False);
Items.EndUpdate;
end;
{Rebuild children for ParentNode}
procedure TIBXTreeView.RebuildNode(ParentNode: TTreeNode; Node_Id: integer);
var Node: TTreeNode;
begin
if ParentNode <> nil then begin
items.BeginUpdate;
BuildNode(ParentNode);
ParentNode.Expand(False);
if Node_Id >= 0 then begin
Node:=GetNode(Node_Id);
if Node <> nil then Node.Selected:=True;
end;
items.EndUpdate;
end;
end;
procedure TIBXTreeView.ClearTree;
begin
While Items.Count>0 do Items.Delete(Items[0]);
end;
procedure Register;
begin
RegisterComponents('InterBase', [TIBXTreeView]);
end;
end.
procedure BuildTree(RootName: String);//创建树
procedure ClearTree;//清空树
procedure InsertNode(Parent_Id: integer; Name: String);//插入节点
procedure MoveNode(Node_Id, NewParent_Id: integer);//移动节点
procedure RenameNode(Node:TTreeNode; Name: String);//重命名节点
procedure DeleteNode(Node:TTreeNode);//删除节点
function GetId(Node: TTreeNode) : Integer;//获得节点ID
function GetNode(Id: Integer) : TTreeNode;//通过ID获得节点信息