As per our requirement -
- User can add multiple nodes and link them .
- On clicking auto arrange button my diagram should get auto arranged automatically.
Our Requirement (Example from some other library)
Before Auto Arrange
After Auto Arrange
While working on GoJS
Before Auto Arrange
After Auto Arrange
What we have tried so far
- Editor (Code)
// Licensed version
myDiagram = $(go.Diagram, “diagram_MBT_Graph”, // must name or refer to the DIV HTML element
{
initialContentAlignment: go.Spot.Center,
draggingTool: new GuidedDraggingTool(), // defined in GuidedDraggingTool.js
“draggingTool.horizontalGuidelineColor”: “blue”,
“draggingTool.verticalGuidelineColor”: “blue”,
“draggingTool.centerGuidelineColor”: “green”,
“draggingTool.guidelineWidth”: 1,
“draggingTool.isCopyEnabled”: false,
“animationManager.isEnabled”: false,
“linkingTool.direction”: go.LinkingTool.ForwardsOnly,
allowDrop: true, // must be true to accept drops from the Palette
“LinkDrawn”: showLinkLabel, // this DiagramEvent listener is defined below
“LinkRelinked”: showLinkLabel,
scrollsPageOnFocus: false,
“undoManager.isEnabled”: true,
allowHorizontalScroll: true,
allowVerticalScroll: true,
}
});
myDiagram.nodeTemplate =
$(go.Node, “Auto”,
{ layoutConditions: go.Part.LayoutAdded | go.Part.LayoutRemoved, zOrder: 2 }, //{ locationSpot: go.Spot.Center, resizable: false, fromSpot: go.Spot.AllSides, toSpot: go.Spot.AllSides, minSize: new go.Size(108, 67) }, new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify), { resizable: false, resizeObjectName: "PANEL", resizeAdornmentTemplate: nodeResizeAdornmentTemplate, desiredSize: new go.Size(108, 67), minSize: new go.Size(108, 67), maxSize: new go.Size(220, 120) }, new go.Binding("angle").makeTwoWay(), new go.Binding("position", "position", go.Point.parse).makeTwoWay(go.Point.stringify), new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify), $(go.Shape, "RoundedRectangle", { parameter1: 2, fill: fill, stroke: "orange", strokeWidth: 2, spot1: new go.Spot(0, 0, 1, 1), spot2: new go.Spot(1, 1, -1, 0), minSize: new go.Size(95, 59), maxSize: new go.Size(220, 120), }, new go.Binding("figure", "figure").makeTwoWay(), new go.Binding("fill", "fill").makeTwoWay(), new go.Binding("stroke", "stroke").makeTwoWay() ),
$(go.Panel, "Vertical", { alignment: go.Spot.Top, stretch: go.GraphObject.Horizontal, minSize: new go.Size(108, 67) }, $(go.Panel, "Table", { background: "lightblue", stretch: go.GraphObject.Horizontal, width: 15.5, height: 13 }, //$("TreeExpanderButton", { alignment: go.Spot.Left }), //$("Button", { alignment: go.Spot.Right, width: 13.5, height: 13.5, visible: false })
$(go.Shape, "StopSign", { alignment: go.Spot.TopLeft, margin: 2, fill: "red", width: 8, height: 8, stroke: null, visible: visible }, new go.Binding("visible", "visible").makeTwoWay())),
$(go.TextBlock, { font: "12px Arial, sans-serif", //stroke: lightText, margin: 4, stretch: go.GraphObject.Horizontal, textAlign: "center", height: 38, maxLines: 3, // cursor: "move", verticalAlignment: go.Spot.Center, editable: true, isMultiline: true, //textValidation: validateText, textEdited: function (textBlock, previousText, currentText) { if (previousText != currentText) { $scope.MBTOperationScope.renameNode(currentText.trim()); } }, }, new go.Binding("text", "text").makeTwoWay())), { contextMenu: $(go.Adornment) }, makePort("T", go.Spot.Top, true, true), makePort("L", go.Spot.Left, true, true), makePort("R", go.Spot.Right, true, true), makePort("B", go.Spot.Bottom, true, true), );
function makePort(name, spot, output, input) {
return $(go.Shape, “Circle”,
{
fill: “gray”,//transparent
stroke: “gray”, // this is changed to “white” in the showPorts function
desiredSize: new go.Size(8, 8),
alignment: spot, alignmentFocus: spot, // align the port on the main Shape
portId: name, // declare this object to be a “port”
fromSpot: spot, toSpot: spot, // declare where links may connect at this port
fromLinkable: output, toLinkable: input, // declare whether the user may draw links to/from here
cursor: “pointer”, // show a different cursor to indicate potential link point
fromLinkableSelfNode: true, fromLinkableDuplicates: true, toLinkableSelfNode: true, toLinkableDuplicates: true,
});
}
myDiagram.linkTemplate = $(go.Link, { relinkableFrom: true, relinkableTo: true, reshapable: true, resegmentable: true, fromLinkable: true, fromLinkableSelfNode: true, fromLinkableDuplicates: true, toLinkable: true, toLinkableSelfNode: true, toLinkableDuplicates: true, zOrder: 1, mouseEnter: function (e, link) { console.log('link focus in'); dataFactory.customNodeObject['e'] = e; dataFactory.customNodeObject['link'] = link; link.findObject("HIGHLIGHT").stroke = "rgba(24,87,255,2.0)"; link.isHighlighted = true;
}, mouseLeave: function (e, link) {
console.log('link focus out'); dataFactory.customNodeObject = new Object(); link.findObject("HIGHLIGHT").stroke = "gray"; link.isHighlighted = false; }, mouseDrop: CheckLockBeforeDragDropOnLink, toShortLength: 2,
}, new go.Binding("points").makeTwoWay(), new go.Binding("zOrder"), new go.Binding("routing", "routing"), new go.Binding("curviness"), $(go.Shape, { stroke: "gray", strokeWidth: 1.5, name: "HIGHLIGHT" }),
$(go.Shape, { fromArrow: "Circle", fill: "gray", strokeWidth: 2, stroke: "gray" }), $(go.Shape, { toArrow: 'Standard', fill: "gray", strokeWidth: 2, stroke: "gray" }),
$(go.Panel, "Auto", { _isLinkLabel: true, cursor: "move" }, // marks this Panel as being a draggable label
$(go.Shape, { isPanelMain: true, fill: "white", stroke: "orange", strokeWidth: 2 }, new go.Binding("stroke", "stroke", function (t) { debugger return t.trim() !== '' }).makeTwoWay() ), $(go.Shape, "StopSign", { alignment: go.Spot.TopLeft, margin: 3, width: 8, height: 8, fill: "red", visible: visible, stroke: null }, new go.Binding("visible", "visible").makeTwoWay()), new go.Binding('visible', 'text', function (t) { return t.trim() !== '' }), $(go.TextBlock, "Label", { margin: 3, editable: true, isMultiline: true, // don't allow embedded newlines textValidation: validateText, segmentIndex: 0, segmentFraction: 0.5, textEdited: function (textBlock, previousText, currentText) { if (previousText != currentText) { var selectedData = myDiagram.selection.first().data; if (selectedData.hasOwnProperty('EdgeID')) { var edgeName = currentText.split('\u00AD'); if (edgeName.length > 1) { edgeName = currentText.split('\u00AD')[1].trim(); } else { edgeName = currentText.trim(); } $scope.MBTOperationScope.renameEdge(edgeName); } } } }, new go.Binding('visible', 'text', function (t) { return t.trim() !== '' }), new go.Binding("text", "text", function (e) { if (e != "") { return "\u00AD " + e; } }).makeTwoWay(), { toolTip: $("ToolTip", new go.Binding("visible", "text", function (t) { if (t.trim('') == "Associated FL Name :") { t = ''; } return !!t; }).ofObject("TB"), $(go.TextBlock, { name: "TB", margin: 4, font: "bold 12px Verdana,serif", stroke: "black" }, new go.Binding("text", "", diagramNodeInfo)) ) } ), { contextMenu: $(go.Adornment) }, new go.Binding("segmentIndex").makeTwoWay(), new go.Binding("segmentFraction").makeTwoWay() ) );
myDiagram.toolManager.linkingTool.temporaryLink.routing = go.Link.Orthogonal;
function SpotLinkingTool() {
debugger
go.LinkingTool.call(this);
}
go.Diagram.inherit(SpotLinkingTool, go.LinkingTool);
function MultiArrowLink() { go.Link.call(this); // this.routing = go.Link.Orthogonal; } go.Diagram.inherit(MultiArrowLink, go.Link);
// produce a Geometry from the Link's route MultiArrowLink.prototype.makeGeometry = function () { debugger // get the Geometry created by the standard behavior var geo = go.Link.prototype.makeGeometry.call(this); if (geo.type !== go.Geometry.Path || geo.figures.length === 0) return geo; var mainfig = geo.figures.elt(0); // assume there's just one PathFigure var mainsegs = mainfig.segments;
var arrowLen = 8; // length for each arrowhead var arrowWid = 3; // actually half-width of each arrowhead var fx = mainfig.startX; var fy = mainfig.startY; for (var i = 0; i < mainsegs.length; i++) { var a = mainsegs.elt(i); // assume each arrowhead is a simple triangle var ax = a.endX; var ay = a.endY; var bx = ax; var by = ay; var cx = ax; var cy = ay; if (fx < ax - arrowLen) { bx -= arrowLen; by += arrowWid; cx -= arrowLen; cy -= arrowWid; } else if (fx > ax + arrowLen) { bx += arrowLen; by += arrowWid; cx += arrowLen; cy -= arrowWid; } else if (fy < ay - arrowLen) { bx -= arrowWid; by -= arrowLen; cx += arrowWid; cy -= arrowLen; } else if (fy > ay + arrowLen) { bx -= arrowWid; by += arrowLen; cx += arrowWid; cy += arrowLen; } geo.add(new go.PathFigure(ax, ay, true) .add(new go.PathSegment(go.PathSegment.Line, bx, by)) .add(new go.PathSegment(go.PathSegment.Line, cx, cy).close())); fx = ax; fy = ay; }
return geo; };
- On Auto Arrange button click
myDiagram.layout =
$(go.LayeredDigraphLayout,
{
direction: 90,
isOngoing: true, // sets the postion of the node to current drag pos
layerSpacing: 50,
setsPortSpots: false,
columnSpacing: 40,
isRouting: true,
isValidLayout: true,
isViewportSized: true,
aggressiveOption: go.LayeredDigraphLayout.AggressiveMore,
cycleRemoveOption: go.LayeredDigraphLayout.CycleDepthFirst,
initializeOption: go.LayeredDigraphLayout.InitDepthFirstOut,
layeringOption: go.LayeredDigraphLayout.LayerOptimalLinkLength,
packOption: go.LayeredDigraphLayout.PackAll
});
myDiagram.layoutDiagram(true)
myDiagram.model = go.Model.fromJson(myDiagram.model.toJSON());
- Problems
- links get hidden behind node
- graph is no precise.