react-diagrams icon indicating copy to clipboard operation
react-diagrams copied to clipboard

Selected links only by clicking (without key SHIFT)

Open ghost opened this issue 4 years ago • 6 comments

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)

ghost avatar Apr 09 '20 06:04 ghost

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());

renato-bohler avatar Apr 09 '20 11:04 renato-bohler

thank you!

ghost avatar Apr 09 '20 14:04 ghost

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)

viennguyendeveloper avatar Jun 19 '20 04:06 viennguyendeveloper

I added

  fireMouseMoved(event) {
    // do nothing
  }

in SelectLinkState.js to ignore the bug.

viennguyendeveloper avatar Jun 19 '20 09:06 viennguyendeveloper

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.

JSv4 avatar Nov 07 '20 18:11 JSv4

@renato-bohler Hey, i tried your solution and it does not work for me. When i click on the link, event is emitted, but element is instanceof PointModel instead of LinkModel (as stated in your code) Could you help me with this?

mecirmartin avatar Dec 04 '21 16:12 mecirmartin