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 { 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 { // TODO only dirty chars const { w, h } = this.screen.getSize(); for (let y = 0; y < h; y++) { for (let x = 0; x < w; x++) { await this.display.setChar({ x, y }, this.screen.get({ x, y })); } } } /** * Start the event loop, waiting for input */ async loop(refresh = 1000): Promise { while (true) { await this.flush(); await new Promise((resolve) => setTimeout(resolve, refresh)); } } private async getPaletteMapping( palette: UIPalette, ): Promise { // 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>;