reformat code

This commit is contained in:
Dylan Vorster
2018-02-24 18:44:28 +02:00
parent 070ed985f6
commit e2285cec16
42 changed files with 300 additions and 351 deletions

View File

@ -12,11 +12,10 @@ import {
import { action } from "@storybook/addon-actions"; import { action } from "@storybook/addon-actions";
import * as React from "react"; import * as React from "react";
import { LinkFactory } from "../../src/AbstractFactory"; import { LinkFactory } from "../../src/AbstractFactory";
import {DefaultLinkModel} from "../../src/defaults/models/DefaultLinkModel"; import { DefaultLinkModel } from "../../src/defaults/models/DefaultLinkModel";
import {DefaultLinkFactory} from "../../src/defaults/factories/DefaultLinkFactory"; import { DefaultLinkFactory } from "../../src/defaults/factories/DefaultLinkFactory";
export class AdvancedLinkModel extends DefaultLinkModel { export class AdvancedLinkModel extends DefaultLinkModel {
constructor() { constructor() {
super("advanced"); super("advanced");
this.width = 10; this.width = 10;
@ -24,61 +23,57 @@ export class AdvancedLinkModel extends DefaultLinkModel {
} }
export class AdvancedPortModel extends DefaultPortModel { export class AdvancedPortModel extends DefaultPortModel {
createLinkModel(): AdvancedLinkModel | null { createLinkModel(): AdvancedLinkModel | null {
return new AdvancedLinkModel(); return new AdvancedLinkModel();
} }
} }
export class AdvancedLinkSegment extends React.Component<{model: AdvancedLinkModel, path: string}>{ export class AdvancedLinkSegment extends React.Component<{ model: AdvancedLinkModel; path: string }> {
path: SVGPathElement; path: SVGPathElement;
circle: SVGCircleElement; circle: SVGCircleElement;
callback : () => any; callback: () => any;
percent: number; percent: number;
handle: any; handle: any;
mounted: boolean; mounted: boolean;
constructor(props){ constructor(props) {
super(props); super(props);
this.percent = 0; this.percent = 0;
} }
componentDidMount(){ componentDidMount() {
this.mounted = true; this.mounted = true;
this.callback = () => { this.callback = () => {
if(!this.circle || !this.path){ if (!this.circle || !this.path) {
return; return;
} }
this.percent+=2; this.percent += 2;
if(this.percent > 100){ if (this.percent > 100) {
this.percent = 0; this.percent = 0;
} }
let point = this.path.getPointAtLength(this.path.getTotalLength() * (this.percent / 100.0));
let point = this.path.getPointAtLength(this.path.getTotalLength()*(this.percent/100.0)); this.circle.setAttribute("cx", "" + point.x);
this.circle.setAttribute("cy", "" + point.y);
this.circle.setAttribute('cx', ""+point.x); if (this.mounted) {
this.circle.setAttribute('cy', ""+point.y);
if(this.mounted){
requestAnimationFrame(this.callback); requestAnimationFrame(this.callback);
} }
} };
requestAnimationFrame(this.callback); requestAnimationFrame(this.callback);
} }
componentWillUnmount(){ componentWillUnmount() {
this.mounted = false; this.mounted = false;
} }
render() {
render(){
return ( return (
<> <>
<path <path
ref={(ref) => { ref={ref => {
this.path = ref; this.path = ref;
}} }}
strokeWidth={this.props.model.width} strokeWidth={this.props.model.width}
@ -86,10 +81,11 @@ export class AdvancedLinkSegment extends React.Component<{model: AdvancedLinkMod
d={this.props.path} d={this.props.path}
/> />
<circle <circle
ref={(ref) => { ref={ref => {
this.circle = ref; this.circle = ref;
}} }}
r={10} fill="orange" r={10}
fill="orange"
/> />
</> </>
); );
@ -97,10 +93,9 @@ export class AdvancedLinkSegment extends React.Component<{model: AdvancedLinkMod
} }
export class AdvancedLinkFactory extends DefaultLinkFactory { export class AdvancedLinkFactory extends DefaultLinkFactory {
constructor() { constructor() {
super(); super();
this.type = "advanced" this.type = "advanced";
} }
getNewInstance(initialConfig?: any): AdvancedLinkModel { getNewInstance(initialConfig?: any): AdvancedLinkModel {
@ -108,9 +103,12 @@ export class AdvancedLinkFactory extends DefaultLinkFactory {
} }
generateLinkSegment(model: AdvancedLinkModel, selected: boolean, path: string) { generateLinkSegment(model: AdvancedLinkModel, selected: boolean, path: string) {
return <g><AdvancedLinkSegment model={model} path={path} /></g>; return (
<g>
<AdvancedLinkSegment model={model} path={path} />
</g>
);
} }
} }
/** /**
* *

View File

@ -1,5 +1,5 @@
import * as SRD from "../../src/main"; import * as SRD from "../../src/main";
import {DiamonNodeWidget} from "./DiamondNodeWidget"; import { DiamonNodeWidget } from "./DiamondNodeWidget";
import { DiamondNodeModel } from "./DiamondNodeModel"; import { DiamondNodeModel } from "./DiamondNodeModel";
import * as React from "react"; import * as React from "react";
@ -9,7 +9,7 @@ export class DiamondNodeFactory extends SRD.NodeFactory {
} }
generateReactWidget(diagramEngine: SRD.DiagramEngine, node: SRD.NodeModel): JSX.Element { generateReactWidget(diagramEngine: SRD.DiagramEngine, node: SRD.NodeModel): JSX.Element {
return <DiamonNodeWidget node={node} /> return <DiamonNodeWidget node={node} />;
} }
getNewInstance() { getNewInstance() {

View File

@ -2,7 +2,6 @@ import * as SRD from "../../src/main";
import { DiamondPortModel } from "./DiamondPortModel"; import { DiamondPortModel } from "./DiamondPortModel";
export class DiamondNodeModel extends SRD.NodeModel { export class DiamondNodeModel extends SRD.NodeModel {
constructor() { constructor() {
super("diamond"); super("diamond");
this.addPort(new DiamondPortModel("top")); this.addPort(new DiamondPortModel("top"));

View File

@ -102,4 +102,4 @@ export class DiamonNodeWidget extends React.Component<DiamonNodeWidgetProps, Dia
</div> </div>
); );
} }
} }

View File

@ -1,8 +1,8 @@
import * as _ from "lodash"; import * as _ from "lodash";
import {LinkModel} from "../../src/models/LinkModel"; import { LinkModel } from "../../src/models/LinkModel";
import {DiagramEngine} from "../../src/DiagramEngine"; import { DiagramEngine } from "../../src/DiagramEngine";
import {PortModel} from "../../src/models/PortModel"; import { PortModel } from "../../src/models/PortModel";
import {DefaultLinkModel} from "../../src/defaults/models/DefaultLinkModel"; import { DefaultLinkModel } from "../../src/defaults/models/DefaultLinkModel";
export class DiamondPortModel extends PortModel { export class DiamondPortModel extends PortModel {
position: string | "top" | "bottom" | "left" | "right"; position: string | "top" | "bottom" | "left" | "right";
@ -23,7 +23,7 @@ export class DiamondPortModel extends PortModel {
this.position = data.position; this.position = data.position;
} }
createLinkModel(): LinkModel{ createLinkModel(): LinkModel {
return new DefaultLinkModel(); return new DefaultLinkModel();
} }
} }

View File

@ -31,7 +31,7 @@ export default () => {
//3-A) create a default node //3-A) create a default node
var node1 = new DefaultNodeModel("Node 1", "rgb(0,192,255)"); var node1 = new DefaultNodeModel("Node 1", "rgb(0,192,255)");
var port1 = node1.addOutPort("Out") var port1 = node1.addOutPort("Out");
node1.setPosition(100, 150); node1.setPosition(100, 150);
//3-B) create our new custom node //3-B) create our new custom node
@ -39,12 +39,12 @@ export default () => {
node2.setPosition(250, 108); node2.setPosition(250, 108);
var node3 = new DefaultNodeModel("Node 3", "red"); var node3 = new DefaultNodeModel("Node 3", "red");
var port3 = node3.addInPort("In") var port3 = node3.addInPort("In");
node3.setPosition(500, 150); node3.setPosition(500, 150);
//3-C) link the 2 nodes together //3-C) link the 2 nodes together
var link1 = port1.link(node2.getPort('left')); var link1 = port1.link(node2.getPort("left"));
var link2 = port3.link(node2.getPort('right')); var link2 = port3.link(node2.getPort("right"));
//4) add the models to the root graph //4) add the models to the root graph
model.addAll(node1, node2, node3, link1, link2); model.addAll(node1, node2, node3, link1, link2);

View File

@ -30,7 +30,6 @@ function connectNodes(nodeFrom, nodeTo) {
* Tests auto distribution * Tests auto distribution
*/ */
class Demo8Widget extends React.Component<any, any> { class Demo8Widget extends React.Component<any, any> {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = {}; this.state = {};

View File

@ -3,10 +3,7 @@ import * as _ from "lodash";
import { TrayWidget } from "./TrayWidget"; import { TrayWidget } from "./TrayWidget";
import { Application } from "../Application"; import { Application } from "../Application";
import { TrayItemWidget } from "./TrayItemWidget"; import { TrayItemWidget } from "./TrayItemWidget";
import { import { DefaultNodeModel, DiagramWidget } from "../../../src/main";
DefaultNodeModel,
DiagramWidget
} from "../../../src/main";
export interface BodyWidgetProps { export interface BodyWidgetProps {
app: Application; app: Application;
@ -48,10 +45,10 @@ export class BodyWidget extends React.Component<BodyWidgetProps, BodyWidgetState
var node = null; var node = null;
if (data.type === "in") { if (data.type === "in") {
node = new DefaultNodeModel("Node " + (nodesCount + 1), "rgb(192,255,0)"); node = new DefaultNodeModel("Node " + (nodesCount + 1), "rgb(192,255,0)");
node.addInPort('In'); node.addInPort("In");
} else { } else {
node = new DefaultNodeModel("Node " + (nodesCount + 1), "rgb(0,192,255)"); node = new DefaultNodeModel("Node " + (nodesCount + 1), "rgb(0,192,255)");
node.addOutPort('Out') node.addOutPort("Out");
} }
var points = this.props.app.getDiagramEngine().getRelativeMousePoint(event); var points = this.props.app.getDiagramEngine().getRelativeMousePoint(event);
node.x = points.x; node.x = points.x;

View File

@ -1,10 +1,4 @@
import { import { DiagramEngine, DiagramModel, DefaultNodeModel, LinkModel, DiagramWidget } from "../../src/main";
DiagramEngine,
DiagramModel,
DefaultNodeModel,
LinkModel,
DiagramWidget
} from "../../src/main";
import * as React from "react"; import * as React from "react";
/** /**
@ -39,5 +33,5 @@ export default () => {
engine.setDiagramModel(model); engine.setDiagramModel(model);
//6) render the diagram! //6) render the diagram!
return <DiagramWidget diagramEngine={engine}/>; return <DiagramWidget diagramEngine={engine} />;
}; };

View File

@ -9,7 +9,7 @@ import {
import * as React from "react"; import * as React from "react";
import { DemoWorkspaceWidget } from "../.helpers/DemoWorkspaceWidget"; import { DemoWorkspaceWidget } from "../.helpers/DemoWorkspaceWidget";
import { action } from "@storybook/addon-actions"; import { action } from "@storybook/addon-actions";
import {DefaultLinkModel} from "../../src/defaults/models/DefaultLinkModel"; import { DefaultLinkModel } from "../../src/defaults/models/DefaultLinkModel";
export default () => { export default () => {
// setup the diagram engine // setup the diagram engine
@ -22,19 +22,19 @@ export default () => {
// create four nodes // create four nodes
const node1 = new DefaultNodeModel("Node A", "rgb(0,192,255)"); const node1 = new DefaultNodeModel("Node A", "rgb(0,192,255)");
const port1 = node1.addOutPort("Out"); const port1 = node1.addOutPort("Out");
node1.setPosition(100,100); node1.setPosition(100, 100);
const node2 = new DefaultNodeModel("Node B", "rgb(255,255,0)"); const node2 = new DefaultNodeModel("Node B", "rgb(255,255,0)");
const port2 = node2.addInPort("In"); const port2 = node2.addInPort("In");
node2.setPosition(400,50); node2.setPosition(400, 50);
const node3 = new DefaultNodeModel("Node C (no label)", "rgb(192,255,255)"); const node3 = new DefaultNodeModel("Node C (no label)", "rgb(192,255,255)");
const port3 = node3.addInPort("In"); const port3 = node3.addInPort("In");
node3.setPosition(450,180); node3.setPosition(450, 180);
const node4 = new DefaultNodeModel("Node D", "rgb(192,0,255)"); const node4 = new DefaultNodeModel("Node D", "rgb(192,0,255)");
const port4 = node4.addInPort("In"); const port4 = node4.addInPort("In");
node4.setPosition(300,250); node4.setPosition(300, 250);
// link node A and B together and give it a label // link node A and B together and give it a label
const link1 = port1.link(port2); const link1 = port1.link(port2);

View File

@ -19,11 +19,11 @@ export default () => {
node1.setPosition(100, 100); node1.setPosition(100, 100);
var node2 = new DefaultNodeModel("Node 2", "rgb(192,255,0)"); var node2 = new DefaultNodeModel("Node 2", "rgb(192,255,0)");
var port2 = node2.addInPort('In'); var port2 = node2.addInPort("In");
node2.setPosition(400, 40); node2.setPosition(400, 40);
var node3 = new DefaultNodeModel("Node 3", "rgb(128,99,255)"); var node3 = new DefaultNodeModel("Node 3", "rgb(128,99,255)");
var port3 = node3.addInPort('In'); var port3 = node3.addInPort("In");
node3.setPosition(300, 160); node3.setPosition(300, 160);
//link the nodes //link the nodes

View File

@ -1,8 +1,6 @@
import * as SRD from "../../src/main"; import * as SRD from "../../src/main";
import * as React from "react"; import * as React from "react";
import { import { DiagramEngine, DiagramModel, DefaultNodeModel, LinkModel, PointModel, DiagramWidget } from "../../src/main";
DiagramEngine, DiagramModel, DefaultNodeModel, LinkModel, PointModel, DiagramWidget
} from "../../src/main";
/** /**
* *
@ -19,11 +17,11 @@ export default () => {
// sample for link with simple line (no additional points) // sample for link with simple line (no additional points)
var node1 = new DefaultNodeModel("Node 1", "rgb(0,192,255)"); var node1 = new DefaultNodeModel("Node 1", "rgb(0,192,255)");
var port1 = node1.addOutPort('Out'); var port1 = node1.addOutPort("Out");
node1.setPosition(100, 100); node1.setPosition(100, 100);
var node2 = new DefaultNodeModel("Node 2", "rgb(192,255,0)"); var node2 = new DefaultNodeModel("Node 2", "rgb(192,255,0)");
var port2 = node2.addInPort('In'); var port2 = node2.addInPort("In");
node2.setPosition(400, 100); node2.setPosition(400, 100);
let link1 = port1.link(port2); let link1 = port1.link(port2);
@ -32,11 +30,11 @@ export default () => {
// sample for link with complex line (additional points) // sample for link with complex line (additional points)
var node3 = new DefaultNodeModel("Node 3", "rgb(0,192,255)"); var node3 = new DefaultNodeModel("Node 3", "rgb(0,192,255)");
var port3 = node3.addOutPort('Out'); var port3 = node3.addOutPort("Out");
node3.setPosition(100, 250); node3.setPosition(100, 250);
var node4 = new DefaultNodeModel("Node 4", "rgb(192,255,0)"); var node4 = new DefaultNodeModel("Node 4", "rgb(192,255,0)");
var port4 = node4.addInPort('In'); var port4 = node4.addInPort("In");
node4.setPosition(400, 250); node4.setPosition(400, 250);
var link2 = port3.link(port4); var link2 = port3.link(port4);

View File

@ -1,10 +1,4 @@
import { import { DiagramEngine, DiagramModel, DefaultNodeModel, LinkModel, DiagramWidget } from "../../src/main";
DiagramEngine,
DiagramModel,
DefaultNodeModel,
LinkModel,
DiagramWidget
} from "../../src/main";
import * as React from "react"; import * as React from "react";
import { DemoWorkspaceWidget } from "../.helpers/DemoWorkspaceWidget"; import { DemoWorkspaceWidget } from "../.helpers/DemoWorkspaceWidget";
@ -46,8 +40,12 @@ class NodeDelayedPosition extends React.Component<any, any> {
return ( return (
<DemoWorkspaceWidget <DemoWorkspaceWidget
buttons={[ buttons={[
<button key={1} onClick={this.updatePosition}>Update position</button>, <button key={1} onClick={this.updatePosition}>
<button key={2} onClick={this.updatePositionViaSerialize}>Update position via serialize</button> Update position
</button>,
<button key={2} onClick={this.updatePositionViaSerialize}>
Update position via serialize
</button>
]} ]}
> >
<DiagramWidget diagramEngine={engine} /> <DiagramWidget diagramEngine={engine} />

View File

@ -1,10 +1,4 @@
import { import { DiagramEngine, DiagramModel, DefaultNodeModel, LinkModel, DiagramWidget } from "../../src/main";
DiagramEngine,
DiagramModel,
DefaultNodeModel,
LinkModel,
DiagramWidget
} from "../../src/main";
import * as React from "react"; import * as React from "react";
/** /**
@ -23,7 +17,7 @@ export default () => {
//3-A) create a default node //3-A) create a default node
var node1 = new DefaultNodeModel("Node 1", "rgb(0,192,255)"); var node1 = new DefaultNodeModel("Node 1", "rgb(0,192,255)");
var port1 = node1.addOutPort("Out"); var port1 = node1.addOutPort("Out");
node1.setPosition(100 + offsetX, 100 + offsetY) node1.setPosition(100 + offsetX, 100 + offsetY);
//3-B) create another default node //3-B) create another default node
var node2 = new DefaultNodeModel("Node 2", "rgb(192,255,0)"); var node2 = new DefaultNodeModel("Node 2", "rgb(192,255,0)");

View File

@ -1,10 +1,4 @@
import { import { DiagramEngine, DiagramModel, DefaultNodeModel, LinkModel, DiagramWidget } from "../../src/main";
DiagramEngine,
DiagramModel,
DefaultNodeModel,
LinkModel,
DiagramWidget
} from "../../src/main";
import * as React from "react"; import * as React from "react";
import { DemoWorkspaceWidget } from "../.helpers/DemoWorkspaceWidget"; import { DemoWorkspaceWidget } from "../.helpers/DemoWorkspaceWidget";
import { action } from "@storybook/addon-actions"; import { action } from "@storybook/addon-actions";

View File

@ -1,10 +1,4 @@
import { import { DiagramEngine, DiagramModel, DefaultNodeModel, LinkModel, DiagramWidget } from "../../src/main";
DiagramEngine,
DiagramModel,
DefaultNodeModel,
LinkModel,
DiagramWidget
} from "../../src/main";
import * as React from "react"; import * as React from "react";
export default () => { export default () => {
@ -17,12 +11,12 @@ export default () => {
//3-A) create a default node //3-A) create a default node
var node1 = new DefaultNodeModel("Node 1", "rgb(0,192,255)"); var node1 = new DefaultNodeModel("Node 1", "rgb(0,192,255)");
var port1 = node1.addOutPort('Out') var port1 = node1.addOutPort("Out");
node1.setPosition(100,100); node1.setPosition(100, 100);
//3-B) create another default node //3-B) create another default node
var node2 = new DefaultNodeModel("Node 2", "rgb(192,255,0)"); var node2 = new DefaultNodeModel("Node 2", "rgb(192,255,0)");
var port2 = node2.addInPort('In') var port2 = node2.addInPort("In");
node2.setPosition(400, 100); node2.setPosition(400, 100);
//3-C) link the 2 nodes together //3-C) link the 2 nodes together
@ -30,8 +24,8 @@ export default () => {
//3-D) create an orphaned node //3-D) create an orphaned node
var node3 = new DefaultNodeModel("Node 3", "rgb(0,192,255)"); var node3 = new DefaultNodeModel("Node 3", "rgb(0,192,255)");
node3.addOutPort('Out'); node3.addOutPort("Out");
node3.setPosition(100,200); node3.setPosition(100, 200);
//4) add the models to the root graph //4) add the models to the root graph
model.addAll(node1, node2, node3, link1); model.addAll(node1, node2, node3, link1);

View File

@ -1,12 +1,6 @@
import { import { DiagramEngine, DiagramModel, DefaultNodeModel, LinkModel, DiagramWidget } from "../../src/main";
DiagramEngine,
DiagramModel,
DefaultNodeModel,
LinkModel,
DiagramWidget
} from "../../src/main";
import * as React from "react"; import * as React from "react";
import {DefaultLinkModel} from "../../src/defaults/models/DefaultLinkModel"; import { DefaultLinkModel } from "../../src/defaults/models/DefaultLinkModel";
export default () => { export default () => {
//1) setup the diagram engine //1) setup the diagram engine
@ -36,7 +30,6 @@ export default () => {
//5) load model into engine //5) load model into engine
engine.setDiagramModel(model); engine.setDiagramModel(model);
//6) render the diagram! //6) render the diagram!
return <DiagramWidget diagramEngine={engine} />; return <DiagramWidget diagramEngine={engine} />;
}; };

View File

@ -7,8 +7,8 @@ import {
DiagramWidget DiagramWidget
} from "../../src/main"; } from "../../src/main";
import * as React from "react"; import * as React from "react";
import {DemoWorkspaceWidget} from "../.helpers/DemoWorkspaceWidget"; import { DemoWorkspaceWidget } from "../.helpers/DemoWorkspaceWidget";
import {action} from "@storybook/addon-actions"; import { action } from "@storybook/addon-actions";
export default () => { export default () => {
// setup the diagram engine // setup the diagram engine
@ -35,7 +35,6 @@ export default () => {
const node5 = new DefaultNodeModel("Node E", "rgb(192,255,0)"); const node5 = new DefaultNodeModel("Node E", "rgb(192,255,0)");
node5.setPosition(250, 180); node5.setPosition(250, 180);
// linking things together // linking things together
const link1 = port1.link(port4); const link1 = port1.link(port4);
const link2 = port2.link(port3); const link2 = port2.link(port3);
@ -58,11 +57,7 @@ export default () => {
</button> </button>
} }
> >
<DiagramWidget <DiagramWidget diagramEngine={engine} smartRouting={true} maxNumberPointsPerLink={0} />
diagramEngine={engine}
smartRouting={true}
maxNumberPointsPerLink={0}
/>
</DemoWorkspaceWidget> </DemoWorkspaceWidget>
); );
}; };

View File

@ -7,7 +7,7 @@ import {
DiagramWidget DiagramWidget
} from "../../src/main"; } from "../../src/main";
import * as React from "react"; import * as React from "react";
import {DemoWorkspaceWidget} from "../.helpers/DemoWorkspaceWidget"; import { DemoWorkspaceWidget } from "../.helpers/DemoWorkspaceWidget";
/** /**
* *
@ -53,7 +53,7 @@ export default () => {
//6) render the diagram! //6) render the diagram!
return ( return (
<DemoWorkspaceWidget buttons={<button onClick={() => engine.zoomToFit()}>Zoom to fit</button>}> <DemoWorkspaceWidget buttons={<button onClick={() => engine.zoomToFit()}>Zoom to fit</button>}>
<DiagramWidget diagramEngine={engine}/> <DiagramWidget diagramEngine={engine} />
</DemoWorkspaceWidget> </DemoWorkspaceWidget>
); );
}; };

View File

@ -1,9 +1,9 @@
import * as React from "react"; import * as React from "react";
import {storiesOf, addDecorator} from "@storybook/react"; import { storiesOf, addDecorator } from "@storybook/react";
import {setOptions} from "@storybook/addon-options"; import { setOptions } from "@storybook/addon-options";
import {host} from "storybook-host"; import { host } from "storybook-host";
import {Helper} from "./.helpers/Helper"; import { Helper } from "./.helpers/Helper";
import {Toolkit} from "../src/Toolkit"; import { Toolkit } from "../src/Toolkit";
//include the SCSS for the demo //include the SCSS for the demo
require("./.helpers/demo.scss"); require("./.helpers/demo.scss");

View File

@ -1,10 +1,10 @@
import {BaseModel} from "./models/BaseModel"; import { BaseModel } from "./models/BaseModel";
import {NodeModel} from "./models/NodeModel"; import { NodeModel } from "./models/NodeModel";
import {LinkModel} from "./models/LinkModel"; import { LinkModel } from "./models/LinkModel";
import {DiagramEngine} from "./DiagramEngine"; import { DiagramEngine } from "./DiagramEngine";
import {PortModel} from "./models/PortModel"; import { PortModel } from "./models/PortModel";
import {PointModel} from "./models/PointModel"; import { PointModel } from "./models/PointModel";
import {LabelModel} from "./models/LabelModel"; import { LabelModel } from "./models/LabelModel";
export abstract class AbstractFactory<T extends BaseModel> { export abstract class AbstractFactory<T extends BaseModel> {
type: string; type: string;
@ -25,18 +25,14 @@ export abstract class NodeFactory<T extends NodeModel = NodeModel> extends Abstr
} }
export abstract class LinkFactory<T extends LinkModel = LinkModel> extends AbstractFactory<T> { export abstract class LinkFactory<T extends LinkModel = LinkModel> extends AbstractFactory<T> {
abstract generateReactWidget(diagramEngine: DiagramEngine, link: T): JSX.Element; abstract generateReactWidget(diagramEngine: DiagramEngine, link: T): JSX.Element;
} }
export abstract class LabelFactory<T extends LabelModel = LabelModel> extends AbstractFactory<T>{ export abstract class LabelFactory<T extends LabelModel = LabelModel> extends AbstractFactory<T> {
abstract generateReactWidget(diagramEngine: DiagramEngine, label: T): JSX.Element; abstract generateReactWidget(diagramEngine: DiagramEngine, label: T): JSX.Element;
} }
export abstract class PortFactory<T extends PortModel = PortModel> extends AbstractFactory<T> { export abstract class PortFactory<T extends PortModel = PortModel> extends AbstractFactory<T> {}
}
export class SimplePortFactory extends PortFactory { export class SimplePortFactory extends PortFactory {
cb: (initialConfig?: any) => PortModel; cb: (initialConfig?: any) => PortModel;

View File

@ -1,6 +1,6 @@
import {Toolkit} from "./Toolkit"; import { Toolkit } from "./Toolkit";
import * as _ from "lodash"; import * as _ from "lodash";
import {DiagramEngine} from "./DiagramEngine"; import { DiagramEngine } from "./DiagramEngine";
/** /**
* @author Dylan Vorster * @author Dylan Vorster
@ -18,7 +18,7 @@ export interface BaseListener<T extends BaseEntity = any> {
export type BaseEntityType = "node" | "link" | "port" | "point"; export type BaseEntityType = "node" | "link" | "port" | "point";
export class BaseEntity< T extends BaseListener = BaseListener> { export class BaseEntity<T extends BaseListener = BaseListener> {
public listeners: { [s: string]: T }; public listeners: { [s: string]: T };
public id: string; public id: string;
public locked: boolean; public locked: boolean;
@ -33,8 +33,7 @@ export class BaseEntity< T extends BaseListener = BaseListener> {
return this.id; return this.id;
} }
doClone(lookupTable = {}, clone) { doClone(lookupTable = {}, clone) {}
}
clone(lookupTable = {}) { clone(lookupTable = {}) {
// try and use an existing clone first // try and use an existing clone first
@ -104,7 +103,7 @@ export class BaseEntity< T extends BaseListener = BaseListener> {
this.locked = locked; this.locked = locked;
this.iterateListeners((listener, event) => { this.iterateListeners((listener, event) => {
if (listener.lockChanged) { if (listener.lockChanged) {
listener.lockChanged({...event, locked: locked}); listener.lockChanged({ ...event, locked: locked });
} }
}); });
} }

View File

@ -1,18 +1,18 @@
import {BaseEntity, BaseListener} from "./BaseEntity"; import { BaseEntity, BaseListener } from "./BaseEntity";
import {DiagramModel} from "./models/DiagramModel"; import { DiagramModel } from "./models/DiagramModel";
import * as _ from "lodash"; import * as _ from "lodash";
import {BaseModel, BaseModelListener} from "./models/BaseModel"; import { BaseModel, BaseModelListener } from "./models/BaseModel";
import {NodeModel} from "./models/NodeModel"; import { NodeModel } from "./models/NodeModel";
import {PointModel} from "./models/PointModel"; import { PointModel } from "./models/PointModel";
import {PortModel} from "./models/PortModel"; import { PortModel } from "./models/PortModel";
import {LinkModel} from "./models/LinkModel"; import { LinkModel } from "./models/LinkModel";
import {LabelFactory, LinkFactory, NodeFactory, PortFactory} from "./AbstractFactory"; import { LabelFactory, LinkFactory, NodeFactory, PortFactory } from "./AbstractFactory";
import {DefaultLinkFactory, DefaultNodeFactory} from "./main"; import { DefaultLinkFactory, DefaultNodeFactory } from "./main";
import { ROUTING_SCALING_FACTOR } from "./routing/PathFinding"; import { ROUTING_SCALING_FACTOR } from "./routing/PathFinding";
import {DefaultPortFactory} from "./defaults/factories/DefaultPortFactory"; import { DefaultPortFactory } from "./defaults/factories/DefaultPortFactory";
import {LabelModel} from "./models/LabelModel"; import { LabelModel } from "./models/LabelModel";
import {DefaultLabelFactory} from "./defaults/factories/DefaultLabelFactory"; import { DefaultLabelFactory } from "./defaults/factories/DefaultLabelFactory";
import {Toolkit} from "./Toolkit"; import { Toolkit } from "./Toolkit";
/** /**
* @author Dylan Vorster * @author Dylan Vorster
*/ */
@ -63,12 +63,12 @@ export class DiagramEngine extends BaseEntity<DiagramEngineListener> {
this.paintableWidgets = null; this.paintableWidgets = null;
this.linksThatHaveInitiallyRendered = {}; this.linksThatHaveInitiallyRendered = {};
if(Toolkit.TESTING){ if (Toolkit.TESTING) {
Toolkit.TESTING_UID = 0; Toolkit.TESTING_UID = 0;
//pop it onto the window so our E2E helpers can find it //pop it onto the window so our E2E helpers can find it
if(window){ if (window) {
(window as any)['diagram_instance'] = this; (window as any)["diagram_instance"] = this;
} }
} }
} }
@ -128,7 +128,7 @@ export class DiagramEngine extends BaseEntity<DiagramEngineListener> {
this.linksThatHaveInitiallyRendered = {}; this.linksThatHaveInitiallyRendered = {};
} }
canEntityRepaint(baseModel: BaseModel<BaseEntity,BaseModelListener>) { canEntityRepaint(baseModel: BaseModel<BaseEntity, BaseModelListener>) {
//no rules applied, allow repaint //no rules applied, allow repaint
if (this.paintableWidgets === null) { if (this.paintableWidgets === null) {
return true; return true;
@ -150,7 +150,6 @@ export class DiagramEngine extends BaseEntity<DiagramEngineListener> {
return this.diagramModel; return this.diagramModel;
} }
//!-------------- FACTORIES ------------ //!-------------- FACTORIES ------------
getNodeFactories(): { [s: string]: NodeFactory } { getNodeFactories(): { [s: string]: NodeFactory } {
@ -271,7 +270,7 @@ export class DiagramEngine extends BaseEntity<DiagramEngineListener> {
getRelativePoint(x, y) { getRelativePoint(x, y) {
var canvasRect = this.canvas.getBoundingClientRect(); var canvasRect = this.canvas.getBoundingClientRect();
return {x: x - canvasRect.left, y: y - canvasRect.top}; return { x: x - canvasRect.left, y: y - canvasRect.top };
} }
getNodeElement(node: NodeModel): Element { getNodeElement(node: NodeModel): Element {
@ -289,10 +288,10 @@ export class DiagramEngine extends BaseEntity<DiagramEngineListener> {
if (selector === null) { if (selector === null) {
throw new Error( throw new Error(
"Cannot find Node Port element with nodeID: [" + "Cannot find Node Port element with nodeID: [" +
port.getParent().getID() + port.getParent().getID() +
"] and name: [" + "] and name: [" +
port.getName() + port.getName() +
"]" "]"
); );
} }
return selector; return selector;
@ -306,11 +305,11 @@ export class DiagramEngine extends BaseEntity<DiagramEngineListener> {
return { return {
x: x:
sourceElement.offsetWidth / 2 + sourceElement.offsetWidth / 2 +
(rel.x - this.diagramModel.getOffsetX()) / (this.diagramModel.getZoomLevel() / 100.0), (rel.x - this.diagramModel.getOffsetX()) / (this.diagramModel.getZoomLevel() / 100.0),
y: y:
sourceElement.offsetHeight / 2 + sourceElement.offsetHeight / 2 +
(rel.y - this.diagramModel.getOffsetY()) / (this.diagramModel.getZoomLevel() / 100.0) (rel.y - this.diagramModel.getOffsetY()) / (this.diagramModel.getZoomLevel() / 100.0)
}; };
} }
@ -345,7 +344,7 @@ export class DiagramEngine extends BaseEntity<DiagramEngineListener> {
* Determine the width and height of the node passed in. * Determine the width and height of the node passed in.
* It currently assumes nodes have a rectangular shape, can be overriden for customised shapes. * It currently assumes nodes have a rectangular shape, can be overriden for customised shapes.
*/ */
getNodeDimensions(node: NodeModel): { width: number; height: number; } { getNodeDimensions(node: NodeModel): { width: number; height: number } {
if (!this.canvas) { if (!this.canvas) {
return { return {
width: 0, width: 0,

View File

@ -1,5 +1,5 @@
import closest = require("closest"); import closest = require("closest");
import {PointModel} from "./models/PointModel"; import { PointModel } from "./models/PointModel";
import { ROUTING_SCALING_FACTOR } from "./routing/PathFinding"; import { ROUTING_SCALING_FACTOR } from "./routing/PathFinding";
import * as Path from "paths-js/path"; import * as Path from "paths-js/path";
/** /**
@ -16,7 +16,7 @@ export class Toolkit {
public static UID(): string { public static UID(): string {
if (Toolkit.TESTING) { if (Toolkit.TESTING) {
Toolkit.TESTING_UID++; Toolkit.TESTING_UID++;
return ''+Toolkit.TESTING_UID; return "" + Toolkit.TESTING_UID;
} }
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) { return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
var r = (Math.random() * 16) | 0, var r = (Math.random() * 16) | 0,
@ -42,13 +42,10 @@ export class Toolkit {
return `M${firstPoint.x},${firstPoint.y} L ${lastPoint.x},${lastPoint.y}`; return `M${firstPoint.x},${firstPoint.y} L ${lastPoint.x},${lastPoint.y}`;
} }
public static generateCurvePath( public static generateCurvePath(firstPoint: PointModel, lastPoint: PointModel, curvy: number = 0): string {
firstPoint: PointModel, return `M${firstPoint.x},${firstPoint.y} C ${firstPoint.x + curvy},${firstPoint.y} ${lastPoint.x + -curvy},${
lastPoint: PointModel, lastPoint.y
curvy: number = 0, } ${lastPoint.x},${lastPoint.y}`;
): string {
return `M${firstPoint.x},${firstPoint.y} C ${firstPoint.x + curvy},${firstPoint.y} ${lastPoint.x +
-curvy},${lastPoint.y} ${lastPoint.x},${lastPoint.y}`;
} }
public static generateDynamicPath(pathCoords: number[][]) { public static generateDynamicPath(pathCoords: number[][]) {

View File

@ -1,8 +1,8 @@
import * as React from "react"; import * as React from "react";
import {DiagramEngine} from "../../DiagramEngine"; import { DiagramEngine } from "../../DiagramEngine";
import {LabelFactory} from "../../AbstractFactory"; import { LabelFactory } from "../../AbstractFactory";
import {DefaultLabelModel} from "../models/DefaultLabelModel"; import { DefaultLabelModel } from "../models/DefaultLabelModel";
import {DefaultLabelWidget} from "../widgets/DefaultLabelWidget"; import { DefaultLabelWidget } from "../widgets/DefaultLabelWidget";
/** /**
* @author Dylan Vorster * @author Dylan Vorster

View File

@ -1,8 +1,8 @@
import * as React from "react"; import * as React from "react";
import {DefaultLinkWidget} from "../widgets/DefaultLinkWidget"; import { DefaultLinkWidget } from "../widgets/DefaultLinkWidget";
import {DiagramEngine} from "../../DiagramEngine"; import { DiagramEngine } from "../../DiagramEngine";
import {LinkFactory} from "../../AbstractFactory"; import { LinkFactory } from "../../AbstractFactory";
import {DefaultLinkModel} from "../models/DefaultLinkModel"; import { DefaultLinkModel } from "../models/DefaultLinkModel";
/** /**
* @author Dylan Vorster * @author Dylan Vorster
@ -23,16 +23,7 @@ export class DefaultLinkFactory extends LinkFactory<DefaultLinkModel> {
return new DefaultLinkModel(); return new DefaultLinkModel();
} }
generateLinkSegment(model: DefaultLinkModel, selected: boolean, path: string) { generateLinkSegment(model: DefaultLinkModel, selected: boolean, path: string) {
return ( return <path className={selected ? "selected" : ""} strokeWidth={model.width} stroke={model.color} d={path} />;
<path
className={selected ? "selected" : ''}
strokeWidth={model.width}
stroke={model.color}
d={path}
/>
);
} }
} }

View File

@ -1,14 +1,14 @@
import {LabelModel} from "../../models/LabelModel"; import { LabelModel } from "../../models/LabelModel";
export class DefaultLabelModel extends LabelModel { export class DefaultLabelModel extends LabelModel {
label: string; label: string;
constructor(){ constructor() {
super("default"); super("default");
this.offsetY = -23; this.offsetY = -23;
} }
setLabel(label: string){ setLabel(label: string) {
this.label = label; this.label = label;
} }
} }

View File

@ -1,35 +1,33 @@
/** /**
* @author Dylan Vorster * @author Dylan Vorster
*/ */
import {LinkModel, LinkModelListener} from "../../models/LinkModel"; import { LinkModel, LinkModelListener } from "../../models/LinkModel";
import {BaseEvent} from "../../BaseEntity"; import { BaseEvent } from "../../BaseEntity";
import * as _ from "lodash"; import * as _ from "lodash";
import {PointModel} from "../../models/PointModel"; import { PointModel } from "../../models/PointModel";
import {DiagramEngine} from "../../DiagramEngine"; import { DiagramEngine } from "../../DiagramEngine";
import {DefaultLabelModel} from "./DefaultLabelModel"; import { DefaultLabelModel } from "./DefaultLabelModel";
import {LabelModel} from "../../models/LabelModel"; import { LabelModel } from "../../models/LabelModel";
export interface DefaultLinkModelListener extends LinkModelListener{
export interface DefaultLinkModelListener extends LinkModelListener {
colorChanged?(event: BaseEvent<DefaultLinkModel> & { color: null | string }); colorChanged?(event: BaseEvent<DefaultLinkModel> & { color: null | string });
widthChanged?(event: BaseEvent<DefaultLinkModel> & { width: 0 | number }); widthChanged?(event: BaseEvent<DefaultLinkModel> & { width: 0 | number });
} }
export class DefaultLinkModel extends LinkModel<DefaultLinkModelListener>{ export class DefaultLinkModel extends LinkModel<DefaultLinkModelListener> {
width: number; width: number;
color: string; color: string;
curvyness: number; curvyness: number;
constructor(type: string = 'default'){ constructor(type: string = "default") {
super(type); super(type);
this.color = "rgba(255,255,255,0.5)"; this.color = "rgba(255,255,255,0.5)";
this.width = 3; this.width = 3;
this.curvyness = 50; this.curvyness = 50;
} }
serialize(){ serialize() {
return _.merge(super.serialize(), { return _.merge(super.serialize(), {
width: this.width, width: this.width,
color: this.color, color: this.color,
@ -44,8 +42,8 @@ export class DefaultLinkModel extends LinkModel<DefaultLinkModelListener>{
this.curvyness = ob.curvyness; this.curvyness = ob.curvyness;
} }
addLabel(label: LabelModel | string){ addLabel(label: LabelModel | string) {
if(label instanceof LabelModel){ if (label instanceof LabelModel) {
return super.addLabel(label); return super.addLabel(label);
} }
let labelOb = new DefaultLabelModel(); let labelOb = new DefaultLabelModel();
@ -53,18 +51,17 @@ export class DefaultLinkModel extends LinkModel<DefaultLinkModelListener>{
return super.addLabel(labelOb); return super.addLabel(labelOb);
} }
setWidth(width: number){ setWidth(width: number) {
this.width = width; this.width = width;
this.iterateListeners((listener: DefaultLinkModelListener, event: BaseEvent) => { this.iterateListeners((listener: DefaultLinkModelListener, event: BaseEvent) => {
listener.widthChanged && listener.widthChanged({ ...event, width: width }); listener.widthChanged && listener.widthChanged({ ...event, width: width });
}); });
} }
setColor(color: string){ setColor(color: string) {
this.color = color; this.color = color;
this.iterateListeners((listener: DefaultLinkModelListener, event: BaseEvent) => { this.iterateListeners((listener: DefaultLinkModelListener, event: BaseEvent) => {
listener.colorChanged && listener.colorChanged({ ...event, color: color }); listener.colorChanged && listener.colorChanged({ ...event, color: color });
}); });
} }
}
}

View File

@ -2,8 +2,8 @@ import { DefaultPortModel } from "./DefaultPortModel";
import * as _ from "lodash"; import * as _ from "lodash";
import { NodeModel } from "../../models/NodeModel"; import { NodeModel } from "../../models/NodeModel";
import {Toolkit} from "../../Toolkit"; import { Toolkit } from "../../Toolkit";
import {DiagramEngine} from "../../DiagramEngine"; import { DiagramEngine } from "../../DiagramEngine";
/** /**
* @author Dylan Vorster * @author Dylan Vorster
@ -19,11 +19,11 @@ export class DefaultNodeModel extends NodeModel {
this.color = color; this.color = color;
} }
addInPort(label: string): DefaultPortModel{ addInPort(label: string): DefaultPortModel {
return this.addPort(new DefaultPortModel(true, Toolkit.UID(), label)); return this.addPort(new DefaultPortModel(true, Toolkit.UID(), label));
} }
addOutPort(label: string): DefaultPortModel{ addOutPort(label: string): DefaultPortModel {
return this.addPort(new DefaultPortModel(false, Toolkit.UID(), label)); return this.addPort(new DefaultPortModel(false, Toolkit.UID(), label));
} }

View File

@ -1,11 +1,10 @@
import * as _ from "lodash"; import * as _ from "lodash";
import { PortModel } from "../../models/PortModel"; import { PortModel } from "../../models/PortModel";
import {DiagramEngine} from "../../DiagramEngine"; import { DiagramEngine } from "../../DiagramEngine";
import {DefaultLinkModel} from "./DefaultLinkModel"; import { DefaultLinkModel } from "./DefaultLinkModel";
import {LinkModel} from "../../models/LinkModel"; import { LinkModel } from "../../models/LinkModel";
export class DefaultPortModel extends PortModel { export class DefaultPortModel extends PortModel {
in: boolean; in: boolean;
label: string; label: string;
links: { [id: string]: DefaultLinkModel }; links: { [id: string]: DefaultLinkModel };
@ -29,7 +28,7 @@ export class DefaultPortModel extends PortModel {
}); });
} }
link(port: PortModel): LinkModel{ link(port: PortModel): LinkModel {
let link = this.createLinkModel(); let link = this.createLinkModel();
link.setSourcePort(this); link.setSourcePort(this);
link.setTargetPort(port); link.setTargetPort(port);
@ -37,7 +36,7 @@ export class DefaultPortModel extends PortModel {
} }
canLinkToPort(port: PortModel): boolean { canLinkToPort(port: PortModel): boolean {
if(port instanceof DefaultPortModel){ if (port instanceof DefaultPortModel) {
return this.in !== port.in; return this.in !== port.in;
} }
return true; return true;

View File

@ -1,15 +1,12 @@
import * as React from "react"; import * as React from "react";
import {DefaultLabelModel} from "../models/DefaultLabelModel"; import { DefaultLabelModel } from "../models/DefaultLabelModel";
export interface DefaultLabelWidgetProps{ export interface DefaultLabelWidgetProps {
model: DefaultLabelModel; model: DefaultLabelModel;
} }
export class DefaultLabelWidget extends React.Component<DefaultLabelWidgetProps>{ export class DefaultLabelWidget extends React.Component<DefaultLabelWidgetProps> {
render() {
render(){ return <div className="default-label">{this.props.model.label}</div>;
return (
<div className="default-label">{this.props.model.label}</div>
);
} }
} }

View File

@ -1,12 +1,12 @@
import * as React from "react"; import * as React from "react";
import {DiagramEngine} from "../../DiagramEngine"; import { DiagramEngine } from "../../DiagramEngine";
import {PointModel} from "../../models/PointModel"; import { PointModel } from "../../models/PointModel";
import {Toolkit} from "../../Toolkit"; import { Toolkit } from "../../Toolkit";
import {DefaultLinkFactory} from "../factories/DefaultLinkFactory"; import { DefaultLinkFactory } from "../factories/DefaultLinkFactory";
import {DefaultLinkModel} from "../models/DefaultLinkModel"; import { DefaultLinkModel } from "../models/DefaultLinkModel";
import PathFinding from "../../routing/PathFinding"; import PathFinding from "../../routing/PathFinding";
import * as _ from "lodash"; import * as _ from "lodash";
import {LabelModel} from "../../models/LabelModel"; import { LabelModel } from "../../models/LabelModel";
export interface DefaultLinkProps { export interface DefaultLinkProps {
color?: string; color?: string;
@ -28,7 +28,7 @@ export class DefaultLinkWidget extends React.Component<DefaultLinkProps, Default
link: null, link: null,
engine: null, engine: null,
smooth: false, smooth: false,
diagramEngine: null, diagramEngine: null
}; };
// DOM references to the label and paths (if label is given), used to calculate dynamic positioning // DOM references to the label and paths (if label is given), used to calculate dynamic positioning
@ -51,10 +51,10 @@ export class DefaultLinkWidget extends React.Component<DefaultLinkProps, Default
} }
} }
calculateAllLabelPosition(){ calculateAllLabelPosition() {
_.forEach(this.props.link.labels, (label, index) => { _.forEach(this.props.link.labels, (label, index) => {
this.calculateLabelPosition(label, index+1); this.calculateLabelPosition(label, index + 1);
}) });
} }
componentDidUpdate() { componentDidUpdate() {
@ -93,10 +93,10 @@ export class DefaultLinkWidget extends React.Component<DefaultLinkProps, Default
/> />
<circle <circle
onMouseLeave={() => { onMouseLeave={() => {
this.setState({selected: false}); this.setState({ selected: false });
}} }}
onMouseEnter={() => { onMouseEnter={() => {
this.setState({selected: true}); this.setState({ selected: true });
}} }}
data-id={this.props.link.points[pointIndex].id} data-id={this.props.link.points[pointIndex].id}
data-linkid={this.props.link.id} data-linkid={this.props.link.id}
@ -113,9 +113,16 @@ export class DefaultLinkWidget extends React.Component<DefaultLinkProps, Default
generateLabel(label: LabelModel) { generateLabel(label: LabelModel) {
const canvas = this.props.diagramEngine.canvas as HTMLElement; const canvas = this.props.diagramEngine.canvas as HTMLElement;
return ( return (
<foreignObject key={label.id} className="link-label" width={canvas.offsetWidth} height={canvas.offsetHeight}> <foreignObject
key={label.id}
className="link-label"
width={canvas.offsetWidth}
height={canvas.offsetHeight}
>
<div ref={ref => (this.refLabels[label.id] = ref)}> <div ref={ref => (this.refLabels[label.id] = ref)}>
{this.props.diagramEngine.getFactoryForLabel(label).generateReactWidget(this.props.diagramEngine, label)} {this.props.diagramEngine
.getFactoryForLabel(label)
.generateReactWidget(this.props.diagramEngine, label)}
</div> </div>
</foreignObject> </foreignObject>
); );
@ -124,23 +131,28 @@ export class DefaultLinkWidget extends React.Component<DefaultLinkProps, Default
generateLink(path: string, extraProps: any, id: string | number): JSX.Element { generateLink(path: string, extraProps: any, id: string | number): JSX.Element {
var props = this.props; var props = this.props;
var Bottom = React.cloneElement((props.diagramEngine.getFactoryForLink(this.props.link) as DefaultLinkFactory) var Bottom = React.cloneElement(
.generateLinkSegment(this.props.link, this.state.selected || this.props.link.isSelected(), path), { (props.diagramEngine.getFactoryForLink(this.props.link) as DefaultLinkFactory).generateLinkSegment(
ref:ref => ref && this.refPaths.push(ref), this.props.link,
}); this.state.selected || this.props.link.isSelected(),
path
),
{
ref: ref => ref && this.refPaths.push(ref)
}
);
var Top = React.cloneElement(Bottom, { var Top = React.cloneElement(Bottom, {
...extraProps, ...extraProps,
strokeLinecap: "round", strokeLinecap: "round",
onMouseLeave: () => { onMouseLeave: () => {
this.setState({selected: false}); this.setState({ selected: false });
}, },
onMouseEnter: () => { onMouseEnter: () => {
this.setState({selected: true}); this.setState({ selected: true });
}, },
ref: null, ref: null,
'data-linkid': this.props.link.getID(), "data-linkid": this.props.link.getID(),
strokeOpacity: this.state.selected ? 0.1 : 0, strokeOpacity: this.state.selected ? 0.1 : 0,
strokeWidth: 20, strokeWidth: 20,
onContextMenu: () => { onContextMenu: () => {
@ -159,12 +171,14 @@ export class DefaultLinkWidget extends React.Component<DefaultLinkProps, Default
); );
} }
findPathAndRelativePositionToRenderLabel = (index: number): { path: any; position: number; } => { findPathAndRelativePositionToRenderLabel = (index: number): { path: any; position: number } => {
// an array to hold all path lengths, making sure we hit the DOM only once to fetch this information // an array to hold all path lengths, making sure we hit the DOM only once to fetch this information
const lengths = this.refPaths.map(path => path.getTotalLength()); const lengths = this.refPaths.map(path => path.getTotalLength());
// calculate the point where we want to display the label // calculate the point where we want to display the label
let labelPosition = lengths.reduce((previousValue, currentValue) => previousValue + currentValue, 0) * (index / (this.props.link.labels.length + 1)); let labelPosition =
lengths.reduce((previousValue, currentValue) => previousValue + currentValue, 0) *
(index / (this.props.link.labels.length + 1));
// find the path where the label will be rendered and calculate the relative position // find the path where the label will be rendered and calculate the relative position
let pathIndex = 0; let pathIndex = 0;
@ -182,13 +196,13 @@ export class DefaultLinkWidget extends React.Component<DefaultLinkProps, Default
} }
}; };
calculateLabelPosition = (label, index:number) => { calculateLabelPosition = (label, index: number) => {
if (!this.refLabels[label.id]) { if (!this.refLabels[label.id]) {
// no label? nothing to do here // no label? nothing to do here
return; return;
} }
const {path, position} = this.findPathAndRelativePositionToRenderLabel(index); const { path, position } = this.findPathAndRelativePositionToRenderLabel(index);
const labelDimensions = { const labelDimensions = {
width: this.refLabels[label.id].offsetWidth, width: this.refLabels[label.id].offsetWidth,
@ -198,13 +212,15 @@ export class DefaultLinkWidget extends React.Component<DefaultLinkProps, Default
const pathCentre = path.getPointAtLength(position); const pathCentre = path.getPointAtLength(position);
const labelCoordinates = { const labelCoordinates = {
x: (pathCentre.x - labelDimensions.width / 2) + label.offsetX, x: pathCentre.x - labelDimensions.width / 2 + label.offsetX,
y: (pathCentre.y - labelDimensions.height / 2) + label.offsetY y: pathCentre.y - labelDimensions.height / 2 + label.offsetY
}; };
this.refLabels[label.id].setAttribute("style", `transform: translate(${labelCoordinates.x}px, ${labelCoordinates.y}px);`); this.refLabels[label.id].setAttribute(
"style",
`transform: translate(${labelCoordinates.x}px, ${labelCoordinates.y}px);`
);
}; };
/** /**
* Smart routing is only applicable when all conditions below are true: * Smart routing is only applicable when all conditions below are true:
* - smart routing is set to true on the engine * - smart routing is set to true on the engine
@ -212,7 +228,7 @@ export class DefaultLinkWidget extends React.Component<DefaultLinkProps, Default
* - no custom points exist along the line * - no custom points exist along the line
*/ */
isSmartRoutingApplicable(): boolean { isSmartRoutingApplicable(): boolean {
const {diagramEngine, link} = this.props; const { diagramEngine, link } = this.props;
if (!diagramEngine.isSmartRoutingEnabled()) { if (!diagramEngine.isSmartRoutingEnabled()) {
return false; return false;
@ -230,7 +246,7 @@ export class DefaultLinkWidget extends React.Component<DefaultLinkProps, Default
} }
render() { render() {
const {diagramEngine} = this.props; const { diagramEngine } = this.props;
if (!diagramEngine.nodesRendered) { if (!diagramEngine.nodesRendered) {
return null; return null;
} }
@ -249,7 +265,7 @@ export class DefaultLinkWidget extends React.Component<DefaultLinkProps, Default
const smartLink = this.pathFinding.calculateLinkStartEndCoords(routingMatrix, directPathCoords); const smartLink = this.pathFinding.calculateLinkStartEndCoords(routingMatrix, directPathCoords);
if (smartLink) { if (smartLink) {
const {start, end, pathToStart, pathToEnd} = smartLink; const { start, end, pathToStart, pathToEnd } = smartLink;
// second step: calculate a path avoiding hitting other elements // second step: calculate a path avoiding hitting other elements
const simplifiedPath = this.pathFinding.calculateDynamicPath( const simplifiedPath = this.pathFinding.calculateDynamicPath(
@ -267,7 +283,7 @@ export class DefaultLinkWidget extends React.Component<DefaultLinkProps, Default
{ {
onMouseDown: event => { onMouseDown: event => {
this.addPointToLink(event, 1); this.addPointToLink(event, 1);
}, }
}, },
"0" "0"
) )
@ -302,9 +318,9 @@ export class DefaultLinkWidget extends React.Component<DefaultLinkProps, Default
{ {
onMouseDown: event => { onMouseDown: event => {
this.addPointToLink(event, 1); this.addPointToLink(event, 1);
}, }
}, },
"0", "0"
) )
); );
@ -315,20 +331,21 @@ export class DefaultLinkWidget extends React.Component<DefaultLinkProps, Default
} else { } else {
//draw the multiple anchors and complex line instead //draw the multiple anchors and complex line instead
for (let i = 0; i < points.length - 1; i++) { for (let i = 0; i < points.length - 1; i++) {
paths.push(this.generateLink( paths.push(
Toolkit.generateLinePath(points[i], points[i + 1]), this.generateLink(
{ Toolkit.generateLinePath(points[i], points[i + 1]),
"data-linkid": this.props.link.id, {
"data-point": i, "data-linkid": this.props.link.id,
onMouseDown: (event: MouseEvent) => { "data-point": i,
this.addPointToLink(event, i + 1); onMouseDown: (event: MouseEvent) => {
this.addPointToLink(event, i + 1);
}
}, },
}, i
i, )
)); );
} }
//render the circles //render the circles
for (var i = 1; i < points.length - 1; i++) { for (var i = 1; i < points.length - 1; i++) {
paths.push(this.generatePoint(i)); paths.push(this.generatePoint(i));
@ -345,11 +362,9 @@ export class DefaultLinkWidget extends React.Component<DefaultLinkProps, Default
return ( return (
<g> <g>
{paths} {paths}
{ {_.map(this.props.link.labels, labelModel => {
_.map(this.props.link.labels, (labelModel) => { return this.generateLabel(labelModel);
return this.generateLabel(labelModel); })}
})
}
</g> </g>
); );
} }

View File

@ -1,7 +1,7 @@
import { BaseEntity, BaseListener } from "../BaseEntity"; import { BaseEntity, BaseListener } from "../BaseEntity";
import * as _ from "lodash"; import * as _ from "lodash";
import { BaseEvent } from "../BaseEntity"; import { BaseEvent } from "../BaseEntity";
import {DiagramEngine} from "../DiagramEngine"; import { DiagramEngine } from "../DiagramEngine";
export interface BaseModelListener extends BaseListener { export interface BaseModelListener extends BaseListener {
selectionChanged?(event: BaseEvent<BaseModel> & { isSelected: boolean }): void; selectionChanged?(event: BaseEvent<BaseModel> & { isSelected: boolean }): void;
@ -12,7 +12,10 @@ export interface BaseModelListener extends BaseListener {
/** /**
* @author Dylan Vorster * @author Dylan Vorster
*/ */
export class BaseModel<X extends BaseEntity = BaseEntity,T extends BaseModelListener = BaseModelListener> extends BaseEntity<BaseModelListener> { export class BaseModel<
X extends BaseEntity = BaseEntity,
T extends BaseModelListener = BaseModelListener
> extends BaseEntity<BaseModelListener> {
type: string; type: string;
selected: boolean; selected: boolean;
parent: X; parent: X;
@ -23,15 +26,15 @@ export class BaseModel<X extends BaseEntity = BaseEntity,T extends BaseModelList
this.selected = false; this.selected = false;
} }
public getParent(): X{ public getParent(): X {
return this.parent; return this.parent;
} }
public setParent(parent: X){ public setParent(parent: X) {
this.parent = parent; this.parent = parent;
} }
public getSelectedEntities(): BaseModel<any,T>[] { public getSelectedEntities(): BaseModel<any, T>[] {
if (this.isSelected()) { if (this.isSelected()) {
return [this]; return [this];
} }

View File

@ -104,7 +104,7 @@ export class DiagramModel extends BaseEntity<DiagramListener> {
}); });
} }
clearSelection(ignore: BaseModel<BaseEntity,BaseModelListener> | null = null) { clearSelection(ignore: BaseModel<BaseEntity, BaseModelListener> | null = null) {
_.forEach(this.getSelectedItems(), element => { _.forEach(this.getSelectedItems(), element => {
if (ignore && ignore.getID() === element.getID()) { if (ignore && ignore.getID() === element.getID()) {
return; return;
@ -113,7 +113,7 @@ export class DiagramModel extends BaseEntity<DiagramListener> {
}); });
} }
getSelectedItems(...filters: BaseEntityType[]): BaseModel<BaseEntity,BaseModelListener>[] { getSelectedItems(...filters: BaseEntityType[]): BaseModel<BaseEntity, BaseModelListener>[] {
if (!Array.isArray(filters)) { if (!Array.isArray(filters)) {
filters = [filters]; filters = [filters];
} }
@ -228,11 +228,11 @@ export class DiagramModel extends BaseEntity<DiagramListener> {
return this.links[link]; return this.links[link];
} }
addAll(...models: BaseModel[]): BaseModel[]{ addAll(...models: BaseModel[]): BaseModel[] {
_.forEach(models, (model) =>{ _.forEach(models, model => {
if(model instanceof LinkModel){ if (model instanceof LinkModel) {
this.addLink(model); this.addLink(model);
}else if(model instanceof NodeModel){ } else if (model instanceof NodeModel) {
this.addNode(model); this.addNode(model);
} }
}); });

View File

@ -1,8 +1,7 @@
import {BaseModel} from "./BaseModel"; import { BaseModel } from "./BaseModel";
import {LinkModel} from "./LinkModel"; import { LinkModel } from "./LinkModel";
export class LabelModel extends BaseModel<LinkModel> { export class LabelModel extends BaseModel<LinkModel> {
offsetX: number; offsetX: number;
offsetY: number; offsetY: number;
@ -11,4 +10,4 @@ export class LabelModel extends BaseModel<LinkModel> {
this.offsetX = 0; this.offsetX = 0;
this.offsetY = 0; this.offsetY = 0;
} }
} }

View File

@ -1,11 +1,11 @@
import {BaseModel, BaseModelListener} from "./BaseModel"; import { BaseModel, BaseModelListener } from "./BaseModel";
import {PortModel} from "./PortModel"; import { PortModel } from "./PortModel";
import {PointModel} from "./PointModel"; import { PointModel } from "./PointModel";
import * as _ from "lodash"; import * as _ from "lodash";
import {BaseEvent} from "../BaseEntity"; import { BaseEvent } from "../BaseEntity";
import {LabelModel} from "./LabelModel"; import { LabelModel } from "./LabelModel";
import {DiagramEngine} from "../DiagramEngine"; import { DiagramEngine } from "../DiagramEngine";
import {DiagramModel} from "./DiagramModel"; import { DiagramModel } from "./DiagramModel";
export interface LinkModelListener extends BaseModelListener { export interface LinkModelListener extends BaseModelListener {
sourcePortChanged?(event: BaseEvent<LinkModel> & { port: null | PortModel }): void; sourcePortChanged?(event: BaseEvent<LinkModel> & { port: null | PortModel }): void;
@ -13,8 +13,7 @@ export interface LinkModelListener extends BaseModelListener {
targetPortChanged?(event: BaseEvent<LinkModel> & { port: null | PortModel }): void; targetPortChanged?(event: BaseEvent<LinkModel> & { port: null | PortModel }): void;
} }
export class LinkModel<T extends LinkModelListener = LinkModelListener> extends BaseModel<DiagramModel,T> { export class LinkModel<T extends LinkModelListener = LinkModelListener> extends BaseModel<DiagramModel, T> {
sourcePort: PortModel | null; sourcePort: PortModel | null;
targetPort: PortModel | null; targetPort: PortModel | null;
labels: LabelModel[]; labels: LabelModel[];
@ -23,7 +22,7 @@ export class LinkModel<T extends LinkModelListener = LinkModelListener> extends
constructor(linkType: string = "default", id?: string) { constructor(linkType: string = "default", id?: string) {
super(linkType, id); super(linkType, id);
this.points = [new PointModel(this, {x: 0, y: 0}), new PointModel(this, {x: 0, y: 0})]; this.points = [new PointModel(this, { x: 0, y: 0 }), new PointModel(this, { x: 0, y: 0 })];
this.extras = {}; this.extras = {};
this.sourcePort = null; this.sourcePort = null;
this.targetPort = null; this.targetPort = null;
@ -34,7 +33,7 @@ export class LinkModel<T extends LinkModelListener = LinkModelListener> extends
super.deSerialize(ob, engine); super.deSerialize(ob, engine);
this.extras = ob.extras; this.extras = ob.extras;
this.points = _.map(ob.points || [], (point: { x; y }) => { this.points = _.map(ob.points || [], (point: { x; y }) => {
var p = new PointModel(this, {x: point.x, y: point.y}); var p = new PointModel(this, { x: point.x, y: point.y });
p.deSerialize(point, engine); p.deSerialize(point, engine);
return p; return p;
}); });
@ -42,13 +41,20 @@ export class LinkModel<T extends LinkModelListener = LinkModelListener> extends
this.labels = ob.label || null; this.labels = ob.label || null;
if (ob.target) { if (ob.target) {
this.setTargetPort(this.getParent().getNode(ob.target).getPortFromID(ob.targetPort)); this.setTargetPort(
this.getParent()
.getNode(ob.target)
.getPortFromID(ob.targetPort)
);
} }
if (ob.source) { if (ob.source) {
this.setSourcePort(this.getParent().getNode(ob.source).getPortFromID(ob.sourcePort)); this.setSourcePort(
this.getParent()
.getNode(ob.source)
.getPortFromID(ob.sourcePort)
);
} }
} }
serialize() { serialize() {
@ -63,7 +69,7 @@ export class LinkModel<T extends LinkModelListener = LinkModelListener> extends
extras: this.extras, extras: this.extras,
labels: _.map(this.labels, label => { labels: _.map(this.labels, label => {
return label.serialize(); return label.serialize();
}), })
}); });
} }
@ -147,7 +153,7 @@ export class LinkModel<T extends LinkModelListener = LinkModelListener> extends
} }
this.sourcePort = port; this.sourcePort = port;
this.iterateListeners((listener: LinkModelListener, event) => { this.iterateListeners((listener: LinkModelListener, event) => {
listener.sourcePortChanged && listener.sourcePortChanged({...event, port: port}); listener.sourcePortChanged && listener.sourcePortChanged({ ...event, port: port });
}); });
} }
@ -169,15 +175,15 @@ export class LinkModel<T extends LinkModelListener = LinkModelListener> extends
} }
this.targetPort = port; this.targetPort = port;
this.iterateListeners((listener: LinkModelListener, event) => { this.iterateListeners((listener: LinkModelListener, event) => {
listener.targetPortChanged && listener.targetPortChanged({...event, port: port}); listener.targetPortChanged && listener.targetPortChanged({ ...event, port: port });
}); });
} }
point(x: number, y: number): PointModel{ point(x: number, y: number): PointModel {
return this.addPoint(this.generatePoint(x, y)); return this.addPoint(this.generatePoint(x, y));
} }
addLabel(label: LabelModel){ addLabel(label: LabelModel) {
label.setParent(this); label.setParent(this);
this.labels.push(label); this.labels.push(label);
} }
@ -218,6 +224,6 @@ export class LinkModel<T extends LinkModelListener = LinkModelListener> extends
} }
generatePoint(x: number = 0, y: number = 0): PointModel { generatePoint(x: number = 0, y: number = 0): PointModel {
return new PointModel(this, {x: x, y: y}); return new PointModel(this, { x: x, y: y });
} }
} }

View File

@ -1,8 +1,8 @@
import {BaseModel, BaseModelListener} from "./BaseModel"; import { BaseModel, BaseModelListener } from "./BaseModel";
import {PortModel} from "./PortModel"; import { PortModel } from "./PortModel";
import * as _ from "lodash"; import * as _ from "lodash";
import {DiagramEngine} from "../DiagramEngine"; import { DiagramEngine } from "../DiagramEngine";
import {DiagramModel} from "./DiagramModel"; import { DiagramModel } from "./DiagramModel";
export class NodeModel extends BaseModel<DiagramModel, BaseModelListener> { export class NodeModel extends BaseModel<DiagramModel, BaseModelListener> {
x: number; x: number;

View File

@ -1,9 +1,9 @@
import { BaseModel, BaseModelListener } from "./BaseModel"; import { BaseModel, BaseModelListener } from "./BaseModel";
import { LinkModel } from "./LinkModel"; import { LinkModel } from "./LinkModel";
import * as _ from "lodash"; import * as _ from "lodash";
import {DiagramEngine} from "../DiagramEngine"; import { DiagramEngine } from "../DiagramEngine";
export class PointModel extends BaseModel<LinkModel,BaseModelListener> { export class PointModel extends BaseModel<LinkModel, BaseModelListener> {
x: number; x: number;
y: number; y: number;
@ -25,7 +25,7 @@ export class PointModel extends BaseModel<LinkModel,BaseModelListener> {
return this.parent.getPortForPoint(this) !== null; return this.parent.getPortForPoint(this) !== null;
} }
getLink(): LinkModel{ getLink(): LinkModel {
return this.getParent(); return this.getParent();
} }

View File

@ -1,8 +1,8 @@
import {BaseModel, BaseModelListener} from "./BaseModel"; import { BaseModel, BaseModelListener } from "./BaseModel";
import {NodeModel} from "./NodeModel"; import { NodeModel } from "./NodeModel";
import {LinkModel} from "./LinkModel"; import { LinkModel } from "./LinkModel";
import * as _ from "lodash"; import * as _ from "lodash";
import {DiagramEngine} from "../DiagramEngine"; import { DiagramEngine } from "../DiagramEngine";
export class PortModel extends BaseModel<NodeModel, BaseModelListener> { export class PortModel extends BaseModel<NodeModel, BaseModelListener> {
name: string; name: string;
@ -84,7 +84,7 @@ export class PortModel extends BaseModel<NodeModel, BaseModelListener> {
return null; return null;
} }
updateCoords({x, y, width, height}: { x: number; y: number; width: number; height: number }) { updateCoords({ x, y, width, height }: { x: number; y: number; width: number; height: number }) {
this.x = x; this.x = x;
this.y = y; this.y = y;
this.width = width; this.width = width;
@ -95,7 +95,6 @@ export class PortModel extends BaseModel<NodeModel, BaseModelListener> {
return true; return true;
} }
isLocked() { isLocked() {
return super.isLocked() || this.getParent().isLocked(); return super.isLocked() || this.getParent().isLocked();
} }

View File

@ -10,10 +10,10 @@ import { PointModel } from "../models/PointModel";
import { PortModel } from "../models/PortModel"; import { PortModel } from "../models/PortModel";
import { LinkModel } from "../models/LinkModel"; import { LinkModel } from "../models/LinkModel";
import { BaseModel, BaseModelListener } from "../models/BaseModel"; import { BaseModel, BaseModelListener } from "../models/BaseModel";
import {BaseEntity} from "../BaseEntity"; import { BaseEntity } from "../BaseEntity";
export interface SelectionModel { export interface SelectionModel {
model: BaseModel<BaseEntity,BaseModelListener>; model: BaseModel<BaseEntity, BaseModelListener>;
initialX: number; initialX: number;
initialY: number; initialY: number;
} }
@ -137,7 +137,7 @@ export class DiagramWidget extends React.Component<DiagramProps, DiagramState> {
/** /**
* Gets a model and element under the mouse cursor * Gets a model and element under the mouse cursor
*/ */
getMouseElement(event): { model: BaseModel<BaseEntity,BaseModelListener>; element: Element } { getMouseElement(event): { model: BaseModel<BaseEntity, BaseModelListener>; element: Element } {
var target = event.target as Element; var target = event.target as Element;
var diagramModel = this.props.diagramEngine.diagramModel; var diagramModel = this.props.diagramEngine.diagramModel;

View File

@ -1,7 +1,7 @@
import * as React from "react"; import * as React from "react";
import { DiagramEngine } from "../DiagramEngine"; import { DiagramEngine } from "../DiagramEngine";
import { NodeModel } from "../models/NodeModel"; import { NodeModel } from "../models/NodeModel";
import {Toolkit} from "../Toolkit"; import { Toolkit } from "../Toolkit";
export interface NodeProps { export interface NodeProps {
node: NodeModel; node: NodeModel;
@ -25,7 +25,6 @@ export class NodeWidget extends React.Component<NodeProps, NodeState> {
} }
render() { render() {
return ( return (
<div <div
data-nodeid={this.props.node.id} data-nodeid={this.props.node.id}

View File

@ -2,7 +2,7 @@ import * as React from "react";
import { DiagramEngine } from "../../DiagramEngine"; import { DiagramEngine } from "../../DiagramEngine";
import * as _ from "lodash"; import * as _ from "lodash";
import { NodeWidget } from "../NodeWidget"; import { NodeWidget } from "../NodeWidget";
import {NodeModel} from "../../models/NodeModel"; import { NodeModel } from "../../models/NodeModel";
export interface NodeLayerProps { export interface NodeLayerProps {
diagramEngine: DiagramEngine; diagramEngine: DiagramEngine;