Compare commits

...

6 Commits

Author SHA1 Message Date
347e210f5f added statelessVirtualTermWriter
- changed how WindowManager handles new contexts
2023-03-21 00:53:07 +01:00
d0670325f2 windowContext inlined the TermWriteable functions 2023-03-20 19:09:07 +01:00
8991a99585 added debug kernel event count 2023-03-20 16:24:25 +01:00
05fa6203d1 removed unused kernel events 2023-03-20 01:19:52 +01:00
204e464b1b Added kernel log ui app 2023-03-20 01:15:22 +01:00
84d437104d Improved Log system 2023-03-20 01:15:07 +01:00
11 changed files with 523 additions and 212 deletions

65
src/bin/KernelLog.hx Normal file
View File

@@ -0,0 +1,65 @@
package bin;
import lib.Color;
import lib.MathI;
import kernel.log.Log;
import kernel.ui.WindowContext;
import lib.ui.UIApp;
using tink.CoreApi;
class KernelLog extends UIApp{
private var ctx:WindowContext;
private var exitTrigger: Bool -> Void;
public function new() {}
public function invoke(context:WindowContext):Future<Bool> {
this.ctx = context;
Log.instance.onLog.handle(()->{
render();
});
render();
return new Future<Bool>(cb -> {
this.exitTrigger = cb;
return null;
});
}
private function render() {
ctx.clear();
ctx.setCursorPos(0,0);
var lines = Log.instance.getLines();
var height = ctx.getSize().y;
var start = MathI.max(lines.length - height,0);
for (i in start...lines.length) {
var line = lines[i];
switch (line.level){
case Info:
ctx.setTextColor(Color.White);
ctx.write("[INFO] ");
case Warn:
ctx.setTextColor(Color.Yellow);
ctx.write("[WARN] ");
case Error:
ctx.setTextColor(Color.Red);
ctx.write("[ERRO] ");
case Debug:
ctx.setTextColor(Color.Gray);
ctx.write("[DEBG] ");
case Silly:
ctx.setTextColor(Color.Gray);
ctx.write("[SILL] ");
}
ctx.write(line.message);
ctx.setCursorPos(0,ctx.getCursorPos().y + 1);
}
}
}

View File

@@ -1,5 +1,6 @@
package kernel; package kernel;
import kernel.log.Log;
import kernel.turtle.Turtle; import kernel.turtle.Turtle;
import haxe.MainLoop; import haxe.MainLoop;
import kernel.net.Routing; import kernel.net.Routing;
@@ -12,6 +13,7 @@ import kernel.net.Net;
class Init { class Init {
public static function initKernel() { public static function initKernel() {
// Init singeltons here because haxe is confused about the order to create them. // Init singeltons here because haxe is confused about the order to create them.
Log.instance = new Log();
KernelEvents.instance = new KernelEvents(); KernelEvents.instance = new KernelEvents();
Peripheral.instance = new Peripheral(); Peripheral.instance = new Peripheral();

View File

@@ -45,7 +45,6 @@ class KernelEvents {
public final onPaste:Signal<String>; public final onPaste:Signal<String>;
public final onPeripheral:Signal<String>; public final onPeripheral:Signal<String>;
public final onPeripheralDetach:Signal<String>; public final onPeripheralDetach:Signal<String>;
public final onRednetMessage:Signal<{sender:Int, message:Any, protocol:Any}>;
public final onRedstone:Signal<Noise>; public final onRedstone:Signal<Noise>;
public final onSpeakerAudioEmpty:Signal<String>; public final onSpeakerAudioEmpty:Signal<String>;
public final onTaskComplete:Signal<{id:Int, success:Bool, failedReason:String}>; public final onTaskComplete:Signal<{id:Int, success:Bool, failedReason:String}>;
@@ -117,7 +116,6 @@ class KernelEvents {
this.onPaste = onPasteTrigger.asSignal(); this.onPaste = onPasteTrigger.asSignal();
this.onPeripheral = onPeripheralTrigger.asSignal(); this.onPeripheral = onPeripheralTrigger.asSignal();
this.onPeripheralDetach = onPeripheralDetachTrigger.asSignal(); this.onPeripheralDetach = onPeripheralDetachTrigger.asSignal();
this.onRednetMessage = onRednetMessageTrigger.asSignal();
this.onRedstone = onRedstoneTrigger.asSignal(); this.onRedstone = onRedstoneTrigger.asSignal();
this.onSpeakerAudioEmpty = onSpeakerAudioEmptyTrigger.asSignal(); this.onSpeakerAudioEmpty = onSpeakerAudioEmptyTrigger.asSignal();
this.onTaskComplete = onTaskCompleteTrigger.asSignal(); this.onTaskComplete = onTaskCompleteTrigger.asSignal();
@@ -194,8 +192,6 @@ class KernelEvents {
this.onPeripheralTrigger.trigger(event[2]); this.onPeripheralTrigger.trigger(event[2]);
case "peripheral_detach": case "peripheral_detach":
this.onPeripheralDetachTrigger.trigger(event[2]); this.onPeripheralDetachTrigger.trigger(event[2]);
case "rednet_message":
this.onRednetMessageTrigger.trigger({sender: event[2], message: event[3], protocol: event[4]});
case "redstone": case "redstone":
this.onRedstoneTrigger.trigger(null); this.onRedstoneTrigger.trigger(null);
case "speaker_audio_empty": case "speaker_audio_empty":
@@ -235,4 +231,38 @@ class KernelEvents {
throw new Exception("Invalid input"); throw new Exception("Invalid input");
} }
} }
@:allow(lib.Debug)
private function printListenerCount() {
if (onAlarmTrigger.getLength() > 0) Log.debug("onAlarm: " + onAlarmTrigger.getLength());
if (onCharTrigger.getLength() > 0) Log.debug("onChar: " + onCharTrigger.getLength());
if (onDiskTrigger.getLength() > 0) Log.debug("onDisk: " + onDiskTrigger.getLength());
if (onDiskEjectTrigger.getLength() > 0) Log.debug("onDiskEject: " + onDiskEjectTrigger.getLength());
if (onHttpCheckTrigger.getLength() > 0) Log.debug("onHttpCheck: " + onHttpCheckTrigger.getLength());
if (onHttpFailureTrigger.getLength() > 0) Log.debug("onHttpFailure: " + onHttpFailureTrigger.getLength());
if (onHttpSuccessTrigger.getLength() > 0) Log.debug("onHttpSuccess: " + onHttpSuccessTrigger.getLength());
if (onKeyTrigger.getLength() > 0) Log.debug("onKey: " + onKeyTrigger.getLength());
if (onKeyUpTrigger.getLength() > 0) Log.debug("onKeyUp: " + onKeyUpTrigger.getLength());
if (onModemMessageTrigger.getLength() > 0) Log.debug("onModemMessage: " + onModemMessageTrigger.getLength());
if (onMonitorResizeTrigger.getLength() > 0) Log.debug("onMonitorResize: " + onMonitorResizeTrigger.getLength());
if (onMonitorTouchTrigger.getLength() > 0) Log.debug("onMonitorTouch: " + onMonitorTouchTrigger.getLength());
if (onMouseClickTrigger.getLength() > 0) Log.debug("onMouseClick: " + onMouseClickTrigger.getLength());
if (onMouseDragTrigger.getLength() > 0) Log.debug("onMouseDrag: " + onMouseDragTrigger.getLength());
if (onMouseScrollTrigger.getLength() > 0) Log.debug("onMouseScroll: " + onMouseScrollTrigger.getLength());
if (onMouseUpTrigger.getLength() > 0) Log.debug("onMouseUp: " + onMouseUpTrigger.getLength());
if (onPasteTrigger.getLength() > 0) Log.debug("onPaste: " + onPasteTrigger.getLength());
if (onPeripheralTrigger.getLength() > 0) Log.debug("onPeripheral: " + onPeripheralTrigger.getLength());
if (onPeripheralDetachTrigger.getLength() > 0) Log.debug("onPeripheralDetach: " + onPeripheralDetachTrigger.getLength());
if (onRedstoneTrigger.getLength() > 0) Log.debug("onRedstone: " + onRedstoneTrigger.getLength());
if (onSpeakerAudioEmptyTrigger.getLength() > 0) Log.debug("onSpeakerAudioEmpty: " + onSpeakerAudioEmptyTrigger.getLength());
if (onTaskCompleteTrigger.getLength() > 0) Log.debug("onTaskComplete: " + onTaskCompleteTrigger.getLength());
if (onTermResizeTrigger.getLength() > 0) Log.debug("onTermResize: " + onTermResizeTrigger.getLength());
if (onTerminateTrigger.getLength() > 0) Log.debug("onTerminate: " + onTerminateTrigger.getLength());
if (onTimerTrigger.getLength() > 0) Log.debug("onTimer: " + onTimerTrigger.getLength());
if (onTurtleInventoryTrigger.getLength() > 0) Log.debug("onTurtleInventory: " + onTurtleInventoryTrigger.getLength());
if (onWebsocketCloseTrigger.getLength() > 0) Log.debug("onWebsocketClose: " + onWebsocketCloseTrigger.getLength());
if (onWebsocketFailureTrigger.getLength() > 0) Log.debug("onWebsocketFailure: " + onWebsocketFailureTrigger.getLength());
if (onWebsocketMessageTrigger.getLength() > 0) Log.debug("onWebsocketMessage: " + onWebsocketMessageTrigger.getLength());
if (onWebsocketSuccessTrigger.getLength() > 0) Log.debug("onWebsocketSuccess: " + onWebsocketSuccessTrigger.getLength());
}
} }

View File

@@ -1,40 +1,52 @@
package kernel.log; package kernel.log;
import haxe.ds.ReadOnlyArray;
#if webconsole #if webconsole
import lib.Debug; import lib.Debug;
#end #end
using tink.CoreApi;
/** /**
Log messages to specified output. Log messages to specified output.
**/ **/
class Log { class Log {
public static var instance:Log;
private static inline final MAX_LINES:Int = 100; private static inline final MAX_LINES:Int = 100;
private static final logLines:Array<LogLine> = []; public final onLog:Signal<LogLine>;
private final onLogTrigger:SignalTrigger<LogLine> = new SignalTrigger();
private final logLines:Array<LogLine> = [];
public function new() {
onLog = onLogTrigger.asSignal();
}
public static function info(msg:Dynamic, ?pos:haxe.PosInfos) { public static function info(msg:Dynamic, ?pos:haxe.PosInfos) {
log({level: Info, message: Std.string(msg),time: 0}); instance.log({level: Info, message: Std.string(msg),time: 0});
} }
public static function warn(msg:Dynamic, ?pos:haxe.PosInfos) { public static function warn(msg:Dynamic, ?pos:haxe.PosInfos) {
log({level: Warn, message: Std.string(msg),time: 0}); instance.log({level: Warn, message: Std.string(msg),time: 0});
} }
public static function error(msg:Dynamic, ?pos:haxe.PosInfos) { public static function error(msg:Dynamic, ?pos:haxe.PosInfos) {
log({level: Error, message: Std.string(msg),time: 0}); instance.log({level: Error, message: Std.string(msg),time: 0});
} }
public static function debug(msg:Dynamic, ?pos:haxe.PosInfos) { public static function debug(msg:Dynamic, ?pos:haxe.PosInfos) {
#if debug #if debug
log({level: Debug, message: Std.string(msg),time: 0}); instance.log({level: Debug, message: Std.string(msg),time: 0});
#end #end
} }
public static function silly(msg:Dynamic, ?pos:haxe.PosInfos) { public static function silly(msg:Dynamic, ?pos:haxe.PosInfos) {
log({level: Silly, message: Std.string(msg),time: 0}); instance.log({level: Silly, message: Std.string(msg),time: 0});
} }
private static function log(line: LogLine, ?pos:haxe.PosInfos) { private function log(line: LogLine, ?pos:haxe.PosInfos) {
logLines.push(line); logLines.push(line);
if (logLines.length > MAX_LINES) { if (logLines.length > MAX_LINES) {
@@ -44,5 +56,11 @@ class Log {
#if webconsole #if webconsole
Debug.printWeb('[${Std.string(line.level)}] ${line.message}'); Debug.printWeb('[${Std.string(line.level)}] ${line.message}');
#end #end
onLogTrigger.trigger(line);
}
public function getLines():ReadOnlyArray<LogLine> {
return logLines;
} }
} }

View File

@@ -0,0 +1,180 @@
package kernel.ui;
import lib.Pos;
import lib.Vec.Vec2;
import lib.Color;
import kernel.ui.TermWriteable;
using tink.CoreApi;
/**
A term writer that can switch beetween its internal buffer and another termwriter.
The other target is most of the time a real screen
**/
class BufferedVirtualTermWriter implements VirtualTermWriter extends TermBuffer {
private static final defaultSize:Vec2<Int> = {x: 50, y: 50};
private var target:TermWriteable;
private var enabled:Bool = false;
private var onResizeLink:CallbackLink;
@:allow(kernel.ui)
private function new(?target:TermWriteable) {
setTarget(target);
if (enabled) {
enable();
}
super();
}
public function enable() {
if (target != null) {
enabled = true;
super.copyBufferToTarget(target);
}
}
public function disable() {
enabled = false;
}
public inline function isEnabled():Bool {
return enabled;
}
public function setTarget(newTarget:TermWriteable) {
if (newTarget != null) {
super.setSize(newTarget.getSize());
// Remove old target event listner
if (onResizeLink != null) {
onResizeLink.cancel();
}
// Add new target event listner
onResizeLink = newTarget.onResize.handle(newSize -> {
setSuperSize(newSize);
});
newTarget.reset();
target = newTarget;
}
}
private function setSuperSize(size:Vec2<Int>) {
super.setSize(target.getSize());
}
//
// TermWriteable functions.
//
public override function write(text:String) {
if (isEnabled()) {
target.write(text);
}
super.write(text);
}
public override function scroll(y:Int) {
if (isEnabled()) {
target.scroll(y);
}
super.scroll(y);
}
public override function getCursorPos():Pos {
if (isEnabled()) {
return target.getCursorPos();
} else {
return super.getCursorPos();
}
}
public override function setCursorPos(x:Int, y:Int) {
if (isEnabled()) {
target.setCursorPos(x, y);
}
super.setCursorPos(x, y);
}
public override function getCursorBlink():Bool {
if (isEnabled()){
return target.getCursorBlink();
}else{
return super.getCursorBlink();
}
}
public override function setCursorBlink(blink:Bool) {
if (isEnabled()){
target.setCursorBlink(blink);
}
super.setCursorBlink(blink);
}
public override function getSize():Vec2<Int> {
// TODO: make sense ?
if (target != null) {
return target.getSize();
}
return defaultSize;
}
public override function clear() {
if (isEnabled()) {
target.clear();
}
super.clear();
}
public override function clearLine() {
if (isEnabled()) {
target.clearLine();
}
super.clearLine();
}
public override function getTextColor():Color {
if (isEnabled()) {
return target.getTextColor();
}
return super.getTextColor();
}
public override function setTextColor(color:Color) {
if (isEnabled()) {
target.setTextColor(color);
}
super.setTextColor(color);
}
public override function getBackgroundColor():Color {
if (isEnabled()) {
return target.getBackgroundColor();
}
return super.getBackgroundColor();
}
public override function setBackgroundColor(color:Color) {
if (isEnabled()) {
target.setBackgroundColor(color);
}
super.setBackgroundColor(color);
}
public override function isColor():Bool {
throw new haxe.exceptions.NotImplementedException();
}
}

View File

@@ -0,0 +1,159 @@
package kernel.ui;
import kernel.log.Log;
import lib.Pos;
import lib.Vec.Vec2;
import lib.Color;
using tink.CoreApi;
/**
Normal TermWriteable but without storing the the state in a buffer wehen disabled.
When enabled or the screen size changes the render function is called.
The render function is only called when needed.
You can also request a re-render by calling `requestRender`.
**/
class StatelessVirtualTermWriter implements VirtualTermWriter {
public var onResize(default, null):Signal<Vec2<Int>>;
private var onResizeTrigger: SignalTrigger<Vec2<Int>> = Signal.trigger();
private var target:TermWriteable;
private var enabled:Bool = false;
private var renderFunc:Null<Void->Void> = null;
private var renderRequested:Bool = false;
private var onResizeLink: CallbackLink;
@:allow(kernel.ui)
private function new(?target:TermWriteable) {
onResize = onResizeTrigger.asSignal();
setTarget(target);
}
public function setRenderFunc(func: (Void->Void)) {
this.renderFunc = func;
}
public function requestRender() {
if (renderFunc == null) {
Log.warn("Render requested, but no render function set");
return;
}
if (enabled) {
renderFunc();
renderRequested = false;
}else{
renderRequested = true;
}
}
//
// VirtualTermWriter implementation
//
public function enable() {
if (target == null) {
return;
}
enabled = true;
if (renderFunc != null){
renderFunc();
}
renderRequested = false;
}
public function disable() {
enabled = false;
}
public function setTarget(newTarget:TermWriteable) {
if (newTarget == null) {
return;
}
if (target != null) {
onResizeLink.cancel();
}
onResizeLink = newTarget.onResize.handle((size) -> {
requestRender();
onResizeTrigger.trigger(size);
});
target = newTarget;
}
public function isEnabled():Bool {
return enabled;
}
//
// TermWriteable implementation
//
// Some functions return defualt values if the target is not set. This should not be an issue since
// the render func is only called when the target is set.
//
public inline function write(text:String) {
if (enabled) target.write(text);
}
public inline function scroll(y:Int) {
if (enabled) target.scroll(y);
}
public inline function getCursorPos():Pos {
return enabled ? target.getCursorPos() : new Pos({x: 0, y: 0});
}
public inline function setCursorPos(x:Int, y:Int) {
if (enabled) target.setCursorPos(x, y);
}
public inline function getCursorBlink():Bool {
return enabled ? target.getCursorBlink() : false;
}
public inline function setCursorBlink(blink:Bool) {
if (enabled) target.setCursorBlink(blink);
}
public inline function getSize():Vec2<Int> {
return enabled ? target.getSize() : {x: 0, y: 0};
}
public inline function clear() {
if (enabled) target.clear();
}
public inline function clearLine() {
if (enabled) target.clearLine();
}
public inline function getTextColor():Color {
return enabled ? target.getTextColor() : Color.White;
}
public inline function setTextColor(color:Color) {
if (enabled) target.setTextColor(color);
}
public inline function getBackgroundColor():Color {
return enabled ? target.getBackgroundColor() : Color.Black;
}
public inline function setBackgroundColor(color:Color) {
if (enabled) target.setBackgroundColor(color);
}
public inline function isColor():Bool {
return enabled ? target.isColor() : false;
}
public inline function reset() {
if (enabled) target.reset();
}
}

View File

@@ -1,180 +1,12 @@
package kernel.ui; package kernel.ui;
import lib.Pos;
import lib.Vec.Vec2;
import lib.Color;
import kernel.ui.TermWriteable;
using tink.CoreApi;
/** /**
A term writer that can switch beetween its internal buffer and another termwriter. A VirtualTermWriter is a TermWriteable that can be enabled or disabled.
The other target is most of the time a real screen When disabled, it will not write to its target. When enabled, it will.
**/ **/
class VirtualTermWriter implements TermWriteable extends TermBuffer { interface VirtualTermWriter extends TermWriteable {
private static final defaultSize:Vec2<Int> = {x: 50, y: 50}; public function enable():Void;
public function disable():Void;
private var target:TermWriteable; public function isEnabled():Bool;
private var enabled:Bool = false; public function setTarget(newTarget:TermWriteable):Void;
private var onResizeLink:CallbackLink;
@:allow(kernel.ui)
private function new(?target:TermWriteable) {
setTarget(target);
if (enabled) {
enable();
}
super();
}
public function enable() {
if (target != null) {
enabled = true;
super.copyBufferToTarget(target);
}
}
public function disable() {
enabled = false;
}
public inline function isEnabled():Bool {
return enabled;
}
public function setTarget(newTarget:TermWriteable) {
if (newTarget != null) {
super.setSize(newTarget.getSize());
// Remove old target event listner
if (onResizeLink != null) {
onResizeLink.cancel();
}
// Add new target event listner
onResizeLink = newTarget.onResize.handle(newSize -> {
setSuperSize(newSize);
});
newTarget.reset();
target = newTarget;
}
}
private function setSuperSize(size:Vec2<Int>) {
super.setSize(target.getSize());
}
//
// TermWriteable functions.
//
public override function write(text:String) {
if (isEnabled()) {
target.write(text);
}
super.write(text);
}
public override function scroll(y:Int) {
if (isEnabled()) {
target.scroll(y);
}
super.scroll(y);
}
public override function getCursorPos():Pos {
if (isEnabled()) {
return target.getCursorPos();
} else {
return super.getCursorPos();
}
}
public override function setCursorPos(x:Int, y:Int) {
if (isEnabled()) {
target.setCursorPos(x, y);
}
super.setCursorPos(x, y);
}
public override function getCursorBlink():Bool {
if (isEnabled()){
return target.getCursorBlink();
}else{
return super.getCursorBlink();
}
}
public override function setCursorBlink(blink:Bool) {
if (isEnabled()){
target.setCursorBlink(blink);
}
super.setCursorBlink(blink);
}
public override function getSize():Vec2<Int> {
// TODO: make sense ?
if (target != null) {
return target.getSize();
}
return defaultSize;
}
public override function clear() {
if (isEnabled()) {
target.clear();
}
super.clear();
}
public override function clearLine() {
if (isEnabled()) {
target.clearLine();
}
super.clearLine();
}
public override function getTextColor():Color {
if (isEnabled()) {
return target.getTextColor();
}
return super.getTextColor();
}
public override function setTextColor(color:Color) {
if (isEnabled()) {
target.setTextColor(color);
}
super.setTextColor(color);
}
public override function getBackgroundColor():Color {
if (isEnabled()) {
return target.getBackgroundColor();
}
return super.getBackgroundColor();
}
public override function setBackgroundColor(color:Color) {
if (isEnabled()) {
target.setBackgroundColor(color);
}
super.setBackgroundColor(color);
}
public override function isColor():Bool {
throw new haxe.exceptions.NotImplementedException();
}
} }

View File

@@ -62,82 +62,82 @@ class WindowContext implements TermWriteable {
public var onResize(default, null):Signal<Vec2<Int>>; public var onResize(default, null):Signal<Vec2<Int>>;
@:allow(kernel.ui) @:allow(kernel.ui)
private function setTarget(target:TermWriteable) { private inline function setTarget(target:TermWriteable) {
writer.setTarget(target); writer.setTarget(target);
} }
@:allow(kernel.ui) @:allow(kernel.ui)
private function enable() { private inline function enable() {
writer.enable(); writer.enable();
} }
@:allow(kernel.ui) @:allow(kernel.ui)
private function disable() { private inline function disable() {
writer.disable(); writer.disable();
} }
@:allow(kernel.ui) @:allow(kernel.ui)
private function isEnabled() { private inline function isEnabled() {
return writer.isEnabled(); return writer.isEnabled();
} }
public function write(text:String) { public inline function write(text:String) {
writer.write(text); writer.write(text);
} }
public function scroll(y:Int) { public inline function scroll(y:Int) {
writer.scroll(y); writer.scroll(y);
} }
public function getCursorPos():Pos { public inline function getCursorPos():Pos {
return writer.getCursorPos(); return writer.getCursorPos();
} }
public function setCursorPos(x:Int, y:Int) { public inline function setCursorPos(x:Int, y:Int) {
writer.setCursorPos(x, y); writer.setCursorPos(x, y);
} }
public function getCursorBlink():Bool { public inline function getCursorBlink():Bool {
return writer.getCursorBlink(); return writer.getCursorBlink();
} }
public function setCursorBlink(blink:Bool) { public inline function setCursorBlink(blink:Bool) {
writer.setCursorBlink(blink); writer.setCursorBlink(blink);
} }
public function getSize():Vec2<Int> { public inline function getSize():Vec2<Int> {
return writer.getSize(); return writer.getSize();
} }
public function clear() { public inline function clear() {
writer.clear(); writer.clear();
} }
public function clearLine() { public inline function clearLine() {
writer.clearLine(); writer.clearLine();
} }
public function getTextColor():Color { public inline function getTextColor():Color {
return writer.getTextColor(); return writer.getTextColor();
} }
public function setTextColor(color:Color) { public inline function setTextColor(color:Color) {
writer.setTextColor(color); writer.setTextColor(color);
} }
public function getBackgroundColor():Color { public inline function getBackgroundColor():Color {
return writer.getBackgroundColor(); return writer.getBackgroundColor();
} }
public function setBackgroundColor(color:Color) { public inline function setBackgroundColor(color:Color) {
writer.setBackgroundColor(color); writer.setBackgroundColor(color);
} }
public function isColor():Bool { public inline function isColor():Bool {
return writer.isColor(); return writer.isColor();
} }
public function reset() { public inline function reset() {
writer.reset(); writer.reset();
} }
@@ -145,7 +145,7 @@ class WindowContext implements TermWriteable {
Delegate events to an UIEventDelegate. Delegate events to an UIEventDelegate.
Set to null to stop delegating events. Set to null to stop delegating events.
**/ **/
public function delegateEvents(delegate: Null<UIEventDelegate>){ public inline function delegateEvents(delegate: Null<UIEventDelegate>){
this.eventDelegate = delegate; this.eventDelegate = delegate;
} }
} }

View File

@@ -111,12 +111,26 @@ class WindowManager {
}); });
} }
/**
Same as createNewBufferedContext because it is the most simple context.
**/
public function createNewContext():WindowContext { public function createNewContext():WindowContext {
var newContext = new WindowContext(new VirtualTermWriter()); return createNewBufferedContext();
}
public function createNewBufferedContext():WindowContext {
var newContext = new WindowContext(new BufferedVirtualTermWriter());
return newContext; return newContext;
} }
public function createNewStatelessContext():{ctx:WindowContext, setRenderFunc:(() -> Void) -> Void, requestRender:Void->Void} {
var writer = new StatelessVirtualTermWriter();
var newContext = new WindowContext(writer);
return {ctx: newContext, setRenderFunc: writer.setRenderFunc, requestRender: writer.requestRender};
}
public function getOutputs():ReadOnlyArray<String> { public function getOutputs():ReadOnlyArray<String> {
var arr = Peripheral.instance.getScreens().map(screen -> return screen.getAddr()); var arr = Peripheral.instance.getScreens().map(screen -> return screen.getAddr());
arr.push("main"); arr.push("main");

View File

@@ -1,5 +1,6 @@
package lib; package lib;
import kernel.KernelEvents;
import kernel.log.Log; import kernel.log.Log;
import lua.NativeStringTools; import lua.NativeStringTools;
import lib.ui.Canvas; import lib.ui.Canvas;
@@ -38,6 +39,12 @@ class Debug {
Log.debug("\n" + lines.join("\n")); Log.debug("\n" + lines.join("\n"));
} }
#if Debug
public static function printKernelEventsCount(){
KernelEvents.instance.printListenerCount();
}
#end
#if webconsole #if webconsole
public static function printWeb(msg:String) { public static function printWeb(msg:String) {
HTTP.request("http://127.0.0.1:8080/"+Net.instance.networkID,msg); HTTP.request("http://127.0.0.1:8080/"+Net.instance.networkID,msg);

View File

@@ -18,20 +18,23 @@ class HomeContext {
private var ctx:WindowContext = null; private var ctx:WindowContext = null;
private final workspaces:Map<Int, WindowContext> = []; private final workspaces:Map<Int, WindowContext> = [];
private var currentWorkspace:Int = -1; private var currentWorkspace:Int = -1;
private var requestRender: Void->Void;
private var renderer:RootElement; private var renderer:RootElement;
public function new() {} public function new() {}
public function run() { public function run() {
// Create main terminal context // Create main terminal context
ctx = WindowManager.instance.createNewContext(); var stateless = WindowManager.instance.createNewStatelessContext();
ctx = stateless.ctx;
requestRender = stateless.requestRender;
WindowManager.instance.focusContextToOutput(ctx, "main"); WindowManager.instance.focusContextToOutput(ctx, "main");
renderer = new RootElement(); renderer = new RootElement();
ctx.delegateEvents(renderer); ctx.delegateEvents(renderer);
render(); stateless.setRenderFunc(this.render);
requestRender();
// Register global key bindings to react to main terminal // Register global key bindings to react to main terminal
KernelEvents.instance.onKey.handle(e -> { KernelEvents.instance.onKey.handle(e -> {
@@ -71,7 +74,7 @@ class HomeContext {
} }
private function focusMainTerm() { private function focusMainTerm() {
render(); requestRender();
WindowManager.instance.focusContextToOutput(ctx, "main"); WindowManager.instance.focusContextToOutput(ctx, "main");
currentWorkspace = -1; currentWorkspace = -1;
} }
@@ -80,7 +83,7 @@ class HomeContext {
if (workspaces[contextId] != null) { if (workspaces[contextId] != null) {
focusContext(contextId); focusContext(contextId);
} else { } else {
var newContext = WindowManager.instance.createNewContext(); var newContext = WindowManager.instance.createNewBufferedContext();
// Create new terminal // Create new terminal
var term = new Terminal(); var term = new Terminal();
@@ -93,6 +96,7 @@ class HomeContext {
private function render() { private function render() {
ctx.clear(); ctx.clear();
ctx.setCursorBlink(false);
var list = [ var list = [
for (i in 0...MAX_CONTEXT) workspaces.exists(i) ? 'Switch to context ${i}' : 'Create new Terminal on context ${i}' for (i in 0...MAX_CONTEXT) workspaces.exists(i) ? 'Switch to context ${i}' : 'Create new Terminal on context ${i}'