src/js/tool/node-tool.js
import Tool from '../tool/tool';
import Node from '../data/node/node';
import CircleNode from '../data/node/circle-node';
import TriangleNode from '../data/node/triangle-node';
import SquareNode from '../data/node/square-node';
import DiamondNode from '../data/node/diamond-node';
import PentagonNode from '../data/node/pentagon-node';
import HexagonNode from '../data/node/hexagon-node';
import OctagonNode from '../data/node/octagon-node';
/**
* Tool for adding nodes to the graph.
* @class NodeTool
*/
class NodeTool extends Tool {
currentMode = 'circle';
static modes = {
circle: CircleNode,
triangle: TriangleNode,
square: SquareNode,
diamond: DiamondNode,
pentagon: PentagonNode,
hexagon: HexagonNode,
octagon: OctagonNode
};
optionMap = {
circle: {
label: 'Circle'
},
triangle: {
label: 'Triangle'
},
square: {
label: 'Square'
},
diamond: {
label: 'Diamond'
},
pentagon: {
label: 'Pentagon'
},
hexagon: {
label: 'Hexagon'
},
octagon: {
label: 'Octagon'
}
};
optionContent = {
html: '<canvas class="canvas-preview" width="50" height="50"></canvas>',
init: (optionElement, mode) => {
let canvas = optionElement.querySelector('canvas');
let context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
let node = new NodeTool.modes[mode](25, 25);
for (let field of Object.keys(this.inputs)) {
node[field] = this.inputs[field];
}
node.radius = 15;
node.draw(context);
}
};
inputs = {
isAcceptingState: false,
isStartingState: false,
radius: 30,
color: '#000000',
fillColor: '#ffffff',
lineWidth: 1
};
inputTypes = [
{
type: 'boolean',
name: 'isAcceptingState',
displayName: 'Accepting State'
},
{
type: 'boolean',
name: 'isStartingState',
displayName: 'Starting State'
},
{
type: 'number',
name: 'radius',
displayName: 'Radius'
},
{
type: 'color',
name: 'color',
displayName: 'Line Color'
},
{
type: 'color',
name: 'fillColor',
displayName: 'Fill Color'
},
{
type: 'number',
name: 'lineWidth',
displayName: 'Line Width'
}
];
/**
* Handler for object selection. Attempts to create a node at the mouse's location.
* @param {Event} event - Event object from event listener.
* @param {Graph} graph - The current graph object.
* @param {(Node|Edge|Label)} obj - Selected graph component.
* @param {number} x - Mouse x-coordinate (in canvas coordinates).
* @param {number} y - Mouse y-coordinate (in canvas coordinates).
*/
selectObject(event, graph, obj, x, y) {
if (!(obj instanceof Node)) {
this.selectNone(event, graph, x, y);
}
}
/**
* Handler for clicking empty space. Attempts to create a node at the mouse's location.
* @param {Event} event - Event object from event listener.
* @param {Graph} graph - The current graph object.
* @param {number} x - Mouse x-coordinate (in canvas coordinates).
* @param {number} y - Mouse y-coordinate (in canvas coordinates).
*/
selectNone(event, graph, x, y) {
this.addNode(this.currentMode, graph, x, y);
}
/**
* Handler for dropping object on empty space. The dropped object is ignored and attempts to create a node at the mouse's location.
* @param {Event} event - Event object from event listener.
* @param {Graph} graph - The current graph object.
* @param {(Node|Edge|Label)} droppedObj - Dropped graph component.
* @param {number} x - Mouse x-coordinate (in canvas coordinates).
* @param {number} y - Mouse y-coordinate (in canvas coordinates).
*/
dropOnNone(event, graph, droppedObj, x, y) {
this.selectNone(event, graph, x, y);
}
/**
* Helper function for creating a node can be added at the given position.
* @param {string} mode - Name of the current mode.
* @param {Graph} graph - The current graph object.
* @param {number} x - x-coordinate (in canvas coordinates) of the point to create the node.
* @param {number} y - y-coordinate (in canvas coordinates) of the point to create the node.
*/
addNode(mode, graph, x, y) {
let NodeClass = NodeTool.modes[mode];
let node = new NodeClass(x, y);
for (let field of Object.keys(this.inputs)) {
node[field] = this.inputs[field];
}
if (!graph.isNodeCollision(node, x, y)) {
graph.addNode(node);
}
}
}
export { NodeTool };
export default NodeTool;