When using Option+drag (Mac) or Ctrl+drag (Windows) to copy a selection that includes a link with adjusting: LinkAdjusting.End, the copied link maintains the original link’s absolute point coordinates
instead of recalculating its route relative to the copied nodes.
Use case:
We allow users to manually reshape orthogonal links. After reshaping, we set adjusting: LinkAdjusting.End to preserve the user’s manual adjustments when nodes are moved. This works correctly for normal node
movement.
Steps to reproduce:
- Create a diagram with 2 nodes connected by an orthogonal link
- Reshape the link by dragging its segment handles
- After reshaping, set link.data.adjusting = go.LinkAdjusting.End (we do this in LinkReshapingTool.doDeactivate)
- Select both nodes and the link (cmnd + A)
- Hold Option (Mac) / Ctrl (Windows) and drag to copy
Actual result:
The copied link visually connects back to the original link’s position. The copied link’s points array contains the same absolute coordinates as the original, causing it to stretch back to those
coordinates.
Expected result:
The copied link should recalculate its route based on the positions of the copied nodes, while ideally preserving the general shape/routing style.
Minimal reproduction:
See attached HTML file.
Question:
What is the recommended approach to handle this scenario? I would expect that it works in the same way as copy pasting and then dragging - keeping
Minimal code for reproduction is attached:
<!DOCTYPE html>
<html>
<head>
<title>GoJS Link Copy Issue - adjusting: End</title>
<script src="https://unpkg.com/gojs/release/go.js"></script>
<style>
#myDiagramDiv {
width: 100%;
height: 600px;
border: 1px solid black;
}
</style>
</head>
<body>
<h3>Steps to reproduce:</h3>
<ol>
<li>Reshape the link by dragging the diamond handles</li>
<li>Select both nodes and the link (Cmd/Ctrl+A)</li>
<li>Hold Option (Mac) / Ctrl (Windows) and drag to copy</li>
</ol>
<p><strong>Issue:</strong> The copied link visually connects back to the original link's position.</p>
<div id="myDiagramDiv"></div>
<script>
const $ = go.GraphObject.make;
const myDiagram = $(go.Diagram, "myDiagramDiv", {
"undoManager.isEnabled": true,
"draggingTool.isCopyEnabled": true,
});
myDiagram.nodeTemplate =
$(go.Node, "Auto",
{ locationSpot: go.Spot.Center },
$(go.Shape, "RoundedRectangle",
{ fill: "lightblue", strokeWidth: 2 },
new go.Binding("fill", "color")
),
$(go.TextBlock,
{ margin: 10, font: "14px sans-serif" },
new go.Binding("text", "name")
)
);
myDiagram.linkTemplate =
$(go.Link,
{
routing: go.Routing.Orthogonal,
adjusting: go.LinkAdjusting.None,
reshapable: true,
resegmentable: true,
},
new go.Binding("adjusting"),
new go.Binding("points").makeTwoWay(),
$(go.Shape, { strokeWidth: 2, stroke: "gray" }),
$(go.Shape, { toArrow: "Standard", stroke: "gray", fill: "gray" })
);
// Set adjusting to End after reshaping to preserve manual adjustments
class CustomLinkReshapingTool extends go.LinkReshapingTool {
doDeactivate() {
const link = this.adornedLink;
if (link) {
myDiagram.model.set(link.data, "adjusting", go.LinkAdjusting.End);
}
super.doDeactivate();
}
}
myDiagram.toolManager.linkReshapingTool = new CustomLinkReshapingTool();
myDiagram.model = new go.GraphLinksModel(
[
{ key: 1, name: "Node 1", color: "lightblue" },
{ key: 2, name: "Node 2", color: "lightgreen" }
],
[
{ from: 1, to: 2 }
]
);
myDiagram.findNodeForKey(1).location = new go.Point(100, 100);
myDiagram.findNodeForKey(2).location = new go.Point(300, 200);
</script>
</body>
</html>