mirror of
https://github.com/projectstorm/react-diagrams.git
synced 2026-03-13 09:50:09 +08:00
Make custom state demo where linking is done by clicking ports
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
import {
|
||||
Action,
|
||||
ActionEvent,
|
||||
InputType,
|
||||
State
|
||||
} from '@projectstorm/react-canvas-core';
|
||||
import { PortModel, LinkModel, DiagramEngine } from '@projectstorm/react-diagrams-core';
|
||||
import { MouseEvent, KeyboardEvent } from 'react';
|
||||
|
||||
/**
|
||||
* This state is controlling the creation of a link.
|
||||
*/
|
||||
export class CreateLinkState extends State<DiagramEngine> {
|
||||
sourcePort: PortModel;
|
||||
link: LinkModel;
|
||||
|
||||
constructor() {
|
||||
super({ name: 'create-new-link' });
|
||||
|
||||
this.registerAction(
|
||||
new Action({
|
||||
type: InputType.MOUSE_UP,
|
||||
fire: (actionEvent: ActionEvent<MouseEvent>) => {
|
||||
const element = this.engine.getActionEventBus().getModelForEvent(actionEvent);
|
||||
const { event: { clientX, clientY } } = actionEvent;
|
||||
const ox = this.engine.getModel().getOffsetX();
|
||||
const oy = this.engine.getModel().getOffsetY();
|
||||
|
||||
if (element instanceof PortModel && !this.sourcePort) {
|
||||
this.sourcePort = element;
|
||||
|
||||
/* would be cool if link creating could be done somewhat like
|
||||
const link = createLink({
|
||||
sourcePort: this.sourcePort,
|
||||
points: [{ x: clientX, y: clientY }, { x: clientX, y: clientY }]
|
||||
})
|
||||
*/
|
||||
const link = this.sourcePort.createLinkModel();
|
||||
link.setSourcePort(this.sourcePort);
|
||||
link.getFirstPoint().setPosition(clientX - ox, clientY - oy);
|
||||
link.getLastPoint().setPosition(clientX - ox + 20, clientY - oy + 20);
|
||||
|
||||
this.link = this.engine.getModel().addLink(link);
|
||||
} else if (element instanceof PortModel && this.sourcePort && element != this.sourcePort) {
|
||||
if (this.sourcePort.canLinkToPort(element)) {
|
||||
this.link.setTargetPort(element);
|
||||
element.reportPosition();
|
||||
this.eject();
|
||||
}
|
||||
} else if (element === this.link.getLastPoint()) {
|
||||
this.link.point(clientX - ox, clientY - oy, -1);
|
||||
}
|
||||
|
||||
this.engine.repaintCanvas();
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
this.registerAction(
|
||||
new Action({
|
||||
type: InputType.MOUSE_MOVE,
|
||||
fire: (actionEvent: ActionEvent<React.MouseEvent>) => {
|
||||
if (!this.link) return;
|
||||
const { event } = actionEvent;
|
||||
this.link.getLastPoint().setPosition(event.clientX, event.clientY);
|
||||
this.engine.repaintCanvas();
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
this.registerAction(
|
||||
new Action({
|
||||
type: InputType.KEY_UP,
|
||||
fire: (actionEvent: ActionEvent<KeyboardEvent>) => {
|
||||
// on esc press remove any started link and pop back to default state
|
||||
if (actionEvent.event.keyCode === 27) {
|
||||
this.link.remove();
|
||||
this.link = undefined;
|
||||
this.sourcePort = undefined;
|
||||
this.eject();
|
||||
this.engine.repaintCanvas();
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import { MouseEvent } from 'react';
|
||||
import {
|
||||
SelectingState,
|
||||
State,
|
||||
Action,
|
||||
InputType,
|
||||
ActionEvent,
|
||||
DragCanvasState
|
||||
} from '@projectstorm/react-canvas-core';
|
||||
import {
|
||||
PortModel,
|
||||
DiagramEngine,
|
||||
DragDiagramItemsState
|
||||
} from '@projectstorm/react-diagrams-core';
|
||||
import { CreateLinkState } from './CreateLinkState';
|
||||
|
||||
export class DefaultState extends State<DiagramEngine> {
|
||||
dragCanvas: DragCanvasState;
|
||||
createLink: CreateLinkState;
|
||||
dragItems: DragDiagramItemsState;
|
||||
|
||||
constructor() {
|
||||
super({ name: 'starting-state' });
|
||||
this.childStates = [new SelectingState()];
|
||||
this.dragCanvas = new DragCanvasState();
|
||||
this.createLink = new CreateLinkState();
|
||||
this.dragItems = new DragDiagramItemsState();
|
||||
|
||||
// determine what was clicked on
|
||||
this.registerAction(
|
||||
new Action({
|
||||
type: InputType.MOUSE_DOWN,
|
||||
fire: (event: ActionEvent<MouseEvent>) => {
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
// move the items (and potentially link points)
|
||||
else {
|
||||
this.transitionWithEvent(this.dragItems, event);
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
this.registerAction(
|
||||
new Action({
|
||||
type: InputType.MOUSE_UP,
|
||||
fire: (event: ActionEvent<MouseEvent>) => {
|
||||
const element = this.engine.getActionEventBus().getModelForEvent(event);
|
||||
|
||||
if (element instanceof PortModel)
|
||||
this.transitionWithEvent(this.createLink, event);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import * as React from 'react';
|
||||
import createEngine, { DiagramModel, DefaultNodeModel } from '@projectstorm/react-diagrams';
|
||||
import { CanvasWidget } from '@projectstorm/react-canvas-core';
|
||||
import { DemoCanvasWidget } from '../helpers/DemoCanvasWidget';
|
||||
import { DefaultState } from './DefaultState';
|
||||
|
||||
export default () => {
|
||||
const engine = createEngine();
|
||||
const model = new DiagramModel();
|
||||
|
||||
const node1 = new DefaultNodeModel('Node 1', 'rgb(0,192,255)');
|
||||
node1.addOutPort('Out');
|
||||
node1.setPosition(100, 100);
|
||||
|
||||
const node2 = new DefaultNodeModel('Node 2', 'rgb(192,255,0)');
|
||||
node2.addInPort('In');
|
||||
node2.setPosition(400, 100);
|
||||
|
||||
model.addAll(node1, node2);
|
||||
|
||||
engine.setModel(model);
|
||||
|
||||
// Use this custom "DefaultState" instead of the actual default state we get with the engine
|
||||
engine.getStateMachine().pushState(new DefaultState());
|
||||
|
||||
return (
|
||||
<DemoCanvasWidget>
|
||||
<CanvasWidget engine={engine} />
|
||||
</DemoCanvasWidget>
|
||||
);
|
||||
};
|
||||
@@ -33,6 +33,7 @@ import demo_listeners from './demos/demo-listeners';
|
||||
import demo_zoom from './demos/demo-zoom-to-fit';
|
||||
import demo_labels from './demos/demo-labelled-links';
|
||||
import demo_dynamic_ports from './demos/demo-dynamic-ports';
|
||||
import demo_alternative_linking from './demos/demo-alternative-linking';
|
||||
|
||||
storiesOf('Simple Usage', module)
|
||||
.add('Simple example', demo_simple)
|
||||
@@ -58,7 +59,8 @@ storiesOf('Advanced Techniques', module)
|
||||
.add('Programatically modifying graph', demo_adv_prog)
|
||||
.add('Drag and drop', demo_adv_dnd)
|
||||
.add('Smart routing', demo_smart_routing)
|
||||
.add('Right angles routing', demo_right_angles_routing);
|
||||
.add('Right angles routing', demo_right_angles_routing)
|
||||
.add('Create link by clicking instead of dragging', demo_alternative_linking);
|
||||
|
||||
import demo_cust_nodes from './demos/demo-custom-node1';
|
||||
import demo_cust_links from './demos/demo-custom-link1';
|
||||
|
||||
@@ -244,8 +244,8 @@ export class LinkModel<G extends LinkModelGenerics = LinkModelGenerics> extends
|
||||
this.fireEvent({ port }, 'targetPortChanged');
|
||||
}
|
||||
|
||||
point(x: number, y: number): PointModel {
|
||||
return this.addPoint(this.generatePoint(x, y));
|
||||
point(x: number, y: number, index: number = 1): PointModel {
|
||||
return this.addPoint(this.generatePoint(x, y), index);
|
||||
}
|
||||
|
||||
addLabel(label: LabelModel) {
|
||||
|
||||
Reference in New Issue
Block a user