Files
tsvm/assets/disk0/tvdos/tuidev/demo.js
minjaesong f1f5d46c8e tui wip
2021-02-01 15:26:37 +09:00

184 lines
4.6 KiB
JavaScript

/*
Screen:
===================
Titlebar
===================
C A N V A S
===================
there are usually two separate canvases: main-screen and menu-screen
*/
class SimpleScreen {
constructor(title) {
this.title = title;
this.termWidth = con.getmaxyx()[1];
this.termHeight = con.getmaxyx()[0];
}
drawTitlebar() {
let titleLeftPad = (this.termWidth - this.title.length - 6) >> 1;
let titleRightPad = this.termWidth - titleLeftPad - this.title.length - 6;
con.move(1,1);
con.color_pair(253,255);
print(' ');con.addch(17);con.curs_right();
con.color_pair(0,253);
print(" ".repeat(titleLeftPad)+this.title+" ".repeat(titleRightPad));
con.color_pair(253,255);
con.addch(16);con.curs_right();print(' ');
con.move(3,1);
}
redraw() {
con.color_pair(239,255);
con.clear();
this.drawTitlebar();
if (this.canvas !== undefined) this.canvas.redraw();
}
update() {
if (this.canvas !== undefined) this.canvas.update();
}
}
class Canvas {
constructor(identifier) {
this.id = identifier;
}
redraw() {}
update() {}
}
class UIItem {
constructor(w,h,identifier) {
this.width = w;
this.height = h;
this.id = identifier;
}
redraw(y,x) {} // index starts from 0 (so that y=1 would starts from the line right after the titlebar)
update() {} // returns true when the screen must be re-drawn after the update
}
class TextList extends UIItem {
constructor(w,h,item,selection) {
super(w,h,"uiitem-textlist");
this.item = item;
this.selection = (isNaN(selection)) ? 0 : selection|0;
this.visible = true;
this.scroll = 0;
this.redrawReq = false;
}
getInternalHeight() {
return this.item.length() * 2 + 1;
}
getLongestItemLength() {
return this.item.map(it => (''+it).length).reduce((a,i) => (i>a) ? i : a);
}
redraw(y,x) {
// TODO: up/down scroll mark
let videoReversed = false
for (let i = this.scroll; i < this.item.length; i++) {
let printy = ((i - this.scroll) * 2) + 2;
if (printy < y + this.termHeight || printy < this.height) {
if (i == this.scroll + this.selection) {
con.video_reverse();
videoReversed = true;
}
con.move(y + printy, x);
print(` ${this.item[i]} `);
}
// un-reverse the video
if (videoReversed) {
con.video_reverse();
videoReversed = false;
}
}
}
cursorUp() {
if ((this.selection + this.scroll) > 0) {
this.selection -= 1;
this.redrawReq = true;
}
}
cursorDown() {
if ((this.selection + this.scroll) < this.item.length - 1) {
this.selection += 1;
this.redrawReq = true;
}
}
getSelection() {
return {index: (this.scroll + this.selection), item: this.item[this.scroll + this.selection]};
}
update() {
let r = this.redrawReq;
this.redrawReq = false;
return r;
}
}
class Demo extends SimpleScreen {
constructor(title) {
super(title);
let mainCanvas = new Canvas("main");
con.curs_set(0);
mainCanvas.selector = new TextList(40, 31, ["The", "Quick", "Brown", "Fox", "Jumps"]);
mainCanvas.redraw = () => {
mainCanvas.selector.redraw(1,2);
}
this.keyLatched = false;
mainCanvas.update = () => {
let keys = con.poll_keys();
let redraw = false;
// un-latch
if (this.keyLatched && keys[0] == 0) {
this.keyLatched = false;
}
// up
if (!this.keyLatched && keys[0] == 19) {
mainCanvas.selector.cursorUp();
}
// down
else if (!this.keyLatched && keys[0] == 20) {
mainCanvas.selector.cursorDown();
}
if (mainCanvas.selector.update())
mainCanvas.selector.redraw(1,2);
if (this.keyLatched && keys[0] == 66) {
con.mvaddch(20,20); print("SEL:"+mainCanvas.selector.getSelection().item);
}
// finally update key latched state
this.keyLatched = keys[0] != 0;
}
this.mainCanvas = mainCanvas
this.canvas = this.mainCanvas;
}
}
let s = new Demo("Ctrl-C to exit");
s.redraw();
while (!con.hitterminate()) {
s.update();
sys.spin();
}
con.clear();