moebius-web

web based ansi art editor

moebius-web

tools/copy.js


function copyTool(editor) {
    "use strict";
    var canvas, ctx, startX, startY, oldEndX, oldEndY, selectionCanvas, x, y, imageData, updateStatus;

    function selectionPattern() {
        var patternCanvas, patternCtx, halfWidth, halfHeight;
        patternCanvas = ElementHelper.create("canvas", {"width": editor.codepage.fontHeight, "height": editor.codepage.fontHeight});
        halfWidth = patternCanvas.width / 2;
        halfHeight = patternCanvas.height / 2;
        patternCtx = patternCanvas.getContext("2d");
        patternCtx.fillStyle = "rgb(255, 255, 255)";
        patternCtx.fillRect(0, 0, halfWidth, halfHeight);
        patternCtx.fillRect(halfWidth, halfHeight, halfWidth, halfHeight);
        patternCtx.fillStyle = "rgb(0, 0, 0)";
        patternCtx.fillRect(halfWidth, 0, halfWidth, halfHeight);
        patternCtx.fillRect(0, halfHeight, halfWidth, halfHeight);
        return patternCanvas;
    }

    canvas = ElementHelper.create("canvas", {"width": 80 * editor.codepage.fontWidth, "height": editor.height * editor.codepage.fontHeight, "style": {"opacity": "0.8"}});
    ctx = canvas.getContext("2d");
    ctx.strokeStyle = ctx.createPattern(selectionPattern(), "repeat");
    ctx.lineWidth = editor.codepage.fontWidth / 2;

    function translateCoords(fromTextX, fromTextY, toTextX, toTextY) {
        var textX, textY, width, height;

        if (toTextX < fromTextX) {
            textX = toTextX;
            width = (fromTextX - toTextX + 1);
        } else {
            textX = fromTextX;
            width = (toTextX - fromTextX + 1);
        }
        if (toTextY < fromTextY) {
            textY = toTextY;
            height = (fromTextY - toTextY + 1);
        } else {
            textY = fromTextY;
            height = (toTextY - fromTextY + 1);
        }

        return {
            "textX": textX,
            "textY": textY,
            "width": width,
            "height": height
        };
    }

    function clearPaste() {
        if (selectionCanvas) {
            ctx.clearRect((x - Math.floor(imageData.width / 2)) * editor.codepage.fontWidth, (y - Math.floor(imageData.height / 2)) * editor.codepage.fontHeight, selectionCanvas.width, selectionCanvas.height);
        }
    }

    function redrawPaste(textX, textY) {
        clearPaste();
        if (selectionCanvas) {
            ctx.drawImage(selectionCanvas, (textX - Math.floor(imageData.width / 2)) * editor.codepage.fontWidth, (textY - Math.floor(imageData.height / 2)) * editor.codepage.fontHeight);
        }
        x = textX;
        y = textY;
    }

    function canvasMove(evt) {
        redrawPaste(evt.detail.textX, evt.detail.textY);
    }

    function canvasDown(evt) {
        if (selectionCanvas) {
            editor.takeUndoSnapshot();
            editor.putImageData(imageData, evt.detail.textX - Math.floor(imageData.width / 2), evt.detail.textY - Math.floor(imageData.height / 2));
        } else {
            startX = evt.detail.textX;
            startY = evt.detail.textY;
        }
    }

    function clearSelection() {
        var coords;
        if (oldEndX !== undefined && oldEndY !== undefined) {
            coords = translateCoords(startX, startY, oldEndX, oldEndY);
            ctx.clearRect(coords.textX * editor.codepage.fontWidth, coords.textY * editor.codepage.fontHeight, coords.width * editor.codepage.fontWidth, coords.height * editor.codepage.fontHeight);
        }
    }

    function canvasDrag(evt) {
        var coords;
        if (!selectionCanvas) {
            clearSelection();
            coords = translateCoords(startX, startY, evt.detail.textX, evt.detail.textY);
            ctx.strokeRect(coords.textX * editor.codepage.fontWidth + ctx.lineWidth, coords.textY * editor.codepage.fontHeight + ctx.lineWidth, coords.width * editor.codepage.fontWidth - ctx.lineWidth * 2, coords.height * editor.codepage.fontHeight - ctx.lineWidth * 2);
            oldEndX = evt.detail.textX;
            oldEndY = evt.detail.textY;
        }
    }

    function canvasUp(evt) {
        var coords, pasteY, pasteX, block;
        if (!selectionCanvas) {
            clearSelection();
            coords = translateCoords(startX, startY, evt.detail.textX, evt.detail.textY);
            imageData = editor.getImageData(coords.textX, coords.textY, coords.width, coords.height, !evt.detail.shiftKey);
            selectionCanvas = editor.renderImageData(imageData);
            redrawPaste(evt.detail.textX, evt.detail.textY);
            updateStatus("Reselect");
            if (evt.detail.altKey) {
                editor.takeUndoSnapshot();
                for (pasteY = 0; pasteY < coords.height; ++pasteY) {
                    for (pasteX = 0; pasteX < coords.width; ++pasteX) {
                        block = editor.getTextBlock(coords.textX + pasteX, coords.textY + pasteY);
                        editor.setTextBlock(block, editor.codepage.NULL, block.foreground, 0);
                    }
                }
            }
        }
    }

    function canvasOut() {
        clearPaste();
        clearSelection();
    }

    function modeChange() {
        if (selectionCanvas) {
            clearPaste();
            selectionCanvas = undefined;
        }
    }

    function init(callback) {
        editor.canvas.addEventListener("canvasMove", canvasMove, false);
        editor.canvas.addEventListener("canvasDown", canvasDown, false);
        editor.canvas.addEventListener("canvasDrag", canvasDrag, false);
        editor.canvas.addEventListener("canvasUp", canvasUp, false);
        editor.canvas.addEventListener("canvasOut", canvasOut, false);
        editor.addOverlay(canvas, "copy");
        clearPaste();
        selectionCanvas = undefined;
        updateStatus = callback;
        return true;
    }

    function remove() {
        modeChange();
        updateStatus();
        editor.canvas.removeEventListener("canvasMove", canvasMove);
        editor.canvas.removeEventListener("canvasDown", canvasDown);
        editor.canvas.removeEventListener("canvasDrag", canvasDrag);
        editor.canvas.removeEventListener("canvasUp", canvasUp);
        editor.canvas.removeEventListener("canvasOut", canvasOut);
        editor.removeOverlay("copy");
    }

    function toString() {
        return "Copy";
    }

    return {
        "init": init,
        "remove": remove,
        "toString": toString,
        "modeChange": modeChange,
        "uid": "copy"
    };
}

AnsiEditController.addTool(copyTool, "tools-right", 99);

Download

raw zip tar