nope/resources/ui/gojs/DiagramWrapper.tsx

135 lines
4.1 KiB
TypeScript
Raw Normal View History

2021-07-27 10:55:15 +00:00
/**
* @author Martin Karkowski
* @email m.karkowski@zema.de
* @create date 2021-07-23 10:44:48
* @modify date 2021-07-23 10:44:48
* @desc [description]
2020-12-01 12:05:35 +00:00
*/
import * as go from "gojs";
import { ReactDiagram } from "gojs-react";
import * as React from "react";
2021-07-27 10:55:15 +00:00
import { generateGraph, ImplentedGraph } from "./graph-types/generateGraph";
2020-12-01 12:05:35 +00:00
interface DiagramProps {
nodeDataArray: Array<go.ObjectData>;
linkDataArray: Array<go.ObjectData>;
2021-07-27 10:55:15 +00:00
initDiagram?: () => go.Diagram;
diagramType?: ImplentedGraph;
templates: Array<{
name: string;
template: go.Part;
}>;
modelData?: go.ObjectData;
2020-12-01 12:05:35 +00:00
skipsDiagramUpdate: boolean;
2021-07-27 10:55:15 +00:00
onDiagramEvent?: (e: go.DiagramEvent) => void;
eventsToSubscribe?: go.DiagramEventName[];
onModelChange?: (e: go.IncrementalData) => void;
2020-12-01 12:05:35 +00:00
}
2021-07-27 10:55:15 +00:00
export class DiagramWrapper extends React.Component<DiagramProps, never> {
2020-12-01 12:05:35 +00:00
/**
* Ref to keep a reference to the Diagram component, which provides access to the GoJS diagram via getDiagram().
*/
private diagramRef: React.RefObject<ReactDiagram>;
/** @internal */
constructor(props: DiagramProps) {
super(props);
this.diagramRef = React.createRef();
}
/**
* Get the diagram reference and add any desired diagram listeners.
* Typically the same function will be used for each listener, with the function using a switch statement to handle the events.
*/
2021-07-27 10:55:15 +00:00
public componentDidMount(): void {
2020-12-01 12:05:35 +00:00
if (!this.diagramRef.current) return;
2021-07-27 10:55:15 +00:00
2020-12-01 12:05:35 +00:00
const diagram = this.diagramRef.current.getDiagram();
2021-07-27 10:55:15 +00:00
// Adapt its size
diagram.div.style.height = "100%";
diagram.div.style.width = "100%";
2020-12-01 12:05:35 +00:00
if (diagram instanceof go.Diagram) {
2021-07-27 10:55:15 +00:00
// If the Diagram is ready, we try to add the Templates.
const templates = Array.isArray(this.props.templates)
? this.props.templates
: [];
for (const template of templates) {
diagram.nodeTemplateMap.add(template.name, template.template);
}
if (typeof this.props.onDiagramEvent === "function") {
// Now we define the events we are listening on.
// We will forward these events to the callback
// "onDiagramEvent"
const subscribedEvents: go.DiagramEventName[] = Array.isArray(
this.props.eventsToSubscribe
)
? this.props.eventsToSubscribe
: [];
for (const eventName of subscribedEvents) {
diagram.addDiagramListener(eventName, this.props.onDiagramEvent);
}
}
2020-12-01 12:05:35 +00:00
}
}
/**
* Get the diagram reference and remove listeners that were added during mounting.
*/
2021-07-27 10:55:15 +00:00
public componentWillUnmount(): void {
2020-12-01 12:05:35 +00:00
if (!this.diagramRef.current) return;
const diagram = this.diagramRef.current.getDiagram();
if (diagram instanceof go.Diagram) {
diagram.removeDiagramListener(
"ChangedSelection",
this.props.onDiagramEvent
);
}
}
/**
* Diagram initialization method, which is passed to the ReactDiagram component.
* This method is responsible for making the diagram and initializing the model, any templates,
* and maybe doing other initialization tasks like customizing tools.
* The model's data should not be set here, as the ReactDiagram component handles that.
*/
2021-07-27 10:55:15 +00:00
protected initDiagram(): go.Diagram {
if (typeof this.props.initDiagram === "function") {
return this.props.initDiagram();
} else if (typeof this.props.diagramType === "string") {
return generateGraph(this.props.diagramType);
}
2020-12-01 12:05:35 +00:00
2021-07-27 10:55:15 +00:00
throw Error("");
2020-12-01 12:05:35 +00:00
}
2021-07-27 10:55:15 +00:00
public render(): JSX.Element {
const _this = this;
2020-12-01 12:05:35 +00:00
return (
<ReactDiagram
ref={this.diagramRef}
2021-07-27 10:55:15 +00:00
divClassName="None"
initDiagram={() => {
const diagram = _this.initDiagram();
console.log("diagram", diagram);
return diagram;
}}
nodeDataArray={_this.props.nodeDataArray}
linkDataArray={_this.props.linkDataArray}
modelData={_this.props.modelData}
onModelChange={(e) => {
if (typeof _this.props.onModelChange === "function") {
_this.props.onModelChange(e);
}
}}
skipsDiagramUpdate={_this.props.skipsDiagramUpdate}
2020-12-01 12:05:35 +00:00
/>
);
}
}