All of the meaningful code in that new sample is in the Form1_Load event handler.
The first part of that method loads the document from the XML using a GoXmlBindingTransformer. That’s new for version 3.0. You could implement precisely the same functionality pretty easily by overriding a few GoXmlTransformer methods in version 2.x. There are some examples of this in the samples as well as in the documentation. For version 3.0 many (most?) of the samples have been converted to use the simpler and more declarative GoXmlBindingTransformer, although some remain because of the flexibility that the more general GoXmlTransformer mechanism affords.
The second part of that Form1_Load method actually does the layout. It does two separate tree layouts. This code should work in version 2.5+ as well as in version 3.0.
First it just operates on the root node and all of the nodes and links that are supposed to grow towards the left. Then it just operates on the root node and all of the nodes and links that are supposed to grow towards the right.
Laying out a subset of the nodes and links is done by initializing a GoLayoutTreeNetwork for the whole document and then removing the GoLayoutTreeNodes that are not going in the desired direction. That also automatically removes the GoLayoutTreeLinks that connect to those deleted nodes.
The winnowing is done by the DeleteNetworkChildren method on each of the nodes that is marked by a particular flag. These nodes are the immediate children of the root node. DeleteNetworkChildren recurses through the subtrees from that point, deleting all of those nodes from the GoLayoutTreeNetwork.
Here’s the whole Form1_Load method, for those who are curious but aren’t curious enough to download the ZIP file:
[code] private void Form1_Load(object sender, EventArgs e) {
goView1.UseWaitCursor = true;
GoDocument doc = goView1.Document;
// load the tree, as nodes and links, from an XML file
using (Stream stream = typeof(Form1).Assembly.GetManifestResourceStream("DoubleTree.data.xml")) {
// construct a prototype node
GoBasicNode protonode = new GoBasicNode();
protonode.Shape = new GoRoundedRectangle();
protonode.LabelSpot = GoObject.Middle;
protonode.Text = "";
protonode.Label.Multiline = true;
GoXmlBindingTransformer tr = new GoXmlBindingTransformer("node", protonode);
tr.AddBinding("text", "Text");
tr.AddBinding("dir", "UserFlags");
tr.AddBinding("color", "Shape.BrushColor");
// construct a prototype link
tr.TreeStructured = true; // XML will consist of nested <node>s
GoLink protolink = new GoLink();
protolink.ToArrow = true;
tr.TreeLinkPrototype = protolink;
GoXmlReader xr = new GoXmlReader();
xr.AddTransformer(tr);
xr.RootObject = doc; // add nodes and links to the view's document
xr.Consume(stream);
}
// automatically layout the graph in two directions by doing two layouts,
// each laying out only the nodes and links in each direction
// grows towards the left
GoLayoutTree lay = new GoLayoutTree();
GoLayoutTreeNetwork net = new GoLayoutTreeNetwork(doc);
// remove all nodes whose "dir" attribute, now stored in UserFlags, means "lay out rightward"
// (this will leave the root node)
foreach (GoObject obj in doc) {
IGoNode node = obj as IGoNode;
if (node != null && (node.UserFlags & 1) == 1) DeleteNetworkChildren(node, net);
}
lay.Document = doc;
lay.Network = net;
lay.Angle = 180;
lay.SetsPortSpot = false;
lay.PerformLayout();
// grows towards the right, but doesn't move the root node positioned by the earlier tree layout
lay = new GoLayoutTree();
net = new GoLayoutTreeNetwork(doc);
// remove all nodes whose "dir" attribute, now stored in UserFlags, means "lay out leftward"
// (this will leave the root node)
foreach (GoObject obj in doc) {
IGoNode node = obj as IGoNode;
if (node != null && (node.UserFlags & 2) == 2) DeleteNetworkChildren(node, net);
}
lay.Document = doc;
lay.Network = net;
lay.Angle = 0;
lay.SetsPortSpot = false;
lay.Arrangement = GoLayoutTreeArrangement.FixedRoots;
lay.PerformLayout();
// make the window fit the graph, which will resize goView1 to fill the client area of the Form
this.ClientSize = new Size((int)goView1.DocumentSize.Width+10, (int)goView1.DocumentSize.Height+10);
// make sure there aren't any unnecessary scrollbars,
// if the GoDocument fits in the GoView at the current GoView.DocScale
goView1.DocPosition = goView1.DocumentTopLeft;
goView1.UseWaitCursor = false;
}
// remove PARENT and all of its children, connected by links from the PARENT node to a child node
private void DeleteNetworkChildren(IGoNode parent, GoLayoutTreeNetwork net) {
if (parent == null) return;
foreach (IGoNode child in parent.Destinations) {
DeleteNetworkChildren(child, net);
}
net.DeleteNode(parent.GoObject);
}[/code]