using RemSox.Kernel.Processing; using RemSox.Kernel.UI.GUI.UIEelements; using RemSox.Kernel.UI.GUI.UIEelements.Controls; using RemSox.Kernel.UI.GUI.UIEelements.Shapes; using RemSox.Kernel.UI.GUI.Windows; using System.Diagnostics.CodeAnalysis; using System.Drawing; using YesNt.Interpreter.Runtime; using YesNt.Interpreter.Utilities; using ShapesRectangle = RemSox.Kernel.UI.GUI.UIEelements.Shapes.Rectangle; namespace RemSox.Kernel.Utils; /// /// /// Registers all YesNt statements that expose the WindowManager / UI element API. /// /// /// 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 ///
/// /// 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 ///
/// /// 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) { private readonly Dictionary windows = []; private readonly Dictionary uiElements = []; private int lastWindowId; private int lastUiId; public void Register(YesNtInterpreter interpreter) { RegisterWindowStatements(interpreter); RegisterButtonStatement(interpreter); 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" 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 }, (args, context) => { string trimmed = args.Trim(); string title; int w, h; bool chrome = true; if (trimmed.StartsWith('"')) { 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)); win.HasChrome = chrome; int id = lastWindowId = win.Id; windows[id] = win; }); // 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 }, (args, context) => { if (TryGetWindow(args, out Window? win)) { WindowManager.CloseWindow(win); _ = windows.Remove(win.Id); } }); // 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 }, (args, context) => { if (TryGetWindow(args, out Window? win)) { win.Flush(); } }); // 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 }, (args, context) => { string trimmed = args.Trim(); string[] tokens = ParseTokens(trimmed); bool named = IsNamed(tokens); if (!TryGetInt(tokens, named, "id", 0, out int id) || !windows.TryGetValue(id, out Window? win)) { 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 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 }, (args, context) => { 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_chrome id true|false interpreter.AddStatement( new StatementInformation("win_chrome", 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) && 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()); } // --- 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 }, (args, context) => { if (!TryGetWindowAndArgs(args, out Window? win, out string[] tokens, out bool named)) { return; } 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] Usage: ui_button winId x y w h \"Label\" [r g b]", false); return; } Color color = ParseColor(tokens, named, 5); Button button = win.CreateUIElement