Changing layout types not quite behaving right

This seems like a simple problem but I can’t figure it out. I give users the option to change the layout from a tree layout to a digraph layout (while the digraph layout is more appropriate, the tree is way faster so I start with the tree). When they change the diagram, the following code is executed:

var $ = go.GraphObject.make;
workItemDiagram.layout = $(go.LayeredDigraphLayout,
{ setsPortSpots: false },
{ layerSpacing: parseFloat(50, 10) });

It works fine and the diagraph is changed. However, the links are still drawn as using the ports set by the tree diagram (which when going from left to right is in on the left side and out on the right). The only way to “fix” this problem that I’ve found is to do something like change the layout to a force directed layout and then back to a digraph layout and then it’s correct.

I think the problem is that I can’t figure out how to get the diagram to redraw the layout from scratch. I’ve tried invalidateLayout but that didn’t seem to work.

Any ideas?

I suspect that your TreeLayout is setting the Link.fromSpot and .toSpot, and then this LayeredDigraphLayout is not setting them, so the Links continue to have the same values. So I suggest that you take out the setsPortSpots: false.

Hi Walter. I gave that a try but when I take out the set port spots, the digraph never behaves correctly and always shows the tree link. For whatever reason (maybe this is just a bug) the diagram is ignoring the setsPortSpots on the first re-draw and I can’t figure out how to refresh the diagram without changing something unrelated.

What do you mean by “shows the tree link”?
Perhaps you could provide a few screenshots showing what you are getting and what you want?

Sorry this is a complete blast from the past. I hadn’t solved this before but I need to figure it out again.

Set as a treeview I correctly get this:

Changing the diagram using the following:

workItemDiagram.layout = g(go.LayeredDigraphLayout,


{ setsPortSpots: false },

{ layerSpacing: parseFloat(100, 25) });

I get the following:

(ignore the labels - they're being drawn wrong because the diagram is being drawn wrong).

Does this point in the right direction? I'm also calling layoutDiagram(true) to try to redraw everything with no luck.

I don’t think anyone can see the images that you posted. You need to upload the images first, in the full post editor of this forum (the Quick Reply editor doesn’t have the button for uploading images).

This is the treeview (I couldn’t get the images to insert even though they uploaded correctly):
https://onedrive.live.com/redir?resid=7C40E6C8524F7A0C!329976&authkey=!AOR6myW3_Y8MqmI&v=3&ithint=photo%2Cpng

This is the same view after I change it to a digraph:
https://onedrive.live.com/redir?resid=7C40E6C8524F7A0C!329975&authkey=!AK0k77582JcAels&v=3&ithint=photo%2Cpng

Sorry about that walter… hopefully these links will work.

I don’t know how your TreeLayout is defined, but why don’t you start off with not setting any of the properties LayeredDigraphLayout.setsPortSpots or TreeLayout.setsPortSpot or TreeLayout.setsChildPortSpot to false.

So that’s the crazy thing. This is my tree view layout setup:

workItemDiagram.layout = g(go.TreeLayout, { layerSpacing: 200, nodeSpacing: 50 });

I literally don’t have anything else there when I set it up. Can I set something to explicitly ignore port spots?

OK, but also remove setting LayeredDigraphLayout.setsPortSpots to false.

No luck. It’s the same situation.

What’s your node template? You aren’t changing any node or link categories (templates) when you are changing the Diagram.layout, are you?

I have three node templates but only one in use for the current diagram:


var workItemDetailTemplate =
g(go.Node, “Spot”,
{
selectionObjectName: “PANEL”,
isTreeExpanded: false,
isTreeLeaf: false,
selectionChanged: nodeSelectionChanged
},
g(go.Panel, “Auto”,
{ name: “PANEL” },
g(go.Shape, “RoundedRectangle”,
{ stroke: “grey” },
{ fill: “white” },
{ name: “background” },
new go.Binding(“fill”, “color”)
), //end rectangle
g(go.Panel, “Table”,
{ defaultAlignment: go.Spot.Left },
g(go.TextBlock, { row: 0, column: 0, margin: 1, font: “10pt Segoe UI” },
{ name: “text1” },
new go.Binding(“text”, “id”)),
g(go.TextBlock, “:”, { row: 0, column: 1, font: “10pt Segoe UI” },
{ name: “text3” }),
g(go.TextBlock, { row: 0, column: 2, margin: 1, font: “10pt Segoe UI” },
{ name: “text2” },
new go.Binding(“text”, “title”)))),
g(“TreeExpanderButton”,
new go.Binding(“alignment”, “alignment”),
new go.Binding(“alignmentFocus”, “alignmentFocus”),
{ visible: true },
{ click: expandNode },
{ name: “treeButton” }
),
{ // this tooltip Adornment is shared by all nodes
toolTip:
g(go.Adornment, “Auto”,
g(go.Shape, { fill: “#FFFFCC” }),
g(go.TextBlock, { margin: 4 }, // the tooltip shows the result of calling nodeInfo(data)
new go.Binding(“text”, “”, nodeInfo))
)
}
);


At the time I’m doing this I’m simply responding to a user desiring to change the diagram type from a tree to a directed links graph. No changes are being made to anything else.


Thanks Walter!

Your node template looks fine.

I took the DOM Tree sample (http://gojs.net/latest/samples/DOMTree.html) and added this function, called from an HTML button:

function toggleLayout() { var $ = go.GraphObject.make; // for conciseness in defining templates myDiagram.startTransaction("tl"); if (myDiagram.layout instanceof go.TreeLayout) { myDiagram.layout = $(go.LayeredDigraphLayout, { columnSpacing: 5, layerSpacing: 10 }); } else { myDiagram.layout = $(go.TreeLayout, { nodeSpacing: 5, layerSpacing: 30 }); } myDiagram.commitTransaction("tl"); }
Clicking the button repeatedly worked just fine, whether the Link template had Link.routing: go.Link.AvoidsNodes or not.

For another sample that dynamically replaces the Diagram.layout, try http://gojs.net/latest/extensions/fishbone.html.

Okay, I have a question on this. I’ve tried this about 20 different ways and I’m getting close, but still not there. I decided to go another way - way than having the routing data bound, I simply created three different link templates and added a category to my link data. Now, when the user changes direction I loop through the link data array and call setCategoryForLinkData (updating the category values directly didn’t seem to work, but no big deal).

After doing this, I still run into the same problem. If I start off as a directed diagram, everything draws correctly and I can change it to a tree just fine. Once I’ve changed it to a tree, when I try to change it back to a directed diagram I end up with the same problem. But here’s the weird part:

  • After I set it to a LayeredDigraph, when I add a completely new node, and its’ links are displayed correct. It looks like this: http://1drv.ms/1BJPvji. It appears that I have no way to go back and fix existing nodes and links (please note that the node types have not changed in any way).

Any other thoughts on this? I must have spent 8 hours trying to get this to work now.

I’m so sorry walter. This is going to go down in history as 8 hours of dumbness… I was using version 1.3. I guess this was a bug. As a last resort I upgraded to 1.4 - all of the problems went away…