I have a heirarchy of data that is displayed in a VirtualStringTree. I use this heirarchy multiple times in my application with slight modifications to the way the tree is drawn/displayed. My method currently utilizes the AddChild() procedure for adding nodes an d as such i have multiple copies of the data when the application is run.
I would now like to consolidate these trees and have a 'master' tree which points to the actual data, but then have the 'slave' trees point to the SAME data.
I am a little unsure of if/how this can be acheived. I would think i could simply load the master tree and populate its NodeData with pointers to where the data i being held, and then for all the slave trees, simply store the same pointer in their nodedata.
However im not having much luck.
My current code looks like:
//Initialize the NodeDataSize
procedure TForm1.FormCreate(Sender: TObject);
begin
TreeMasterComponents.NodeDataSize := SizeOf(rMasterComponent);
VST.NodeDataSize := SizeOf(Pointer);
end;
Procedure to copy the master tree to slave trees
procedure TForm1.LoadSlaveTree(ATree: TVirtualStringTree);
var Node : PVirtualNode;
procedure RecursiveCopy(SrcPNode,SrcTNode : PVirtualNode; ATree : TVirtualStringTree);
var SrcNode, TargetNode : PVirtualNode;
SrcData : PMasterComponent;
begin
SrcNode := TreeMasterComponents.GetFirstChild(SrcPNode);
while Assigned(SrcNode) do
begin
SrcData := TreeMasterComponents.GetNodeData(SrcNode);
TargetNode := ATree.AddChild(SrcTNode,SrcData);
RecursiveCopy(SrcNode,TargetNode,ATree);
SrcNode := SrcNode.NextSibling;
end;
end;
begin
ATree.BeginUpdate;
ATree.Clear;
Node := TreeMasterComponents.GetFirst(true);
while Assigned(Node) do
begin
RecursiveCopy(Node,nil,ATree);
Node := Node.NextSibling;
end;
ATree.EndUpdate;
end;
Procedure for slave tree to getCellText
procedure TForm1.SlaveGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
var Data : PMasterComponent;
begin
Data := Sender.GetNodeData(Node);
Case column of
0:CellText := Data^.ComponentCode;
1:CellText := Data^.FullLocation;
end;
end;
At the moment, the nodes are added in the correct heirarchy, however there is no text appearing for the slave trees. Any help would be appreciated.
Ok so i beleive i have found a solution:
The trick was to create a new record to store the Pointer to the original data:
type PRefMasterComponent = ^RefMasterComponent;
RefMasterComponent = packed record
PMCData : PMasterComponent;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
TreeMasterComponents.NodeDataSize := SizeOf(rMasterComponent);
VST.NodeDataSize := SizeOf(RefMasterComponent);
end;
Now the Copy code looks like:
procedure TForm1.LoadTree(ATree: TVirtualStringTree);
var Node,TargetNode : PVirtualNode;
SrcData : PMasterComponent;
Data : PRefMasterComponent;
procedure RecursiveCopy(SrcPNode, TargetPNode : PVirtualNode; ATree : TVirtualStringTree);
var Node, TargetNode : PVirtualNode;
SrcData : PMasterComponent;
Data : PRefMasterComponent;
begin
Node := TreeMasterComponents.GetFirstChild(SrcPNode);
while Assigned(Node) do
begin
SrcData := TreeMasterComponents.GetNodeData(Node);
TargetNode := ATree.AddChild(TargetPNode);
Data := ATree.GetNodeData(TargetNode);
Data.PMCData := SrcData;
RecursiveCopy(Node,TargetNode,ATree);
Node := Node.NextSibling;
end;
end;
begin
ATree.BeginUpdate;
ATree.Clear;
Node := TreeMasterComponents.GetFirst(true);
while Assigned(Node) do
begin
SrcData := TreeMasterComponents.GetNodeData(Node);
TargetNode := ATree.AddChild(nil);
Data := ATree.GetNodeData(TargetNode);
Data.PMCData := SrcData;
RecursiveCopy(Node,TargetNode,ATree);
Node := Node.NextSibling;
end;
ATree.EndUpdate;
end;
and the OnGetText:
procedure TForm1.vstGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
var Data : PRefMasterComponent;
RefData : PMasterComponent;
begin
Data := Sender.GetNodeData(Node);
RefData := Data.PMCData;
Case column of
0:CellText := RefData.ComponentCode;
1:CellText := RefData.FullLocation;
end;
end;
Now if i change data in one tree all i have to do is call VST.Invalidate and the changes are reflected in the other tree.