Is the problem that the UndoManager is not recording the selection history of the Palette, so that an undo will also change the Palette’s selection?
Or do you not want that behavior when the user does an undo? If not, perhaps you should implement “FinishedUndo” and “FinishedRedo” Model Changed event listeners that reset the Diagram.defaultCursor appropriately based on the Palette’s selection.
Here’s a complete sample:
<!DOCTYPE html>
<html>
<head>
<title>Minimal GoJS Editor</title>
<!-- Copyright 1998-2023 by Northwoods Software Corporation. -->
</head>
<body>
<div style="width: 100%; display: flex; justify-content: space-between">
<div style="display: flex; flex-direction: column; margin: 0 2px 0 0">
<div id="myPaletteDiv" style="flex-grow: 1; width: 100px; background-color: floralwhite; border: solid 1px black"></div>
</div>
<div id="myDiagramDiv" style="flex-grow: 1; height: 400px; border: solid 1px black"></div>
</div>
<div>
<button id="myLoadButton">Load</button>
<button id="mySaveButton">Save</button>
</div>
<textarea id="mySavedModel" style="width:100%;height:200px">
{ "class": "go.GraphLinksModel",
"nodeDataArray": [
{"key":1, "text":"hello", "color":"green", "location":"0 0"},
{"key":2, "text":"world", "color":"red", "location":"70 0"}
],
"linkDataArray": [
{"from":1, "to":2}
]}
</textarea>
<script src="https://unpkg.com/gojs/release/go-debug.js"></script>
<script id="code">
const $ = go.GraphObject.make;
// initialize main Diagram
const myDiagram =
new go.Diagram("myDiagramDiv",
{
"toolManager.standardMouseOver": function() {
if (this.diagram.defaultCursor.startsWith("url")) {
this.diagram.currentCursor = this.diagram.defaultCursor;
return;
}
go.Tool.prototype.standardMouseOver.call(this);
},
"ModelChanged": e => {
if (e.change === go.ChangedEvent.Transaction &&
(e.propertyName === "FinishedUndo" || e.propertyName === "FinishedRedo")) {
updateCursor();
}
},
"clickCreatingTool.isDoubleClick": false, // single click inserts a new node selected in Palette
"defaultTool.doCancel": function() {
go.ToolManager.prototype.doCancel.call(this);
myPalette.clearSelection();
},
"undoManager.isEnabled": true
});
myDiagram.nodeTemplate =
$(go.Node, "Auto",
{ locationSpot: go.Spot.Center, cursor: "crosshair" },
new go.Binding("location", "location", go.Point.parse).makeTwoWay(go.Point.stringify),
$(go.Shape,
{
fill: "white", stroke: "gray", strokeWidth: 2,
portId: "", fromLinkable: true, toLinkable: true,
fromLinkableDuplicates: true, toLinkableDuplicates: true,
fromLinkableSelfNode: true, toLinkableSelfNode: true
},
new go.Binding("stroke", "color")),
$(go.TextBlock,
{
margin: new go.Margin(5, 5, 3, 5), font: "10pt sans-serif",
minSize: new go.Size(16, 16), maxSize: new go.Size(120, NaN),
editable: true
},
new go.Binding("text").makeTwoWay())
);
// initialize Palette
const palTemplate = myDiagram.nodeTemplate.copyTemplate();
palTemplate.cursor = "";
myPalette =
new go.Palette("myPaletteDiv",
{
"ChangedSelection": updateCursor,
nodeTemplate: palTemplate,
model: new go.GraphLinksModel([
{ text: "red node", color: "red" },
{ text: "green node", color: "green" },
{ text: "blue node", color: "blue" },
{ text: "orange node", color: "orange" }
])
});
function updateCursor() {
const node = myPalette.selection.first();
if (node) {
myDiagram.toolManager.clickCreatingTool.archetypeNodeData = node.data;
const b = node.actualBounds;
myDiagram.defaultCursor = //myDiagram.toolManager.draggingTool.copyCursor =
`url(${myPalette.makeImageData({ parts: new go.List().add(node) })}) ${Math.round(b.width/2)} ${Math.round(b.height/2)}, auto`;
} else {
myDiagram.toolManager.clickCreatingTool.archetypeNodeData = null;
//myDiagram.toolManager.draggingTool.copyCursor = "copy";
myDiagram.defaultCursor = "auto";
}
}
// save a model to and load a model from Json text, displayed below the Diagram
function save() {
const str = myDiagram.model.toJson();
document.getElementById("mySavedModel").value = str;
}
document.getElementById("mySaveButton").addEventListener("click", save);
function load() {
const str = document.getElementById("mySavedModel").value;
myDiagram.model = go.Model.fromJson(str);
}
document.getElementById("myLoadButton").addEventListener("click", load);
load();
</script>
</body>
</html>