moebius-web

web based ansi art editor

moebius-web

public/js/keyboard.js


function createFKeyShorcut(canvas, charCode) {
	"use strict";
	function update() {
		canvas.style.width = font.getWidth() + "px";
		canvas.style.height = font.getHeight() + "px";
		font.draw(charCode, palette.getForegroundColour(), palette.getBackgroundColour(), canvas.getContext("2d"), 0, 0);
	}
	document.addEventListener("onForegroundChange", update);
	document.addEventListener("onBackgroundChange", update);
	document.addEventListener("onFontChange", update);

	update();
}

function createFKeysShortcut() {
	"use strict";
	var shortcuts = [176, 177, 178, 219, 223, 220, 221, 222, 254, 249, 7, 0];

	for (var i = 0; i < 12; i++) {
		createFKeyShorcut($("fkey" + i), shortcuts[i]);
	}

	function keyDown(evt) {
		var keyCode = (evt.keyCode || evt.which);
		if (evt.altKey === false && evt.ctrlKey === false && evt.metaKey === false && keyCode >= 112 && keyCode <= 124) {
			evt.preventDefault();
			textArtCanvas.startUndo();
			textArtCanvas.draw((callback) => {
				callback(shortcuts[keyCode - 112], palette.getForegroundColour(), palette.getBackgroundColour(), cursor.getX(), cursor.getY());
			}, false);
			cursor.right();
		}
	}

	function enable() {
		document.addEventListener("keydown", keyDown);

	}

	function disable() {
		document.removeEventListener("keydown", keyDown);
	}

	return {
		"enable": enable,
		"disable": disable
	};
}

function createCursor(canvasContainer) {
	"use strict";
	var canvas = createCanvas(font.getWidth(), font.getHeight());
	var x = 0;
	var y = 0;
	var dx = 0;
	var dy = 0;
	var visible = false;

	function show() {
		canvas.style.display = "block";
		visible = true;
	}

	function hide() {
		canvas.style.display = "none";
		visible = false;
	}

	function startSelection() {
		selectionCursor.setStart(x, y);
		dx = x;
		dy = y;
		hide();
	}

	function endSelection() {
		selectionCursor.hide();
		show();
	}

	function move(newX, newY) {
		if (selectionCursor.isVisible() === true) {
			endSelection();
		}
		x = Math.min(Math.max(newX, 0), textArtCanvas.getColumns() - 1);
		y = Math.min(Math.max(newY, 0), textArtCanvas.getRows() - 1);
		var canvasWidth = font.getWidth();
		canvas.style.left = (x * canvasWidth) - 1 + "px";
		canvas.style.top = (y * font.getHeight()) - 1 + "px";
		positionInfo.update(x, y);
		pasteTool.setSelection(x, y, 1, 1);
	}

	function updateDimensions() {
		canvas.width = font.getWidth() + 1;
		canvas.height = font.getHeight() + 1;
		move(x, y);
	}

	function getX() {
		return x;
	}

	function getY() {
		return y;
	}

	function left() {
		move(x - 1, y);
	}

	function right() {
		move(x + 1, y);
	}

	function up() {
		move(x, y - 1);
	}

	function down() {
		move(x, y + 1);
	}

	function newLine() {
		move(0, y + 1);
	}

	function startOfCurrentRow() {
		move(0, y);
	}

	function endOfCurrentRow() {
		move(textArtCanvas.getColumns() - 1, y);
	}

	function shiftLeft() {
		if (selectionCursor.isVisible() === false) {
			startSelection();
		}
		dx = Math.max(dx - 1, 0);
		selectionCursor.setEnd(dx, dy);
	}

	function shiftRight() {
		if (selectionCursor.isVisible() === false) {
			startSelection();
		}
		dx = Math.min(dx + 1, textArtCanvas.getColumns() - 1);
		selectionCursor.setEnd(dx, dy);
	}

	function shiftUp() {
		if (selectionCursor.isVisible() === false) {
			startSelection();
		}
		dy = Math.max(dy - 1, 0);
		selectionCursor.setEnd(dx, dy);
	}

	function shiftDown() {
		if (selectionCursor.isVisible() === false) {
			startSelection();
		}
		dy = Math.min(dy + 1, textArtCanvas.getRows() - 1);
		selectionCursor.setEnd(dx, dy);
	}

	function keyDown(evt) {
		var keyCode = (evt.keyCode || evt.which);
		if (evt.ctrlKey === false && evt.altKey === false) {
			if (evt.shiftKey === false && evt.metaKey === false) {
				switch (keyCode) {
					case 13:
						evt.preventDefault();
						newLine();
						break;
					case 35:
						evt.preventDefault();
						endOfCurrentRow();
						break;
					case 36:
						evt.preventDefault();
						startOfCurrentRow();
						break;
					case 37:
						evt.preventDefault();
						left();
						break;
					case 38:
						evt.preventDefault();
						up();
						break;
					case 39:
						evt.preventDefault();
						right();
						break;
					case 40:
						evt.preventDefault();
						down();
						break;
					default:
						break;
				}
			} else if (evt.metaKey === true && evt.shiftKey === false) {
				switch (keyCode) {
					case 37:
						evt.preventDefault();
						startOfCurrentRow();
						break;
					case 39:
						evt.preventDefault();
						endOfCurrentRow();
						break;
					default:
						break;
				}
			} else if (evt.shiftKey === true && evt.metaKey === false) {
				switch (keyCode) {
					case 37:
						evt.preventDefault();
						shiftLeft();
						break;
					case 38:
						evt.preventDefault();
						shiftUp();
						break;
					case 39:
						evt.preventDefault();
						shiftRight();
						break;
					case 40:
						evt.preventDefault();
						shiftDown();
						break;
					default:
						break;
				}
			}
		}
	}

	function enable() {
		document.addEventListener("keydown", keyDown);
		show();
		pasteTool.setSelection(x, y, 1, 1);
	}

	function disable() {
		document.removeEventListener("keydown", keyDown);
		hide();
		pasteTool.disable();
	}

	function isVisible() {
		return visible;
	}

	canvas.classList.add("cursor");
	hide();
	canvasContainer.insertBefore(canvas, canvasContainer.firstChild);
	document.addEventListener("onLetterSpacingChange", updateDimensions);
	document.addEventListener("onTextCanvasSizeChange", updateDimensions);
	document.addEventListener("onFontChange", updateDimensions);
	document.addEventListener("onOpenedFile", updateDimensions);
	move(x, y);

	return {
		"show": show,
		"hide": hide,
		"move": move,
		"getX": getX,
		"getY": getY,
		"left": left,
		"right": right,
		"up": up,
		"down": down,
		"newLine": newLine,
		"startOfCurrentRow": startOfCurrentRow,
		"endOfCurrentRow": endOfCurrentRow,
		"shiftLeft": shiftLeft,
		"shiftRight": shiftRight,
		"enable": enable,
		"disable": disable,
		"isVisible": isVisible
	};
}

function createSelectionCursor(divElement) {
	"use strict";
	var cursor = createCanvas(0, 0);
	var sx, sy, dx, dy, x, y, width, height;
	var visible = false;

	function processCoords() {
		x = Math.min(sx, dx);
		y = Math.min(sy, dy);
		x = Math.max(x, 0);
		y = Math.max(y, 0);
		var columns = textArtCanvas.getColumns();
		var rows = textArtCanvas.getRows();
		width = Math.abs(dx - sx) + 1;
		height = Math.abs(dy - sy) + 1;
		width = Math.min(width, columns - x);
		height = Math.min(height, rows - y);
	}

	function show() {
		cursor.style.display = "block";
	}

	function hide() {
		cursor.style.display = "none";
		visible = false;
		pasteTool.disable();
	}

	function updateCursor() {
		var fontWidth = font.getWidth();
		var fontHeight = font.getHeight();
		cursor.style.left = x * fontWidth - 1 + "px";
		cursor.style.top = y * fontHeight - 1 + "px";
		cursor.width = width * fontWidth + 1;
		cursor.height = height * fontHeight + 1;
	}

	function setStart(startX, startY) {
		sx = startX;
		sy = startY;
		processCoords();
		x = startX;
		y = startY;
		width = 1;
		height = 1;
		updateCursor();
	}

	function setEnd(endX, endY) {
		show();
		dx = endX;
		dy = endY;
		processCoords();
		updateCursor();
		pasteTool.setSelection(x, y, width, height);
		visible = true;
	}

	function isVisible() {
		return visible;
	}

	cursor.classList.add("selection-cursor");
	cursor.style.display = "none";
	divElement.appendChild(cursor);

	return {
		"show": show,
		"hide": hide,
		"setStart": setStart,
		"setEnd": setEnd,
		"isVisible": isVisible
	};
}

function createKeyboardController() {
	"use strict";
	var fkeys = createFKeysShortcut();
	var enabled = false;
	var ignored = false;

	function draw(charCode) {
		textArtCanvas.startUndo();
		textArtCanvas.draw((callback) => {
			callback(charCode, palette.getForegroundColour(), palette.getBackgroundColour(), cursor.getX(), cursor.getY());
		}, false);
		cursor.right();
	}

	function deleteText() {
		textArtCanvas.startUndo();
		textArtCanvas.draw((callback) => {
			callback(0, 7, 0, cursor.getX() - 1, cursor.getY());
		}, false);
		cursor.left();
	}

	function keyDown(evt) {
		var keyCode = (evt.keyCode || evt.which);
		if (ignored === false) {
			if (evt.altKey === false && evt.ctrlKey === false && evt.metaKey === false) {
				if (keyCode === 9) {
					evt.preventDefault();
					draw(keyCode);
				} else if (keyCode === 8) {
					evt.preventDefault();
					if (cursor.getX() > 0) {
						deleteText();
					}
				}
			}
		}
	}

	function convertUnicode(keyCode) {
		switch (keyCode) {
			case 0x2302: return 127;
			case 0x00C7: return 128;
			case 0x00FC: return 129;
			case 0x00E9: return 130;
			case 0x00E2: return 131;
			case 0x00E4: return 132;
			case 0x00E0: return 133;
			case 0x00E5: return 134;
			case 0x00E7: return 135;
			case 0x00EA: return 136;
			case 0x00EB: return 137;
			case 0x00E8: return 138;
			case 0x00EF: return 139;
			case 0x00EE: return 140;
			case 0x00EC: return 141;
			case 0x00C4: return 142;
			case 0x00C5: return 143;
			case 0x00C9: return 144;
			case 0x00E6: return 145;
			case 0x00C6: return 146;
			case 0x00F4: return 147;
			case 0x00F6: return 148;
			case 0x00F2: return 149;
			case 0x00FB: return 150;
			case 0x00F9: return 151;
			case 0x00FF: return 152;
			case 0x00D6: return 153;
			case 0x00DC: return 154;
			case 0x00A2: return 155;
			case 0x00A3: return 156;
			case 0x00A5: return 157;
			case 0x20A7: return 158;
			case 0x0192: return 159;
			case 0x00E1: return 160;
			case 0x00ED: return 161;
			case 0x00F3: return 162;
			case 0x00FA: return 163;
			case 0x00F1: return 164;
			case 0x00D1: return 165;
			case 0x00AA: return 166;
			case 0x00BA: return 167;
			case 0x00BF: return 168;
			case 0x2310: return 169;
			case 0x00AC: return 170;
			case 0x00BD: return 171;
			case 0x00BC: return 172;
			case 0x00A1: return 173;
			case 0x00AB: return 174;
			case 0x00BB: return 175;
			case 0x2591: return 176;
			case 0x2592: return 177;
			case 0x2593: return 178;
			case 0x2502: return 179;
			case 0x2524: return 180;
			case 0x2561: return 181;
			case 0x2562: return 182;
			case 0x2556: return 183;
			case 0x2555: return 184;
			case 0x2563: return 185;
			case 0x2551: return 186;
			case 0x2557: return 187;
			case 0x255D: return 188;
			case 0x255C: return 189;
			case 0x255B: return 190;
			case 0x2510: return 191;
			case 0x2514: return 192;
			case 0x2534: return 193;
			case 0x252C: return 194;
			case 0x251C: return 195;
			case 0x2500: return 196;
			case 0x253C: return 197;
			case 0x255E: return 198;
			case 0x255F: return 199;
			case 0x255A: return 200;
			case 0x2554: return 201;
			case 0x2569: return 202;
			case 0x2566: return 203;
			case 0x2560: return 204;
			case 0x2550: return 205;
			case 0x256C: return 206;
			case 0x2567: return 207;
			case 0x2568: return 208;
			case 0x2564: return 209;
			case 0x2565: return 210;
			case 0x2559: return 211;
			case 0x2558: return 212;
			case 0x2552: return 213;
			case 0x2553: return 214;
			case 0x256B: return 215;
			case 0x256A: return 216;
			case 0x2518: return 217;
			case 0x250C: return 218;
			case 0x2588: return 219;
			case 0x2584: return 220;
			case 0x258C: return 221;
			case 0x2590: return 222;
			case 0x2580: return 223;
			case 0x03B1: return 224;
			case 0x00DF: return 225;
			case 0x0393: return 226;
			case 0x03C0: return 227;
			case 0x03A3: return 228;
			case 0x03C3: return 229;
			case 0x00B5: return 230;
			case 0x03C4: return 231;
			case 0x03A6: return 232;
			case 0x0398: return 233;
			case 0x03A9: return 234;
			case 0x03B4: return 235;
			case 0x221E: return 236;
			case 0x03C6: return 237;
			case 0x03B5: return 238;
			case 0x2229: return 239;
			case 0x2261: return 240;
			case 0x00B1: return 241;
			case 0x2265: return 242;
			case 0x2264: return 243;
			case 0x2320: return 244;
			case 0x2321: return 245;
			case 0x00F7: return 246;
			case 0x2248: return 247;
			case 0x00B0: return 248;
			case 0x2219: return 249;
			case 0x00B7: return 250;
			case 0x221A: return 251;
			case 0x207F: return 252;
			case 0x00B2: return 253;
			case 0x25A0: return 254;
			case 0x00A0: return 255;
			default: return keyCode;
		}
	}

	function keyPress(evt) {
		var keyCode = (evt.keyCode || evt.which);
		if (ignored === false) {
			if (evt.altKey === false && evt.ctrlKey === false && evt.metaKey === false) {
				if (keyCode >= 32) {
					evt.preventDefault();
					draw(convertUnicode(keyCode));
				} else if (keyCode === 13) {
					evt.preventDefault();
					cursor.newLine();
				} else if (keyCode === 8) {
					evt.preventDefault();
					if (cursor.getX() > 0) {
						deleteText();
					}
				} else if (keyCode === 167) {
					evt.preventDefault();
					draw(21);
				}
			} else if (evt.ctrlKey === true) {
				if (keyCode === 21) {
					evt.preventDefault();
					var block = textArtCanvas.getBlock(cursor.getX(), cursor.getY());
					palette.setForegroundColour(block.foregroundColour);
					palette.setBackgroundColour(block.backgroundColour);
				}
			}
		}
	}

	function textCanvasDown(evt) {
		cursor.move(evt.detail.x, evt.detail.y);
		selectionCursor.setStart(evt.detail.x, evt.detail.y);
	}

	function textCanvasDrag(evt) {
		cursor.hide();
		selectionCursor.setEnd(evt.detail.x, evt.detail.y);
	}

	function enable() {
		document.addEventListener("keydown", keyDown);
		document.addEventListener("keypress", keyPress);
		document.addEventListener("onTextCanvasDown", textCanvasDown);
		document.addEventListener("onTextCanvasDrag", textCanvasDrag);
		cursor.enable();
		fkeys.enable();
		positionInfo.update(cursor.getX(), cursor.getY());
		enabled = true;
	}

	function disable() {
		document.removeEventListener("keydown", keyDown);
		document.removeEventListener("keypress", keyPress);
		document.removeEventListener("onTextCanvasDown", textCanvasDown);
		document.removeEventListener("onTextCanvasDrag", textCanvasDrag);
		selectionCursor.hide();
		cursor.disable();
		fkeys.disable();
		enabled = false;
	}

	function ignore() {
		ignored = true;
		if (enabled === true) {
			cursor.disable();
			fkeys.disable();
		}
	}

	function unignore() {
		ignored = false;
		if (enabled === true) {
			cursor.enable();
			fkeys.enable();
		}
	}

	return {
		"enable": enable,
		"disable": disable,
		"ignore": ignore,
		"unignore": unignore
	};
}

function createPasteTool(cutItem, copyItem, pasteItem, deleteItem) {
	"use strict";
	var buffer;
	var x = 0;
	var y = 0;
	var width = 0;
	var height = 0;
	var enabled = false;

	function setSelection(newX, newY, newWidth, newHeight) {
		x = newX;
		y = newY;
		width = newWidth;
		height = newHeight;
		if (buffer !== undefined) {
			pasteItem.classList.remove("disabled");
		}
		cutItem.classList.remove("disabled");
		copyItem.classList.remove("disabled");
		deleteItem.classList.remove("disabled");
		enabled = true;
	}

	function disable() {
		pasteItem.classList.add("disabled");
		cutItem.classList.add("disabled");
		copyItem.classList.add("disabled");
		deleteItem.classList.add("disabled");
		enabled = false;
	}

	function copy() {
		buffer = textArtCanvas.getArea(x, y, width, height);
		pasteItem.classList.remove("disabled");
	}

	function deleteSelection() {
		if (selectionCursor.isVisible() || cursor.isVisible()) {
			textArtCanvas.startUndo();
			textArtCanvas.deleteArea(x, y, width, height, palette.getBackgroundColour());
		}
	}

	function cut() {
		if (selectionCursor.isVisible() || cursor.isVisible()) {
			copy();
			deleteSelection();
		}
	}

	function paste() {
		if (buffer !== undefined && (selectionCursor.isVisible() || cursor.isVisible())) {
			textArtCanvas.startUndo();
			textArtCanvas.setArea(buffer, x, y);
		}
	}

	function keyDown(evt) {
		var keyCode = (evt.keyCode || evt.which);
		if (enabled) {
			if ((evt.ctrlKey === true || evt.metaKey === true) && evt.altKey === false && evt.shiftKey === false) {
				switch (keyCode) {
					case 88:
						evt.preventDefault();
						cut();
						break;
					case 67:
						evt.preventDefault();
						copy();
						break;
					case 86:
						evt.preventDefault();
						paste();
						break;
					default:
						break;
				}
			}
		}
		if ((evt.ctrlKey === true || evt.metaKey === true) && keyCode === 8) {
			evt.preventDefault();
			deleteSelection();
		}
	}


	document.addEventListener("keydown", keyDown);

	return {
		"setSelection": setSelection,
		"cut": cut,
		"copy": copy,
		"paste": paste,
		"deleteSelection": deleteSelection,
		"disable": disable
	};
}

Download

raw zip tar