custom link demo

This commit is contained in:
Karel Frajtak
2017-11-28 19:35:52 +01:00
parent a1369453c1
commit 9b047ca4e4
6 changed files with 168 additions and 10 deletions

130
demos/demo12/index.tsx Normal file
View File

@@ -0,0 +1,130 @@
import {
DiagramEngine,
DefaultNodeFactory,
DefaultLinkFactory,
DiagramModel,
DefaultNodeModel,
LinkModel,
DefaultPortModel,
DiagramWidget,
LinkWidget,
LinkProps,
DefaultLinkWidget,
CustomizableLinkProps
} from "../../src/main";
import { action } from "@storybook/addon-actions";
import * as React from "react";
import { LinkWidgetFactory } from "../../src/WidgetFactories";
export class AdvancedLinkModel extends LinkModel {
constructor() {
super();
this.linkType = "advanced";
}
}
export class AdvancedPortModel extends DefaultPortModel
{
constructor(isInput: boolean, name: string, label: string = null, id?: string) {
super(isInput, name, label, id);
}
createLinkModel(): LinkModel | null {
return new AdvancedLinkModel();
}
}
export class AdvancedLinkWidget extends DefaultLinkWidget {
constructor(props: LinkProps) {
super(props);
}
beforeLinkGenerated(props: CustomizableLinkProps): CustomizableLinkProps {
return {
color: 'green',
width: 4,
smooth: props.smooth
};
}
}
export class AdvancedLinkWidgetFactory extends LinkWidgetFactory {
constructor() {
super("advanced");
}
generateReactWidget(diagramEngine: DiagramEngine, link: LinkModel): JSX.Element {
return React.createElement(AdvancedLinkWidget, {
link: link,
diagramEngine: diagramEngine
});
}
}
/**
*
* Simple link styling demo
*
* @Author kfrajtak
*/
export default () => {
//1) setup the diagram engine
var engine = new DiagramEngine();
engine.registerNodeFactory(new DefaultNodeFactory());
engine.registerLinkFactory(new AdvancedLinkWidgetFactory());
engine.registerLinkFactory(new DefaultLinkFactory());
var node1 = new DefaultNodeModel("Source", "rgb(0,192,255)");
var port1 = node1.addPort(new AdvancedPortModel(false, "out-1", "Out solid"));
var port2 = node1.addPort(new AdvancedPortModel(false, "out-2", "Out dashed"));
var port3 = node1.addPort(new DefaultPortModel(false, "out-3", "Out default"));
node1.x = 100;
node1.y = 100;
var node2 = new DefaultNodeModel("Target", "rgb(192,255,0)");
var port4 = node2.addPort(new AdvancedPortModel(true, "in-1", "In solid"));
var port5 = node2.addPort(new AdvancedPortModel(true, "in-2", "In dashed"));
var port6 = node2.addPort(new DefaultPortModel(true, "in-3", "In default"));
node2.x = 300;
node2.y = 100;
[node1, node2].forEach((item) => {
item.addListener({
selectionChanged: action('selectionChanged')
});
});
/*function generateNodes(model: DiagramModel, offsetX: number, offsetY: number) {
//3-A) create a default node
//3-B) create another default node
//3-C) link the 2 nodes together
var link1 = new LinkModel();
link1.setSourcePort(port1);
link1.setTargetPort(port2);
//4) add the models to the root graph
model.addNode(node1);
model.addNode(node2);
model.addLink(link1);
}*/
//2) setup the diagram model
var model = new DiagramModel();
model.addNode(node1);
model.addNode(node2);
//5) load model into engine
engine.setDiagramModel(model);
//6) render the diagram!
return (
<div>
<DiagramWidget diagramEngine={engine} />
</div>
);
};

View File

@@ -14,6 +14,7 @@ import demo8 from "./demo8/index";
import demo9 from "./demo9/index";
import demo10 from "./demo10/index";
import demo11 from "./demo11/index";
import demo12 from "./demo12/index";
import demoDagre from "./demo-dagre/index";
import {Helper} from "./Helper";
@@ -59,6 +60,9 @@ storiesOf("React Diagrams", module)
})
.add("Zoom to fit", () => {
return demo11();
})
.add("Link types", () => {
return demo12();
});
// enable this to log mouse location when writing new puppeteer tests

View File

@@ -1,6 +1,7 @@
import { BaseEntity, BaseListener } from "./BaseEntity";
import * as _ from "lodash";
import { port } from "_debugger";
import { DiagramEngine } from "./DiagramEngine";
export interface BaseModelListener extends BaseListener {
selectionChanged?(item: BaseModel<BaseModelListener>, isSelected: boolean): void;
@@ -74,8 +75,8 @@ export class PointModel extends BaseModel<BaseModelListener> {
this.x = points.x;
this.y = points.y;
this.link = link;
}
}
getSelectedEntities() {
if (super.isSelected() && !this.isConnectedToPort()) {
return [this];
@@ -272,6 +273,10 @@ export class LinkModel extends BaseModel<LinkModelListener> {
getType(): string {
return this.linkType;
}
generateLinkWidget(diagramEngine: DiagramEngine): JSX.Element | null {
return diagramEngine.generateWidgetForLink(this);
}
}
export class PortModel extends BaseModel<BaseModelListener> {
@@ -324,6 +329,10 @@ export class PortModel extends BaseModel<BaseModelListener> {
getLinks(): { [id: string]: LinkModel } {
return this.links;
}
createLinkModel(): LinkModel | null {
return null;
}
}
export class NodeModel extends BaseModel<BaseModelListener> {

View File

@@ -3,11 +3,14 @@ import { LinkModel, PointModel } from "../Common";
import * as _ from "lodash";
import { DiagramEngine } from "../DiagramEngine";
export interface DefaultLinkProps {
export interface CustomizableLinkProps {
color?: string;
width?: number;
smooth?: boolean;
}
export interface DefaultLinkProps extends CustomizableLinkProps {
link: LinkModel;
smooth?: boolean;
diagramEngine: DiagramEngine;
pointAdded?: (point: PointModel, event) => any;
}
@@ -81,12 +84,22 @@ export class DefaultLinkWidget extends React.Component<DefaultLinkProps, Default
);
}
beforeLinkGenerated(props: CustomizableLinkProps): CustomizableLinkProps {
return props;
}
generateLink(extraProps: any, id: string | number): JSX.Element {
var props = this.beforeLinkGenerated({
color: this.props.color,
smooth: this.props.smooth,
width: this.props.width
});
var Bottom = (
<path
className={this.state.selected || this.props.link.isSelected() ? "selected" : ""}
strokeWidth={this.props.width}
stroke={this.props.color}
strokeWidth={props.width}
stroke={props.color}
{...extraProps}
/>
);
@@ -101,7 +114,7 @@ export class DefaultLinkWidget extends React.Component<DefaultLinkProps, Default
this.setState({ selected: true });
}}
data-linkid={this.props.link.getID()}
stroke={this.props.color}
stroke={props.color}
strokeOpacity={this.state.selected ? 0.1 : 0}
strokeWidth={20}
onContextMenu={() => {

View File

@@ -414,8 +414,9 @@ export class DiagramWidget extends React.Component<DiagramProps, DiagramState> {
//its a port element, we want to drag a link
if (!this.props.diagramEngine.isModelLocked(model.model)) {
var relative = diagramEngine.getRelativeMousePoint(event);
var link = new LinkModel();
link.setSourcePort(model.model);
var sourcePort = model.model;
var link = sourcePort.createLinkModel() || new LinkModel();
link.setSourcePort(sourcePort);
link.getFirstPoint().updateLocation(relative);
link.getLastPoint().updateLocation(relative);

View File

@@ -4,6 +4,7 @@ import { DiagramEngine } from "../DiagramEngine";
import { PointModel } from "../Common";
import { LinkWidget } from "./LinkWidget";
import * as _ from "lodash";
import { LinkModel } from "../main";
export interface LinkLayerProps {
diagramEngine: DiagramEngine;
@@ -57,7 +58,7 @@ export class LinkLayerWidget extends React.Component<LinkLayerProps, LinkLayerSt
}
//generate links
var generatedLink = this.props.diagramEngine.generateWidgetForLink(link);
var generatedLink = link.generateLinkWidget(this.props.diagramEngine);
if (!generatedLink) {
console.log("no link generated for type: " + link.getType());
return null;