initial commit
This commit is contained in:
5
src/lib/IUserProgramm.hx
Normal file
5
src/lib/IUserProgramm.hx
Normal file
@@ -0,0 +1,5 @@
|
||||
package lib;
|
||||
|
||||
interface IUserProgramm {
|
||||
public function getName(): String;
|
||||
}
|
||||
48
src/lib/TermIO.hx
Normal file
48
src/lib/TermIO.hx
Normal 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
38
src/lib/TermWriteable.hx
Normal 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
74
src/lib/ui/Canvas.hx
Normal 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
7
src/lib/ui/IElement.hx
Normal 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
80
src/lib/ui/ReactiveUI.hx
Normal 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
31
src/lib/ui/TextElement.hx
Normal 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;
|
||||
}
|
||||
}
|
||||
18
src/lib/ui/VSplitLayout.hx
Normal file
18
src/lib/ui/VSplitLayout.hx
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user