89 lines
2.2 KiB
TypeScript
89 lines
2.2 KiB
TypeScript
import {
|
|
BufferDrawing,
|
|
BufferSize,
|
|
CharBuffer,
|
|
Color,
|
|
PaletteMap,
|
|
} from "./base.ts";
|
|
import { Display } from "./display.ts";
|
|
|
|
/**
|
|
* Common abstraction for a textual UI
|
|
*/
|
|
export class TextUI {
|
|
private screen = new CharBuffer({ w: 1, h: 1 });
|
|
private palettemap: PaletteMap = [];
|
|
|
|
constructor(private display: Display) {
|
|
}
|
|
|
|
get drawing(): BufferDrawing {
|
|
return new BufferDrawing(this.screen, this.palettemap);
|
|
}
|
|
|
|
/**
|
|
* Initializes the display
|
|
*/
|
|
async init(palette: UIPalette): Promise<void> {
|
|
var size = await this.display.getSize();
|
|
this.screen = new CharBuffer(size);
|
|
this.palettemap = await this.getPaletteMapping(palette);
|
|
await this.display.clear();
|
|
}
|
|
|
|
/**
|
|
* Get the current display size
|
|
*/
|
|
getSize(): BufferSize {
|
|
return this.screen.getSize();
|
|
}
|
|
|
|
/**
|
|
* Flush the internal buffer to the display
|
|
*/
|
|
async flush(): Promise<void> {
|
|
// TODO only dirty chars
|
|
const { w, h } = this.screen.getSize();
|
|
for (let x = 0; x < w; x++) {
|
|
for (let y = 0; y < h; y++) {
|
|
await this.display.setChar({ x, y }, this.screen.get({ x, y }));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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));
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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>>;
|