initial commit

This commit is contained in:
2021-12-20 01:55:30 +01:00
commit bd790c1488
38 changed files with 2320 additions and 0 deletions

5
src/lib/IUserProgramm.hx Normal file
View File

@@ -0,0 +1,5 @@
package lib;
interface IUserProgramm {
public function getName(): String;
}

48
src/lib/TermIO.hx Normal file
View File

@@ -0,0 +1,48 @@
package lib;
import util.Vec.Vec2;
import util.Color;
import lib.TermWriteable;
/**
Helpfull class for writing onto a `TermWriteable`.
**/
class TermIO {
private var output: TermWriteable;
public function new(output: TermWriteable) {
this.output = output;
output.clear();
output.setCursorPos(0,0);
}
public function writeLn(text: String,?textColor: Color){
if (textColor != null){
output.setTextColor(textColor);
}
var size = output.getSize();
for (i in 0...Math.floor(text.length / size.x) + 1){
output.write(text.substr(i * size.x,size.x));
newLine();
}
if (textColor != null){
output.setTextColor(White);
}
}
private function newLine() {
var cPos = output.getCursorPos();
if (cPos.y == output.getSize().y){
output.scroll(1);
output.setCursorPos(0,cPos.y);
}else{
output.setCursorPos(0,cPos.y + 1);
}
}
}

38
src/lib/TermWriteable.hx Normal file
View File

@@ -0,0 +1,38 @@
package lib;
import util.Signal;
import util.Color;
import util.Vec.Vec2;
/**
Interface describing a terminal. E.g. the main computer screen or a external screen.
**/
interface TermWriteable {
public var onResize(get,null): SignalReadonly<Vec2<Int>>;
public function write(text: String): Void;
public function scroll(y: Int): Void;
/**
Even though CC is 1 based we use a 0 based index.
**/
public function getCursorPos(): Vec2<Int>;
/**
Even though CC is 1 based we use a 0 based index.
**/
public function setCursorPos(x: Int, y: Int):Void;
public function getCursorBlink(): Bool;
public function setCursorBlink(blink: Bool):Void;
public function getSize(): Vec2<Int>;
public function clear(): Void;
public function clearLine(): Void;
public function getTextColor():Color;
public function setTextColor(colour: Color):Void;
public function getBackgroundColor(): Color;
public function setBackgroundColor(color: Color):Void;
public function isColor(): Bool;
// setPaletteColor(...)
// getPaletteColor(colour)
}

74
src/lib/ui/Canvas.hx Normal file
View File

@@ -0,0 +1,74 @@
package lib.ui;
import util.Vec.Vec2;
import kernel.ui.TermBuffer.Pixel;
abstract Canvas(Array<Array<Pixel>>) to Array<Array<Pixel>> {
inline public function new() {
this = [[]];
}
public inline function set(i:Vec2<Int>,pixel:Pixel) {
if (this[i.y] == null){
this[i.y] = [];
}
this[i.y][i.x] = pixel;
}
public inline function get(i:Vec2<Int>): Pixel {
return this[i.y][i.x];
}
public function keyValueIterator(): KeyValueIterator<Vec2<Int>,Pixel>{
return new CanvasKeyValueIterator(this);
}
public function combine(other: Canvas,offset: Vec2<Int>) {
for (key => value in other) {
if (value == null){
continue;
}
var y = offset.y + key.y;
var x = offset.x + key.x;
if (this[y] == null){
this[y] = [];
}
this[y][x] = value;
}
}
}
class CanvasKeyValueIterator{
private final canvas:Array<Array<Pixel>>;
private var index:Vec2<Int> = {x: 0,y: 0};
@:allow(lib.ui.Canvas)
private function new(canvas: Array<Array<Pixel>>) {
this.canvas = canvas;
}
public function hasNext():Bool{
return index.y < canvas.length && index.x < canvas[index.y].length;
}
public function next():{key:Vec2<Int>, value:Pixel}{
var oldIndex: Vec2<Int> = this.index;
if (index.x >= canvas[index.y].length){
// Goto next line
index = {x:0,y: index.y + 1};
}else{
// Goto next pixel in line
index = {x:index.x + 1,y: index.y};
}
return {
key: oldIndex,
value: this.canvas[oldIndex.y][oldIndex.x]
};
}
}

7
src/lib/ui/IElement.hx Normal file
View File

@@ -0,0 +1,7 @@
package lib.ui;
import util.Vec.Vec2;
interface IElement {
public function render(bounds: Vec2<Int>): Canvas;
}

80
src/lib/ui/ReactiveUI.hx Normal file
View File

@@ -0,0 +1,80 @@
package lib.ui;
import kernel.Log;
import util.Color;
import util.Vec.Vec2;
import kernel.ui.WindowContext;
class ReactiveUI {
private final context:WindowContext;
public function new(context: WindowContext) {
this.context = context;
}
public function render(children: Array<IElement>) {
var size = context.getSize();
var screen = renderChildren(children,size);
writeToContext(screen);
}
private function writeToContext(screen: Canvas) {
var currentBg: Color = Black;
var currentFg: Color = White;
var currentLine = 0;
context.setBackgroundColor(currentBg);
context.setTextColor(currentFg);
context.setCursorPos(0,0);
for (key => pixel in screen) {
if (key.y != currentLine){
currentLine = key.y;
context.setCursorPos(key.x,key.y);
}
if (pixel == null){
context.write(' ');
}else{
if (pixel.bg != currentBg){
context.setBackgroundColor(pixel.bg);
currentBg = pixel.bg;
}
if (pixel.textColor != currentFg){
context.setTextColor(pixel.textColor);
currentFg = pixel.textColor;
}
context.write(pixel.char);
}
}
}
public static function renderChildren(children: Array<IElement>,bounds: Vec2<Int>): Canvas {
var rtn: Canvas = new Canvas();
var writePoint: Vec2<Int> = {x: 0,y: 0};
for (child in children) {
if (bounds.y - writePoint.y <= 0){
// No more space to render children
Log.debug("No more space");
break;
}
var childRender = child.render({
x: bounds.x,
y: bounds.y - writePoint.y
});
rtn.combine(childRender,writePoint);
}
return rtn;
}
}

31
src/lib/ui/TextElement.hx Normal file
View File

@@ -0,0 +1,31 @@
package lib.ui;
import kernel.Log;
import util.Color;
import util.Vec.Vec2;
import util.MathI;
class TextElement implements IElement {
private final text:String;
private final bg:Color;
private final fg:Color;
public function new(text: String,?background: Color = Black,?textColor: Color = White) {
this.text = text;
this.bg = background;
this.fg = textColor;
}
public function render(bounds: Vec2<Int>):Canvas {
var rtn = new Canvas();
for (i in 0...MathI.min(Math.floor(text.length / bounds.x) + 1,bounds.y)){
var line = (text.substr(i * bounds.x,bounds.x));
for (char in 0...line.length) {
rtn.set({x: char,y: i},{textColor: fg,char: line.charAt(char),bg: bg});
}
}
return rtn;
}
}

View File

@@ -0,0 +1,18 @@
package lib.ui;
import util.Vec.Vec2;
import kernel.ui.TermBuffer.Pixel;
class VSplitLayout implements IElement{
public function new(childrenLeft: Array<IElement>,childrenRight: Array<IElement>) {
}
public function render(bounds:Vec2<Int>):Canvas {
var boundsLeft: Vec2<Int> = { x: Math.ceil(bounds.x / 2), y: bounds.y};
var boundsRight: Vec2<Int> = { x: Math.floor(bounds.x / 2), y: bounds.y};
return null;
}
}