Cancel node selection upon click

Hi,
When my mouse cursor is hovering a node, I wish, at certain circumstances, to avoid node selection upon click.
I was expecting to see in the API something like:
diagram.lastInput.doCancel(), but there isn’t.

There is something related to diagram.lastInput.bubble, and it is not clear if it works the same.
Can anyone clarify this issue?

Thanks,
Ran

That is rather unusual behavior, because many commands operate on the selection, and users are accustomed to selecting something when they click on it.

However, you can make the node not selectable by setting or binding Part.selectable to false. But you haven’t described the circumstances in which you don’t want to select the node upon a click. Do you still want the node to be selectable, but not via a click? If so, then clearly you cannot set/bind selectable to false.

Hi,
Thanks you for the very quick response.
I was trying to avoid a long question, so I’ve spared the circumstances.
In 95% of the cases I DO want the node to be selected regularly.
However, if the user clicks some kind of toolbar in order to make an action (ex. adding a comment), he now has to choose a location on the canvas where to put it.
In case he chooses to stick it on a node, what currently happens is that the node is being selected, instead of adding the comment to the unit.
Few things I have to note:

  • I’ve got the feeling that the select action cancells the ability to attach the comment.
  • When click is over, I wish the comment to be selected, and not the node itself. The user can choose now if he wants to delete it right away or start adding the text to it, w/o the need to select it.
  • Also the cursor is replaced to the ‘move’ cursor, which is not good for us.
  • Off course I want this change to be temporary, only for the next event.

BTW - in the past we used to “drag” the comment into the canvas, so this was probably an easier scenario to deal with, since it didn’t involve a click anywhere on the canvas, only mouseup (to end the dragging) - thus, no conflict with other item selection.

It sounds like you want there to be a different “mode” in which the usual mouse/finger behaviors are quite different and restricted in purpose.

Modes are usually implemented using a separate Tool. When the user clicks the HTML button to go into this “comment” mode, you change the Diagram.currentTool to be an instance of your custom CommentingTool or whatever you want to call that subclass of Tool, and then call Tool.doActivate on that tool.

Please read GoJS Tools -- Northwoods Software

In that subclass you would override all of the relevant Tool methods to do what you want. That would typically include at least the doMouseUp method. Maybe you’ll want to override doActivate and doDeactivate to set up some state and to clean up afterwards.

I’m not sure if you want to make sure it was a click – if so, call Tool.isBeyondDragSize to make sure the mouse up event didn’t happen too far from the mouse down event.

Can you please show me the most relevant example for my usecase?
I searched in the link you’ve provided, there is no mentioning in the code about Diagram.currentTool.
What I DID so there is all kinds of activations like:

myDiagram.toolManager.mouseDownTools.add(new RowResizingTool());
myDiagram.toolManager.mouseDownTools.add(new ColumnResizingTool());
toolManager.mouseWheelBehavior": go.ToolManager.WheelZoom
myDiagram.toolManager.mouseMoveTools.insertAt(2, $(DragCreatingTool,
myDiagram.toolManager.mouseDownTools.insertAt(3, new GeometryReshapingTool());
dragSelectingTool: $(RealtimeDragSelectingTool,
resizingTool: new ResizeMultipleTool(),

If I build a new tool, how do I activate & deactivate? (mouseDownTools sounds good to me)

I activating by using:
myDiagram.toolManager.mouseDownTools.add(new …) is OK?

Not sure I saw any example for the deactivation.
Do i have to go to remove it from that array?

Here’s a complete stand-alone sample:

<!DOCTYPE html>
<html>
<head>
  <title>Modal GoJS Tool</title>
  <!-- Copyright 1998-2023 by Northwoods Software Corporation. -->
  <meta name="description" content="Demonstrate a mode where the user can click to insert a node; the mode is controlled outside of the Diagram">
  <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
  <div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:400px"></div>
  <button id="myTestButton">Start Insertion Mode</button>
  <button id="myStopButton" disabled>Stop Mode</button>
  <textarea id="mySavedModel" style="width:100%;height:350px"></textarea>

  <script src="../release/go.js"></script>
  <script id="code">
const $ = go.GraphObject.make;

const myDiagram =
  new go.Diagram("myDiagramDiv",
    {
      "undoManager.isEnabled": true,
      "ModelChanged": e => {     // just for demonstration purposes,
        if (e.isTransactionFinished) {  // show the model data in the page's TextArea
          document.getElementById("mySavedModel").textContent = e.model.toJson();
        }
      }
    });

myDiagram.nodeTemplate =
  $(go.Node, "Auto",
    new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
    $(go.Shape,
      { fill: "white" },
      new go.Binding("fill", "color")),
    $(go.TextBlock,
      { margin: 8 },
      new go.Binding("text"))
  );

myDiagram.model = new go.GraphLinksModel(
[
  { key: 1, text: "Alpha", color: "lightblue" },
  { key: 2, text: "Beta", color: "orange" },
  { key: 3, text: "Gamma", color: "lightgreen" },
  { key: 4, text: "Delta", color: "pink" }
],
[
  { from: 1, to: 2 },
  { from: 1, to: 3 },
  { from: 2, to: 2 },
  { from: 3, to: 4 },
  { from: 4, to: 1 }
]);

// This custom tool implements a "mode" where the only thing that the user can do
// is click to insert a node or cancel the tool by hitting the Escape key.
class CustomTool extends go.Tool {
  isMultiShot = false;
  doActivate() {
    this.isActive = true;
    this.diagram.defaultCursor = "crosshair";
  }
  doDeactivate() {
    this.isActive = false;
    this.diagram.defaultCursor = "";
    document.getElementById("myStopButton").disabled = true;
  }
  doMouseUp() {
    if (!this.isBeyondDragSize()) {
      this.diagram.model.commit(m => {
        m.addNodeData({
          text: "Inserted by\nCustomTool",
          loc: go.Point.stringify(this.diagram.lastInput.documentPoint),
          color: "magenta"
        });
      });
      // This is a one-shot tool -- it stops after successfully operating by inserting a node.
      // Remove this call if you want the user to be able to keep inserting nodes by clicking.
      // But then you'll need another way to stop this tool unless the user knows that they
      // can cancel the tool by hitting Escape, which is not possible on touch-only devices.
      // So we suggest that you only remove this call if you have that other mechanism,
      // such as the "Stop Mode" button in this sample.
      if (!this.isMultiShot) this.stopTool();
    }
  }
}

document.getElementById("myTestButton").addEventListener("click", e => {
  myDiagram.currentTool = new CustomTool();
  myDiagram.currentTool.doActivate();
  document.getElementById("myStopButton").disabled = false;
});
document.getElementById("myStopButton").addEventListener("click", e => {
  myDiagram.currentTool.stopTool();
});
  </script>
</body>
</html>

[EDIT] I have extended the sample to support multi-shot operation of the CustomTool by allowing removal of the call to Tool.stopTool in the doMouseUp override. Users could then stop the tool by hitting that “Stop Model” HTML button.
[EDIT 2} I have extended it even further by adding a CustomTool.isMultiShot property.