textui/base.ts

95 lines
2 KiB
TypeScript
Raw Normal View History

2021-05-13 22:04:47 +00:00
/**
* Color represented by RGB (0.0-1.0) components
*/
export type Color = {
r: number;
g: number;
b: number;
};
/**
* Displayable character, with background and foreground color taken from the palette
*/
export type Char = Readonly<{
ch: string;
bg: number;
fg: number;
}>;
export type BufferSize = Readonly<{ w: number; h: number }>;
export type BufferLocation = Readonly<{ x: number; y: number }>;
export const SPACE: Char = { ch: " ", bg: 0, fg: 0 } as const;
/**
* Rectangular buffer of displayable characters
*/
export class CharBuffer {
private chars: Array<Char>;
constructor(private size: BufferSize) {
this.chars = new Array(size.w * size.h).fill(SPACE);
}
/**
* Get the character buffered at a given at
*
* This does not properly check for out-of-bounds coordinates,
* use BufferDrawing for this
*/
get(at: BufferLocation): Char {
const i = at.y * this.size.w + at.x;
if (i > 0 && i < this.chars.length) {
return this.chars[i];
} else {
return SPACE;
}
}
/**
* Change the character buffered at a given location
*
* This does not properly check for out-of-bounds coordinates,
* use BufferDrawing for this
*/
set(at: BufferLocation, char: Char): void {
const i = at.y * this.size.w + at.x;
if (i >= 0 && i < this.chars.length) {
this.chars[i] = char;
}
}
getSize(): BufferSize {
return this.size;
}
toString(): string {
return this.chars.map((c) => c.ch).join("");
}
}
/**
* Tools for drawing inside a display buffer
*/
export class BufferDrawing {
constructor(private readonly buffer: CharBuffer) {
}
/**
* Draw a piece of text of the same color
*/
text(content: string, from: BufferLocation): void {
let { w, h } = this.buffer.getSize();
let { x, y } = from;
let buf = this.buffer;
if (y >= 0 && y < h) {
for (let ch of content) {
if (x >= 0 && x < w) {
buf.set({ x, y }, { ch, bg: 0, fg: 0 });
}
x++;
}
}
}
}