From 5584663f2906322e19ac17ac3b889b8a0959af84 Mon Sep 17 00:00:00 2001 From: Maximilian Giller <m.giller@tu-bs.de> Date: Tue, 19 Jul 2022 00:51:12 +0200 Subject: [PATCH] Implements somewhat working node type editor --- src/editor/js/components/editor.tsx | 84 +++++++++++--------- src/editor/js/components/nodetypeentry.css | 7 ++ src/editor/js/components/nodetypeentry.tsx | 83 +++++++++++++++++++ src/editor/js/components/nodetypeseditor.css | 5 ++ src/editor/js/components/nodetypeseditor.tsx | 45 +++++++++++ 5 files changed, 185 insertions(+), 39 deletions(-) create mode 100644 src/editor/js/components/nodetypeentry.css create mode 100644 src/editor/js/components/nodetypeentry.tsx create mode 100644 src/editor/js/components/nodetypeseditor.css create mode 100644 src/editor/js/components/nodetypeseditor.tsx diff --git a/src/editor/js/components/editor.tsx b/src/editor/js/components/editor.tsx index ac1d650..6c33719 100644 --- a/src/editor/js/components/editor.tsx +++ b/src/editor/js/components/editor.tsx @@ -10,6 +10,7 @@ import { Node } from "../structures/graph/node"; import { HistoryNavigator } from "./historynavigator"; import { GraphElement } from "../structures/graph/graphelement"; import { Link } from "../structures/graph/link"; +import { NodeTypesEditor } from "./nodetypeseditor"; type propTypes = any; type stateTypes = { @@ -420,45 +421,50 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> { onChange={this.forceUpdate} /> <hr /> - <div> - <input - id="node-labe-visibility" - type={"checkbox"} - checked={this.state.visibleLabels} - onChange={(event) => { - const newValue = event.target.checked; - if (newValue == this.state.visibleLabels) { - return; - } - - this.setState({ - visibleLabels: newValue, - }); - }} - /> - <label htmlFor="node-labe-visibility"> - Node labels - </label> - <br /> - <input - id="connect-on-drag" - type={"checkbox"} - checked={this.state.connectOnDrag} - onChange={(event) => { - const newValue = event.target.checked; - if (newValue == this.state.connectOnDrag) { - return; - } - - this.setState({ - connectOnDrag: newValue, - }); - }} - /> - <label htmlFor="connect-on-drag"> - Connect nodes when dragged - </label> - </div> + <h3>Node types</h3> + <NodeTypesEditor + onChange={this.forceUpdate} + graph={this.state.graph} + /> + <hr /> + <h3>Settings</h3> + <input + id="node-labe-visibility" + type={"checkbox"} + checked={this.state.visibleLabels} + onChange={(event) => { + const newValue = event.target.checked; + if (newValue == this.state.visibleLabels) { + return; + } + + this.setState({ + visibleLabels: newValue, + }); + }} + /> + <label htmlFor="node-labe-visibility"> + Node labels + </label> + <br /> + <input + id="connect-on-drag" + type={"checkbox"} + checked={this.state.connectOnDrag} + onChange={(event) => { + const newValue = event.target.checked; + if (newValue == this.state.connectOnDrag) { + return; + } + + this.setState({ + connectOnDrag: newValue, + }); + }} + /> + <label htmlFor="connect-on-drag"> + Connect nodes when dragged + </label> </div> {this.state.graph ? ( <ReactForceGraph2d diff --git a/src/editor/js/components/nodetypeentry.css b/src/editor/js/components/nodetypeentry.css new file mode 100644 index 0000000..d40ed0c --- /dev/null +++ b/src/editor/js/components/nodetypeentry.css @@ -0,0 +1,7 @@ +div#ks-editor .node-type-name { + width: 45%; +} + +div#ks-editor .node-type-color { + width: 5rem; +} diff --git a/src/editor/js/components/nodetypeentry.tsx b/src/editor/js/components/nodetypeentry.tsx new file mode 100644 index 0000000..42fa108 --- /dev/null +++ b/src/editor/js/components/nodetypeentry.tsx @@ -0,0 +1,83 @@ +import React from "react"; +import { ReactNode } from "react"; +import { Graph } from "../structures/graph/graph"; +import { NodeType } from "../structures/graph/nodetype"; +import "./nodetypeentry.css"; + +type propTypes = { + graph: Graph; + type: NodeType; + onChange: { (): void }; +}; + +export class NodeTypeEntry extends React.Component<propTypes> { + constructor(props: propTypes) { + super(props); + this.deleteType = this.deleteType.bind(this); + this.handleTextChange = this.handleTextChange.bind(this); + } + + private deleteType() { + this.props.type.delete(); + } + + private isValidColor(color: string): boolean { + if (color.length <= 0 || color[0] !== "#") { + return false; + } + + const colorCode = color.substring(1); + + if (!(colorCode.length === 3 || colorCode.length === 6)) { + return false; + } + + colorCode; + } + + /** + * Generic function for handeling a changing text input and applying the new value to the node type. + * @param event Change event of text input. + * @param property Property to give new value. + */ + private handleTextChange(event: any, property: string) { + const newValue = event.target.value; + + // Actual change? + if ((this.props.type as any)[property] == newValue) { + return; + } + + //TODO: Make sure, that this event is not triggered to quickly! + (this.props.type as any)[property] = newValue; + this.props.type.graph.storeCurrentData( + "Changed " + property + " of type [" + this.props.type + "]" + ); + + this.props.onChange(); + } + + render(): ReactNode { + return ( + <li className="node-type"> + <input + className="node-type-name" + type={"text"} + value={this.props.type.name} + onChange={(event) => this.handleTextChange(event, "name")} + /> + <input + className="node-type-color" + type={"text"} + value={this.props.type.color} + onChange={(event) => this.handleTextChange(event, "color")} + /> + {this.props.graph && this.props.graph.types.length > 1 ? ( + <button onClick={this.deleteType}>Delete</button> + ) : ( + "" + )} + </li> + ); + } +} diff --git a/src/editor/js/components/nodetypeseditor.css b/src/editor/js/components/nodetypeseditor.css new file mode 100644 index 0000000..db57894 --- /dev/null +++ b/src/editor/js/components/nodetypeseditor.css @@ -0,0 +1,5 @@ +div#ks-editor #node-types-editor ul { + list-style-type: none; + margin: 0; + padding: 0; +} diff --git a/src/editor/js/components/nodetypeseditor.tsx b/src/editor/js/components/nodetypeseditor.tsx new file mode 100644 index 0000000..b649a1d --- /dev/null +++ b/src/editor/js/components/nodetypeseditor.tsx @@ -0,0 +1,45 @@ +import React from "react"; +import { ReactNode } from "react"; +import { Graph } from "../structures/graph/graph"; +import "./nodetypeseditor.css"; +import { NodeTypeEntry } from "./nodetypeentry"; +import { NodeType } from "../structures/graph/nodetype"; + +type propTypes = { + graph: Graph; + onChange: { (): void }; +}; + +export class NodeTypesEditor extends React.Component<propTypes> { + constructor(props: propTypes) { + super(props); + this.addType = this.addType.bind(this); + } + + private addType() { + const type = new NodeType(this.props.graph); + type.add(); + } + + render(): ReactNode { + if (this.props.graph === undefined) { + return "No graph selected."; + } + + return ( + <div id="node-types-editor"> + <ul> + {this.props.graph.types.map((type) => ( + <NodeTypeEntry + onChange={this.props.onChange} + key={type.id} + type={type} + graph={this.props.graph} + /> + ))} + </ul> + <button onClick={this.addType}>Add type</button> + </div> + ); + } +} -- GitLab