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;
|
|
|
|
}
|