diff --git a/editor/editor.html b/editor/editor.html index d45958ec1204a133442fedfbc3e2127ff5154ef0..527abd44ef3fc12f8ba68f1d8b699bd7f4fa04e9 100644 --- a/editor/editor.html +++ b/editor/editor.html @@ -29,6 +29,7 @@ <script src="%WWW%editor/js/tools/selecttool.js"></script> <script src="%WWW%editor/js/tools/collecttool.js"></script> <script src="%WWW%editor/js/tools/deletetool.js"></script> + <script src="%WWW%editor/js/tools/addnodetool.js"></script> <script src="%WWW%editor/js/display.js"></script> <script src="%WWW%editor/js/state.js"></script> <script src="%WWW%editor/js/editor.js"></script> diff --git a/editor/images/tools/addnode.png b/editor/images/tools/addnode.png new file mode 100644 index 0000000000000000000000000000000000000000..a899e0a587dd2538612438fbac1f40e060ece5b0 Binary files /dev/null and b/editor/images/tools/addnode.png differ diff --git a/editor/js/editor.js b/editor/js/editor.js index c9b0694ee2a652b8070fcacbcfcba8cc49a1f79d..be00eeaa97d648f69c25a889797f75e267be6b66 100644 --- a/editor/js/editor.js +++ b/editor/js/editor.js @@ -35,7 +35,7 @@ function downloadJson() { function extractPositions(event) { return { - graph: { x: event.layerX, y: event.layerY }, + graph: graphObj.screen2GraphCoords(event.layerX, event.layerY), window: { x: event.clientX, y: event.clientY }, }; } @@ -57,8 +57,14 @@ function load() { .linkDirectionalParticleWidth((link) => state.linkDirectionalParticleWidth(link) ) - .onBackgroundClick((event) => state.onBackgroundClick(event, extractPositions(event))) + .onBackgroundClick((event) => + state.onBackgroundClick(event, extractPositions(event)) + ) .nodeCanvasObjectMode((node) => state.nodeCanvasObjectMode(node)) .nodeCanvasObject((node, ctx) => state.nodeCanvasObject(node, ctx)) .onLinkClick((link) => state.onLinkClick(link)); + + graph.externUpdate.push(() => { + graphObj.graphData(graph.data); + }); } diff --git a/editor/js/graph.js b/editor/js/graph.js index 52fffdc693061eeefdfa1362a3c78a6235c39fd1..a8d3d4095dbc985562d40dc69f2ccba09fdc204b 100644 --- a/editor/js/graph.js +++ b/editor/js/graph.js @@ -13,7 +13,7 @@ const GRAPH_NODES = "nodes"; const GRAPH_LINKS = "links"; const IMAGE_SIZE = 12; -const IMAGE_SRC = PLUGIN_PATH + "datasets/images/" +const IMAGE_SRC = PLUGIN_PATH + "datasets/images/"; const LINK_PARAMS = [LINK_TYPE]; const NODE_PARAMS = [NODE_ID, NODE_LABEL, NODE_IMAGE, NODE_DESCRIPTION]; @@ -22,10 +22,13 @@ const JSON_CONFIG = PLUGIN_PATH + "datasets/aud1.json"; const STOP_PHYSICS_DELAY = 5000; // ms - - const graph = { data: undefined, + externUpdate: [], + + update() { + graph.externUpdate.forEach((fn) => fn()); + }, deleteNode(nodeId) { // Delete node from nodes @@ -159,4 +162,60 @@ const graph = { return cleanLink; }, + + existsNodeId(nodeId) { + var nodes = graph.data[GRAPH_NODES]; + for (var i = 0; i < nodes.length; i++) { + if (nodes[i][NODE_ID] === nodeId) { + return true; + } + } + return false; + }, + + getUnusedNodeId() { + var id; + do { + id = graph.getRandomString(); + } while (graph.existsNodeId(id)); + return id; + }, + + getRandomString(length = 8) { + // Based on: https://stackoverflow.com/a/1349426/7376120 + var characters = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + var charactersLength = characters.length; + + var result = ""; + for (var i = 0; i < length; i++) { + result += characters.charAt( + Math.floor(Math.random() * charactersLength) + ); + } + return result; + }, + + addNode(nodeDetails) { + // Copy params + var newNode = nodeDetails; + + // Make sure the ID is set and unique + if (newNode[NODE_ID] === undefined) { + newNode[NODE_ID] = graph.getUnusedNodeId(); + } else if (graph.existsNodeId(newNode[NODE_ID])) { + return; + } + + // Basic node properties + newNode.node = true; + newNode.link = false; + newNode.index = graph.data[GRAPH_NODES].length; + + // Add node + graph.data[GRAPH_NODES].push(newNode); + graph.update(); + + return newNode; + }, }; diff --git a/editor/js/state.js b/editor/js/state.js index 9370f8d140743a7e1d34ff2b16548d1048383cf3..a58d25332e55150220ad2ed0b38eb6fd925fb6dc 100644 --- a/editor/js/state.js +++ b/editor/js/state.js @@ -2,6 +2,7 @@ const TOOLS = { select: new SelectTool("select"), collect: new CollectTool("collect"), delete: new DeleteTool("delete"), + addnode: new AddNodeTool("addnode"), }; const CONTEXT = { @@ -184,7 +185,6 @@ class State extends Tool { } onBackgroundClick(event, positions) { - console.log(event); this.tool.onBackgroundClick(event, positions); } diff --git a/editor/js/tools/addnodetool.js b/editor/js/tools/addnodetool.js new file mode 100644 index 0000000000000000000000000000000000000000..c72c189d8ac795d2ab22be6553476e07dc359a76 --- /dev/null +++ b/editor/js/tools/addnodetool.js @@ -0,0 +1,22 @@ +class AddNodeTool extends Tool { + constructor(key) { + super("Add node", "addnode", key); + } + + onBackgroundClick(event, positions) { + var node = {}; + + // Set position + node.fx = positions.graph.x; + node.fy = positions.graph.y; + + var node = graph.addNode(node); + + if (node === undefined) { + console.error("Couldn't add new node"); + return; + } + + state.setSelectedItem(node); + } +} \ No newline at end of file