Skip to content
Snippets Groups Projects
state.js 4.78 KiB
Newer Older
  • Learn to ignore specific revisions
  • Maximilian Giller's avatar
    Maximilian Giller committed
    const TOOLS = {
        select: new SelectTool("select"),
        collect: new CollectTool("collect"),
        delete: new DeleteTool("delete"),
    
        addnode: new AddNodeTool("addnode"),
    
    Maximilian Giller's avatar
    Maximilian Giller committed
        connect: new ConnectTool("connect"),
    
    Maximilian Giller's avatar
    Maximilian Giller committed
    };
    
    const CONTEXT = {
        node: "node",
        link: "link",
        mixed: "mixed",
    };
    
    class State extends Tool {
        constructor() {
            super("State");
    
            this.display = new Display(TOOLS);
    
            this.tool = undefined;
            this.setTool(TOOLS.select);
    
            // Shared variables
            this.selectedItem = undefined;
            this.selectedItems = new Set();
            this.itemsContext = undefined;
    
            this.keyStates = {};
        }
    
        setTool(tool) {
    
            if (this.tool === tool) {
    
    Maximilian Giller's avatar
    Maximilian Giller committed
                return;
            }
    
            this.previousTool = this.tool;
            this.tool = tool;
            this.display.setSelectedTool(tool);
        }
    
        setSelectedItem(item) {
            this.selectedItem = item;
            this.display.setSelectedItem(item);
        }
    
        addSelectedItem(item) {
            this.selectedItems.add(item);
            this.display.setSelectedItems(this.selectedItems, this.itemsContext);
        }
    
        removeSelectedItem(item) {
            this.selectedItems.delete(item);
            this.display.setSelectedItems(this.selectedItems, this.itemsContext);
        }
    
        clearSelectedItems() {
            this.selectedItems.clear();
            this.itemsContext = undefined;
            this.display.setSelectedItems(this.selectedItems, this.itemsContext);
        }
    
        onNodeClick(node) {
            this.tool.onNodeClick(node);
        }
    
        onLinkClick(link) {
            this.tool.onLinkClick(link);
        }
    
        onKeyDown(key) {
            var id = this.getKeyId(key);
            var previous = this.keyStates[id];
    
            this.keyStates[id] = true;
    
            if (previous !== true) {
                this.tool.onKeyDown(key);
            }
        }
    
        onKeyUp(key) {
            var id = this.getKeyId(key);
            var previous = this.keyStates[id];
    
            this.keyStates[id] = false;
    
            if (previous !== false) {
                this.tool.onKeyUp(key);
            }
        }
    
        getKeyId(key) {
            return key.keyCode;
        }
    
        nodeCanvasObject(node, ctx) {
            var toolValue = this.tool.nodeCanvasObject(node, ctx);
    
            if (toolValue !== undefined) {
                return toolValue;
            }
    
            // TODO: Clean up function
    
            // add ring just for highlighted nodes
            if (this.selectedItem === node || this.selectedItems.has(node)) {
                ctx.beginPath();
                ctx.arc(node.x, node.y, 5 * 1.4, 0, 2 * Math.PI, false);
                ctx.fillStyle = this.selectedItem === node ? "red" : "green";
                ctx.fill();
            }
    
            // Draw image
            if (node[NODE_IMAGE] !== undefined) {
                var path = IMAGE_SRC + node[NODE_IMAGE];
                var img = new Image();
                img.src = path;
    
                ctx.drawImage(
                    img,
                    node.x - IMAGE_SIZE / 2,
                    node.y - IMAGE_SIZE / 2,
                    IMAGE_SIZE,
                    IMAGE_SIZE
                );
            }
    
            // TODO: Render label as always visible
        }
    
        nodePointerAreaPaint(node, color, ctx) {
            var toolValue = this.tool.nodePointerAreaPaint(node, color, ctx);
    
            if (toolValue !== undefined) {
                return toolValue;
            }
    
            ctx.fillStyle = color;
            ctx.fillRect(
                node.x - IMAGE_SIZE / 2,
                node.y - IMAGE_SIZE / 2,
                IMAGE_SIZE,
                IMAGE_SIZE
            ); // draw square as pointer trap
        }
    
        nodeCanvasObjectMode(node) {
            var toolValue = this.tool.nodeCanvasObjectMode(node);
    
            if (toolValue !== undefined) {
                return toolValue;
            }
    
            return "after";
        }
    
        linkWidth(link) {
            var toolValue = this.tool.linkWidth(link);
    
            if (toolValue !== undefined) {
                return toolValue;
            }
    
            return this.isLinkHighlighted(link) ? 5 : 1;
        }
    
        linkDirectionalParticles() {
            var toolValue = this.tool.linkDirectionalParticles();
    
            if (toolValue !== undefined) {
                return toolValue;
            }
    
            return 4;
        }
    
        linkDirectionalParticleWidth(link) {
            var toolValue = this.tool.linkDirectionalParticleWidth(link);
    
            if (toolValue !== undefined) {
                return toolValue;
            }
    
            return this.isLinkHighlighted(link) ? LINK_PARTICLE_COUNT : 0;
        }
    
    
        onBackgroundClick(event, positions) {
            this.tool.onBackgroundClick(event, positions);
        }
    
    
    Maximilian Giller's avatar
    Maximilian Giller committed
        redraw() {
            this.display.setSelectedTool(this.tool);
            this.display.setSelectedItem(this.selectedItem);
            this.display.setSelectedItems(this.selectedItems, this.itemsContext);
        }
    
        isLinkHighlighted(link) {
            return (
                this.selectedItem === link ||
                graph.isLinkOnNode(link, state.selectedItem)
            );
        }
    }