textui/ui.ts

90 lines
2.2 KiB
TypeScript
Raw Normal View History

2021-06-24 22:41:34 +00:00
import {
BufferDrawing,
BufferSize,
CharBuffer,
Color,
PaletteMap,
} from "./base.ts";
2021-05-13 22:04:47 +00:00
import { Display } from "./display.ts";
/**
* Common abstraction for a textual UI
*/
export class TextUI {
private screen = new CharBuffer({ w: 1, h: 1 });
2021-06-24 22:41:34 +00:00
private palettemap: PaletteMap = [];
2021-05-13 22:04:47 +00:00
constructor(private display: Display) {
}
get drawing(): BufferDrawing {
2021-06-24 22:41:34 +00:00
return new BufferDrawing(this.screen, this.palettemap);
2021-05-13 22:04:47 +00:00
}
/**
* Initializes the display
*/
2021-06-24 22:41:34 +00:00
async init(palette: UIPalette): Promise<void> {
2021-05-13 22:04:47 +00:00
var size = await this.display.getSize();
this.screen = new CharBuffer(size);
2021-06-24 22:41:34 +00:00
this.palettemap = await this.getPaletteMapping(palette);
2021-05-13 22:04:47 +00:00
await this.display.clear();
}
2021-05-19 13:00:52 +00:00
/**
* Get the current display size
*/
getSize(): BufferSize {
return this.screen.getSize();
}
2021-05-13 22:04:47 +00:00
/**
* Flush the internal buffer to the display
*/
async flush(): Promise<void> {
// TODO only dirty chars
const { w, h } = this.screen.getSize();
2021-06-24 23:09:05 +00:00
for (let y = 0; y < h; y++) {
for (let x = 0; x < w; x++) {
2021-05-13 22:04:47 +00:00
await this.display.setChar({ x, y }, this.screen.get({ x, y }));
}
}
}
2021-05-19 13:00:52 +00:00
/**
* Start the event loop, waiting for input
*/
async loop(refresh = 1000): Promise<void> {
while (true) {
await this.flush();
await new Promise((resolve) => setTimeout(resolve, refresh));
}
}
2021-06-24 22:41:34 +00:00
private async getPaletteMapping(
palette: UIPalette,
): Promise<PaletteMap> {
// get the colors supported by display
const allcolors = palette
.map((c): Color[] => Array.isArray(c) ? c : [c])
.reduce((acc, val) => acc.concat(val), []);
const supported = await this.display.setupPalette(allcolors);
// TODO find the best color mapping for each source color
return palette.map((_, idx) => idx);
}
2021-05-13 22:04:47 +00:00
}
2021-06-24 22:41:34 +00:00
/**
* Color palette requirements.
*
* The array represents the "ideal" colors desired by the application.
* When drawing things, *bg* and *fg* color information should be an index
* in this palette.
*
* For each palette index, a single color can be requested, or an
* array of accepted alternatives, with decreasing priority.
*/
export type UIPalette = ReadonlyArray<Color | ReadonlyArray<Color>>;