improved reactive ui and events
This commit is contained in:
		
							parent
							
								
									043d431e94
								
							
						
					
					
						commit
						46f03fbfe4
					
				@ -13,42 +13,42 @@ import lib.TermWriteable;
 | 
			
		||||
class WindowContext implements TermWriteable {
 | 
			
		||||
	private final writer:VirtualTermWriter;
 | 
			
		||||
 | 
			
		||||
	public var clickSignal(default, null):Signal<{button:ButtonType, pos:Vec2<Int>}>;
 | 
			
		||||
	public var keySignal(default, null):Signal<{keyCode:Int, isHeld:Bool}>;
 | 
			
		||||
	public var keyUpSignal(default, null):Signal<Int>;
 | 
			
		||||
	public var mouseDragSignal(default, null):Signal<{button:ButtonType, pos:Vec2<Int>}>;
 | 
			
		||||
	public var mouseScrollSignal(default, null):Signal<{dir:Int, pos:Vec2<Int>}>;
 | 
			
		||||
	public var mouseUpSignal(default, null):Signal<{button:ButtonType, pos:Vec2<Int>}>;
 | 
			
		||||
	public var pasteSignal(default, null):Signal<String>;
 | 
			
		||||
	public var onClick(default, null):Signal<{button:ButtonType, pos:Vec2<Int>}>;
 | 
			
		||||
	public var onKey(default, null):Signal<{keyCode:Int, isHeld:Bool}>;
 | 
			
		||||
	public var onKeyUp(default, null):Signal<Int>;
 | 
			
		||||
	public var onMouseDrag(default, null):Signal<{button:ButtonType, pos:Vec2<Int>}>;
 | 
			
		||||
	public var onMouseScroll(default, null):Signal<{dir:Int, pos:Vec2<Int>}>;
 | 
			
		||||
	public var onMouseUp(default, null):Signal<{button:ButtonType, pos:Vec2<Int>}>;
 | 
			
		||||
	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 keyTrigger:SignalTrigger<{keyCode:Int, isHeld:Bool}>;
 | 
			
		||||
	@:allow(kernel.ui.WindowManager) private final keyUpTrigger:SignalTrigger<Int>;
 | 
			
		||||
	@:allow(kernel.ui.WindowManager) private final mouseDragTrigger: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 mouseUpTrigger:SignalTrigger<{button:ButtonType, pos:Vec2<Int>}>;
 | 
			
		||||
	@:allow(kernel.ui.WindowManager) private final pasteTrigger:SignalTrigger<String>;
 | 
			
		||||
	@:allow(kernel.ui.WindowManager) private final onClickTrigger:SignalTrigger<{button:ButtonType, pos:Vec2<Int>}>;
 | 
			
		||||
	@:allow(kernel.ui.WindowManager) private final onKeyTrigger:SignalTrigger<{keyCode:Int, isHeld:Bool}>;
 | 
			
		||||
	@:allow(kernel.ui.WindowManager) private final onKeyUpTrigger:SignalTrigger<Int>;
 | 
			
		||||
	@:allow(kernel.ui.WindowManager) private final onMouseDragTrigger:SignalTrigger<{button:ButtonType, pos:Vec2<Int>}>;
 | 
			
		||||
	@:allow(kernel.ui.WindowManager) private final onMouseScrollTrigger:SignalTrigger<{dir:Int, pos:Vec2<Int>}>;
 | 
			
		||||
	@:allow(kernel.ui.WindowManager) private final onMouseUpTrigger:SignalTrigger<{button:ButtonType, pos:Vec2<Int>}>;
 | 
			
		||||
	@:allow(kernel.ui.WindowManager) private final onPasteTrigger:SignalTrigger<String>;
 | 
			
		||||
 | 
			
		||||
	@:allow(kernel.ui.WindowManager)
 | 
			
		||||
	private function new(writer:VirtualTermWriter) {
 | 
			
		||||
		this.writer = writer;
 | 
			
		||||
		this.onResize = writer.onResize;
 | 
			
		||||
 | 
			
		||||
		this.clickTrigger = Signal.trigger();
 | 
			
		||||
		this.keyTrigger = Signal.trigger();
 | 
			
		||||
		this.keyUpTrigger = Signal.trigger();
 | 
			
		||||
		this.mouseDragTrigger = Signal.trigger();
 | 
			
		||||
		this.mouseScrollTrigger = Signal.trigger();
 | 
			
		||||
		this.mouseUpTrigger = Signal.trigger();
 | 
			
		||||
		this.pasteTrigger = Signal.trigger();
 | 
			
		||||
		this.onClickTrigger = Signal.trigger();
 | 
			
		||||
		this.onKeyTrigger = Signal.trigger();
 | 
			
		||||
		this.onKeyUpTrigger = Signal.trigger();
 | 
			
		||||
		this.onMouseDragTrigger = Signal.trigger();
 | 
			
		||||
		this.onMouseScrollTrigger = Signal.trigger();
 | 
			
		||||
		this.onMouseUpTrigger = Signal.trigger();
 | 
			
		||||
		this.onPasteTrigger = Signal.trigger();
 | 
			
		||||
 | 
			
		||||
		this.clickSignal = clickTrigger.asSignal();
 | 
			
		||||
		this.keySignal = keyTrigger.asSignal();
 | 
			
		||||
		this.keyUpSignal = keyUpTrigger.asSignal();
 | 
			
		||||
		this.mouseDragSignal = mouseDragTrigger.asSignal();
 | 
			
		||||
		this.mouseScrollSignal = mouseScrollTrigger.asSignal();
 | 
			
		||||
		this.mouseUpSignal = mouseUpTrigger.asSignal();
 | 
			
		||||
		this.pasteSignal = pasteTrigger.asSignal();
 | 
			
		||||
		this.onClick = onClickTrigger.asSignal();
 | 
			
		||||
		this.onKey = onKeyTrigger.asSignal();
 | 
			
		||||
		this.onKeyUp = onKeyUpTrigger.asSignal();
 | 
			
		||||
		this.onMouseDrag = onMouseDragTrigger.asSignal();
 | 
			
		||||
		this.onMouseScroll = onMouseScrollTrigger.asSignal();
 | 
			
		||||
		this.onMouseUp = onMouseUpTrigger.asSignal();
 | 
			
		||||
		this.onPaste = onPasteTrigger.asSignal();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public var onResize(default, null):Signal<Vec2<Int>>;
 | 
			
		||||
 | 
			
		||||
@ -8,48 +8,51 @@ class WindowManager {
 | 
			
		||||
		Depends on: KernelEvents, Peripheral
 | 
			
		||||
	**/
 | 
			
		||||
	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)
 | 
			
		||||
	private function new() {
 | 
			
		||||
		KernelEvents.instance.onKey.handle(params -> {
 | 
			
		||||
			if (currentMainContext != null) {
 | 
			
		||||
				currentMainContext.keyTrigger.trigger(params);
 | 
			
		||||
				currentMainContext.onKeyTrigger.trigger(params);
 | 
			
		||||
			}
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		KernelEvents.instance.onKeyUp.handle(keyCode -> {
 | 
			
		||||
			if (currentMainContext != null) {
 | 
			
		||||
				currentMainContext.keyUpTrigger.trigger(keyCode);
 | 
			
		||||
				currentMainContext.onKeyUpTrigger.trigger(keyCode);
 | 
			
		||||
			}
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		KernelEvents.instance.onMouseClick.handle(params -> {
 | 
			
		||||
			if (currentMainContext != null) {
 | 
			
		||||
				currentMainContext.clickTrigger.trigger(params);
 | 
			
		||||
				currentMainContext.onClickTrigger.trigger(params);
 | 
			
		||||
			}
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		KernelEvents.instance.onMouseDrag.handle(params -> {
 | 
			
		||||
			if (currentMainContext != null) {
 | 
			
		||||
				currentMainContext.mouseDragTrigger.trigger(params);
 | 
			
		||||
				currentMainContext.onMouseDragTrigger.trigger(params);
 | 
			
		||||
			}
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		KernelEvents.instance.onMouseScroll.handle(params -> {
 | 
			
		||||
			if (currentMainContext != null) {
 | 
			
		||||
				currentMainContext.mouseScrollTrigger.trigger(params);
 | 
			
		||||
				currentMainContext.onMouseScrollTrigger.trigger(params);
 | 
			
		||||
			}
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		KernelEvents.instance.onMouseUp.handle(params -> {
 | 
			
		||||
			if (currentMainContext != null) {
 | 
			
		||||
				currentMainContext.mouseUpTrigger.trigger(params);
 | 
			
		||||
			}
 | 
			
		||||
			// if (currentMainContext != null) {
 | 
			
		||||
				currentMainContext.onMouseUpTrigger.trigger(params);
 | 
			
		||||
			// }
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		KernelEvents.instance.onPaste.handle(text -> {
 | 
			
		||||
			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 {
 | 
			
		||||
		var newContext = new WindowContext(new VirtualTermWriter());
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										15
									
								
								src/lib/ui/UIEvents.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/lib/ui/UIEvents.hx
									
									
									
									
									
										Normal 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>;
 | 
			
		||||
}
 | 
			
		||||
@ -28,13 +28,76 @@ class ReactiveUI {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private function setupEvents() {
 | 
			
		||||
		context.clickSignal.handle(params ->{
 | 
			
		||||
			for (k => v in this.elementMap){
 | 
			
		||||
		context.onClick.handle(params ->{
 | 
			
		||||
			for (k => v in elementMap){
 | 
			
		||||
				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() {
 | 
			
		||||
@ -88,7 +151,6 @@ class ReactiveUI {
 | 
			
		||||
		for (child in children) {
 | 
			
		||||
			if (bounds.y - writePoint.y <= 0) {
 | 
			
		||||
				// No more space to render children
 | 
			
		||||
				Log.debug("No more space");
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -14,8 +14,8 @@ class TextElement extends UIElement {
 | 
			
		||||
	private final bg:Color;
 | 
			
		||||
	private final fg:Color;
 | 
			
		||||
 | 
			
		||||
	public function new(text:Observable<String>, ?background:Color = Black, ?textColor:Color = White) {
 | 
			
		||||
		super();
 | 
			
		||||
	public function new(text:Observable<String>, ?background:Color = Black, ?textColor:Color = White, events: UIEvents = null) {
 | 
			
		||||
		super(events);
 | 
			
		||||
 | 
			
		||||
		this.text = text;
 | 
			
		||||
		this.bg = background;
 | 
			
		||||
@ -38,8 +38,4 @@ class TextElement extends UIElement {
 | 
			
		||||
 | 
			
		||||
		return rtn;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public override function handleClickEvent(pos: Vec2<Int>,button: ButtonType):Void {
 | 
			
		||||
		Log.debug('Click: ${this.text.get()}');
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,5 @@
 | 
			
		||||
package lib.ui.reactive;
 | 
			
		||||
 | 
			
		||||
import kernel.Log;
 | 
			
		||||
import kernel.ButtonType;
 | 
			
		||||
import util.Vec.Vec2;
 | 
			
		||||
 | 
			
		||||
using tink.CoreApi;
 | 
			
		||||
@ -10,11 +8,12 @@ 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 final eventListner:UIEvents = {};
 | 
			
		||||
 | 
			
		||||
	public function new() {
 | 
			
		||||
	public function new(events: UIEvents = null) {
 | 
			
		||||
		changed = changedTrigger.asSignal();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public function handleClickEvent(pos: Vec2<Int>,button: ButtonType):Void {
 | 
			
		||||
		if (events != null){
 | 
			
		||||
			this.eventListner = events;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user