start using tinker

This commit is contained in:
Djeeberjr 2022-02-21 01:50:19 +01:00
parent 829484cb67
commit c78bdab7e4
16 changed files with 172 additions and 255 deletions

View File

@ -1,33 +1,25 @@
import kernel.Init;
import lib.ui.Observable; import lib.ui.Observable;
import lib.ui.TextElement; import lib.ui.TextElement;
import lib.ui.ReactiveUI; import lib.ui.ReactiveUI;
import kernel.Log;
import util.Debug;
import kernel.ui.WindowManager; import kernel.ui.WindowManager;
import kernel.net.Net;
import kernel.KernelEvents; import kernel.KernelEvents;
using util.Extender.LambdaExtender; using util.Extender.LambdaExtender;
class Startup { class Startup {
static public function main() { public static function main() {
// OS.sleep(Math.random() * 3); // Native lua call to `sleep` Init.initKernel();
Net.instance.init();
WindowManager.instance.init();
Debug.printBuildInfo();
exampleUI(); exampleUI();
Log.moveToOutput("top");
KernelEvents.instance.startEventLoop(); KernelEvents.instance.startEventLoop();
} }
static function exampleProgramm() { static function exampleProgramm() {
var context = WindowManager.instance.createNewContext(); var context = WindowManager.instance.createNewContext();
context.clickSignal.on(data -> { context.clickSignal.handle(data -> {
context.setCursorPos(data.pos.x,data.pos.y); context.setCursorPos(data.pos.x,data.pos.y);
context.write("x"); context.write("x");
}); });
@ -47,7 +39,7 @@ class Startup {
ui.render(); ui.render();
context.clickSignal.on(data -> { context.clickSignal.handle(data -> {
text.set("Holla mundo"); text.set("Holla mundo");
}); });

22
src/kernel/Init.hx Normal file
View File

@ -0,0 +1,22 @@
package kernel;
import util.Debug;
import kernel.ui.WindowManager;
import kernel.peripherals.Peripherals.Peripheral;
import kernel.net.Net;
class Init {
public static function initKernel() {
// Init singeltons here because haxe is confused about the order to create them.
KernelEvents.instance = new KernelEvents();
Peripheral.instance = new Peripheral();
WindowManager.instance = new WindowManager();
MainTerm.instance = new MainTerm();
Net.instance = new Net();
Log.init();
Debug.printBuildInfo();
}
}

View File

@ -1,7 +1,6 @@
package kernel; package kernel;
import cc.OS; import cc.OS;
import lua.Coroutine;
import util.EventBus; import util.EventBus;
using lua.Table; using lua.Table;
@ -10,7 +9,9 @@ using lua.Table;
Class for interacting with the native pullEvent system. Class for interacting with the native pullEvent system.
**/ **/
class KernelEvents{ class KernelEvents{
public static final instance:KernelEvents = new KernelEvents(); public static var instance:KernelEvents;
@:allow(kernel.Init)
private function new () {} private function new () {}
private var eventBus: util.EventBus<Array<Dynamic>> = new EventBus(); private var eventBus: util.EventBus<Array<Dynamic>> = new EventBus();
@ -33,15 +34,15 @@ class KernelEvents{
} }
} }
public function on(eventName:String, callback:Array<Dynamic> -> Void):EventBusListner<Array<Dynamic>> { public function on(eventName:String, callback:Array<Dynamic> -> Void):EventBusListner {
return eventBus.on(eventName,callback); return eventBus.on(eventName,callback);
} }
public function once(eventName:String, callback:Array<Dynamic> -> Void):EventBusListner<Array<Dynamic>> { public function once(eventName:String, callback:Array<Dynamic> -> Void):EventBusListner {
return eventBus.once(eventName,callback); return eventBus.once(eventName,callback);
} }
public function removeListner(id:EventBusListner<Array<Dynamic>>) { public function removeListner(id:EventBusListner) {
return eventBus.removeListner(id); return eventBus.removeListner(id);
} }
} }

View File

@ -1,6 +1,5 @@
package kernel; package kernel;
import util.Debug;
import kernel.ui.WindowContext; import kernel.ui.WindowContext;
import kernel.ui.WindowManager; import kernel.ui.WindowManager;
import lib.TermWriteable; import lib.TermWriteable;
@ -10,8 +9,14 @@ import lib.TermIO;
Log messages to specified output. Log messages to specified output.
**/ **/
class Log { class Log {
private static final context:WindowContext = WindowManager.instance.createNewContext(); private static var context:WindowContext;
private static var writer:TermIO = new TermIO(context); private static var writer:TermIO;
@:allow(kernel.Init)
private static function init() {
Log.context = WindowManager.instance.createNewContext();
Log.writer = new TermIO(Log.context);
}
private static function setMainoutout(newOutput: TermWriteable) { private static function setMainoutout(newOutput: TermWriteable) {
writer = new TermIO(newOutput); writer = new TermIO(newOutput);

View File

@ -1,6 +1,7 @@
package kernel; package kernel;
import util.Signal; using tink.CoreApi;
import lib.TermWriteable; import lib.TermWriteable;
import cc.Term; import cc.Term;
import util.Vec.Vec2; import util.Vec.Vec2;
@ -10,19 +11,21 @@ import util.Color;
Represents the main computer screen. Represents the main computer screen.
**/ **/
class MainTerm implements TermWriteable{ class MainTerm implements TermWriteable{
public static final instance:MainTerm = new MainTerm(); public static var instance:MainTerm;
public var onResize(default, null):Signal<Vec2<Int>>;
private var onResizeTrigger:SignalTrigger<Vec2<Int>>;
@:allow(kernel.Init)
private function new() { private function new() {
this.onResizeTrigger = Signal.trigger();
this.onResize = this.onResizeTrigger.asSignal();
KernelEvents.instance.on("term_resize",params ->{ KernelEvents.instance.on("term_resize",params ->{
_onResize.emit(null); onResizeTrigger.trigger(getSize());
}); });
} }
public var onResize(get, null):SignalReadonly<Vec2<Int>>;
private var _onResize:Signal<Vec2<Int>> = new Signal();
function get_onResize():SignalReadonly<Vec2<Int>> {
return _onResize;
}
public function write(text:String) { public function write(text:String) {
Term.write(text); Term.write(text);

View File

@ -1,5 +1,7 @@
package kernel; package kernel;
using tink.CoreApi;
import util.EventBus.EventBusListner; import util.EventBus.EventBusListner;
import cc.OS; import cc.OS;
@ -8,19 +10,19 @@ import cc.OS;
**/ **/
class Timer { class Timer {
private final timerID:Int; private final timerID:Int;
private final callback:Void->Void; private final callback:Callback<Noise>;
private final timerListner:EventBusListner<Array<Dynamic>>; private final timerListner:EventBusListner;
/** /**
Create new timer with timeout in seconds. Create new timer with timeout in seconds.
**/ **/
public function new(timeout: Int, cb: Void->Void) { public function new(timeout: Int, callback: Callback<Noise>) {
timerID = OS.startTimer(timeout); timerID = OS.startTimer(timeout);
callback = cb; this.callback = callback;
timerListner = KernelEvents.instance.on("timer",(params)->{ timerListner = KernelEvents.instance.on("timer",(params)->{
if (params[1] == timerID){ if (params[1] == timerID){
cb(); callback.invoke(null);
KernelEvents.instance.removeListner(timerListner); KernelEvents.instance.removeListner(timerListner);
} }
}); });

View File

@ -17,8 +17,18 @@ using util.Extender.LambdaExtender;
Used to send and recceive packages. Used to send and recceive packages.
**/ **/
class Net{ class Net{
public static final instance:Net = new Net(); public static var instance:Net;
private function new () {}
@:allow(kernel.Init)
private function new () {
KernelEvents.instance.on("modem_message",(params)->{
var pack = Package.fromEvent(params);
handelIncomming(pack,params[1]);
});
allModems = Peripheral.instance.getModems();
open();
discoverNeighbors();
}
public static inline final BRODCAST_PORT:Int = 65533; public static inline final BRODCAST_PORT:Int = 65533;
public static inline final MESSAGE_TIMEOUT:Int = 3; public static inline final MESSAGE_TIMEOUT:Int = 3;
@ -29,16 +39,6 @@ class Net{
private var allModems:Array<kernel.peripherals.Modem>; private var allModems:Array<kernel.peripherals.Modem>;
private var routingTable: Map<Int,kernel.peripherals.Modem> = new Map(); private var routingTable: Map<Int,kernel.peripherals.Modem> = new Map();
public function init() {
KernelEvents.instance.on("modem_message",(params)->{
var pack = Package.fromEvent(params);
handelIncomming(pack,params[1]);
});
allModems = Peripheral.instance.getModems();
open();
discoverNeighbors();
}
private function handelIncomming(pack: Package, ?addr:String) { private function handelIncomming(pack: Package, ?addr:String) {
switch pack.type { switch pack.type {
case Data(_): case Data(_):

View File

@ -10,7 +10,9 @@ using Lambda;
Class responseable for retrieving peripherals. Class responseable for retrieving peripherals.
**/ **/
class Peripheral { class Peripheral {
public static final instance:Peripheral = new Peripheral(); public static var instance:Peripheral;
@:allow(kernel.Init)
private function new() {} private function new() {}
/** /**

View File

@ -1,6 +1,7 @@
package kernel.peripherals; package kernel.peripherals;
import util.Signal; using tink.CoreApi;
import cc.Term.TerminalSize; import cc.Term.TerminalSize;
import lib.TermWriteable; import lib.TermWriteable;
import util.Vec.Vec2; import util.Vec.Vec2;
@ -11,14 +12,21 @@ class Screen implements TermWriteable{
private final addr:String; private final addr:String;
private final onResizeTrigger: SignalTrigger<Vec2<Int>>;
public var onResize(default,null):Signal<Vec2<Int>>;
@:allow(kernel.peripherals) @:allow(kernel.peripherals)
public function new(nativePeripherals: cc.periphs.Monitor.Monitor,addr: String) { public function new(nativePeripherals: cc.periphs.Monitor.Monitor,addr: String) {
this.onResizeTrigger = Signal.trigger();
this.onResize = onResizeTrigger.asSignal();
this.nativ = nativePeripherals; this.nativ = nativePeripherals;
this.addr = addr; this.addr = addr;
KernelEvents.instance.on("monitor_resize",params -> { KernelEvents.instance.on("monitor_resize",params -> {
if (params[1] == this.addr){ if (params[1] == this.addr){
_onResize.emit(null); onResizeTrigger.trigger(getSize());
} }
}); });
@ -29,13 +37,6 @@ class Screen implements TermWriteable{
return this.addr; return this.addr;
} }
public var onResize(get,null):SignalReadonly<Vec2<Int>>;
private final _onResize:Signal<Vec2<Int>> = new Signal();
function get_onResize():SignalReadonly<Vec2<Int>> {
return _onResize;
}
public function getTextScale(): Float { public function getTextScale(): Float {
return nativ.getTextScale(); return nativ.getTextScale();
} }
@ -109,4 +110,3 @@ class Screen implements TermWriteable{
return nativ.isColor(); return nativ.isColor();
} }
} }

View File

@ -1,6 +1,7 @@
package kernel.ui; package kernel.ui;
import util.Signal; using tink.CoreApi;
import util.Vec.Vec2; import util.Vec.Vec2;
import util.Color; import util.Color;
import lib.TermWriteable; import lib.TermWriteable;
@ -22,13 +23,18 @@ class TermBuffer implements TermWriteable {
private var currentBgColor: Color = Black; private var currentBgColor: Color = Black;
private var size: Vec2<Int> = {x: 51,y:19}; // Default size set to default size of the main terminal private var size: Vec2<Int> = {x: 51,y:19}; // Default size set to default size of the main terminal
public var onResize(default,null):Signal<Vec2<Int>>;
private final onResizeTrigger:SignalTrigger<Vec2<Int>>;
public function new() { public function new() {
this.onResizeTrigger = Signal.trigger();
this.onResize = onResizeTrigger.asSignal();
initScreenBuffer(size); initScreenBuffer(size);
} }
private function setSize(size: Vec2<Int>) { private function setSize(size: Vec2<Int>) {
if (this.size != size){ if (this.size != size){
this._onResize.emit(size); this.onResizeTrigger.trigger(size);
} }
this.size = size; this.size = size;
@ -96,13 +102,6 @@ class TermBuffer implements TermWriteable {
// TermWriteable functions // TermWriteable functions
// //
public var onResize(get,null):SignalReadonly<Vec2<Int>>;
private final _onResize:Signal<Vec2<Int>> = new Signal();
function get_onResize():Signal<Vec2<Int>> {
return _onResize;
}
public function write(text:String) { public function write(text:String) {
for (i in 0...text.length){ for (i in 0...text.length){
safeWriteScreenBuffer({x: cursorPos.x,y: cursorPos.y},text.charAt(i)); safeWriteScreenBuffer({x: cursorPos.x,y: cursorPos.y},text.charAt(i));
@ -171,4 +170,3 @@ class TermBuffer implements TermWriteable {
throw new haxe.exceptions.NotImplementedException(); throw new haxe.exceptions.NotImplementedException();
} }
} }

View File

@ -1,6 +1,7 @@
package kernel.ui; package kernel.ui;
import util.Signal.SignalListner; using tink.CoreApi;
import util.Vec.Vec2; import util.Vec.Vec2;
import util.Color; import util.Color;
import lib.TermWriteable; import lib.TermWriteable;
@ -10,7 +11,7 @@ class VirtualTermWriter implements TermWriteable extends TermBuffer {
private var target: TermWriteable; private var target: TermWriteable;
private var enabled:Bool = false; private var enabled:Bool = false;
private var onResizeListner: SignalListner<Vec2<Int>>; private var onResizeLink: CallbackLink;
public function new(?target: TermWriteable) { public function new(?target: TermWriteable) {
setTarget(target); setTarget(target);
@ -42,12 +43,12 @@ class VirtualTermWriter implements TermWriteable extends TermBuffer {
super.setSize(newTarget.getSize()); super.setSize(newTarget.getSize());
// Remove old target event listner // Remove old target event listner
if (onResizeListner != null && target != null){ if (onResizeLink != null){
target.onResize.remove(onResizeListner); onResizeLink.cancel();
} }
// Add new target event listner // Add new target event listner
onResizeListner = newTarget.onResize.on(newSize -> { onResizeLink = newTarget.onResize.handle(newSize -> {
setSuperSize(newSize); setSuperSize(newSize);
}); });

View File

@ -1,7 +1,8 @@
package kernel.ui; package kernel.ui;
using tink.CoreApi;
import util.Color; import util.Color;
import util.Signal;
import kernel.ui.WindowManager.ButtonType; import kernel.ui.WindowManager.ButtonType;
import util.Vec.Vec2; import util.Vec.Vec2;
import lib.TermWriteable; import lib.TermWriteable;
@ -9,31 +10,46 @@ import lib.TermWriteable;
class WindowContext implements TermWriteable { class WindowContext implements TermWriteable {
private final writer:VirtualTermWriter; private final writer:VirtualTermWriter;
private final _clickSignal:Signal<{button: ButtonType, pos: Vec2<Int>}> = new Signal(); public var clickSignal(default,null):Signal<{button: ButtonType, pos: Vec2<Int>}>;
private final _keySignal:Signal<{keyCode: Int, isHeld: Bool}> = new Signal(); public var keySignal(default,null):Signal<{keyCode: Int, isHeld: Bool}>;
private final _keyUpSignal:Signal<Int> = new Signal(); public var keyUpSignal(default,null):Signal<Int>;
private final _mouseDragSignal:Signal<{button: ButtonType, pos: Vec2<Int>}> = new Signal(); public var mouseDragSignal(default,null):Signal<{button: ButtonType, pos: Vec2<Int>}>;
private final _mouseScrollSignal:Signal<{dir: Int,pos: Vec2<Int>}> = new Signal(); public var mouseScrollSignal(default,null):Signal<{dir: Int,pos: Vec2<Int>}>;
private final _mouseUpSignal:Signal<{button: ButtonType,pos: Vec2<Int>}> = new Signal(); public var mouseUpSignal(default,null):Signal<{button: ButtonType,pos: Vec2<Int>}>;
private final _pasteSignal:Signal<String> = new Signal(); public var pasteSignal(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>;
public var clickSignal(get,null):SignalReadonly<{button: ButtonType, pos: Vec2<Int>}>;
public var keySignal(get,null):SignalReadonly<{keyCode: Int, isHeld: Bool}>;
public var keyUpSignal(get,null):SignalReadonly<Int>;
public var mouseDragSignal(get,null):SignalReadonly<{button: ButtonType, pos: Vec2<Int>}>;
public var mouseScrollSignal(get,null):SignalReadonly<{dir: Int,pos: Vec2<Int>}>;
public var mouseUpSignal(get,null):SignalReadonly<{button: ButtonType,pos: Vec2<Int>}>;
public var pasteSignal(get,null):SignalReadonly<String> ;
public function new(writer: VirtualTermWriter) { public function new(writer: VirtualTermWriter) {
this.writer = writer; 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.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();
} }
public var onResize(get, null):SignalReadonly<Vec2<Int>>; public var onResize(default, null):Signal<Vec2<Int>>;
function get_onResize():SignalReadonly<Vec2<Int>> {
return writer.onResize;
}
@:allow(kernel.ui) @:allow(kernel.ui)
private function setTarget(target: TermWriteable) { private function setTarget(target: TermWriteable) {
@ -55,69 +71,6 @@ class WindowContext implements TermWriteable {
return writer.isEnabled(); return writer.isEnabled();
} }
public function get_clickSignal(){
return _clickSignal;
}
public function get_keySignal(){
return _keySignal;
}
public function get_keyUpSignal(){
return _keyUpSignal;
}
public function get_mouseDragSignal(){
return _mouseDragSignal;
}
public function get_mouseScrollSignal(){
return _mouseScrollSignal;
}
public function get_mouseUpSignal(){
return _mouseUpSignal;
}
public function get_pasteSignal(){
return _pasteSignal;
}
@:allow(kernel.ui.WindowManager) // Package private
private function click(button:ButtonType ,pos: Vec2<Int>) {
_clickSignal.emit({button: button,pos: pos});
}
@:allow(kernel.ui.WindowManager) // Package private
private function key(keyCode: Int, isHeld: Bool) {
_keySignal.emit({keyCode: keyCode,isHeld: isHeld});
}
@:allow(kernel.ui.WindowManager) // Package private
private function keyUp(keyCode: Int) {
_keyUpSignal.emit(keyCode);
}
@:allow(kernel.ui.WindowManager) // Package private
private function mouseDrag(button: ButtonType, pos: Vec2<Int>) {
_mouseDragSignal.emit({button: button,pos: pos});
}
@:allow(kernel.ui.WindowManager) // Package private
private function mouseScroll(dir: Int,pos: Vec2<Int>) {
_mouseScrollSignal.emit({dir: dir,pos: pos});
}
@:allow(kernel.ui.WindowManager) // Package private
private function mouseUp(button: ButtonType,pos: Vec2<Int>) {
_mouseUpSignal.emit({button: button,pos: pos});
}
@:allow(kernel.ui.WindowManager) // Package private
private function paste(text: String) {
_pasteSignal.emit(text);
}
public function write(text:String) { public function write(text:String) {
writer.write(text); writer.write(text);
} }

View File

@ -1,7 +1,6 @@
package kernel.ui; package kernel.ui;
import lib.TermWriteable; import lib.TermWriteable;
import kernel.peripherals.Screen;
import kernel.peripherals.Peripherals.Peripheral; import kernel.peripherals.Peripherals.Peripheral;
import haxe.Exception; import haxe.Exception;
import util.Vec.Vec2; import util.Vec.Vec2;
@ -13,26 +12,22 @@ enum ButtonType {
} }
class WindowManager { class WindowManager {
public static final instance:WindowManager = new WindowManager(); public static var instance:WindowManager;
private function new() {}
private var currentMainContext:WindowContext; @:allow(kernel.Init)
private final allContexts:Array<WindowContext> = new Array(); private function new() {
private final outputMap:Map<String,WindowContext> = new Map();
public function init() {
KernelEvents.instance.on("key",params -> { KernelEvents.instance.on("key",params -> {
var keyCode: Int = params[1]; var keyCode: Int = params[1];
var isHeld: Bool = params[2]; var isHeld: Bool = params[2];
if (currentMainContext != null){ if (currentMainContext != null){
currentMainContext.key(keyCode,isHeld); currentMainContext.keyTrigger.trigger({keyCode: keyCode,isHeld: isHeld});
} }
}); });
KernelEvents.instance.on("key_up",params -> { KernelEvents.instance.on("key_up",params -> {
var keyCode: Int = params[1]; var keyCode: Int = params[1];
if (currentMainContext != null){ if (currentMainContext != null){
currentMainContext.keyUp(keyCode); currentMainContext.keyUpTrigger.trigger(keyCode);
} }
}); });
@ -44,7 +39,7 @@ class WindowManager {
}; };
if (currentMainContext != null){ if (currentMainContext != null){
currentMainContext.click(button,clickPos); currentMainContext.clickTrigger.trigger({button: button,pos: clickPos});
} }
}); });
@ -55,7 +50,7 @@ class WindowManager {
y: (params[3]:Int) - 1, y: (params[3]:Int) - 1,
} }
if (currentMainContext != null){ if (currentMainContext != null){
currentMainContext.mouseDrag(button,pos); currentMainContext.mouseDragTrigger.trigger({button: button,pos: pos});
} }
}); });
@ -67,7 +62,7 @@ class WindowManager {
} }
if (currentMainContext != null){ if (currentMainContext != null){
currentMainContext.mouseScroll(dir,pos); currentMainContext.mouseScrollTrigger.trigger({dir: dir,pos: pos});
} }
}); });
@ -79,7 +74,7 @@ class WindowManager {
} }
if (currentMainContext != null){ if (currentMainContext != null){
currentMainContext.mouseUp(button,pos); currentMainContext.mouseUpTrigger.trigger({button: button,pos: pos});
} }
}); });
@ -87,7 +82,7 @@ class WindowManager {
var text: String = params[1]; var text: String = params[1];
if (currentMainContext != null){ if (currentMainContext != null){
currentMainContext.paste(text); currentMainContext.pasteTrigger.trigger(text);
} }
}); });
@ -96,12 +91,16 @@ 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());
allContexts.push(newContext); allContexts.push(newContext);
newContext.setTarget(MainTerm.instance); // newContext.setTarget(MainTerm.instance);
newContext.enable(); newContext.enable();
currentMainContext = newContext; currentMainContext = newContext;

View File

@ -1,6 +1,7 @@
package lib; package lib;
import util.Signal; using tink.CoreApi;
import util.Color; import util.Color;
import util.Vec.Vec2; import util.Vec.Vec2;
@ -9,7 +10,7 @@ import util.Vec.Vec2;
**/ **/
interface TermWriteable { interface TermWriteable {
public var onResize(get,null): SignalReadonly<Vec2<Int>>; public var onResize(default,null): Signal<Vec2<Int>>;
public function write(text: String): Void; public function write(text: String): Void;
public function scroll(y: Int): Void; public function scroll(y: Int): Void;

View File

@ -1,17 +1,17 @@
package util; package util;
import util.Signal.SignalListner; using tink.CoreApi;
class EventBusListner<T> { class EventBusListner {
@:allow(util.EventBus) @:allow(util.EventBus)
private final signalListner:SignalListner<T>; private final link:CallbackLink;
@:allow(util.EventBus) @:allow(util.EventBus)
private final eventName:String; private final eventName:String;
@:allow(util.EventBus) @:allow(util.EventBus)
private function new(signalListner: SignalListner<T>,eventName: String) { private function new(link: CallbackLink,eventName: String) {
this.signalListner = signalListner; this.link = link;
this.eventName = eventName; this.eventName = eventName;
} }
} }
@ -20,43 +20,42 @@ class EventBusListner<T> {
Generic event handler. Generic event handler.
**/ **/
class EventBus<T>{ class EventBus<T>{
private var listner: Map<String,Signal<T>> = new Map(); private var listner: Map<String,SignalTrigger<T>> = new Map();
public function new() { public function new() {
} }
public function on(eventName: String, callback: T->Void):EventBusListner<T>{ public function on(eventName: String, callback: Callback<T>):EventBusListner{
if (!listner.exists(eventName)){ if (!listner.exists(eventName)){
listner[eventName] = new Signal(); listner[eventName] = Signal.trigger();
} }
var signalListner = listner[eventName].on(callback); var link = listner[eventName].asSignal().handle(callback);
return new EventBusListner(signalListner,eventName); return new EventBusListner(link,eventName);
} }
public function once(eventName: String,callback: T->Void):EventBusListner<T> { public function once(eventName: String,callback: Callback<T>):EventBusListner {
if (!listner.exists(eventName)){ if (!listner.exists(eventName)){
listner[eventName] = new Signal(); listner[eventName] = Signal.trigger();
} }
var signalListner = listner[eventName].once(callback); var link = listner[eventName].asSignal().handle(callback);
return new EventBusListner(signalListner,eventName); return new EventBusListner(link,eventName);
} }
public function emit(eventName: String, data: Any) { public function emit(eventName: String, data: T) {
if (listner.exists(eventName)){ if (listner.exists(eventName)){
var signal = listner[eventName]; var trigger = listner[eventName];
signal.emit(data); trigger.trigger(data);
} }
} }
public function removeListner(id: EventBusListner<T>) { public function removeListner(id: EventBusListner) {
if (!listner.exists(id.eventName)) { if (!listner.exists(id.eventName)) {
return; return;
} }
id.link.cancel();
listner[id.eventName].remove(id.signalListner);
} }
} }

View File

@ -1,61 +0,0 @@
package util;
interface SignalReadonly<T> {
public function on(cb: T->Void):SignalListner<T>;
public function once(cb: T->Void):SignalListner<T>;
public function remove(id:SignalListner<T>):Void;
}
class SignalListner<T> {
private final callback:T->Void;
@:allow(util.Signal)
private final once:Bool;
@:allow(util.Signal)
private function new(callback: T->Void,?once: Bool = false) {
this.callback = callback;
this.once = once;
}
@:allow(util.Signal)
private function invoke(params: T) {
if (callback != null){
callback(params);
}
}
}
/**
Simple event system for one event type other than EventBus which has multiple events.
**/
class Signal<T> implements SignalReadonly<T>{
public final listner:Array<SignalListner<T>> = new Array();
public function new() {}
public function on(cb: T->Void):SignalListner<T> {
var l = new SignalListner<T>(cb,false);
listner.push(l);
return l;
}
public function once(cb: T->Void):SignalListner<T> {
var l = new SignalListner<T>(cb,true);
listner.push(l);
return l;
}
public function emit(data: T) {
for (cb in listner){
cb.invoke(data);
if (cb.once){
listner.remove(cb);
}
}
}
public function remove(id:SignalListner<T> ) {
listner.remove(id);
}
}