Add mouse click events for web displays

This commit is contained in:
Michaël Lemaire 2021-08-29 23:56:46 +02:00
parent 204d29a69e
commit c0bde58ac4
7 changed files with 30 additions and 74 deletions

View File

@ -1,6 +1,6 @@
# TODO
- Add click events
- Add click events for ansi display
- Fix resizing on web_div display
- Prevent ctrl+c on web display
- Optimize drawing to display, by allowing sequences of characters with the same

1
config/fmt.flags Normal file
View File

@ -0,0 +1 @@
--ignore=web-demo/textui.js

View File

@ -17,6 +17,11 @@ const config: Partial<UIConfig> = {
ui.drawing.color(1, 0).text(key, { x, y: 7 });
x += key.length + 1;
},
onMouseClick: (loc) => {
const text = `${loc.x}:${loc.y}`;
ui.drawing.color(1, 0).text(text, { x, y: 7 });
x += text.length + 1;
},
};
const ui = new TextUI(display, config);
await ui.init();

16
mod.ts
View File

@ -2,18 +2,13 @@ import { AnsiTerminalDisplay } from "./ansi.ts";
import { UIConfig } from "./config.ts";
import { Display } from "./display.ts";
import { TextUI } from "./ui.ts";
import {
CanvasTerminalDisplay,
DivTerminalDisplay,
PreTerminalDisplay,
} from "./web.ts";
import { CanvasTerminalDisplay, DivTerminalDisplay } from "./web.ts";
export { TextUI };
export const UI_DISPLAY_TYPES = {
autodetect: undefined,
ansi: AnsiTerminalDisplay,
web_pre: PreTerminalDisplay,
web_div: DivTerminalDisplay,
web_canvas: CanvasTerminalDisplay,
dummy: Display,
@ -26,8 +21,15 @@ export async function createTextUI(
if (display_type == "autodetect") {
if (typeof (window as any).document != "undefined") {
display_type = "web_canvas";
} else {
// TODO if canvas is not available, fall back to div
} else if (typeof (Deno as any) != "undefined") {
display_type = "ansi";
} else {
const message = "Cannot initialize display";
if (typeof alert == "function") {
alert(message);
}
throw new Error(message);
}
}

View File

@ -14,6 +14,11 @@ export async function demo(display_type) {
ui.drawing.color(1, 0).text(key, { x, y: 7 });
x += key.length + 1;
},
onMouseClick: (loc) => {
const text = `${loc.x}:${loc.y}`;
ui.drawing.color(1, 0).text(text, { x, y: 7 });
x += text.length + 1;
},
}, display_type);
function draw() {
ui.drawing.color(2, 0).text("hello", { x: 10, y: 3 });

View File

@ -1,14 +0,0 @@
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="demo.css">
<script type="module">
import { demo } from "./demo.js";
demo("web_pre");
</script>
</head>
<body></body>
</html>

61
web.ts
View File

@ -59,10 +59,6 @@ class WebDisplay extends Display {
async setChar(at: BufferLocation, char: Char): Promise<void> {
}
async getKeyStrokes(): Promise<string[]> {
return [];
}
//
// Get the size in pixels of the target area
//
@ -134,43 +130,6 @@ class WebDisplay extends Display {
}
}
//
// Basic terminal display using a single "pre" tag
//
export class PreTerminalDisplay extends WebDisplay {
element: any;
override async init(): Promise<void> {
await super.init();
if (!this.element) {
this.element = this.document.createElement("pre");
this.parent.appendChild(this.element);
}
const { w, h } = this.size;
const line = Array(w).fill(" ").join("");
this.element.textContent = Array(h).fill(line).join("\n");
}
override async uninit(): Promise<void> {
if (this.element) {
this.parent.removeChild(this.element);
this.element = null;
}
await super.uninit();
}
override async setChar(at: BufferLocation, char: Char): Promise<void> {
const { w, h } = this.size;
const offset = at.y * (w + 1) + at.x;
const text = this.element.textContent;
this.element.textContent = text.slice(0, offset) + char.ch +
text.slice(offset + 1);
}
}
//
// Terminal display using one div per char
//
@ -232,11 +191,9 @@ export class DivTerminalDisplay extends WebDisplay {
div.style.overflow = "hidden";
this.parent.appendChild(div);
divs.push(div);
/*div.addEventListener("click", () => {
if (this.onclick) {
this.onclick({ x, y });
}
});*/
div.addEventListener("click", () => {
this.pushEvent({ click: { x, y } });
});
}
}
@ -262,14 +219,14 @@ export class CanvasTerminalDisplay extends WebDisplay {
this.compose = new Canvas(this.document, undefined);
this.present = new Canvas(this.document, this.parent);
/*this.present.element.addEventListener("click", (ev) => {
if (this.onclick) {
this.onclick({
this.present.element.addEventListener("click", (ev: any) => {
this.pushEvent({
click: {
x: Math.round((ev.offsetX * this.ratio) / this.char_size.x),
y: Math.round((ev.offsetY * this.ratio) / this.char_size.y),
});
}
});*/
},
});
});
}
override getTargetSize(): { x: number; y: number } {