real reactive ui

This commit is contained in:
Djeeberjr 2022-02-20 20:56:37 +01:00
parent 7b33667e04
commit 829484cb67
6 changed files with 73 additions and 29 deletions

View File

@ -1,3 +1,4 @@
import lib.ui.Observable;
import lib.ui.TextElement; import lib.ui.TextElement;
import lib.ui.ReactiveUI; import lib.ui.ReactiveUI;
import kernel.Log; import kernel.Log;
@ -36,13 +37,20 @@ class Startup {
static function exampleUI() { static function exampleUI() {
var context = WindowManager.instance.createNewContext(); var context = WindowManager.instance.createNewContext();
var ui = new ReactiveUI(context);
ui.render([ var text = new Observable("Hello world");
new TextElement("Hello world"),
new TextElement("Hello world",Green,Red), var ui = new ReactiveUI(context,[
new TextElement(text),
new TextElement(text,Green,Red),
]); ]);
ui.render();
context.clickSignal.on(data -> {
text.set("Holla mundo");
});
WindowManager.instance.focusContextToOutput(context,"main"); WindowManager.instance.focusContextToOutput(context,"main");
} }
} }

View File

@ -1,7 +1,9 @@
package lib.ui; package lib.ui;
using tink.CoreApi;
import util.Vec.Vec2; import util.Vec.Vec2;
interface IElement { interface IElement {
public function render(bounds: Vec2<Int>): Canvas; public function render(bounds: Vec2<Int>): Canvas;
public var changed(default, null):Signal<Noise>;
} }

28
src/lib/ui/Observable.hx Normal file
View File

@ -0,0 +1,28 @@
package lib.ui;
using tink.CoreApi;
class Observable<T> {
private var value: T;
private var callbacks: CallbackList<T> = new CallbackList(true);
public function new(value: T) {
this.value = value;
}
public function set(value: T) {
if (value != this.value){
this.value = value;
callbacks.invoke(value);
}
}
public function get(): T {
return value;
}
public function subscribe(callback: Callback<T>):CallbackLink {
callback.invoke(value);
return callbacks.add(callback);
}
}

View File

@ -7,12 +7,20 @@ import kernel.ui.WindowContext;
class ReactiveUI { class ReactiveUI {
private final context:WindowContext; private final context:WindowContext;
private final children:Array<IElement>;
public function new(context: WindowContext) { public function new(context: WindowContext,children: Array<IElement>) {
this.context = context; this.context = context;
this.children = children;
for(child in children){
child.changed.handle(v -> {
render();
});
}
} }
public function render(children: Array<IElement>) { public function render() {
var size = context.getSize(); var size = context.getSize();
var screen = renderChildren(children,size); var screen = renderChildren(children,size);

View File

@ -1,26 +1,42 @@
package lib.ui; package lib.ui;
import kernel.Log; using tink.CoreApi;
import util.Color; import util.Color;
import util.Vec.Vec2; import util.Vec.Vec2;
import util.MathI; import util.MathI;
class TextElement implements IElement { class TextElement implements IElement {
private final text:String; public var changed(default, null):Signal<Noise>;
private var changedTrigger:SignalTrigger<Noise>;
private final text: Observable<String>;
private final bg:Color; private final bg:Color;
private final fg:Color; private final fg:Color;
public function new(text: String,?background: Color = Black,?textColor: Color = White) { public function new(text: Observable<String>,?background: Color = Black,?textColor: Color = White) {
setupTrigger();
this.text = text; this.text = text;
this.bg = background; this.bg = background;
this.fg = textColor; this.fg = textColor;
this.text.subscribe(value -> {
this.changedTrigger.trigger(null);
});
}
private function setupTrigger() {
changedTrigger = Signal.trigger();
changed = changedTrigger.asSignal();
} }
public function render(bounds: Vec2<Int>):Canvas { public function render(bounds: Vec2<Int>):Canvas {
var rtn = new Canvas(); var rtn = new Canvas();
for (i in 0...MathI.min(Math.floor(text.length / bounds.x) + 1,bounds.y)){ for (i in 0...MathI.min(Math.floor(text.get().length / bounds.x) + 1,bounds.y)){
var line = (text.substr(i * bounds.x,bounds.x)); var line = (text.get().substr(i * bounds.x,bounds.x));
for (char in 0...line.length) { for (char in 0...line.length) {
rtn.set({x: char,y: i},{textColor: fg,char: line.charAt(char),bg: bg}); rtn.set({x: char,y: i},{textColor: fg,char: line.charAt(char),bg: bg});
} }

View File

@ -1,18 +0,0 @@
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;
}
}