Hello,
I took an example of adding Assistants from your site ( Org Chart Editor with Assistants )
I need to change alignment and ordering for this.
Alignment
When even elements Alignment is OK.
Alignment is staggered when odd elements.
I need that elements on the left side will be on the contrary of right side.
How to do it?
Order
Order changes when I add new Assistant. There is different order for even and odd elements. There is wrong order for even elements.
for 1 element order is OK
for 3 elements order is OK
for 2 elements order is WRONG
for 4 elements order is WRONG
what should I do to set right order for even elements?
2 -
4 -
You could test it here Plunker - Gojs Assistant (click right mouse button on Node and add Assistant)
Here’s a version of SideTreeLayout that sorts assistants.
// This is a custom TreeLayout that knows about "assistants".
// A Node for which isAssistant(n) is true will be placed at the side below the parent node
// but above all of the other child nodes.
// An assistant node may be the root of its own subtree.
// An assistant node may have its own assistant nodes.
function SideTreeLayout() {
go.TreeLayout.call(this);
}
go.Diagram.inherit(SideTreeLayout, go.TreeLayout);
SideTreeLayout.prototype.makeNetwork = function(coll) {
var net = go.TreeLayout.prototype.makeNetwork.call(this, coll);
// copy the collection of TreeVertexes, because we will modify the network
var vertexcoll = new go.Set(go.TreeVertex);
vertexcoll.addAll(net.vertexes);
for (var it = vertexcoll.iterator; it.next() ;) {
var parent = it.value;
// count the number of assistants
var acount = 0;
var ait = parent.destinationVertexes;
while (ait.next()) {
if (isAssistant(ait.value.node)) acount++;
}
// if a vertex has some number of children that should be assistants
if (acount > 0) {
// remember the assistant edges and the regular child edges
var asstedges = new go.Set(go.TreeEdge);
var childedges = new go.Set(go.TreeEdge);
var eit = parent.destinationEdges;
while (eit.next()) {
var e = eit.value;
if (isAssistant(e.toVertex.node)) {
asstedges.add(e);
} else {
childedges.add(e);
}
}
// first remove all edges from PARENT
eit = asstedges.iterator;
while (eit.next()) { parent.deleteDestinationEdge(eit.value); }
eit = childedges.iterator;
while (eit.next()) { parent.deleteDestinationEdge(eit.value); }
// if the number of assistants is odd, add a dummy assistant, to make the count even
if (acount % 2 == 1) {
var dummy = net.createVertex();
dummy.bounds = asstedges.first().toVertex.bounds;
net.addVertex(dummy);
net.linkVertexes(parent, dummy, asstedges.first().link);
}
// now PARENT should get all of the assistant children
eit = asstedges.iterator;
while (eit.next()) {
parent.addDestinationEdge(eit.value);
}
// create substitute vertex to be new parent of all regular children
var subst = net.createVertex();
net.addVertex(subst);
// reparent regular children to the new substitute vertex
eit = childedges.iterator;
while (eit.next()) {
var ce = eit.value;
ce.fromVertex = subst;
subst.addDestinationEdge(ce);
}
// finally can add substitute vertex as the final odd child,
// to be positioned at the end of the PARENT's immediate subtree.
var newedge = net.linkVertexes(parent, subst, null);
}
}
return net;
};
SideTreeLayout.prototype.assignTreeVertexValues = function(v) {
// if a vertex has any assistants, use Bus alignment
var any = false;
var children = v.children;
for (var i = 0; i < children.length; i++) {
var c = children[i];
if (isAssistant(c.node)) {
any = true;
break;
}
}
if (any) {
// this is the parent for the assistant(s)
v.alignment = go.TreeLayout.AlignmentBus; // this is required
v.nodeSpacing = 50; // control the distance of the assistants from the parent's main links
} else if (v.node == null && v.childrenCount > 0) {
// found the substitute parent for non-assistant children
//v.alignment = go.TreeLayout.AlignmentCenterChildren;
//v.breadthLimit = 3000;
v.layerSpacing = 0;
}
};
SideTreeLayout.prototype.sortTreeVertexChildren = function(v) {
var arr = []; // assistants
var other = []; // non-assistants
var children = v.children;
for (var i = 0; i < children.length; i++) {
var c = children[i];
if (isAssistant(c.node)) arr.push(c); else other.push(c);
}
// only sort assistants
arr.sort(function(va, vb) {
if (va.node === null) return 1;
var da = va.node.data;
if (da === null) return 1;
if (vb.node === null) return -1;
var db = vb.node.data;
if (db === null) return -1;
if (da.key < db.key) return -1;
if (da.key > db.key) return 1;
return 0;
});
for (var i = 0; i < arr.length; i++) {
children[i] = arr[i];
}
for (var j = 0; j < other.length; j++) {
children[i++] = other[j];
}
};
SideTreeLayout.prototype.setPortSpots = function(v) {
// if a vertex has any assistants, use Bus alignment
var any = false;
var children = v.children;
var childrenLength = children.length;
for (var i = 0; i < childrenLength; i++) {
var c = children[i];
if (isAssistant(c.node)) {
any = true;
break;
}
}
if (any) {
var angle = v.angle;
var parentspot;
switch (angle) {
case 0: parentspot = go.Spot.MiddleRight; break;
case 90: parentspot = go.Spot.MiddleBottom; break;
case 180: parentspot = go.Spot.MiddleLeft; break;
default: parentspot = go.Spot.MiddleTop; break;
}
for (var i = 0; i < childrenLength; i++) {
var c = children[i];
var e = c.sourceEdges.first();
if (c.node === null || e === null || e.link === null) continue;
var childspot = (angle === 90 || angle === 270) ? go.Spot.MiddleLeft : go.Spot.MiddleTop;
if (childrenLength === 1 || (i === childrenLength - 1 && childrenLength % 2 === 1)) {
switch (angle) {
case 0: childspot = go.Spot.MiddleLeft; break;
case 90: childspot = go.Spot.MiddleTop; break;
case 180: childspot = go.Spot.MiddleRight; break;
default: childspot = go.Spot.MiddleBottom; break;
}
} else {
if (i % 2 === 0) {
childspot = (angle === 90 || angle === 270) ? go.Spot.MiddleRight : go.Spot.MiddleBottom;
}
}
if (v.setsPortSpot) e.link.fromSpot = parentspot;
if (v.setsChildPortSpot) e.link.toSpot = childspot;
}
} else {
go.TreeLayout.prototype.setPortSpots.call(this, v);
}
};
SideTreeLayout.prototype.commitLinks = function() {
go.TreeLayout.prototype.commitLinks.call(this);
// make sure the middle segment of an orthogonal link does not cross over the assistant subtree
var eit = this.network.edges.iterator;
while (eit.next()) {
var e = eit.value;
if (e.link == null) continue;
var r = e.link;
// does this edge come from a substitute parent vertex?
var subst = e.fromVertex;
if (subst.node == null && r.routing == go.Link.Orthogonal) {
r.updateRoute();
r.startRoute();
// middle segment goes from point 2 to point 3
var p1 = subst.center; // assume artificial vertex has zero size
var p2 = r.getPoint(2).copy();
var p3 = r.getPoint(3).copy();
var p5 = r.getPoint(r.pointsCount - 1);
var dist = 10;
if (subst.angle == 270 || subst.angle == 180) dist = -20;
if (subst.angle == 90 || subst.angle == 270) {
p2.y = p5.y - dist; // (p1.y+p5.y)/2;
p3.y = p5.y - dist; // (p1.y+p5.y)/2;
} else {
p2.x = p5.x - dist; // (p1.x+p5.x)/2;
p3.x = p5.x - dist; // (p1.x+p5.x)/2;
}
r.setPoint(2, p2);
r.setPoint(3, p3);
r.commitRoute();
}
}
}; // end of SideTreeLayout
_subGraphToggle (e, button) {
let group = button.part;
if (group instanceof go.Adornment) group = group.adornedPart;
if (!(group instanceof go.Group)) return;
let diagram = group.diagram;
if (diagram === null) return;
group.memberParts.each((position) => {
if (position.isSelected) {
diagram.clearSelection();
}
});
let cmd = diagram.commandHandler;
if (group.isSubGraphExpanded) {
if (!cmd.canCollapseSubGraph(group)) return;
} else {
if (!cmd.canExpandSubGraph(group)) return;
}
e.handled = true;
if (group.isSubGraphExpanded) {
cmd.collapseSubGraph(group);
} else {
cmd.expandSubGraph(group); // <- this is the beginning of error
}
const rect = group.actualBounds;
let height = Math.min(rect.height, group.diagram.viewportBounds.height);
group.diagram.scrollToRect(new go.Rect(rect.x, rect.y, rect.width, height));
}
without functions sortTreeVertexChildren and setPortSpots it works fine
Before I gave you the code above, and just now, I used the enhanced SideTreeLayout in my modified Org Chart Assistants sample. I tried a lot of graphs to make sure that everything worked. Or at least seemed to, without any errors.
So I don’t know how to reproduce the problem. Can you give me a reproducible case? Precisely which version of GoJS are you using?