How to override Click and Ctrl-Click handling

My diagram uses LayeredDigraphLayout and contains Groups, Nodes, and Links. Those entities are Selectable.

Entities can be selected by clicking the mouse.
Further entities can be selected by ctrl-click.
Currently-selected entities can be deselected by ctrl-click.

I want to intercept these clicks/ctrl-clicks as not all combinations of selection are valid on my diagram.

How can I do this?

One cannot modify the Diagram.Selection collection in selection-related event handlers or listeners such as the “ChangedSelection” DiagramEvent listener.

EDIT: oops, I had just written that you could override the ClickSelectingTool.StandardMouseSelect method. That works, but it doesn’t prevent the CommandHandler.SelectAll command or the DragSelectingTool from selecting all parts or all of the parts that are within a box, which might be an invalid selection combination for your app.

The natural alternative is to override Part.CanSelect on a Node subclass. In your templates you would replace Node with your custom node class name. But even that doesn’t work in general, since one cannot determine ahead of time precisely which Parts the user might try to select later.

What are your selection collection criteria? I’m wondering if the order in which the user selects Parts might matter or not.

For reference, the predefined commands and tools are smart enough to ignore some selected Parts when inapplicable. For example, the DraggingTool cares about whether Parts are movable or copyable, but the CommandHandler.GroupSelection command doesn’t care about those permissions. That’s a better way to design your software, since the same combination of Parts might permit some actions and disallow others.

Is there a way to prevent Ctrl-Click from doing anything?

Override ClickSelectingTool.StandardMouseSelect to do nothing when the Control modifier is true, or else call the super method.

Thanks. Problem solved.

I made the following changes and was able to control the selection behaviour or my application as I desired.

   private void MyJobsFlowDiagram_ChangedSelection(object? sender, DiagramEvent e)
   {
         //bespoke code to process selections
   }

    public class CustomCommandHandler : CommandHandler
    {
        public override void SelectAll()
        {
            return;
        }
    };

    public class CustomClickSelectingTool : ClickSelectingTool
    {
        public override void StandardMouseSelect()
        {
            InputEvent lastInput = MyJobsFlowDiagram.LastInput;
            if (lastInput.Key == "CONTROLKEY")
            {
                lastInput.Key = "";
                return;
            }
            base.StandardMouseSelect();
        }
    }

    public class CustomDragSelectingTool : DragSelectingTool
    {
        public override void SelectInRect(Rect r)
        {
            return;
        }
    }
    MyJobsFlowDiagram.CommandHandler = new CustomCommandHandler();
    MyJobsFlowDiagram.ToolManager.ClickSelectingTool = new CustomClickSelectingTool();
    MyJobsFlowDiagram.ToolManager.DragSelectingTool = new CustomDragSelectingTool();
    MyJobsFlowDiagram.ChangedSelection += MyJobsFlowDiagram_ChangedSelection;

One recommendation I’d made is to check the value of InputEvent.Control rather than the Key. So your StandardMouseSelect override could look like this:

public class CustomClickSelectingTool : ClickSelectingTool {
  public override void StandardMouseSelect() {
    InputEvent lastInput = MyJobsFlowDiagram.LastInput;
    if (lastInput.Control) return;
    base.StandardMouseSelect();
  }
}

Also, it looks like the DragSelectingTool isn’t supposed to do anything.
It might be easier to just disable it, instead of overriding the behavior to do nothing.
Just set Tool.IsEnabled to false.

MyJobsFlowDiagram.ToolManager.DragSelectingTool.IsEnabled = false;

The other benefit of disabling that tool is that other tools can operate instead of having your custom tool run and do nothing, such as the PanningTool.

Thanks - I incorporated both of the above suggestions.