improved reactive ui and events

This commit is contained in:
Djeeberjr 2022-03-04 13:28:52 +01:00
parent 043d431e94
commit 46f03fbfe4
6 changed files with 128 additions and 57 deletions

View File

@ -13,42 +13,42 @@ import lib.TermWriteable;
class WindowContext implements TermWriteable { class WindowContext implements TermWriteable {
private final writer:VirtualTermWriter; private final writer:VirtualTermWriter;
public var clickSignal(default, null):Signal<{button:ButtonType, pos:Vec2<Int>}>; public var onClick(default, null):Signal<{button:ButtonType, pos:Vec2<Int>}>;
public var keySignal(default, null):Signal<{keyCode:Int, isHeld:Bool}>; public var onKey(default, null):Signal<{keyCode:Int, isHeld:Bool}>;
public var keyUpSignal(default, null):Signal<Int>; public var onKeyUp(default, null):Signal<Int>;
public var mouseDragSignal(default, null):Signal<{button:ButtonType, pos:Vec2<Int>}>; public var onMouseDrag(default, null):Signal<{button:ButtonType, pos:Vec2<Int>}>;
public var mouseScrollSignal(default, null):Signal<{dir:Int, pos:Vec2<Int>}>; public var onMouseScroll(default, null):Signal<{dir:Int, pos:Vec2<Int>}>;
public var mouseUpSignal(default, null):Signal<{button:ButtonType, pos:Vec2<Int>}>; public var onMouseUp(default, null):Signal<{button:ButtonType, pos:Vec2<Int>}>;
public var pasteSignal(default, null):Signal<String>; public var onPaste(default, null):Signal<String>;
@:allow(kernel.ui.WindowManager) private final clickTrigger:SignalTrigger<{button:ButtonType, pos:Vec2<Int>}>; @:allow(kernel.ui.WindowManager) private final onClickTrigger:SignalTrigger<{button:ButtonType, pos:Vec2<Int>}>;
@:allow(kernel.ui.WindowManager) private final keyTrigger:SignalTrigger<{keyCode:Int, isHeld:Bool}>; @:allow(kernel.ui.WindowManager) private final onKeyTrigger:SignalTrigger<{keyCode:Int, isHeld:Bool}>;
@:allow(kernel.ui.WindowManager) private final keyUpTrigger:SignalTrigger<Int>; @:allow(kernel.ui.WindowManager) private final onKeyUpTrigger:SignalTrigger<Int>;
@:allow(kernel.ui.WindowManager) private final mouseDragTrigger:SignalTrigger<{button:ButtonType, pos:Vec2<Int>}>; @:allow(kernel.ui.WindowManager) private final onMouseDragTrigger:SignalTrigger<{button:ButtonType, pos:Vec2<Int>}>;
@:allow(kernel.ui.WindowManager) private final mouseScrollTrigger:SignalTrigger<{dir:Int, pos:Vec2<Int>}>; @:allow(kernel.ui.WindowManager) private final onMouseScrollTrigger:SignalTrigger<{dir:Int, pos:Vec2<Int>}>;
@:allow(kernel.ui.WindowManager) private final mouseUpTrigger:SignalTrigger<{button:ButtonType, pos:Vec2<Int>}>; @:allow(kernel.ui.WindowManager) private final onMouseUpTrigger:SignalTrigger<{button:ButtonType, pos:Vec2<Int>}>;
@:allow(kernel.ui.WindowManager) private final pasteTrigger:SignalTrigger<String>; @:allow(kernel.ui.WindowManager) private final onPasteTrigger:SignalTrigger<String>;
@:allow(kernel.ui.WindowManager) @:allow(kernel.ui.WindowManager)
private function new(writer:VirtualTermWriter) { private function new(writer:VirtualTermWriter) {
this.writer = writer; this.writer = writer;
this.onResize = writer.onResize; this.onResize = writer.onResize;
this.clickTrigger = Signal.trigger(); this.onClickTrigger = Signal.trigger();
this.keyTrigger = Signal.trigger(); this.onKeyTrigger = Signal.trigger();
this.keyUpTrigger = Signal.trigger(); this.onKeyUpTrigger = Signal.trigger();
this.mouseDragTrigger = Signal.trigger(); this.onMouseDragTrigger = Signal.trigger();
this.mouseScrollTrigger = Signal.trigger(); this.onMouseScrollTrigger = Signal.trigger();
this.mouseUpTrigger = Signal.trigger(); this.onMouseUpTrigger = Signal.trigger();
this.pasteTrigger = Signal.trigger(); this.onPasteTrigger = Signal.trigger();
this.clickSignal = clickTrigger.asSignal(); this.onClick = onClickTrigger.asSignal();
this.keySignal = keyTrigger.asSignal(); this.onKey = onKeyTrigger.asSignal();
this.keyUpSignal = keyUpTrigger.asSignal(); this.onKeyUp = onKeyUpTrigger.asSignal();
this.mouseDragSignal = mouseDragTrigger.asSignal(); this.onMouseDrag = onMouseDragTrigger.asSignal();
this.mouseScrollSignal = mouseScrollTrigger.asSignal(); this.onMouseScroll = onMouseScrollTrigger.asSignal();
this.mouseUpSignal = mouseUpTrigger.asSignal(); this.onMouseUp = onMouseUpTrigger.asSignal();
this.pasteSignal = pasteTrigger.asSignal(); this.onPaste = onPasteTrigger.asSignal();
} }
public var onResize(default, null):Signal<Vec2<Int>>; public var onResize(default, null):Signal<Vec2<Int>>;

View File

@ -8,48 +8,51 @@ class WindowManager {
Depends on: KernelEvents, Peripheral Depends on: KernelEvents, Peripheral
**/ **/
public static var instance:WindowManager; public static var instance:WindowManager;
private var currentMainContext:WindowContext;
private final allContexts:Array<WindowContext> = new Array();
private final outputMap:Map<String, WindowContext> = new Map();
@:allow(kernel.Init) @:allow(kernel.Init)
private function new() { private function new() {
KernelEvents.instance.onKey.handle(params -> { KernelEvents.instance.onKey.handle(params -> {
if (currentMainContext != null) { if (currentMainContext != null) {
currentMainContext.keyTrigger.trigger(params); currentMainContext.onKeyTrigger.trigger(params);
} }
}); });
KernelEvents.instance.onKeyUp.handle(keyCode -> { KernelEvents.instance.onKeyUp.handle(keyCode -> {
if (currentMainContext != null) { if (currentMainContext != null) {
currentMainContext.keyUpTrigger.trigger(keyCode); currentMainContext.onKeyUpTrigger.trigger(keyCode);
} }
}); });
KernelEvents.instance.onMouseClick.handle(params -> { KernelEvents.instance.onMouseClick.handle(params -> {
if (currentMainContext != null) { if (currentMainContext != null) {
currentMainContext.clickTrigger.trigger(params); currentMainContext.onClickTrigger.trigger(params);
} }
}); });
KernelEvents.instance.onMouseDrag.handle(params -> { KernelEvents.instance.onMouseDrag.handle(params -> {
if (currentMainContext != null) { if (currentMainContext != null) {
currentMainContext.mouseDragTrigger.trigger(params); currentMainContext.onMouseDragTrigger.trigger(params);
} }
}); });
KernelEvents.instance.onMouseScroll.handle(params -> { KernelEvents.instance.onMouseScroll.handle(params -> {
if (currentMainContext != null) { if (currentMainContext != null) {
currentMainContext.mouseScrollTrigger.trigger(params); currentMainContext.onMouseScrollTrigger.trigger(params);
} }
}); });
KernelEvents.instance.onMouseUp.handle(params -> { KernelEvents.instance.onMouseUp.handle(params -> {
if (currentMainContext != null) { // if (currentMainContext != null) {
currentMainContext.mouseUpTrigger.trigger(params); currentMainContext.onMouseUpTrigger.trigger(params);
} // }
}); });
KernelEvents.instance.onPaste.handle(text -> { KernelEvents.instance.onPaste.handle(text -> {
if (currentMainContext != null) { if (currentMainContext != null) {
currentMainContext.pasteTrigger.trigger(text); currentMainContext.onPasteTrigger.trigger(text);
} }
}); });
@ -58,10 +61,6 @@ class WindowManager {
}); });
} }
private var currentMainContext:WindowContext;
private final allContexts:Array<WindowContext> = new Array();
private final outputMap:Map<String, WindowContext> = new Map();
public function createNewContext():WindowContext { public function createNewContext():WindowContext {
var newContext = new WindowContext(new VirtualTermWriter()); var newContext = new WindowContext(new VirtualTermWriter());

15
src/lib/ui/UIEvents.hx Normal file
View File

@ -0,0 +1,15 @@
package lib.ui;
import util.Vec.Vec2;
import kernel.ButtonType;
using tink.CoreApi;
typedef UIEvents = {
public var ?onClick:Callback<{button:ButtonType, pos:Vec2<Int>}>;
public var ?onKey:Callback<{keyCode:Int, isHeld:Bool}>;
public var ?onKeyUp:Callback<Int>;
public var ?onMouseDrag:Callback<{button:ButtonType, pos:Vec2<Int>}>;
public var ?onMouseScroll:Callback<{dir:Int, pos:Vec2<Int>}>;
public var ?onMouseUp:Callback<{button:ButtonType, pos:Vec2<Int>}>;
public var ?onPaste:Callback<String>;
}

View File

@ -28,13 +28,76 @@ class ReactiveUI {
} }
private function setupEvents() { private function setupEvents() {
context.clickSignal.handle(params ->{ context.onClick.handle(params ->{
for (k => v in this.elementMap){ for (k => v in elementMap){
if (k.isInside(params.pos)){ if (k.isInside(params.pos)){
v.handleClickEvent(params.pos,params.button); if (v.eventListner.onClick != null){
v.eventListner.onClick.invoke(params);
}
} }
} }
}); });
// context.onKey.handle(params ->{
// for (k => v in elementMap){
// if (k.isInside(params.pos)){
// if (v.eventListner.onKey != null){
// v.eventListner.onKey.invoke(params);
// }
// }
// }
// });
// context.onKeyUp.handle(params ->{
// for (k => v in elementMap){
// if (k.isInside(params.pos)){
// if (v.eventListner.onKeyUp != null){
// v.eventListner.onKeyUp.invoke(params);
// }
// }
// }
// });
// context.onMouseDrag.handle(params ->{
// for (k => v in elementMap){
// if (k.isInside(params.pos)){
// if (v.eventListner.onMouseDrag != null){
// v.eventListner.onMouseDrag.invoke(params);
// }
// }
// }
// });
context.onMouseScroll.handle(params ->{
for (k => v in elementMap){
if (k.isInside(params.pos)){
if (v.eventListner.onMouseScroll != null){
v.eventListner.onMouseScroll.invoke(params);
}
}
}
});
context.onMouseUp.handle(params ->{
for (k => v in elementMap){
if (k.isInside(params.pos)){
if (v.eventListner.onMouseUp != null){
v.eventListner.onMouseUp.invoke(params);
}
}
}
});
// context.onPaste.handle(params ->{
// for (k => v in elementMap){
// if (k.isInside(params.pos)){
// if (v.eventListner.onPaste != null){
// v.eventListner.onPaste.invoke(params);
// }
// }
// }
// });
} }
public function render() { public function render() {
@ -88,7 +151,6 @@ class ReactiveUI {
for (child in children) { for (child in children) {
if (bounds.y - writePoint.y <= 0) { if (bounds.y - writePoint.y <= 0) {
// No more space to render children // No more space to render children
Log.debug("No more space");
break; break;
} }

View File

@ -14,8 +14,8 @@ class TextElement extends UIElement {
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, events: UIEvents = null) {
super(); super(events);
this.text = text; this.text = text;
this.bg = background; this.bg = background;
@ -38,8 +38,4 @@ class TextElement extends UIElement {
return rtn; return rtn;
} }
public override function handleClickEvent(pos: Vec2<Int>,button: ButtonType):Void {
Log.debug('Click: ${this.text.get()}');
}
} }

View File

@ -1,7 +1,5 @@
package lib.ui.reactive; package lib.ui.reactive;
import kernel.Log;
import kernel.ButtonType;
import util.Vec.Vec2; import util.Vec.Vec2;
using tink.CoreApi; using tink.CoreApi;
@ -10,11 +8,12 @@ abstract class UIElement {
abstract public function render(bounds:Vec2<Int>):Canvas; abstract public function render(bounds:Vec2<Int>):Canvas;
public var changed(default, null):Signal<Noise>; public var changed(default, null):Signal<Noise>;
private final changedTrigger:SignalTrigger<Noise> = Signal.trigger(); private final changedTrigger:SignalTrigger<Noise> = Signal.trigger();
public final eventListner:UIEvents = {};
public function new() { public function new(events: UIEvents = null) {
changed = changedTrigger.asSignal(); changed = changedTrigger.asSignal();
} if (events != null){
this.eventListner = events;
public function handleClickEvent(pos: Vec2<Int>,button: ButtonType):Void { }
} }
} }