Skip to content

UXColorList

UXColorList maps names to colours. In shape it is NSColorList plus AppKit’s semantic colours.

#use <UXKit> // or #import "UXColorList.xc"
UXColorList* theme = UXColorList.defaultTheme();
theme.color((u8*)"windowBackground");
theme.color((u8*)"accent");
theme.colorOr((u8*)"gridLine", UXColor.gray()); // with a fallback

A widget that hardcodes a pen cannot be re-themed. One that asks for "controlFace" gets whatever the theme says, and swapping the theme restyles the whole interface without touching a control.

They say what a colour is for, not what it looks like:

name
windowBackgroundbehind everything
controlFacea button’s body
controlShadow / controlHighlightits bevel
text / disabledTextlabel text, and the greyed version
accentthe system’s highlight colour
selectionFill / selectedTexta selected row
separatora divider line

Use "text", not "black". A dark theme sets text to white and every label follows; a colour named black would be wrong in that theme.

UXColorList* mine = UXColorList.defaultTheme();
mine.set((u8*)"accent", UXColor.rgb(200, 30, 30));

There is no separate override mechanism. set replaces the entry for a name, and every lookup finds the entry for that name.

An application can also invent names of its own. "gridLine" is no different in kind from "accent"; only the default theme’s own entries are shipped.

theme.has((u8*)"gridLine"); // false
theme.color((u8*)"gridLine"); // 0
theme.colorOr((u8*)"gridLine", UXColor.gray()); // gray

color returns null for a name that is not there, so a typo gives a null rather than a wrong colour. Use colorOr in drawing code: a widget can ask for an optional refinement and fall back without a branch.

This is also how an application adds a name that older themes lack: ask with a fallback, and an old theme uses the fallback.

defaultTheme · set · color · colorOr · has · count

static UXColorList* defaultTheme(void)

The shipped semantic set, made on first use. A shared singleton; see the caution.

void set(u8* name, UXColor* color)

Add or replace. The name is kept, not copied: pass a literal or a UXStr.dup.

The colour is shared rather than copied. This is safe because UXColor is treated as immutable everywhere.

UXColor* color(u8* name)

The colour, or null.

UXColor* colorOr(u8* name, UXColor* fallback)

The colour, or the fallback. Drawing code should use this.

bool has(u8* name)
i32 count(void)

The number of entries. With UXColorEntry, this is how a theme editor enumerates what it can change.

Lookup is a linear scan comparing names by content. A theme has a couple of dozen entries, so this is faster than a hash and simpler.

A colour looked up inside a per-pixel loop costs a string comparison per pixel. Look colours up once, at the top of a draw.

  • A plain class (not an Object subclass)