import Tool from "./tool"; import { graph, state, renderer } from "../editor"; import * as Graph from "../graph"; import jquery from "jquery"; import ToolMenu from "./menus/toolmenu"; /** * Only one instance of this should exist, since box-delete has to work on a global scale. */ var deleteToolInstance = undefined; // Used for box delete export default class DeleteTool extends Tool { constructor(key) { super("Delete", "delete", key, new ToolMenu()); this.setupBoxSelect(); this.isActive = false; if (deleteToolInstance === undefined) { deleteToolInstance = this; } } onToolActivate() { this.isActive = true; } onToolDeactivate(nextTool) { this.isActive = false; } onBoxSelect(left, bottom, top, right) { // Filter out selected nodes const hitNodes = []; const tl = renderer.screen2GraphCoords(left, top); const br = renderer.screen2GraphCoords(right, bottom); graph.data[Graph.GRAPH_NODES].forEach((node) => { if ( tl.x < node.x && node.x < br.x && br.y > node.y && node.y > tl.y ) { hitNodes.push(node); } }); // Delete selected items after confirmation console.log("DELETE"); console.log(hitNodes); } onNodeClick(node) { graph.deleteNode(node[Graph.NODE_ID]); if (state.selectedItem == node) { state.setSelectedItem(undefined); } } onLinkClick(link) { graph.deleteLink( link[Graph.LINK_SOURCE][Graph.NODE_ID], link[Graph.LINK_TARGET][Graph.NODE_ID] ); if (state.selectedItem == link) { state.setSelectedItem(undefined); } } setupBoxSelect() { window.addEventListener("load", () => { // Source: https://github.com/vasturiano/force-graph/issues/151#issuecomment-735850938 // forceGraph element is the element provided to the Force Graph Library jquery("#2d-graph").on( "pointerdown", this.boxSelectOnPointerDown ); jquery("#2d-graph").on( "pointermove", this.boxSelectOnPointerMove ); jquery("#2d-graph").on( "pointerup", this.boxSelectOnPointerUp ); }); } boxSelectOnPointerDown(e) { // Only do anything if delete tool is also active if (deleteToolInstance === undefined || deleteToolInstance.isActive == false) { return; } if (!e.shiftKey) { return; } e.preventDefault(); this.boxSelect = document.createElement("div"); this.boxSelect.id = "box-select"; this.boxSelect.style.left = e.offsetX.toString() + "px"; this.boxSelect.style.top = e.offsetY.toString() + "px"; this.boxSelectStart = { x: e.offsetX, y: e.offsetY, }; // app element is the element just above the forceGraph element. jquery("#box-select-layer").append(this.boxSelect); } boxSelectOnPointerMove(e) { if (!this.boxSelect) { return; } if (!e.shiftKey) { this.boxSelect.remove(); return; } e.preventDefault(); if (e.offsetX < this.boxSelectStart.x) { this.boxSelect.style.left = e.offsetX.toString() + "px"; this.boxSelect.style.width = (this.boxSelectStart.x - e.offsetX).toString() + "px"; } else { this.boxSelect.style.left = this.boxSelectStart.x.toString() + "px"; this.boxSelect.style.width = (e.offsetX - this.boxSelectStart.x).toString() + "px"; } if (e.offsetY < this.boxSelectStart.y) { this.boxSelect.style.top = e.offsetY.toString() + "px"; this.boxSelect.style.height = (this.boxSelectStart.y - e.offsetY).toString() + "px"; } else { this.boxSelect.style.top = this.boxSelectStart.y.toString() + "px"; this.boxSelect.style.height = (e.offsetY - this.boxSelectStart.y).toString() + "px"; } } boxSelectOnPointerUp(e) { if (!this.boxSelect) { return; } if (!e.shiftKey) { this.boxSelect.remove(); return; } e.preventDefault(); let left, bottom, top, right; if (e.offsetX < this.boxSelectStart.x) { left = e.offsetX; right = this.boxSelectStart.x; } else { left = this.boxSelectStart.x; right = e.offsetX; } if (e.offsetY < this.boxSelectStart.y) { top = e.offsetY; bottom = this.boxSelectStart.y; } else { top = this.boxSelectStart.y; bottom = e.offsetY; } this.boxSelect.remove(); deleteToolInstance.onBoxSelect(left, bottom, top, right); } }