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.paramsare 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);