Struct std::Widget
struct Widget {
int kind;
int x;
int y;
int w;
int h;
int prefW;
int prefH;
int stretch;
int alignment;
struct WidgetStyle style;
struct String text;
int visible;
int enabled;
int checked;
double sliderValue;
double sliderMin;
double sliderMax;
unsigned long caret;
int hover;
int pressed;
int focused;
?fn void(&Widget, ?&Erased) onClick;
?&Erased onClickData;
?fn void(&Widget, ?&Erased) onChange;
?&Erased onChangeData;
?fn void(&GuiWindow, &Widget) customDraw;
?fn void(&Widget, int, int, int, int) customLayout;
?fn int(&Widget, &GuiEvent) customEvent;
?&Erased userData;
struct Vec<&Widget> children;
?&Widget parent;
struct String name;
struct String tooltip;
struct String placeholder;
struct String shortcut;
int minW;
int minH;
int maxW;
int maxH;
int marginL;
int marginT;
int marginR;
int marginB;
int padL;
int padT;
int padR;
int padB;
int valign;
int gridRow;
int gridCol;
int gridRowSpan;
int gridColSpan;
int columns;
struct Vec<int> colStretch;
struct Vec<int> rowStretch;
double step;
int decimals;
int selected;
int orientation;
struct Vec<struct String> items;
struct Vec<struct WidgetTreeNode> nodes;
struct Vec<struct WidgetColumn> tableCols;
struct Vec<struct String> cells;
int rowCount;
float scrollX;
float scrollY;
float contentW;
float contentH;
unsigned long anchor;
float textScroll;
int password;
int readOnly;
int wrap;
int indeterminate;
double animPhase;
int open;
int textAlign;
const ?&GuiImage image;
int fit;
struct GuiColor color;
float hue;
float sat;
float val;
int dragPart;
float dragX;
float dragY;
double dragValue;
int hotIndex;
?fn void(&Widget, ?&Erased) onActivate;
?&Erased onActivateData;
?fn void(&Widget, &GuiCanvas, ?&Erased) onDraw;
?&Erased onDrawData;
?&Widget contextMenu;
?&Widget popup;
?&Widget owner;
?&struct GuiUi uiPtr;
int result;
int focusable;
double clickTime;
long tag;
}Fields
box, computed by layout() each frame (window pixels)
box, computed by layout() each frame (window pixels)
box, computed by layout() each frame (window pixels)
box, computed by layout() each frame (window pixels)
sizing hints (all optional — 0/unset means "size to content")
sizing hints (all optional — 0/unset means "size to content")
0 = natural size; >0 = flex weight along the parent box's main axis
WIDGET_ALIGN_* — this widget's position on the parent's cross axis
check box, toggle, checkable menu item
slider, progress, spinner, splitter (value)
text fields: the caret (a byte offset)
Callback/hook slots: typed functions over an erased context (see std/erased.h). The context's type is each caller's own — 'children' below holds buttons, sliders, labels, ... with unrelated userData types in one tree, which one generic Widget<T> couldn't — so the generic setters (on_click<T> & co.) store fn(?&T) / ?&T as fn(?&Erased) / ?&Erased, and every call passes the pair back together.
empty (null) for the root widget
find() looks widgets up by it
text fields, combo boxes
menu items: "Ctrl+S", "Ctrl+Shift+Z", "F5", "Delete"
logical; 0 = none
-1: use style.padding / the theme
stacks and grid cells: vertical alignment (-1: alignment)
grids: number of columns
grids: per column / per row stretch weights
slider/spinner increment (0 = continuous for sliders)
spinner/slider value display
radio, combo, list, tabs, table row, tree node (-1 = none)
WIDGET_HORIZONTAL / WIDGET_VERTICAL
radio, combo, list entries; tab titles
tree view
table: rows x columns, row-major
scroll offsets (pixels)
scrolled content size (pixels)
text fields: the other end of the selection
single-line text: horizontal scroll
labels, text areas: word wrap
progress bar: busy animation
combo / menu popup open
GUI_TEXT_LEFT/CENTER/RIGHT
image view (the widget doesn't own it)
WIDGET_FIT_*
color picker
what the pointer is dragging (internal)
hovered item / row / tab / menu entry (internal)
shown on right click
combo: its drop-down list; menu: its open submenu
popups/menus: the widget that opened it
the GuiUi this tree belongs to (root and overlays)
dialogs: GUI_RESULT_* when closed
-1 = by kind, 0 / 1 = forced
yours
Methods
All return a freshly heap-allocated, non-null widget — a region-less '&Widget' (see README's "Outliving references"), since nothing here cares whether the tree it ends up in is heap/stack/static/arena-owned. A widget is freed with its tree (free() on the root).
Two children (add them with add_child), side by side (WIDGET_HORIZONTAL) or one above the other, with a draggable divider. value() is the first child's share, 0..1.
Pages: add_tab(title, page).
Items with add_item(); selected() / set_selected().
static &Widget spinner(double minValue, double maxValue, double value, double step)source · definitionA modal dialog box with a title bar; add content and buttons as children (it's a column). Show it with GuiUi::show_modal().
generic<T> static &Widget canvas(fn void(&Widget, &GuiCanvas, ?&T) draw, ?&T userData)source · definitionA WIDGET_CANVAS: draw(widget, canvas, userData) paints it; the canvas is already translated to the widget's top-left and clipped to it, in logical units (scaled for the window).
generic<T> static &Widget custom(
fn void(&GuiWindow, &Widget) draw,
fn void(&Widget, int, int, int, int) layout,
fn int(&Widget, &GuiEvent) eventFn,
?&T userData,
)source · definitionA WIDGET_CUSTOM node drawn and laid out by your own functions (see "Custom widgets" below); userData is the caller's type, stored erased. The parameters are WidgetDrawFn / WidgetLayoutFn / WidgetCustomEventFn (declared after this struct), spelled out: a compiler without forward typedef resolution in struct-body declarations (before SafeC#43) can't match them to the definitions otherwise.
Inserts at 'index' (clamped).
Detaches 'child' (not freed: free() it, or add it elsewhere).
Removes and frees every child.
The first widget named 'name' in this subtree (depth first).
The GuiUi this widget's tree is attached to (null before the first render/dispatch or GuiUi::new).
Marks the widget's window for repainting (and relayout).
&Widget set_bg(unsigned char r, unsigned char g, unsigned char b, unsigned char a)source · definition&Widget set_fg(unsigned char r, unsigned char g, unsigned char b, unsigned char a)source · definition&Widget set_border(
unsigned char r,
unsigned char g,
unsigned char b,
unsigned char a,
int width,
)source · definitionBoth axes for stacks and grid cells (horizontal, vertical).
TrueType font size (logical px) and weight for this widget's text.
Grid placement (and spans of 1 or more cells).
slider / progress / spinner / splitter; clamped to the range, rounded to 'step' when it's > 0. Setting a value doesn't fire on_change.
check box / toggle / menu item
items of radio groups, combo boxes and list views
"" out of range
tabs
tree views: a node under 'parent' (-1: top level); returns its index
table views
returns the row index
text fields: the selection (byte offsets, start <= end)
image views
color pickers
menu items: the shortcut shown and triggered ("Ctrl+O", "Ctrl+Shift+S", "F2", "Delete"; Ctrl means Command on macOS)
dialogs: closes it (GuiUi::close_modal) with 'result'
cb(widget, userData). userData's type is the caller's; the widget stores it erased (see the field comment above).
Positions this widget and its whole subtree within the box (x,y,w,h) — window pixels.
Lays the tree out to the window's size and paints it into 'win'. (A tree that's already laid out to another box — layout() called with a box not at the window's origin — keeps that box.)
Routes one event through the tree rooted here: hover/pressed/focus state, clicks, value changes, text editing, scrolling, popups, and a WIDGET_CUSTOM node's customEvent hook. Returns 1 if some widget consumed the event.
After that, for GUI_EVENT_KEY_DOWN, a default action runs — the same idea as a browser's default DOM action for a key event — unless ev.prevent_default() (see gui.h) was called on this event first (typically from a WIDGET_CUSTOM node's WidgetCustomEventFn, the one hook that gets the raw GuiEvent* and can act before the default fires):
Tab / Shift+Tab moves focus to the next/previous focusable widget (wraps around)
Enter / Space activates the focused widget (button click / check box toggle)
Escape closes a popup or dialog, or clears focus
Left/Right nudges a focused slider by 5% of its range (or its step)
These are genuinely default actions: they still run even if dispatch already returned 1 for this event (e.g. a focused text input consuming Backspace doesn't block Tab from later moving focus off it).
Recursively frees this widget and its whole subtree (children, text, style, context menu), including the widget's own allocation. Detach it from its parent first (remove_child) when it has one.
= drop()