Tree Connections appear to display incorrectly after sort
Posted: Mon Feb 27, 2006 7:52 am
I have attached some fairly comprehensive code to show what is happening as a result of a tree sort.
Tom, could you look into this please?
thanks
procedure TForm1.FormCreate(Sender: TObject);
{
This shows a bug in what happens when you do a sort.
When you expand the tree (after a sort),
the connections are painted wrongly
}
{ ====================== }
procedure addKids(const prefix : string;const toNode: TTreeNodeShape);
var k: integer; s: string;
begin
for k := 1 to 26 do begin
s := prefix+chr(ord('z') - k + 1) + inttostr(k);
toNode.Add(s);
end; // end for
end;
{ ====================== }
procedure ChangeOffsets;
var ExplorerAlign: TTreeExplorerAlignChild;
begin
// this is for experimentation ... does not affect outcomes
ExplorerAlign := Tree1.GlobalFormat.ChildManager as TTreeExplorerAlignChild;
ExplorerAlign.HorizMargin := 50; // offset of node image from vertical
ExplorerAlign.VertMargin := 30; // by experimentation .. works OK with 64x64 pics
ExplorerAlign.crossMargin := 20; // offset from the cross box
end;
{ ====================== }
procedure MakeConnectionsLookNice;
var k, knt: integer;
begin
knt := tree1.connections.count - 1;
for k := 0 to knt do begin
with tree1.Connections[k] do begin
// --------- Style (ie how the connecting line is drawn)
// TTreeConnectionStyle=(csAuto, csLine, csSides, csCurve, csInvertedSides);
Style := csAuto;
// -------- the connection line itself (it is called "border", but is really a pen)
// property Border:TTreeConnectionPen read GetBorder write SetBorder;
Border.Color := 1277625; //is a nice brown
Border.Style := psSolid;
Border.Width := 3; // the line thickness
end; // end for
end;
end;
{ ====================== }
procedure KillAllConnections;
var k: integer;
begin
for k := 0 to tree1.shapes.count - 1 do begin
tree1.Connections.DeleteAllTo(tree1.shapes[k]); // deletes all connections to this child
// not clear what happens to the associated connection data ??
end; // end for
end;
procedure ReconnectParentsWithKids(const anode:TTreeNodeShape);
var k: integer; knt : integer;
begin
knt := anode.children.count;
if knt =0 then exit;
for k := 0 to knt - 1 do begin
anode.AddconnectionObject(anode.children[k],nil);
end; // end for
for k := 0 to knt - 1 do begin
ReconnectParentsWithKids(anode.children[k]); // recurse down
end;
end;
var k: integer;
begin
tree1.AssignParent := true; // make nodes copy parent properties
tree1.AddRoot('I am root');
tree1.roots[0].color := clYellow;
// ChangeOffsets;
AddKids('top:',tree1.roots[0]);
// second level
for k := 1 to 26 do begin
AddKids('next=',tree1.roots[0].Children[k - 1]);
end; // end for
MakeConnectionsLookNice;
tree1.sort(true, true); // Ascending, IgnoreCase
tree1.invalidate;
{ the above sort results in all the first level connections becoming
"invisible" }
MakeConnectionsLookNice; // does not help
{
we try killing all the connections, then rebuilding them.
This works if the tree is not sorted, but not if it is sorted
- still get connections all over the place
}
KillAllConnections;
assert(tree1.connections.count=0,'should be no connections');
for k := 0 to tree1.Shapes.count-1 do begin
assert(tree1.shapes[k].connections.count =0,' the shape should have no connections');
end; // end for
ReconnectParentsWithKids(tree1.roots[0]);
// check if every node is connected to 1 or 2 others only
for k := 0 to tree1.Shapes.count-1 do begin
assert((tree1.shapes[k].connections.count <=2) and (tree1.shapes[k].connections.count >=1)
,' the shape ' + inttostr(k) +' should have 1 or 2 connections');
end; // end for
assert(tree1.roots[0].children.count=26,' wrong children of root ');
assert(tree1.roots[0].connections.count=26,' wrong connections of root ');
MakeConnectionsLookNice;
tree1.invalidate;
end;
Tom, could you look into this please?
thanks
procedure TForm1.FormCreate(Sender: TObject);
{
This shows a bug in what happens when you do a sort.
When you expand the tree (after a sort),
the connections are painted wrongly
}
{ ====================== }
procedure addKids(const prefix : string;const toNode: TTreeNodeShape);
var k: integer; s: string;
begin
for k := 1 to 26 do begin
s := prefix+chr(ord('z') - k + 1) + inttostr(k);
toNode.Add(s);
end; // end for
end;
{ ====================== }
procedure ChangeOffsets;
var ExplorerAlign: TTreeExplorerAlignChild;
begin
// this is for experimentation ... does not affect outcomes
ExplorerAlign := Tree1.GlobalFormat.ChildManager as TTreeExplorerAlignChild;
ExplorerAlign.HorizMargin := 50; // offset of node image from vertical
ExplorerAlign.VertMargin := 30; // by experimentation .. works OK with 64x64 pics
ExplorerAlign.crossMargin := 20; // offset from the cross box
end;
{ ====================== }
procedure MakeConnectionsLookNice;
var k, knt: integer;
begin
knt := tree1.connections.count - 1;
for k := 0 to knt do begin
with tree1.Connections[k] do begin
// --------- Style (ie how the connecting line is drawn)
// TTreeConnectionStyle=(csAuto, csLine, csSides, csCurve, csInvertedSides);
Style := csAuto;
// -------- the connection line itself (it is called "border", but is really a pen)
// property Border:TTreeConnectionPen read GetBorder write SetBorder;
Border.Color := 1277625; //is a nice brown
Border.Style := psSolid;
Border.Width := 3; // the line thickness
end; // end for
end;
end;
{ ====================== }
procedure KillAllConnections;
var k: integer;
begin
for k := 0 to tree1.shapes.count - 1 do begin
tree1.Connections.DeleteAllTo(tree1.shapes[k]); // deletes all connections to this child
// not clear what happens to the associated connection data ??
end; // end for
end;
procedure ReconnectParentsWithKids(const anode:TTreeNodeShape);
var k: integer; knt : integer;
begin
knt := anode.children.count;
if knt =0 then exit;
for k := 0 to knt - 1 do begin
anode.AddconnectionObject(anode.children[k],nil);
end; // end for
for k := 0 to knt - 1 do begin
ReconnectParentsWithKids(anode.children[k]); // recurse down
end;
end;
var k: integer;
begin
tree1.AssignParent := true; // make nodes copy parent properties
tree1.AddRoot('I am root');
tree1.roots[0].color := clYellow;
// ChangeOffsets;
AddKids('top:',tree1.roots[0]);
// second level
for k := 1 to 26 do begin
AddKids('next=',tree1.roots[0].Children[k - 1]);
end; // end for
MakeConnectionsLookNice;
tree1.sort(true, true); // Ascending, IgnoreCase
tree1.invalidate;
{ the above sort results in all the first level connections becoming
"invisible" }
MakeConnectionsLookNice; // does not help
{
we try killing all the connections, then rebuilding them.
This works if the tree is not sorted, but not if it is sorted
- still get connections all over the place
}
KillAllConnections;
assert(tree1.connections.count=0,'should be no connections');
for k := 0 to tree1.Shapes.count-1 do begin
assert(tree1.shapes[k].connections.count =0,' the shape should have no connections');
end; // end for
ReconnectParentsWithKids(tree1.roots[0]);
// check if every node is connected to 1 or 2 others only
for k := 0 to tree1.Shapes.count-1 do begin
assert((tree1.shapes[k].connections.count <=2) and (tree1.shapes[k].connections.count >=1)
,' the shape ' + inttostr(k) +' should have 1 or 2 connections');
end; // end for
assert(tree1.roots[0].children.count=26,' wrong children of root ');
assert(tree1.roots[0].connections.count=26,' wrong connections of root ');
MakeConnectionsLookNice;
tree1.invalidate;
end;