Compare commits

..

4 Commits

Author SHA1 Message Date
1881d8f488 minor ui stuff 2022-03-04 00:59:32 +01:00
3b6bc85271 pass events to ui element 2022-03-04 00:59:02 +01:00
bddb80c42d added Rect 2022-03-04 00:58:35 +01:00
1aa3b43d8c added debug target 2022-03-03 15:47:11 +01:00
9 changed files with 102 additions and 39 deletions

View File

@@ -14,6 +14,9 @@ all: clean build
build: $(MIN_PATH) build: $(MIN_PATH)
debug: HAXE_FLAGS += -D webconsole --debug
debug: build
$(HAXE_PATH): $(shell find src -name '*.hx') $(HAXE_PATH): $(shell find src -name '*.hx')
haxe build.hxml $(HAXE_FLAGS) haxe build.hxml $(HAXE_FLAGS)
@@ -30,7 +33,7 @@ clean:
rm -rf $(BUILD_DIR) rm -rf $(BUILD_DIR)
watch: watch:
find src -name "*.hx" | entr make build find src -name "*.hx" | entr make debug
emulator: emulator:
craftos --mount-ro /=build craftos --mount-ro /=build

View File

@@ -7,6 +7,9 @@ import kernel.ButtonType;
import util.Vec.Vec2; import util.Vec.Vec2;
import lib.TermWriteable; import lib.TermWriteable;
/**
The main object you interact with when writing anything to the screen.
**/
class WindowContext implements TermWriteable { class WindowContext implements TermWriteable {
private final writer:VirtualTermWriter; private final writer:VirtualTermWriter;
@@ -26,7 +29,8 @@ class WindowContext implements TermWriteable {
@:allow(kernel.ui.WindowManager) private final mouseUpTrigger:SignalTrigger<{button:ButtonType, pos:Vec2<Int>}>; @:allow(kernel.ui.WindowManager) private final mouseUpTrigger:SignalTrigger<{button:ButtonType, pos:Vec2<Int>}>;
@:allow(kernel.ui.WindowManager) private final pasteTrigger:SignalTrigger<String>; @:allow(kernel.ui.WindowManager) private final pasteTrigger:SignalTrigger<String>;
public function new(writer:VirtualTermWriter) { @:allow(kernel.ui.WindowManager)
private function new(writer:VirtualTermWriter) {
this.writer = writer; this.writer = writer;
this.onResize = writer.onResize; this.onResize = writer.onResize;

View File

@@ -67,10 +67,6 @@ class WindowManager {
allContexts.push(newContext); allContexts.push(newContext);
// newContext.setTarget(MainTerm.instance);
newContext.enable();
currentMainContext = newContext;
return newContext; return newContext;
} }
@@ -84,6 +80,7 @@ class WindowManager {
var target:TermWriteable; var target:TermWriteable;
if (output == "main") { if (output == "main") {
target = MainTerm.instance; target = MainTerm.instance;
currentMainContext = context;
} else { } else {
target = Peripheral.instance.getScreen(output); target = Peripheral.instance.getScreen(output);

View File

@@ -12,7 +12,7 @@ class TermIO {
public function new(output:TermWriteable) { public function new(output:TermWriteable) {
this.output = output; this.output = output;
output.clear(); output.reset();
output.setCursorPos(0, 0); output.setCursorPos(0, 0);
} }

View File

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

View File

@@ -1,31 +1,48 @@
package lib.ui.reactive; package lib.ui.reactive;
import util.Rect;
import kernel.Log; import kernel.Log;
import util.Color; import util.Color;
import util.Vec.Vec2; import util.Vec.Vec2;
import kernel.ui.WindowContext; import kernel.ui.WindowContext;
using tink.CoreApi;
class ReactiveUI { class ReactiveUI {
private final context:WindowContext; private final context:WindowContext;
private final children:Array<IElement>; private final children:Array<UIElement>;
private var elementMap: Map<Rect,UIElement> = new Map();
public function new(context:WindowContext, children:Array<IElement>) { public function new(context:WindowContext, children:Array<UIElement>) {
this.context = context; this.context = context;
this.children = children; this.children = children;
for (child in children) { for (child in children) {
child.changed.handle(v -> { child.changed.handle(_ -> {
context.reset();
render(); render();
}); });
} }
setupEvents();
}
private function setupEvents() {
context.clickSignal.handle(params ->{
for (k => v in this.elementMap){
if (k.isInside(params.pos)){
v.handleClickEvent(params.pos,params.button);
}
}
});
} }
public function render() { public function render() {
var size = context.getSize(); var size = context.getSize();
var result = renderChildren(children, size);
this.elementMap = result.map;
var screen = renderChildren(children, size); writeToContext(result.canvas);
writeToContext(screen);
} }
private function writeToContext(screen:Canvas) { private function writeToContext(screen:Canvas) {
@@ -62,8 +79,9 @@ class ReactiveUI {
} }
} }
public static function renderChildren(children:Array<IElement>, bounds:Vec2<Int>):Canvas { public static function renderChildren(children:Array<UIElement>, bounds:Vec2<Int>):{canvas: Canvas, map: Map<Rect,UIElement>} {
var rtn:Canvas = new Canvas(); var canvas:Canvas = new Canvas();
var elementMap: Map<Rect,UIElement> = new Map();
var writePoint:Vec2<Int> = {x: 0, y: 0}; var writePoint:Vec2<Int> = {x: 0, y: 0};
@@ -79,11 +97,12 @@ class ReactiveUI {
y: bounds.y - writePoint.y y: bounds.y - writePoint.y
}); });
rtn.combine(childRender, writePoint); canvas.combine(childRender, writePoint);
elementMap.set(new Rect(writePoint,{x: childRender.maxWidth(), y: writePoint.y + childRender.hight()}),child);
writePoint = {x: 0, y: writePoint.y + childRender.hight()}; writePoint = {x: 0, y: writePoint.y + childRender.hight()};
} }
return rtn; return {canvas: canvas,map: elementMap};
} }
} }

View File

@@ -1,5 +1,7 @@
package lib.ui.reactive; package lib.ui.reactive;
import kernel.Log;
import kernel.ButtonType;
import util.Observable; import util.Observable;
using tink.CoreApi; using tink.CoreApi;
@@ -7,17 +9,13 @@ import util.Color;
import util.Vec.Vec2; import util.Vec.Vec2;
import util.MathI; import util.MathI;
class TextElement implements IElement { class TextElement extends UIElement {
public var changed(default, null):Signal<Noise>;
private var changedTrigger:SignalTrigger<Noise>;
private final text:Observable<String>; 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:Observable<String>, ?background:Color = Black, ?textColor:Color = White) { public function new(text:Observable<String>, ?background:Color = Black, ?textColor:Color = White) {
setupTrigger(); super();
this.text = text; this.text = text;
this.bg = background; this.bg = background;
@@ -28,11 +26,6 @@ class TextElement implements IElement {
}); });
} }
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();
@@ -45,4 +38,8 @@ class TextElement implements IElement {
return rtn; return rtn;
} }
public override function handleClickEvent(pos: Vec2<Int>,button: ButtonType):Void {
Log.debug('Click: ${this.text.get()}');
}
} }

View File

@@ -0,0 +1,20 @@
package lib.ui.reactive;
import kernel.Log;
import kernel.ButtonType;
import util.Vec.Vec2;
using tink.CoreApi;
abstract class UIElement {
abstract public function render(bounds:Vec2<Int>):Canvas;
public var changed(default, null):Signal<Noise>;
private final changedTrigger:SignalTrigger<Noise> = Signal.trigger();
public function new() {
changed = changedTrigger.asSignal();
}
public function handleClickEvent(pos: Vec2<Int>,button: ButtonType):Void {
}
}

33
src/util/Rect.hx Normal file
View File

@@ -0,0 +1,33 @@
package util;
import util.Vec.Vec2;
class Rect {
private final tr:Vec2<Int>;
private final bl:Vec2<Int>;
public function new(p1: Vec2<Int>,p2:Vec2<Int>) {
this.tr = {
x: MathI.max(p1.x,p2.x),
y: MathI.max(p1.y,p2.y)
};
this.bl = {
x: MathI.min(p1.x,p2.x),
y: MathI.min(p1.y,p2.y)
};
}
public function getSize(): Int {
return (tr.x - bl.x) * (tr.y - bl.y);
}
public function isInside(p: Vec2<Int>): Bool {
return (p.x >= bl.x && p.x <= tr.x) && (p.y >= bl.y && p.y <= tr.y);
}
public function isOutside(p: Vec2<Int>): Bool {
return !this.isInside(p);
}
}