added statelessVirtualTermWriter
- changed how WindowManager handles new contexts
This commit is contained in:
parent
d0670325f2
commit
347e210f5f
180
src/kernel/ui/BufferedVirtualTermWriter.hx
Normal file
180
src/kernel/ui/BufferedVirtualTermWriter.hx
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
159
src/kernel/ui/StatelessVirtualTermWriter.hx
Normal file
159
src/kernel/ui/StatelessVirtualTermWriter.hx
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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");
|
||||||
|
@ -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}'
|
||||||
|
Loading…
Reference in New Issue
Block a user