I'm now using GoDiagram Express and we plan a future development and I'm checking the feasability with GoDiagram (or Express).
I need to work with a network view, it means in my case, a tree view, but a sun could have several parents (but general represenattion is like a tree view with some 'parasite' links.
Questions :
- Is that possible in a treeview to have several parent for an elements ? (not so important as far nodes and links will be sufficient)
- My tree has hierachical step that I would show by vertical zones (swim lanes) and I want that my tree is represnted horizontal. Each object kind should go in a zone and a zone only. Is that possible to manage that in GoDiagram, it means :
* Attach an object type in a zone
* The layout functionalities are avalaible respecting the swin lanes
I hope my explanations are understandable ... (below an image)
Yes, both GoLayoutLayeredDigraph and GoLayoutTree allow non-“tree” graphs to be laid out. GoLayoutLayeredDigraph is specifically meant to handle layout with all kinds of multi-“parent” links. GoLayoutTree can also handle the kinds of cases you are probably dealing with.
Of course you can implement your own layout, if you want.
Then you would identify the layers corresponding to the "Zones" that your application understands. That allows you to set up the "swim lanes" to have the size and position that you want. You might find it convenient to use the SwimmingPool and SwimLane classes that are in Demo1. (The GoLayout algorithms do not modify anything but the nodes and links that they work with, so they do not know about any example SwimmingPool classes.)
However, please understand that the SwimLane example in Demo1 may have different behavior than what you want, since it expects the nodes to belong to the SwimLanes, and it does not permit users to drag a node outside of its SwimLane unless it is dropped along the edge of another SwimLane. You may have different drag-and-drop expectations.
Also in the example classes, the user cannot resize individual SwimLanes, but can resize the whole SwimmingPool, and only along one axis. The resizing is also limited to require including the nodes that are in the SwimLanes. Again, you may have different resizing expectations.
If you don't require the drag-and-drop nor the resizing behavior of SwimmingPool and SwimLane, it should be trivial to remove that behavior and just use the SwimmingPool with its SwimLanes as background decoration.
Make some tests, but before to go further, another question
I test the Auto-Layout functionalities (particulary tree), and it works fine.
- Will it be possible to make auto-layout (tree) and that the objects respect their swim lane ?
In the drawing above, imagine a connection from an element A to a new element C. If executing auto-layout without swim lanes, it will be put in column B. I've seen that it is possible to force element with no connection on the right to be at the end of the tree. But in my case, if an element B has no element C, it has to stay in column B.
The natural thing to try is to add a dummy node between A and C, so that the dummy would be assigned the layer B, and thus C is assigned the layer C. This requires modifying the GoLayoutTreeNetwork from the one created by default, before calling PerformLayout().
I 've tried to find out which objects needs a supplementary node (with 2 links). After that I add this node and links to 'layout.Network.AddLink(fromLink);' where my layout is a GoLayoutTree (before performing auto layout). At runtime, Network is null ? Do I have to set something else (I've set the document).
If I'm good understanding we will add the necessary dummy nodes (and links) in the GoLayoutTree for layouting, but the original doc stay as is ?
Or simply asked, what is firing the creation of the Network in the GoLayoutTree ?
Something like this (note: I’m using LayeredDigraph, not Tree, autolayout):
[code] GoLayoutLayeredDigraph layout = new GoLayoutLayeredDigraph(); layout.Document = doc; GoLayoutLayeredDigraphNetwork net = new GoLayoutLayeredDigraphNetwork(doc); foreach (GoObject obj in doc) { IGoLink link = obj as IGoLink; if (link == null) continue; TaskNode aTask = link.FromNode as TaskNode; TaskNode nextTask = link.ToNode as TaskNode; int zonediff = nextTask.Zone - aTask.Zone; if (zonediff <= 1) continue; GoLayoutLayeredDigraphNode fromnode = net.FindNode(aTask); GoLayoutLayeredDigraphNode tonode = net.FindNode(nextTask); for (int i = 0; i < zonediff-1; i++) { GoLayoutLayeredDigraphNode dummy = net.CreateNetworkNode(); dummy.Bounds = new RectangleF(0, 0, 50, 40); net.AddNode(dummy); net.LinkNodes(fromnode, dummy, null); fromnode = dummy; } net.LinkNodes(fromnode, tonode, null); } layout.Network = net; layout.PerformLayout();[/code]
Obviously you'll need to substitute your own mechanism for determining what Zone each node is supposed to be in.
Caution: I haven't even tried compiling this, so I don't know for sure that I don't have an off-by-one error in introducing those intermediate (dummy) nodes into the GoLayoutLayeredDigraphNetwork.
Yes, the idea is not to modify the original GoDocument, just the network that the layout is using to decide what the relationships are.
I test it (with some adaptations) your code, but it doesn't work (same as with simple automatic layout - my node is not put in the right zone)
A simple question : the old link in the created network between object A and B (A in zone 1, B in zone 3) is remaining ? We create a new dummy node in zone 2, with 2 links, but old link stay. Coul it create the problem ?
Thanks
Didier
PS : the correction was in the second loop, <= instead of <
Sorry I try that and it doesn't work ... (just to be sure that we understand each other) :
What I want :
What I obtained :
The code is as followed :
private void treeLayoutButton_Click(object sender, EventArgs e) { GoLayoutTree layout = new GoLayoutTree(); layout.Document = myDocument; GoLayoutTreeNetwork net = new GoLayoutTreeNetwork(myDocument); foreach (GoObject obj in myDocument) { IGoLink link = obj as IGoLink; if (link == null) continue; TEDNode aTask = link.FromNode as TEDNode; TEDNode nextTask = link.ToNode as TEDNode; int zonediff = nextTask.ZoneId - aTask.ZoneId; if (zonediff <= 1) continue; GoLayoutTreeNode fromnode = net.FindNode(aTask); GoLayoutTreeNode tonode = net.FindNode(nextTask); for (int i = 0; i <= zonediff - 2; i++) { GoLayoutTreeNode dummy = net.CreateNetworkNode(); net.AddNode(dummy); net.LinkNodes(fromnode, dummy, null); fromnode = dummy; } net.LinkNodes(fromnode, tonode, null); net.DeleteLink(link); } layout.PerformLayout(); }
I've checked with debugger, the node is added and links done. I don't know why the drawing will not reflect this new network. I'm probbaly missing something, sorry.
Ah, the reason the drawing does not reflect the connectivity of the new network is because after we created it, we threw it away!
There needs to be the statement:
layout.Network = net;
just before the call to PerformLayout().
Also, now that I'm actually trying this code, I notice that the apparent size of the dummy node is zero. If all your nodes are equally sized (well, in your case with equal widths) and you care about lining up the nodes, you need to assign the dummy nodes Bounds to have the normal node size.
Sorry about the confusion. I have updated my original code post with all three code corrections.
Thanks a lot, it works (with GoLayoutLayeredDiGraph).
With the same code with a GoLayoutTree, I receive the following exception (at PerformLayout) :
System.NullReferenceException was unhandled Message="Object reference not set to an instance of an object." Source="Northwoods.Go.Layout" StackTrace: at Northwoods.Go.Layout.GoLayoutTree.AddComments(GoLayoutTreeNode n) at Northwoods.Go.Layout.GoLayoutTree.AnnotateAll() at Northwoods.Go.Layout.GoLayoutTree.PerformLayout()
Comments are searched ? Have I to set something more ?
Sorry for all of these questions (presently it works :-) is is so far very good - thanks a lot).