CLua Documentation


🖥️ GUI (User Interface)

CLua's graphical interface is built on Terminal.GUI 2.4.4 and is controlled from Lua through high-level factory functions defined in utils/elements.lua. These wrap the raw GUI.* C# calls and return element objects with methods for further manipulation.


📐 XYWH — Position and Size

Most factory functions accept a XYWH table for positioning:

XYWH(x, y, width, height)
local pos = XYWH(5, 2, 40, 10);

🪟 Windows

Windows are the top-level containers. Only one window is visible at a time.

local win = getWindow(name, visible, el)
Parameter Type Description
name string Title of the window
visible boolean Whether the window is shown on startup
--------- ---- -----------
el.schemeName string Name of the scheme to apply instead of the default
local mainWin = getWindow("Main Menu", true, {});

Switching windows

setActiveWindow(win)   -- global helper
win:SetActive()        -- method on the window element

Window methods

Method Description
el:SetVisible(bool) Show or hide the window
el:SetActive() Make this window visible and hide all others
el:ApplyScheme(schemeName) Apply a scheme to the element

🗂️ Frames

A frame is a bordered sub-container inside a window.

local frame = getFrame(parent, coors, name, el)
Parameter Type Description
parent element Parent element (can also be {ID=X} where X is the element's ID)
coors XYWH Position and size
name string Frame title
--------- ---- -----------
el.schemeName string Name of the scheme to apply instead of the default
local panel = getFrame(mainWin, XYWH(1, 1, 38, 8), "Settings", {});

📜 Scrollbox

A scrollable container.

local box = getScrollbox(parent, coors, el)
Parameter Type Description
parent element Parent element
coors XYWH Position and size
--------- ---- -----------
el.schemeName string Name of the scheme to apply instead of the default

🔘 Button

local btn = getButton(parent, coors, name, callback, el)
Parameter Type Description
parent element Parent window or frame
coors XYWH Position and size
name string Button label
callback string or function Called when the button is clicked
--------- ---- -----------
el.params table Arguments for function-type callbacks
el.schemeName string Name of the scheme to apply instead of the default

The callback can be:

  • A function: called directly; el.params are passed as arguments
  • A string: evaluated as Lua in the global scope on each click

Use "__self" inside el.params to refer to the button element itself:

local btn = getButton(mainWin, XYWH(5, 5, 20, 1), "Run", myFunction, {
    params = { "__self", "extraArg" }
});

Button method

btn:SetCallback(fn, ...)   -- change the callback after creation

🏷️ Label

A static text element.

local lbl = getLabel(parent, coors, text, el)
Parameter Type Description
parent element Parent element
coors XYWH Position and size
text string Label text
--------- ---- -----------
el.schemeName string Name of the scheme to apply instead of the default
local lbl = getLabel(mainWin, XYWH(2, 1, 30, 1), "Hello World", {});
lbl:SetText("Updated text");

📊 Progress Bar

local bar = getProgressBar(parent, coors, el)
Parameter Type Description
parent element Parent element
coors XYWH Position and size
--------- ---- -----------
el.schemeName string Name of the scheme to apply instead of the default

Note: only x, y, and width from the XYWH are used.

bar:SetProgress(0.5);   -- value between 0.0 and 1.0

☑️ Checkbox

local cb = getCheckbox(parent, coors, text, el)
Parameter Type Description
parent element Parent element
coors XYWH Position and size
text string Checkbox label
--------- ---- -----------
el.schemeName string Name of the scheme to apply instead of the default

Note: only x and y from the XYWH are used (size is automatic).

cb:SetChecked(true);
local state = cb:GetChecked();   -- returns boolean

🔵 Radio Group

local radio = getRadio(parent, coors, items, el)
Parameter Type Description
parent element Parent element
coors XYWH Position and size
items table or string Either a table of strings, or a comma-separated string
--------- ---- -----------
el.orientation string "vertical" (default) or "horizontal"
el.schemeName string Name of the scheme to apply instead of the default
local radio = getRadio(mainWin, XYWH(2, 3, 0, 0), {"Option A", "Option B", "Option C"}, {});
radio:SetRadioSelected(1);         -- select first option (1-based)
local sel = radio:GetRadioSelected();

✏️ TextField (single line)

local field = getTextField(parent, coors, text, el)
Parameter Type Description
parent element Parent element
coors XYWH Position and size
text string Field text
--------- ---- -----------
el.secret boolean Mask input (password field)
el.callback_keyup string or function Called on each key press
el.params table Extra parameters for the callback
el.schemeName string Name of the scheme to apply instead of the default

The callback_keyup accepts format tokens in both modes:

  • String callback: tokens are replaced inline — %k (key code), %c (char), %id (element ID)
  • Function callback with el.params: use token strings in the params table — replaced with actual values before the function is called:
    • "k%" → key code (number)
    • "c%" → character (string)
    • "id%" → element ID
    • "__self" → reference to the element itself
-- string callback with tokens
local field = getTextField(mainWin, XYWH(2, 5, 30, 1), "", {
    callback_keyup = "print('key: %k, char: %c')"
});

-- function callback with multiple params tokens
local field2 = getTextField(mainWin, XYWH(2, 8, 30, 1), "", {
    callback_keyup = function(key, char, self) print("key:", key, "char:", char) end,
    params = { "k%", "c%", "__self" }
});

field:GetText();
field:SetText("new value");
field:SetReadOnly(true);

📝 TextBox (multi-line)

local box = getTextBox(parent, coors, text, el)
Parameter Type Description
parent element Parent element
coors XYWH Position and size
text string Field text
--------- ---- -----------
el.readOnly boolean Read-only mode
el.callback_keyup string or function Called on each key press
el.params table Extra parameters for the callback
el.schemeName string Name of the scheme to apply instead of the default

callback_keyup supports tokens in both modes:

  • String callback: tokens are replaced inline — %k (key code), %c (char), %id (element ID)
  • Function callback with el.params: use token strings in the params table — replaced with actual values before the function is called:
    • "k%" → key code (number)
    • "c%" → character (string)
    • "id%" → element ID
    • "__self" → reference to the element itself
local box = getTextBox(mainWin, XYWH(2, 5, 40, 10), "", { readOnly = true });
box:SetText("Some content");

🔧 Common Element Methods

All elements (except Window) inherit from ElementClass:

Method Description
el:SetX(x) Set X position
el:SetY(y) Set Y position
el:SetW(w) Set width
el:SetH(h) Set height
el:SetXY(x, y) Set position
el:SetWH(w, h) Set size
el:SetXYWH(xywh) Set position and size from XYWH object
el:SetVisible(bool) Show or hide
el:SetText(str) Set text (Label, TextField, TextBox)
el:GetText() Get text (TextField, TextBox)
------ ---------------
el:SetColor(fg, bg) Set all color states at once (detaches from scheme)
el:SetColorNormal(fg, bg) Set Normal state color
el:SetColorFocus(fg, bg) Set Focus state color
el:SetColorHot(fg, bg) Set HotNormal + HotFocus colors
el:SetColorHotNormal(fg, bg) Set HotNormal color
el:SetColorHotFocus(fg, bg) Set HotFocus color
el:SetColorDisabled(fg, bg) Set Disabled color
el:SetColorHighlight(fg, bg) Set Highlight color
el:ApplyScheme(schemeName) Apply a named scheme to this element

🗑️ Destroying Elements

Elements can be removed from the GUI at runtime:

GUI.DestroyElement(el.ID)       -- removes the element and all its children
GUI.DestroyAllElements()        -- removes everything and clears the menu bar

DestroyElement takes the element's internal ID (el.ID), recursively removes all child elements, and cleans up any registered callbacks. DestroyAllElements removes all elements and clears the menu bar, but does not reset the Lua state.

local lbl = getLabel(win, XYWH(2, 1, 30, 1), "Temporary", {});
-- ... later:
GUI.DestroyElement(lbl.ID);

📋 Menu Bar

The top menu bar can be customized from Lua:

GUI.AddMenuItem("_File", "_Export", "setActiveWindow(exportWin)");
GUI.UpdateMenuItem("_File", "_Export", "New Label");
GUI.RemoveMenuItem("_File", "_Export");

The third argument is a string of Lua code that is executed when the menu item is clicked.

Note: AddMenuItem(...) is a global shorthand — you can call it without the GUI. prefix.


✍️ Example: Simple Window with a Button

local win = getWindow("My Tool", true, {});

local lbl = getLabel(win, XYWH(2, 1, 30, 1), "Press the button:", {});

local btn = getButton(win, XYWH(2, 3, 20, 1), "Run Macro", function()
    lbl:SetText("Running...");
    -- do work here
    lbl:SetText("Done!");
end, {});

-- Register the window in the menu bar
GUI.AddMenuItem("_File", "_My Tool", "setActiveWindow(win)");

-- Activate the window on startup
setActiveWindow(win);