Themes & scale
A theme is data, not code
Every widget draws through a Theme — it never hardcodes a colour or a metric. A theme is data: one renderer (DataTheme) draws every widget from a ThemeData of fonts, metrics, a style mode, and a palette. Swap the data and the whole interface re-skins, live, with no widget code changed.
auto flat = ui::makeFlatTheme(font.get()); // built-in dark palette
auto irix = ui::makeThemeFromFile(device, "irix.theme", scale); // loaded from disk
view->setTheme(irix.get()); // re-skins immediately
Plain-text .theme files
A theme can live in a plain-text file of dotted key = value lines (with # comments and #RRGGBB[AA] colours), so designing a look is editing a file, not recompiling:
style.mode = bevel # bevel (Motif/IRIX) · rounded (flat) · square
font = Helvetica
font.px = 12
color.panel = #2b2f2b
color.accent = #4772b3
color.text = #e8ece8
The same widget tree renders as a flat dark theme, a retro beveled one, or a pixel-art skin purely by which ThemeData it is handed. The style mode changes how chrome is drawn (beveled vs rounded vs square); the palette and metrics fill in the rest.
Semantic colours
The palette is semantic, not a grab-bag: panel, accent, text, selectionText, rowHover, outline, gridLine, and so on. Widgets ask for the role they mean (t.selectionTextColor()), which is why a theme with a light accent still renders readable selected text — a class of bug that hardcoded white text would cause. Node-graph colours (nodeHeader, wire, socket) are part of the same data, so a node editor re-skins with everything else.
One scale factor
uiScale is a single number that scales every metric and font size together — the desktop "UI scale" setting. Metrics return base × uiScale; font sizes round to points × uiScale; and because the FontBook rasterizes at the requested size rather than scaling a bitmap, text stays crisp at any scale. ⌘= / ⌘− live-scale the whole UI in the Editor.
The upshot: look and density are configuration, owned by a file a designer can edit, not constants buried in widget code — which is exactly the separation the example apps lean on (Prism Pixel ships the pixel theme; the Editor defaults to a Blender-inspired dark one).