diff --git a/Utils/YesNtWindowStatements.cs b/Utils/YesNtWindowStatements.cs
index ef655ff..b52f2dd 100644
--- a/Utils/YesNtWindowStatements.cs
+++ b/Utils/YesNtWindowStatements.cs
@@ -1,4 +1,5 @@
using RemSox.Processing;
+using RemSox.UI.GUI.UIEelements;
using RemSox.UI.GUI.UIEelements.Controls;
using RemSox.UI.GUI.UIEelements.Shapes;
using RemSox.UI.GUI.Windows;
@@ -8,49 +9,35 @@ using System.Drawing;
using YesNt.Interpreter.Runtime;
using YesNt.Interpreter.Utilities;
+using ShapesRectangle = RemSox.UI.GUI.UIEelements.Shapes.Rectangle;
+
namespace RemSox.Utils;
///
/// Registers all YesNt statements that expose the WindowManager / UI element API.
///
-/// Window management:
-/// win_create "My Window" 320 240 creates a window, read back id with %win_last_id
-/// win_close ${myWinId} closes/destroys a window by id
-/// win_flush ${myWinId} forces a redraw of the window
-/// win_title ${myWinId} "New Title" changes the window title
-/// win_autoflush ${myWinId} true enables/disables auto-flush
-/// win_invalidate_all invalidates and redraws every window
+/// All ui_* and win_* statements support two argument styles:
+/// positional: ui_rect ${id} 20 20 100 60 0 128 255
+/// named: ui_rect ${id} x=20 y=20 w=100 h=60 r=0 g=128 b=255
///
-/// UI element creation (read back id with %ui_last_id after each call):
-/// ui_button ${myWinId} 20 30 100 30 "Click Me"
-/// ui_checkbox ${myWinId} 20 80 "Check Me" true
-/// ui_label ${myWinId} 20 10 "Hello World"
-/// ui_textbox ${myWinId} 20 50 160 24 "placeholder"
-/// ui_line ${myWinId} 20 130 180 130 255 0 0 (x1 y1 x2 y2 R G B)
-/// ui_rect ${myWinId} 20 20 100 60 0 128 255 (x y w h R G B)
+/// Commas are treated as whitespace in both modes, so you can write:
+/// ui_rect ${id} x=20,y=20,w=100,h=60,r=0,g=128,b=255
///
-/// Inline substitutions (use inside any line, like %read_line):
+/// If any argument contains '=', the statement parses in named mode
+/// (order-independent). Otherwise, positional mode is used.
+///
+/// Substitutions:
/// %win_last_id expands to the id of the last created window
/// %ui_last_id expands to the id of the last created UI element
///
public class YesNtWindowStatements(Process ownerProcess)
{
- // Maps script-visible integer ids to actual Window objects.
private readonly Dictionary windows = [];
private readonly Dictionary uiElements = [];
- private int lastWindowId = 0;
- private int lastUiId = 0;
+ private int lastWindowId;
+ private int lastUiId;
- ///
- /// Call this from to register
- /// every window-related statement with the given interpreter.
- ///
- /// The live interpreter instance.
- ///
- /// The that will own created windows
- /// (usually the itself).
- ///
public void Register(YesNtInterpreter interpreter)
{
RegisterWindowStatements(interpreter);
@@ -58,174 +45,326 @@ public class YesNtWindowStatements(Process ownerProcess)
RegisterCheckBoxStatement(interpreter);
RegisterLabelStatement(interpreter);
RegisterTextBoxStatement(interpreter);
+ RegisterRadioButtonStatement(interpreter);
+ RegisterProgressBarStatement(interpreter);
+ RegisterSliderStatement(interpreter);
+ RegisterPanelStatement(interpreter);
RegisterLineStatement(interpreter);
RegisterRectStatement(interpreter);
+ RegisterCircleStatement(interpreter);
+ RegisterRemoveStatement(interpreter);
RegisterLastIdSubstitutions(interpreter);
}
+ // --- Argument parser ---
+
+ private static string[] ParseTokens(string input)
+ {
+ return input.Split([' ', ','], StringSplitOptions.RemoveEmptyEntries);
+ }
+
+ private static bool IsNamed(string[] tokens)
+ {
+ foreach (string t in tokens)
+ {
+ if (t.Contains('='))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static bool TryGetInt(string[] tokens, bool named, string name, int pos, out int value)
+ {
+ value = 0;
+
+ if (named)
+ {
+ string prefix = name + '=';
+ foreach (string t in tokens)
+ {
+ if (t.StartsWith(prefix) && int.TryParse(t.AsSpan(prefix.Length), out value))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ if (pos < tokens.Length && int.TryParse(tokens[pos], out value))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ private static bool TryGetString(string[] tokens, bool named, string name, int pos, out string value)
+ {
+ value = string.Empty;
+
+ if (named)
+ {
+ string prefix = name + '=';
+ foreach (string t in tokens)
+ {
+ if (t.StartsWith(prefix))
+ {
+ value = t[prefix.Length..].FromSafeString();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ if (pos < tokens.Length)
+ {
+ value = tokens[pos].FromSafeString();
+ return true;
+ }
+ return false;
+ }
+
+ // --- Window statements ---
+
private void RegisterWindowStatements(YesNtInterpreter interpreter)
{
- // win_create "Title" width height
- // Sets %win_last_id to the new window's id.
- //
- // win_create "Control Test" 320 240
- // global winId = %win_last_id
+ // win_create "Title" w h [chrome=true|false]
interpreter.AddStatement(
- new StatementInformation(
- "win_create",
- YesNt.Interpreter.Enums.SearchMode.StartOfLine,
- YesNt.Interpreter.Enums.SpaceAround.End)
- {
- Priority = YesNt.Interpreter.Enums.Priority.Normal
- },
+ new StatementInformation("win_create", YesNt.Interpreter.Enums.SearchMode.StartOfLine, YesNt.Interpreter.Enums.SpaceAround.End)
+ { Priority = YesNt.Interpreter.Enums.Priority.Normal },
(args, context) =>
{
string trimmed = args.Trim();
- if (!TryParseWindowArgs(trimmed, out string title, out int w, out int h))
+ string title;
+ int w, h;
+ bool chrome = true;
+
+ if (trimmed.StartsWith('"'))
{
- context.Exit($"[win_create] Invalid arguments: {trimmed}", false);
- return;
+ int end = trimmed.IndexOf('"', 1);
+ if (end < 0)
+ {
+ context.Exit("[win_create] Missing closing quote", false);
+ return;
+ }
+ title = trimmed[1..end];
+ string[] tokens = ParseTokens(trimmed[(end + 1)..]);
+ bool named = IsNamed(tokens);
+
+ if (!TryGetInt(tokens, named, "w", 0, out w) || !TryGetInt(tokens, named, "h", 1, out h))
+ {
+ context.Exit("[win_create] Expected width and height", false);
+ return;
+ }
+
+ if (TryGetString(tokens, named, "chrome", 2, out string chromeStr))
+ {
+ _ = bool.TryParse(chromeStr, out chrome);
+ }
+ }
+ else
+ {
+ string[] tokens = ParseTokens(trimmed);
+ bool named = IsNamed(tokens);
+
+ if (!TryGetString(tokens, named, "title", 0, out title) ||
+ !TryGetInt(tokens, named, "w", 1, out w) ||
+ !TryGetInt(tokens, named, "h", 2, out h))
+ {
+ context.Exit("[win_create] Usage: win_create \"Title\" w h [chrome=false]", false);
+ return;
+ }
+
+ if (TryGetString(tokens, named, "chrome", 3, out string chromeStr))
+ {
+ _ = bool.TryParse(chromeStr, out chrome);
+ }
}
- Window win = WindowManager.CreateWindow(
- ownerProcess,
- title,
- new Size(w, h));
+ Window win = WindowManager.CreateWindow(ownerProcess, title, new Size(w, h));
+ win.HasChrome = chrome;
int id = lastWindowId = win.Id;
windows[id] = win;
});
- // win_close
+ // win_close id
interpreter.AddStatement(
- new StatementInformation(
- "win_close",
- YesNt.Interpreter.Enums.SearchMode.StartOfLine,
- YesNt.Interpreter.Enums.SpaceAround.End)
- {
- Priority = YesNt.Interpreter.Enums.Priority.Normal
- },
+ new StatementInformation("win_close", YesNt.Interpreter.Enums.SearchMode.StartOfLine, YesNt.Interpreter.Enums.SpaceAround.End)
+ { Priority = YesNt.Interpreter.Enums.Priority.Normal },
(args, context) =>
{
- string idStr = args.Trim();
- if (int.TryParse(idStr, out int id) && windows.TryGetValue(id, out Window? win))
+ if (TryGetWindow(args, out Window? win))
{
WindowManager.CloseWindow(win);
- bool unused = windows.Remove(id);
+ _ = windows.Remove(win.Id);
}
});
- // win_flush
+ // win_flush id
interpreter.AddStatement(
- new StatementInformation(
- "win_flush",
- YesNt.Interpreter.Enums.SearchMode.StartOfLine,
- YesNt.Interpreter.Enums.SpaceAround.End)
- {
- Priority = YesNt.Interpreter.Enums.Priority.Normal
- },
+ new StatementInformation("win_flush", YesNt.Interpreter.Enums.SearchMode.StartOfLine, YesNt.Interpreter.Enums.SpaceAround.End)
+ { Priority = YesNt.Interpreter.Enums.Priority.Normal },
(args, context) =>
{
- string idStr = args.Trim();
- if (int.TryParse(idStr, out int id) && windows.TryGetValue(id, out Window? win))
+ if (TryGetWindow(args, out Window? win))
{
win.Flush();
}
});
- // win_title "New Title"
+ // win_title id "New Title"
interpreter.AddStatement(
- new StatementInformation(
- "win_title",
- YesNt.Interpreter.Enums.SearchMode.StartOfLine,
- YesNt.Interpreter.Enums.SpaceAround.End)
- {
- Priority = YesNt.Interpreter.Enums.Priority.Normal
- },
+ new StatementInformation("win_title", YesNt.Interpreter.Enums.SearchMode.StartOfLine, YesNt.Interpreter.Enums.SpaceAround.End)
+ { Priority = YesNt.Interpreter.Enums.Priority.Normal },
(args, context) =>
{
- string rest = args.Trim();
- int spaceIdx = rest.IndexOf(' ');
- if (spaceIdx < 0) { return; }
+ string trimmed = args.Trim();
+ string[] tokens = ParseTokens(trimmed);
+ bool named = IsNamed(tokens);
- string idStr = rest[..spaceIdx].Trim();
- string newTitle = rest[(spaceIdx + 1)..].Trim().Trim('"');
-
- if (int.TryParse(idStr, out int id) && windows.TryGetValue(id, out Window? win))
+ if (!TryGetInt(tokens, named, "id", 0, out int id) || !windows.TryGetValue(id, out Window? win))
{
- win.Title = newTitle;
+ return;
}
+
+ string title;
+ if (trimmed.Contains('"'))
+ {
+ int start = trimmed.IndexOf('"') + 1;
+ int end = trimmed.IndexOf('"', start);
+ title = end >= 0 ? trimmed[start..end] : trimmed[start..];
+ }
+ else
+ {
+ _ = TryGetString(tokens, named, "title", 1, out title);
+ }
+
+ win.Title = title;
});
- // win_autoflush true|false
+ // win_autoflush id true|false
interpreter.AddStatement(
- new StatementInformation(
- "win_autoflush",
- YesNt.Interpreter.Enums.SearchMode.StartOfLine,
- YesNt.Interpreter.Enums.SpaceAround.End)
- {
- Priority = YesNt.Interpreter.Enums.Priority.Normal
- },
+ new StatementInformation("win_autoflush", YesNt.Interpreter.Enums.SearchMode.StartOfLine, YesNt.Interpreter.Enums.SpaceAround.End)
+ { Priority = YesNt.Interpreter.Enums.Priority.Normal },
(args, context) =>
{
- string rest = args.Trim();
- string[] parts = rest.Split(' ', StringSplitOptions.RemoveEmptyEntries);
- if (parts.Length == 2
- && int.TryParse(parts[0], out int id)
- && bool.TryParse(parts[1], out bool enabled)
- && windows.TryGetValue(id, out Window? win))
+ string[] tokens = ParseTokens(args.Trim());
+ bool named = IsNamed(tokens);
+
+ if (TryGetInt(tokens, named, "id", 0, out int id) &&
+ TryGetString(tokens, named, "enabled", 1, out string enabledStr) &&
+ bool.TryParse(enabledStr, out bool enabled) &&
+ windows.TryGetValue(id, out Window? win))
{
win.AutoFlush = enabled;
}
});
- // win_invalidate_all
+ // win_chrome id true|false
interpreter.AddStatement(
- new StatementInformation(
- "win_invalidate_all",
- YesNt.Interpreter.Enums.SearchMode.Contains,
- YesNt.Interpreter.Enums.SpaceAround.None)
- {
- Priority = YesNt.Interpreter.Enums.Priority.Normal
- },
+ new StatementInformation("win_chrome", YesNt.Interpreter.Enums.SearchMode.StartOfLine, YesNt.Interpreter.Enums.SpaceAround.End)
+ { Priority = YesNt.Interpreter.Enums.Priority.Normal },
(args, context) =>
{
- WindowManager.InvalidateAll();
+ string[] tokens = ParseTokens(args.Trim());
+ bool named = IsNamed(tokens);
+
+ if (TryGetInt(tokens, named, "id", 0, out int id) &&
+ TryGetString(tokens, named, "chrome", 1, out string chromeStr) &&
+ bool.TryParse(chromeStr, out bool chrome) &&
+ windows.TryGetValue(id, out Window? win))
+ {
+ win.HasChrome = chrome;
+ }
});
+
+ // win_focus id
+ interpreter.AddStatement(
+ new StatementInformation("win_focus", YesNt.Interpreter.Enums.SearchMode.StartOfLine, YesNt.Interpreter.Enums.SpaceAround.End)
+ { Priority = YesNt.Interpreter.Enums.Priority.Normal },
+ (args, context) =>
+ {
+ if (TryGetWindow(args, out Window? win))
+ {
+ WindowManager.FocusWindow(win);
+ }
+ });
+
+ // win_move id x y
+ interpreter.AddStatement(
+ new StatementInformation("win_move", YesNt.Interpreter.Enums.SearchMode.StartOfLine, YesNt.Interpreter.Enums.SpaceAround.End)
+ { Priority = YesNt.Interpreter.Enums.Priority.Normal },
+ (args, context) =>
+ {
+ string[] tokens = ParseTokens(args.Trim());
+ bool named = IsNamed(tokens);
+
+ if (TryGetInt(tokens, named, "id", 0, out int id) &&
+ TryGetInt(tokens, named, "x", 1, out int x) &&
+ TryGetInt(tokens, named, "y", 2, out int y) &&
+ windows.TryGetValue(id, out Window? win))
+ {
+ win.Position = new Point(x, y);
+ }
+ });
+
+ // win_resize id w h
+ interpreter.AddStatement(
+ new StatementInformation("win_resize", YesNt.Interpreter.Enums.SearchMode.StartOfLine, YesNt.Interpreter.Enums.SpaceAround.End)
+ { Priority = YesNt.Interpreter.Enums.Priority.Normal },
+ (args, context) =>
+ {
+ string[] tokens = ParseTokens(args.Trim());
+ bool named = IsNamed(tokens);
+
+ if (TryGetInt(tokens, named, "id", 0, out int id) &&
+ TryGetInt(tokens, named, "w", 1, out int w) &&
+ TryGetInt(tokens, named, "h", 2, out int h) &&
+ windows.TryGetValue(id, out Window? win))
+ {
+ win.Size = new Size(w, h);
+ }
+ });
+
+ // win_invalidate_all
+ interpreter.AddStatement(
+ new StatementInformation("win_invalidate_all", YesNt.Interpreter.Enums.SearchMode.Contains, YesNt.Interpreter.Enums.SpaceAround.None)
+ { Priority = YesNt.Interpreter.Enums.Priority.Normal },
+ (args, context) => WindowManager.InvalidateAll());
}
- // ui_button "Label" [R G B]
- // ui_button ${winId} 20 30 100 30 "Click Me"
- // ui_button ${winId} 20 30 100 30 "Click Me" 173 216 230
+ // --- Control statements ---
+
private void RegisterButtonStatement(YesNtInterpreter interpreter)
{
interpreter.AddStatement(
- new StatementInformation(
- "ui_button",
- YesNt.Interpreter.Enums.SearchMode.StartOfLine,
- YesNt.Interpreter.Enums.SpaceAround.End)
- {
- Priority = YesNt.Interpreter.Enums.Priority.Normal
- },
+ new StatementInformation("ui_button", YesNt.Interpreter.Enums.SearchMode.StartOfLine, YesNt.Interpreter.Enums.SpaceAround.End)
+ { Priority = YesNt.Interpreter.Enums.Priority.Normal },
(args, context) =>
{
- string rest = args.Trim();
- if (!TryParseUiArgs(rest, 5, out int winId, out int[] nums, out string label, out Color color))
+ if (!TryGetWindowAndArgs(args, out Window? win, out string[] tokens, out bool named))
{
- context.Exit($"[ui_button] Invalid arguments: {rest}", false);
return;
}
- if (!windows.TryGetValue(winId, out Window? win))
+ if (!TryGetInt(tokens, named, "x", 0, out int x) ||
+ !TryGetInt(tokens, named, "y", 1, out int y) ||
+ !TryGetInt(tokens, named, "w", 2, out int w) ||
+ !TryGetInt(tokens, named, "h", 3, out int h) ||
+ !TryGetString(tokens, named, "label", 4, out string label))
{
- context.Exit($"[ui_button] No window with id {winId}", false);
+ context.Exit("[ui_button] Usage: ui_button winId x y w h \"Label\" [r g b]", false);
return;
}
- Button button = win.CreateUIElement(b =>
+ Color color = ParseColor(tokens, named, 5);
+
+ Button button = win.CreateUIElement