Reputation: 21
I want to plot a GoJs diagram which follows AlignmentStart pattern. For Every node in tree which have children should come in horizontal arrangement and for every node without children i.e. leaf nodes, should follow vertical arrangement/pattern. This pattern should be followed for nodes at all layers.
I have tried using different layout options to achieve above behavior. I even tried Custom layouts but am unable to handle all cases as my tree can be dynamic i.e. can have multiple layers. Attached is the sample image that i am trying to achieve.
Upvotes: 0
Views: 108
Reputation: 4146
Here's a custom TreeLayout that I believe does what you want:
class ChildlessFirstTreeLayout extends go.TreeLayout {
makeNetwork(coll) {
const net = super.makeNetwork(coll);
new go.Set(net.vertexes).each(parent => {
const childless = new go.Set();
const childparents = new go.Set();
parent.destinationVertexes.each(child => {
if (child.destinationEdges.count === 0) {
childless.add(child);
} else {
childparents.add(child);
}
});
// if there are both childless and child-ful children,
// create dummy vertexes
if (childless.count > 0 && childparents.count > 0) {
// the first dummy is for the childless children
const dummy1 = net.createVertex();
dummy1.copyInheritedPropertiesFrom(this.alternateDefaults);
dummy1.width = dummy1.height = 0;
net.addVertex(dummy1);
net.linkVertexes(parent, dummy1, null);
childless.each(child => {
const parentedge = child.sourceEdges.first();
if (!parentedge) throw new Error("no edge from parent to child???");
parent.deleteDestinationEdge(parentedge);
parentedge.fromVertex = dummy1;
dummy1.addDestinationEdge(parentedge);
});
// the second dummy is for the children that have children
const dummy2 = net.createVertex();
dummy2.copyInheritedPropertiesFrom(this.rootDefaults);
dummy2.width = dummy2.height = 0;
net.addVertex(dummy2);
net.linkVertexes(parent, dummy2, null);
childparents.each(child => {
const parentedge = child.sourceEdges.first();
if (!parentedge) throw new Error("no edge from parent to child???");
parent.deleteDestinationEdge(parentedge);
parentedge.fromVertex = dummy2;
dummy2.addDestinationEdge(parentedge);
});
}
});
return net;
}
assignTreeVertexValues(v) {
// change layout for those vertexes with two dummy children
if (v.childrenCount != 2) return;
if (v.destinationVertexes.any(c => c.node !== null)) return;
v.layerSpacing = 0;
v.nodeIndentPastParent = 0.5;
}
}
You could use it in the following manner:
layout:
$(ChildlessFirstTreeLayout,
{
arrangement: go.TreeLayout.ArrangementHorizontal,
// properties for most of the tree:
angle: 90,
alignment: go.TreeLayout.AlignmentStart,
layerSpacing: 30,
nodeSpacing: 30,
// properties for the "last parents":
treeStyle: go.TreeLayout.StyleLastParents,
alternateAngle: 90,
alternateAlignment: go.TreeLayout.AlignmentBottomRightBus,
alternateLayerSpacing: 30,
alternateNodeSpacing: 30,
alternateRowSpacing: 10,
}),
. . .
A complete stand-alone sample is at: https://gojs.net/extras/DualTreeLayout3.html As always, the complete source code is in the page itself.
Upvotes: 0