textui/display.ts

107 lines
2.5 KiB
TypeScript
Raw Normal View History

2021-05-13 22:04:47 +00:00
import { BufferLocation, BufferSize, Char, Color } from "./base.ts";
2021-05-11 21:20:33 +00:00
2021-08-26 18:12:36 +00:00
type DisplayKeyEvent = { key: string };
type DisplayClickEvent = { click: BufferLocation };
type DisplaySizeEvent = { size: BufferSize };
type DisplayEvent = Readonly<
| DisplayKeyEvent
| DisplayClickEvent
| DisplaySizeEvent
>;
type DisplayEventCombined = Partial<
& DisplayKeyEvent
& DisplayClickEvent
& DisplaySizeEvent
>;
2021-05-11 21:20:33 +00:00
/**
* Display protocol, to allow the UI to draw things on "screen"
*/
2021-06-28 18:21:32 +00:00
export class Display {
2021-08-26 18:12:36 +00:00
private events: DisplayEvent[] = [];
private known_size = { w: 0, h: 0 };
2021-05-13 22:04:47 +00:00
/**
2021-07-19 22:48:00 +00:00
* Init the display (will be the first method called)
*/
async init(): Promise<void> {
2021-08-26 18:12:36 +00:00
this.known_size = await this.getSize();
2021-07-19 22:48:00 +00:00
}
/**
* Restore the display as before *init*
*/
async uninit(): Promise<void> {
}
/**
* Get the current grid size
2021-05-13 22:04:47 +00:00
*/
2021-06-28 18:21:32 +00:00
async getSize(): Promise<BufferSize> {
2021-07-19 22:48:00 +00:00
return { w: 0, h: 0 };
2021-06-28 18:21:32 +00:00
}
2021-05-13 22:04:47 +00:00
2021-05-11 21:20:33 +00:00
/**
* Setup the palette for color display
*
* If the display supports the whole RGB range, it may return the array as-is.
* If the display only supports a limited palette, it may return only supported colors.
*
* From this call forward, colors will be received by numbered index in the returned array.
*/
2021-06-28 18:21:32 +00:00
async setupPalette(colors: readonly Color[]): Promise<readonly Color[]> {
return [];
}
2021-05-11 21:20:33 +00:00
/**
2021-07-19 22:48:00 +00:00
* Set the cursor visibility
2021-05-11 21:20:33 +00:00
*/
2021-07-19 22:48:00 +00:00
async setCursorVisibility(visible: boolean): Promise<void> {
2021-06-28 18:21:32 +00:00
}
/**
2021-07-19 22:48:00 +00:00
* Flush the display
2021-06-28 18:21:32 +00:00
*/
2021-07-19 22:48:00 +00:00
async flush(): Promise<void> {
2021-06-28 18:21:32 +00:00
}
2021-05-13 22:04:47 +00:00
/**
* Draw a single character on screen
*/
2021-06-28 18:21:32 +00:00
async setChar(at: BufferLocation, char: Char): Promise<void> {
}
/**
2021-08-26 18:12:36 +00:00
* Push a new event
2021-06-28 18:21:32 +00:00
*/
2021-08-26 18:12:36 +00:00
async pushEvent(event: DisplayEvent): Promise<void> {
if (!this.events.some((ev) => sameEvent(ev, event))) {
this.events.push(event);
}
}
/**
* Get the queued events
*/
async getEvents(auto_resize = true): Promise<DisplayEventCombined[]> {
// TODO check only a few cycles?
if (auto_resize) {
const size = await this.getSize();
if (size.w != this.known_size.w || size.h != this.known_size.h) {
this.known_size = size;
await this.pushEvent({ size });
}
}
const result = this.events;
this.events = [];
return result;
2021-06-28 18:21:32 +00:00
}
2021-05-11 21:20:33 +00:00
}
2021-08-26 18:12:36 +00:00
function sameEvent(ev1: DisplayEventCombined, ev2: DisplayEventCombined) {
return ev1.key == ev2.key && ev1.click?.x == ev2.click?.x &&
ev1.click?.y == ev2.click?.y && ev1.size?.w == ev2.size?.w &&
ev1.size?.h == ev2.size?.h;
}