The widget set
The retained widget tree
A widget is a node in a retained tree with two-phase layout: measure (how big do I want to be, given an available width) then arrange (here is your final rect). A WidgetView hosts the tree inside a region, lays it out, draws it, and routes events with a capture slot for modal drags and a focus slot for typing.
struct Widget {
virtual Size measure(const Theme&, float availW) = 0;
virtual void arrange(const Theme&, Rect);
virtual void draw(gpu::Canvas&, const Theme&) = 0;
virtual bool handle(const Event&) { return false; }
};
The control set
The toolkit ships the controls a real application needs, each drawn through the theme (no hardcoded colours) and acting on synthesized intent:
- Buttons & inputs —
Button,IconButton,Checkbox,Toggle,IconToggle,Slider,NumberField(drag-to-scrub or click-to-type),TextField,SearchField,Stepper. - Choosers —
Dropdown,RadioGroup,SegmentedControl,ColorSwatch(opens a colour picker). - Chrome —
Title,Separator,StatusBar,ProgressBar,Toolbar,TabBar,MenuBar. - Overlays —
MenuPopup(with cascading submenus, shortcut hints, option boxes), context menus,DialogPopup(modal),ColorPickerPopup. - Rich — lists, trees and tables, an editable text editor, and curve/ramp editors.
Construction without ceremony
Widgets are built through the Build.h factories so a tree is one readable expression — containers take their children directly, leaves configure up front, and there is no make_unique, static_cast, or move at the call site:
auto panel = column(
title("Transform"),
field("Position", numberField(0.0f)),
field("Visible", checkbox(true)),
row(flex(button("Cancel"), 1), flex(button("Apply"), 2)));
flex(child, weight) weights a row child; cfg(widget, fn) tweaks any extra knob in place. This parsimony is the toolkit's house style: the common thing is short, and the easy way is the safe way.
Acting on intent
Momentary controls fire on a clean Click (press + release with no drag), so pressing a button and dragging away cancels it — the desktop-correct behaviour. Drags begin on the first Drag event past the threshold (a NumberField scrub, a list reorder). Because the event-value model synthesizes this uniformly, every widget agrees on what a click is. Hover, active and focused states are tracked per widget and drawn through the theme, so the whole set restyles at once when the theme changes.