React-diagrams: Selected links only by clicking (without key SHIFT)

Created on 9 Apr 2020  路  5Comments  路  Source: projectstorm/react-diagrams

I have custom links.
Now they are highlighted only by clicking on the link and key SHIFT. how can I make a link selected by clicking on it (without key SHIFT)

Most helpful comment

I've done this in my project. You can do it by implementing your own state.

SelectLinkState.js

import {
  AbstractDisplacementState,
  Action,
  InputType,
} from '@projectstorm/react-canvas-core';

export default class SelectLinkState extends AbstractDisplacementState {
  constructor() {
    super({ name: 'select-link' });

    this.registerAction(
      new Action({
        type: InputType.MOUSE_DOWN,
        fire: event => {
          const link = this.engine.getMouseElement(event.event);

          if (link.isLocked()) {
            this.eject();
          }

          this.engine.getModel().clearSelection();
          link.setSelected(true);
        },
      }),
    );
  }
}

States.js

import {
  State,
  Action,
  InputType,
} from '@projectstorm/react-canvas-core';
import {
  PortModel,
  LinkModel,
} from '@projectstorm/react-diagrams-core';

import DragCanvasState from './DragCanvasState';
import DragNewLinkState from './DragNewLinkState';
import MoveItemsState from './MoveItemsState';
import SelectingState from './SelectingState';
import SelectLinkState from './SelectLinkState';

/**
 * This class defines custom handlers (called states) to respond to
 * clicking events on certain elements.
 */
export default class States extends State {
  constructor() {
    super({
      name: 'diagram-states',
    });

    // You can grab the default state from `react-diagrams` for every one of these...
    this.childStates = [new SelectingState()];
    this.dragCanvas = new DragCanvasState();
    this.dragNewLink = new DragNewLinkState();
    this.dragItems = new MoveItemsState();

    // But this is a custom one!
   this.selectLink = new SelectLinkState();

    // Determine what was clicked on
    this.registerAction(
      new Action({
        type: InputType.MOUSE_DOWN,
        fire: event => {
          const element = this.engine
            .getActionEventBus()
            .getModelForEvent(event);

          // The canvas was clicked on, transition to the dragging canvas state
          if (!element) {
            this.transitionWithEvent(this.dragCanvas, event);
          }
          // Initiate dragging a new link
          else if (element instanceof PortModel) {
            this.transitionWithEvent(this.dragNewLink, event);
          }
          // Link selection <============================================
          else if (element instanceof LinkModel) {
            this.transitionWithEvent(this.selectLink, event);
          }
          // Move items
          else {
            this.transitionWithEvent(this.dragItems, event);
          }
        },
      }),
    );
  }
}

Register States.js

engine.getStateMachine().pushState(new States());

All 5 comments

I've done this in my project. You can do it by implementing your own state.

SelectLinkState.js

import {
  AbstractDisplacementState,
  Action,
  InputType,
} from '@projectstorm/react-canvas-core';

export default class SelectLinkState extends AbstractDisplacementState {
  constructor() {
    super({ name: 'select-link' });

    this.registerAction(
      new Action({
        type: InputType.MOUSE_DOWN,
        fire: event => {
          const link = this.engine.getMouseElement(event.event);

          if (link.isLocked()) {
            this.eject();
          }

          this.engine.getModel().clearSelection();
          link.setSelected(true);
        },
      }),
    );
  }
}

States.js

import {
  State,
  Action,
  InputType,
} from '@projectstorm/react-canvas-core';
import {
  PortModel,
  LinkModel,
} from '@projectstorm/react-diagrams-core';

import DragCanvasState from './DragCanvasState';
import DragNewLinkState from './DragNewLinkState';
import MoveItemsState from './MoveItemsState';
import SelectingState from './SelectingState';
import SelectLinkState from './SelectLinkState';

/**
 * This class defines custom handlers (called states) to respond to
 * clicking events on certain elements.
 */
export default class States extends State {
  constructor() {
    super({
      name: 'diagram-states',
    });

    // You can grab the default state from `react-diagrams` for every one of these...
    this.childStates = [new SelectingState()];
    this.dragCanvas = new DragCanvasState();
    this.dragNewLink = new DragNewLinkState();
    this.dragItems = new MoveItemsState();

    // But this is a custom one!
   this.selectLink = new SelectLinkState();

    // Determine what was clicked on
    this.registerAction(
      new Action({
        type: InputType.MOUSE_DOWN,
        fire: event => {
          const element = this.engine
            .getActionEventBus()
            .getModelForEvent(event);

          // The canvas was clicked on, transition to the dragging canvas state
          if (!element) {
            this.transitionWithEvent(this.dragCanvas, event);
          }
          // Initiate dragging a new link
          else if (element instanceof PortModel) {
            this.transitionWithEvent(this.dragNewLink, event);
          }
          // Link selection <============================================
          else if (element instanceof LinkModel) {
            this.transitionWithEvent(this.selectLink, event);
          }
          // Move items
          else {
            this.transitionWithEvent(this.dragItems, event);
          }
        },
      }),
    );
  }
}

Register States.js

engine.getStateMachine().pushState(new States());

thank you!

Hi @renato-bohler thank you for your help, it really helpful.
But I got this error when try to click the link and moving.

AbstractDisplacementState.js:54 Uncaught TypeError: _this.fireMouseMoved is not a function
    at Object.fire (AbstractDisplacementState.js:54)
    at ActionEventBus.fireAction (ActionEventBus.js:105)
    at onMouseMove (CanvasWidget.js:141)
    at HTMLUnknownElement.callCallback (react-dom.development.js:189)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:238)
    at invokeGuardedCallback (react-dom.development.js:291)
    at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:306)
    at executeDispatch (react-dom.development.js:391)
    at executeDispatchesInOrder (react-dom.development.js:416)
    at executeDispatchesAndRelease (react-dom.development.js:3301)
    at executeDispatchesAndReleaseTopLevel (react-dom.development.js:3310)
    at forEachAccumulated (react-dom.development.js:3282)
    at runEventsInBatch (react-dom.development.js:3327)
    at runExtractedPluginEventsInBatch (react-dom.development.js:3537)
    at handleTopLevel (react-dom.development.js:3581)
    at batchedEventUpdates$1 (react-dom.development.js:21729)
    at batchedEventUpdates (react-dom.development.js:798)
    at dispatchEventForLegacyPluginEventSystem (react-dom.development.js:3591)
    at attemptToDispatchEvent (react-dom.development.js:4311)
    at dispatchEvent (react-dom.development.js:4232)
    at unstable_runWithPriority (scheduler.development.js:659)
    at dispatchUserBlockingUpdate (react-dom.development.js:4215)

I added

  fireMouseMoved(event) {
    // do nothing
  }

in SelectLinkState.js to ignore the bug.

If anyone is looking for solution to select a link WITHOUT pressing SHIFT WITHOUT CREATING A NODE, this solution works perfectly when combined with setting the maximum number of nodes per link to 0 as discussed in this issue: https://github.com/projectstorm/react-diagrams/issues/49

Combining both of these, users can now select a link purely without a mouse without also creating a node.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

DanieLazarLDAPPS picture DanieLazarLDAPPS  路  3Comments

abhijitnandy2011 picture abhijitnandy2011  路  3Comments

Nesterov-Konstantin picture Nesterov-Konstantin  路  4Comments

kmannislands picture kmannislands  路  3Comments

dixitk13 picture dixitk13  路  3Comments