diff --git a/src/editor/js/components/editor.tsx b/src/editor/js/components/editor.tsx index bb8be8509e817c74e910de494e539664887368fe..88483dc5d91687e0794a62a2cac3a43b26aa7b34 100644 --- a/src/editor/js/components/editor.tsx +++ b/src/editor/js/components/editor.tsx @@ -5,6 +5,7 @@ import * as Interactions from "../interactions"; import { Graph } from "../structures/graph/graph"; import ForceGraph from "force-graph"; import { loadGraphJson } from "../../../datasets"; +import { ToolPool } from "./toolpool"; export class Editor extends React.PureComponent< InferType<typeof Editor.propTypes>, @@ -25,6 +26,12 @@ export class Editor extends React.PureComponent< constructor(props: InferType<typeof Editor.propTypes>) { super(props); + // Set as new state + this.state = { + state: undefined, + graph: undefined, + renderer: undefined, + }; Interactions.initInteractions(); @@ -48,64 +55,73 @@ export class Editor extends React.PureComponent< */ public loadGraph(data: any): boolean { // Create global objects - const state = new State(); - const graph = Graph.parse(data); + // TODO: is not loading properly + Editor.globalState = new State(); + Editor.globalGraph = Graph.parse(data); // Is valid and parsed successfully? - if (graph == undefined) { + if (Editor.globalGraph == undefined) { + Editor.globalState = this.state.state; + Editor.globalGraph = this.state.graph; return false; } // Create renderer const renderTarget = document.getElementById("2d-graph"); const renderWidth = renderTarget.offsetWidth; - const renderer = ForceGraph()(renderTarget); + Editor.globalRenderer = ForceGraph()(renderTarget); // Subscribe to interactions - renderer + Editor.globalRenderer .height(600) .width(renderWidth) - .graphData(graph.data) + .graphData(Editor.globalGraph.data) .nodeLabel("label") - .linkColor((link) => state.linkColor(link)) - .nodeColor((node) => state.nodeColor(node)) - .onNodeClick((node) => state.onNodeClick(node)) - .onNodeDragEnd((node, translate) => - state.onNodeDragEnd(node, translate) + .linkColor((link: any) => Editor.globalState.linkColor(link)) + .nodeColor((node: any) => Editor.globalState.nodeColor(node)) + .onNodeClick((node: any) => Editor.globalState.onNodeClick(node)) + .onNodeDragEnd((node: any, translate: any) => + Editor.globalState.onNodeDragEnd(node, translate) ) .autoPauseRedraw(false) // keep redrawing after engine has stopped - .linkWidth((link) => state.linkWidth(link)) - .linkDirectionalParticles(state.linkDirectionalParticles()) - .linkDirectionalParticleWidth((link) => - state.linkDirectionalParticleWidth(link) + .linkWidth((link: any) => Editor.globalState.linkWidth(link)) + .linkDirectionalParticles( + Editor.globalState.linkDirectionalParticles() + ) + .linkDirectionalParticleWidth((link: any) => + Editor.globalState.linkDirectionalParticleWidth(link) + ) + .onBackgroundClick((event: any) => + Editor.globalState.onBackgroundClick( + event, + this.extractPositions(event) + ) + ) + .nodeCanvasObjectMode((node: any) => + Editor.globalState.nodeCanvasObjectMode(node) ) - .onBackgroundClick((event) => - state.onBackgroundClick(event, this.extractPositions(event)) + .nodeCanvasObject((node: any, ctx: any, globalScale: any) => + Editor.globalState.nodeCanvasObject(node, ctx, globalScale) ) - .nodeCanvasObjectMode((node) => state.nodeCanvasObjectMode(node)) - .nodeCanvasObject((node, ctx, globalScale) => - state.nodeCanvasObject(node, ctx, globalScale) + .linkCanvasObjectMode((link: any) => + Editor.globalState.linkCanvasObjectMode(link) ) - .linkCanvasObjectMode((link) => state.linkCanvasObjectMode(link)) - .linkCanvasObject((link, ctx, globalScale) => - state.linkCanvasObject(link, ctx, globalScale) + .linkCanvasObject((link: any, ctx: any, globalScale: any) => + Editor.globalState.linkCanvasObject(link, ctx, globalScale) ) - .onLinkClick((link) => state.onLinkClick(link)); + .onLinkClick((link: any) => Editor.globalState.onLinkClick(link)); // Connect update event - graph.onChangeCallbacks.push((data) => { - renderer.graphData(data); + Editor.globalGraph.onChangeCallbacks.push((data) => { + Editor.globalRenderer.graphData(data); }); // Set as new state this.setState({ - state: state, - graph: graph, - renderer: renderer, + state: Editor.globalState, + graph: Editor.globalGraph, + renderer: Editor.globalRenderer, }); - Editor.globalState = state; - Editor.globalGraph = graph; - Editor.globalRenderer = renderer; // Subscribe to global key-press events document.onkeydown = this.state.state.onKeyDown; @@ -140,7 +156,7 @@ export class Editor extends React.PureComponent< <div id="box-select-layer"> <div id="2d-graph"></div> </div> - <section id="toolbar"></section> + <ToolPool state={this.state.state} /> <section id="tool-menu"> <div id="delete-menu" className="hidden"> <p> diff --git a/src/editor/js/components/toolbutton.tsx b/src/editor/js/components/toolbutton.tsx new file mode 100644 index 0000000000000000000000000000000000000000..88fd1bfdc56c43d0b7fcbea30f3f4bfcdae60741 --- /dev/null +++ b/src/editor/js/components/toolbutton.tsx @@ -0,0 +1,27 @@ +import { InferType } from "prop-types"; +import React from "react"; +import { State } from "../state"; +import Tool from "../tools/tool"; + +type propTypes = { + tool: Tool; + state: State; +}; + +export class ToolButton extends React.PureComponent< + propTypes, + InferType<typeof ToolButton.stateTypes> +> { + static stateTypes = {}; + + render(): React.ReactNode { + return ( + <button + title={this.props.tool.getName()} + onClick={() => this.props.state.setTool(this.props.tool)} + > + <img src={this.props.tool.getIcon()} /> + </button> + ); + } +} diff --git a/src/editor/js/components/toolpool.tsx b/src/editor/js/components/toolpool.tsx new file mode 100644 index 0000000000000000000000000000000000000000..1438c79252b6f1adf8383d97513cc51bfaebb326 --- /dev/null +++ b/src/editor/js/components/toolpool.tsx @@ -0,0 +1,38 @@ +import { InferType } from "prop-types"; +import React from "react"; +import { State } from "../state"; +import { ToolButton } from "./toolbutton"; + +type propTypes = { + state: State; +}; + +export class ToolPool extends React.PureComponent< + propTypes, + InferType<typeof ToolPool.stateTypes> +> { + static stateTypes = {}; + + constructor(props: propTypes) { + super(props); + } + + render(): React.ReactNode { + // Don't render anything if state is not defined + if (!this.state) { + return <div id="toolpool"></div>; + } + + return ( + <div id="toolpool"> + {this.props.state.display.tools.map((t) => ( + <ToolButton + tool={t} + state={this.props.state} + key={t.getKey()} + /> + ))} + </div> + ); + } +}