i don't even know anymore
This commit is contained in:
parent
2b8aa06117
commit
a7dbdff535
@ -1,7 +1,6 @@
|
|||||||
package bin;
|
package bin;
|
||||||
|
|
||||||
import lib.TermHandle;
|
import lib.TermHandle;
|
||||||
import kernel.fs.FileHandler.WriteHandle;
|
|
||||||
import lib.CLIBase;
|
import lib.CLIBase;
|
||||||
|
|
||||||
class HelloWorld extends CLIBase {
|
class HelloWorld extends CLIBase {
|
||||||
|
76
src/bin/Net.hx
Normal file
76
src/bin/Net.hx
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
package bin;
|
||||||
|
|
||||||
|
import kernel.peripherals.Peripherals.Peripheral;
|
||||||
|
import kernel.net.Routing;
|
||||||
|
import haxe.ds.ReadOnlyArray;
|
||||||
|
import lib.TermHandle;
|
||||||
|
import lib.CLIBase;
|
||||||
|
|
||||||
|
class Net extends CLIBase {
|
||||||
|
private var handle:TermHandle;
|
||||||
|
public function invoke(handle:TermHandle):Bool {
|
||||||
|
this.handle = handle;
|
||||||
|
|
||||||
|
var subcommand = handle.args[0];
|
||||||
|
var subcommand_args = handle.args.slice(1);
|
||||||
|
|
||||||
|
switch (subcommand) {
|
||||||
|
case "route":
|
||||||
|
return route(subcommand_args);
|
||||||
|
case "iface":
|
||||||
|
return iface(subcommand_args);
|
||||||
|
case "help":
|
||||||
|
printHelp();
|
||||||
|
return true;
|
||||||
|
case "ping":
|
||||||
|
ping(subcommand_args);
|
||||||
|
default:
|
||||||
|
handle.writeLn("Unknown subcommand: " + subcommand);
|
||||||
|
printHelp();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function printHelp() {
|
||||||
|
handle.writeLn("net route");
|
||||||
|
handle.writeLn("net iface");
|
||||||
|
handle.writeLn("net help");
|
||||||
|
}
|
||||||
|
|
||||||
|
private function route(args:ReadOnlyArray<String>):Bool {
|
||||||
|
var routes = Routing.instance.getRouteTable();
|
||||||
|
|
||||||
|
for(k => v in routes) {
|
||||||
|
handle.writeLn('${k} => ${v.interf.name()}(${v.cost})');
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function iface(args:ReadOnlyArray<String>):Bool {
|
||||||
|
var modems = Peripheral.instance.getModems();
|
||||||
|
|
||||||
|
for (modem in modems) {
|
||||||
|
handle.writeLn(modem.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ping(args:ReadOnlyArray<String>) {
|
||||||
|
if (args.length != 1) {
|
||||||
|
handle.writeLn("Usage: net ping id");
|
||||||
|
}
|
||||||
|
|
||||||
|
var toID:Null<Int> = Std.parseInt(args[0]);
|
||||||
|
|
||||||
|
if (toID == null) {
|
||||||
|
handle.writeLn("Invalid ID");
|
||||||
|
}
|
||||||
|
|
||||||
|
// var result = kernel.net.Net.instance.ping(toID);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -139,6 +139,8 @@ class Terminal {
|
|||||||
switch (name) {
|
switch (name) {
|
||||||
case "hello":
|
case "hello":
|
||||||
return new HelloWorld();
|
return new HelloWorld();
|
||||||
|
case "net":
|
||||||
|
return new Net();
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
68
src/bin/TurtleRemote.hx
Normal file
68
src/bin/TurtleRemote.hx
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
package bin;
|
||||||
|
|
||||||
|
import lib.ui.reactive.TurtleController;
|
||||||
|
import util.ObservableValue;
|
||||||
|
import kernel.turtle.Turtle;
|
||||||
|
import util.DummyObservable;
|
||||||
|
import lib.ui.reactive.TextElement;
|
||||||
|
import lib.ui.reactive.ReactiveUI;
|
||||||
|
import kernel.ui.WindowManager;
|
||||||
|
import kernel.ui.WindowContext;
|
||||||
|
|
||||||
|
class TurtleRemote {
|
||||||
|
|
||||||
|
private var context:WindowContext;
|
||||||
|
private var ui:ReactiveUI;
|
||||||
|
|
||||||
|
public function new() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute() {
|
||||||
|
this.context = WindowManager.instance.createNewContext();
|
||||||
|
|
||||||
|
// var fuelText = new ObservableValue("");
|
||||||
|
|
||||||
|
// function updateFuel() {
|
||||||
|
// fuelText.set('Fuel: ${Turtle.instance.getFuelLevel()} / ${Turtle.instance.getFuelLimit()}');
|
||||||
|
// }
|
||||||
|
// updateFuel();
|
||||||
|
|
||||||
|
// var fuel = new TextElement(fuelText);
|
||||||
|
|
||||||
|
|
||||||
|
// var bForward = new TextElement(DummyObservable.dummy("Forward"),Black,White,{
|
||||||
|
// onClick: function() {
|
||||||
|
// Turtle.instance.forward();
|
||||||
|
// updateFuel();
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// var bBackward = new TextElement(DummyObservable.dummy("Backward"),Black,White,{
|
||||||
|
// onClick: function() {
|
||||||
|
// Turtle.instance.back();
|
||||||
|
// updateFuel();
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// var bLeft = new TextElement(DummyObservable.dummy("Turn left"),Black,White,{
|
||||||
|
// onClick: function() {
|
||||||
|
// Turtle.instance.turnLeft();
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// var bRight = new TextElement(DummyObservable.dummy("Turn right"),Black,White,{
|
||||||
|
// onClick: function() {
|
||||||
|
// Turtle.instance.turnRight();
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
var ctl = new TurtleController();
|
||||||
|
|
||||||
|
this.ui = new ReactiveUI(this.context,[ctl]);
|
||||||
|
|
||||||
|
this.ui.render();
|
||||||
|
|
||||||
|
WindowManager.instance.focusContextToOutput(context,"main");
|
||||||
|
}
|
||||||
|
}
|
@ -198,4 +198,21 @@ class Net {
|
|||||||
public function removeProto(proto:String) {
|
public function removeProto(proto:String) {
|
||||||
protoHandlers.remove(proto);
|
protoHandlers.remove(proto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sends a ping package to the given id. Returns true if there was a response.
|
||||||
|
**/
|
||||||
|
public function ping(toID: NetworkID): Promise<Bool> {
|
||||||
|
return new Promise<Bool>((resolve,reject)->{
|
||||||
|
this.sendAndAwait(toID,"ping",null).map(pack -> {
|
||||||
|
switch pack {
|
||||||
|
case Success(_):
|
||||||
|
resolve(true);
|
||||||
|
case Failure(err):
|
||||||
|
resolve(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,4 +176,8 @@ class Routing {
|
|||||||
return {interf: route.interf,rep: route.rep};
|
return {interf: route.interf,rep: route.rep};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getRouteTable():Map<NetworkID, Route> {
|
||||||
|
return this.routingTable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
8
src/lib/ui/Dimensions.hx
Normal file
8
src/lib/ui/Dimensions.hx
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package lib.ui;
|
||||||
|
|
||||||
|
typedef Dimensions = {
|
||||||
|
public var ?top:Int;
|
||||||
|
public var ?bottom:Int;
|
||||||
|
public var ?left:Int;
|
||||||
|
public var ?right:Int;
|
||||||
|
}
|
@ -1,40 +1,77 @@
|
|||||||
package lib.ui.reactive;
|
package lib.ui.reactive;
|
||||||
|
|
||||||
|
import lib.ui.Dimensions;
|
||||||
|
import util.ObjMerge;
|
||||||
import util.Pos;
|
import util.Pos;
|
||||||
import util.Observable;
|
import util.Observable;
|
||||||
using tink.CoreApi;
|
|
||||||
|
|
||||||
import util.Color;
|
import util.Color;
|
||||||
import util.Vec.Vec2;
|
import util.Vec.Vec2;
|
||||||
import util.MathI;
|
|
||||||
|
using tink.CoreApi;
|
||||||
|
|
||||||
|
typedef TextElementArgs = {
|
||||||
|
public var ?text:Observable<String>;
|
||||||
|
public var ?simpleText: String;
|
||||||
|
public var ?bg:Color;
|
||||||
|
public var ?fg:Color;
|
||||||
|
public var ?padding: Dimensions;
|
||||||
|
public var ?margin: Dimensions;
|
||||||
|
}
|
||||||
|
|
||||||
class TextElement extends UIElement {
|
class TextElement extends UIElement {
|
||||||
private final text:Observable<String>;
|
private var args:TextElementArgs;
|
||||||
private final bg:Color;
|
|
||||||
private final fg:Color;
|
|
||||||
|
|
||||||
public function new(text:Observable<String>, ?background:Color = Black, ?textColor:Color = White, events: UIEvents = null) {
|
public function new(args: TextElementArgs,events: UIEvents = null) {
|
||||||
super(events);
|
super(events);
|
||||||
|
this.args = args;
|
||||||
|
|
||||||
this.text = text;
|
if (args.text != null) {
|
||||||
this.bg = background;
|
args.text.subscribe(value -> {
|
||||||
this.fg = textColor;
|
|
||||||
|
|
||||||
this.text.subscribe(value -> {
|
|
||||||
this.changedTrigger.trigger(null);
|
this.changedTrigger.trigger(null);
|
||||||
});
|
});
|
||||||
|
}else if (args.simpleText == null) {
|
||||||
|
throw new Error("text or simpleText must be set");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getText() {
|
||||||
|
if (args.text != null) {
|
||||||
|
return args.text.get();
|
||||||
|
} else {
|
||||||
|
return args.simpleText;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render(bounds:Vec2<Int>,offset: Pos):Canvas {
|
public function render(bounds:Vec2<Int>,offset: Pos):Canvas {
|
||||||
var rtn = new Canvas();
|
var rtn = new Canvas();
|
||||||
|
|
||||||
for (i in 0...MathI.min(Math.floor(text.get().length / bounds.x) + 1, bounds.y)) {
|
var fullText = getText();
|
||||||
var line = (text.get().substr(i * bounds.x, bounds.x));
|
|
||||||
for (char in 0...line.length) {
|
var writePoint: Pos = {x: 0,y: 0};
|
||||||
rtn.set({x: char, y: i}, {textColor: fg, char: line.charAt(char), bg: bg});
|
|
||||||
}
|
for (pos in 0...fullText.length) {
|
||||||
|
var char = fullText.charAt(pos);
|
||||||
|
|
||||||
|
if (char == "\n"){
|
||||||
|
writePoint = {x: 0, y: writePoint.y + 1};
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rtn;
|
if (writePoint.y >= bounds.y) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (writePoint.x >= bounds.x) {
|
||||||
|
writePoint = {x: 0, y: writePoint.y + 1};
|
||||||
|
}
|
||||||
|
|
||||||
|
rtn.set(writePoint, {char: char,textColor: this.args.fg, bg: this.args.bg});
|
||||||
|
|
||||||
|
writePoint = {x: writePoint.x + 1, y: writePoint.y};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return UIElement.applyPaddignAndMargin(rtn, this.args.padding, this.args.margin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
62
src/lib/ui/reactive/TurtleController.hx
Normal file
62
src/lib/ui/reactive/TurtleController.hx
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
package lib.ui.reactive;
|
||||||
|
|
||||||
|
import util.Debug;
|
||||||
|
import util.Vec.Vec2;
|
||||||
|
import util.Pos;
|
||||||
|
|
||||||
|
class TurtleController extends UIElement {
|
||||||
|
|
||||||
|
public function new() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function addButton(label:String): Canvas {
|
||||||
|
var txt = new TextElement({simpleText: '$label', fg: Red,bg: Orange});
|
||||||
|
return txt.render({x:3,y:3},{x:0,y:0});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render(bounds:Vec2<Int>, offset:Pos):Canvas {
|
||||||
|
var canvas: Canvas = new Canvas();
|
||||||
|
|
||||||
|
canvas.combine(addButton("F"),{x:1,y:1});
|
||||||
|
canvas.combine(addButton("F"),{x:5,y:2});
|
||||||
|
|
||||||
|
Debug.printCanvasToConsole(canvas);
|
||||||
|
|
||||||
|
return canvas;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// var innerText = switch (sqr) {
|
||||||
|
// case 0: "D";
|
||||||
|
// case 1: "F";
|
||||||
|
// case 2: "U";
|
||||||
|
// case 3: "L";
|
||||||
|
// case 4: "B";
|
||||||
|
// case 5: "R";
|
||||||
|
// case 6: "D";
|
||||||
|
// case 7: "D";
|
||||||
|
// case 8: "D";
|
||||||
|
// default: "?";
|
||||||
|
// };
|
||||||
|
|
||||||
|
// canvas.set({x: offsetX + 0, y: offsetY + 0}, {char: borderChar,bg: bgColor,textColor: textColor});
|
||||||
|
// canvas.set({x: offsetX + 1, y: offsetY + 0}, {char: borderChar,bg: bgColor,textColor: textColor});
|
||||||
|
// canvas.set({x: offsetX + 2, y: offsetY + 0}, {char: borderChar,bg: bgColor,textColor: textColor});
|
||||||
|
// canvas.set({x: offsetX + 3, y: offsetY + 0}, {char: " ",bg: spaceColor,textColor: textColor});
|
||||||
|
|
||||||
|
// canvas.set({x: offsetX + 0, y: offsetY + 1}, {char: borderChar,bg: bgColor,textColor: textColor});
|
||||||
|
// canvas.set({x: offsetX + 1, y: offsetY + 1}, {char: innerText,bg: bgColor,textColor: textColor});
|
||||||
|
// canvas.set({x: offsetX + 2, y: offsetY + 1}, {char: borderChar,bg: bgColor,textColor: textColor});
|
||||||
|
// canvas.set({x: offsetX + 3, y: offsetY + 1}, {char: " ",bg: spaceColor,textColor: textColor});
|
||||||
|
|
||||||
|
// canvas.set({x: offsetX + 0, y: offsetY + 2}, {char: borderChar,bg: bgColor,textColor: textColor});
|
||||||
|
// canvas.set({x: offsetX + 1, y: offsetY + 2}, {char: borderChar,bg: bgColor,textColor: textColor});
|
||||||
|
// canvas.set({x: offsetX + 2, y: offsetY + 2}, {char: borderChar,bg: bgColor,textColor: textColor});
|
||||||
|
// canvas.set({x: offsetX + 3, y: offsetY + 2}, {char: " ",bg: spaceColor,textColor: textColor});
|
||||||
|
|
||||||
|
// canvas.set({x: offsetX + 0, y: offsetY + 3}, {char: " ",bg: spaceColor,textColor: textColor});
|
||||||
|
// canvas.set({x: offsetX + 1, y: offsetY + 3}, {char: " ",bg: spaceColor,textColor: textColor});
|
||||||
|
// canvas.set({x: offsetX + 2, y: offsetY + 3}, {char: " ",bg: spaceColor,textColor: textColor});
|
||||||
|
// canvas.set({x: offsetX + 3, y: offsetY + 3}, {char: " ",bg: spaceColor,textColor: textColor});
|
@ -1,5 +1,6 @@
|
|||||||
package lib.ui.reactive;
|
package lib.ui.reactive;
|
||||||
|
|
||||||
|
import util.ObjMerge;
|
||||||
import util.Pos;
|
import util.Pos;
|
||||||
import util.Rect;
|
import util.Rect;
|
||||||
import util.Vec.Vec2;
|
import util.Vec.Vec2;
|
||||||
@ -33,4 +34,14 @@ abstract class UIElement {
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public static function applyPaddignAndMargin(canvas:Canvas,padding: Dimensions, margin: Dimensions):Canvas{
|
||||||
|
var passing = ObjMerge.merge(padding, {top: 0, left: 0, bottom: 0, right: 0});
|
||||||
|
var margin = ObjMerge.merge(margin, {top: 0, left: 0, bottom: 0, right: 0});
|
||||||
|
var rtn = new Canvas();
|
||||||
|
|
||||||
|
rtn.combine(canvas,{x:margin.left + padding.left,y: margin.top + padding.top});
|
||||||
|
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
27
src/util/DummyObservable.hx
Normal file
27
src/util/DummyObservable.hx
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package util;
|
||||||
|
|
||||||
|
using tink.CoreApi;
|
||||||
|
|
||||||
|
class DummyObservable<T> implements Observable<T> {
|
||||||
|
private var value:T;
|
||||||
|
|
||||||
|
private function new(value:T) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function set(value:T) {
|
||||||
|
throw new haxe.exceptions.NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get():T {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function subscribe(callback:Callback<T>):CallbackLink {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function dummy<T>(value: T): Observable<T> {
|
||||||
|
return new DummyObservable<T>(value);
|
||||||
|
}
|
||||||
|
}
|
24
src/util/ObjMerge.hx
Normal file
24
src/util/ObjMerge.hx
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package util;
|
||||||
|
|
||||||
|
class ObjMerge {
|
||||||
|
public static function merge<T>(obj1:T, obj2:T): T {
|
||||||
|
if (obj1 == null) {
|
||||||
|
return obj2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj2 == null) {
|
||||||
|
return obj1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var rtn:T = Reflect.copy(obj1);
|
||||||
|
var fields = Reflect.fields(obj2);
|
||||||
|
|
||||||
|
for (field in fields) {
|
||||||
|
if (Reflect.getProperty(obj1, field) == null) {
|
||||||
|
Reflect.setProperty(rtn, field, Reflect.getProperty(obj2, field));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (rtn:T);
|
||||||
|
}
|
||||||
|
}
|
@ -2,27 +2,8 @@ package util;
|
|||||||
|
|
||||||
using tink.CoreApi;
|
using tink.CoreApi;
|
||||||
|
|
||||||
class Observable<T> {
|
interface Observable<T> {
|
||||||
private var value:T;
|
public function set(value:T): Void;
|
||||||
private var callbacks:CallbackList<T> = new CallbackList();
|
public function get():T;
|
||||||
|
public function subscribe(callback:Callback<T>):CallbackLink;
|
||||||
public function new(value:T) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function set(value:T) {
|
|
||||||
if (value != this.value) {
|
|
||||||
this.value = value;
|
|
||||||
callbacks.invoke(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function get():T {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function subscribe(callback:Callback<T>):CallbackLink {
|
|
||||||
callback.invoke(value);
|
|
||||||
return callbacks.add(callback);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package util;
|
package util;
|
||||||
|
|
||||||
class ObservableArray<T> extends Observable<Array<T>> {
|
class ObservableArray<T> extends ObservableValue<Array<T>> {
|
||||||
public function new(value: Array<T>) {
|
public function new(value: Array<T>) {
|
||||||
super(value);
|
super(value);
|
||||||
}
|
}
|
||||||
|
28
src/util/ObservableValue.hx
Normal file
28
src/util/ObservableValue.hx
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package util;
|
||||||
|
|
||||||
|
using tink.CoreApi;
|
||||||
|
|
||||||
|
class ObservableValue<T> implements Observable<T> {
|
||||||
|
private var value:T;
|
||||||
|
private var callbacks:CallbackList<T> = new CallbackList();
|
||||||
|
|
||||||
|
public function new(value:T) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function set(value:T) {
|
||||||
|
if (value != this.value) {
|
||||||
|
this.value = value;
|
||||||
|
callbacks.invoke(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get():T {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function subscribe(callback:Callback<T>):CallbackLink {
|
||||||
|
callback.invoke(value);
|
||||||
|
return callbacks.add(callback);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user