Bedtime. /UI Components

UI Components

Ready-made widgets - buttons, meters, frames, images - drawn in the firmware's style

These sit one level above Graphics API: each is a small pile of primitives, so a tapp looks like it belongs on the device. They take the same gfx_t* and obey the same clip state; ui_draw_frame() and ui_draw_scrollbar() draw in colour 1 regardless of the current colour.

Sizes are mostly fixed by the design rather than by arguments - ui_draw_scrollbar()'s track is always 8px wide - so x/y place a known shape rather than defining one. Where a widget does take w/h, they are the outer bounds.

Images and animations

gfx_img_t comes out of the asset pipeline: drop a PNG or GIF in the tapp's assets/ folder and tapp-build compiles it into a gfx_img_t plus an extern declaration in the generated assets header. A GIF becomes a multi-frame image; ui_draw_anim() takes the frame index directly and wraps it, so drive it from os_tick_get() divided down to the desired frame rate - and return true from tick() while the animation is playing; otherwise no frames are scheduled for it. (Not ui_get_frame(): that counts paints, so it stalls as soon as frames stop being requested.)

ui_draw_img(gfx, 20, 20, &asset_logo);
ui_draw_anim(gfx, 120, 60, (uint16_t)(os_tick_get() / 80), &asset_dance_party);
ui_hints_set((const tapp_hint_cell_t[HintsActionsTotal]){[HintPress1] = {"play", gfx_icon(GfxIconPlay)}});
enum gfx_icon_id_t
GfxIconPlay0play triangle
GfxIconPause1pause bars
GfxIconRec2record dot
GfxIconPlayRev3reverse play
GfxIconRewind4rewind, double chevron
GfxIconFwd5fast forward
GfxIconRev6fast reverse
GfxIconLoopStart7loop in point
GfxIconLoopEnd8loop out point
GfxIconVolume9speaker
GfxIconVolumeMute10speaker, muted
GfxIconSos11sound-on-sound
GfxIconMic12microphone
GfxIconJack13line jack
GfxIconFx14effects
GfxIconWet15wet
GfxIconSpeed16varispeed
GfxIconChain17link
GfxIconBpm18tempo
GfxIconApply19tick
GfxIconBack20back arrow
GfxIconAdd21plus
GfxIconRemove22cross
GfxIconErase23erase
GfxIconEdit24edit
GfxIconCut25cut
GfxIconCopy26copy
GfxIconPaste27paste
GfxIconSplit28split
GfxIconBookmark29mark / save
GfxIconRedo30redo
GfxIconMenu31hamburger
GfxIconSettings32cog
GfxIconPower33power
GfxIconRandom34random
GfxIconTotal35
const gfx_img_t* gfx_icon(gfx_icon_id_t id)

One of the system glyphs

gfx_icon_id_tidWhich glyph

Returns — A firmware image, or NULL for an id this firmware does not know

enum gfx_anim_id_t
GfxAnimLoopToPlay0
GfxAnimTotal1how many this header knows - NOT an animation
const gfx_img_t* gfx_anim(gfx_anim_id_t id)

One of the system animations

gfx_anim_id_tidWhich animation

Returns — A firmware image with `frame_count > 1`, or NULL for an id this firmware does not know

ui_draw_anim(gfx, x, y, m->loop_frame, gfx_anim(GfxAnimLoopToPlay));
void ui_draw_img(gfx_t* gfx, gfx_coord_t x, gfx_coord_t y, const gfx_img_t* img)

Draw the first frame of an image at (x, y)

gfx_t*gfxGraphics context
gfx_coord_txLeft edge
gfx_coord_tyTop edge
const gfx_img_t*imgImage from the asset pipeline

Note — Transparent like gfx_draw_xbm(): 1 bits in the current colour, 0 bits left alone (gfx_set_bitmap_mode() makes it opaque).

void ui_draw_anim(gfx_t* gfx, gfx_coord_t x, gfx_coord_t y, uint16_t frame, const gfx_img_t* img)

Draw one frame of a multi-frame image

gfx_t*gfxGraphics context
gfx_coord_txLeft edge
gfx_coord_tyTop edge
uint16_tframeFrame index; wrapped modulo the image's frame count, so a free-running counter is fine
const gfx_img_t*imgImage from the asset pipeline
void ui_draw_scrollbar(gfx_t* gfx, gfx_coord_t x, gfx_coord_t y, uint16_t height, uint16_t pos, uint16_t total)

Vertical scrollbar with a proportional thumb

gfx_t*gfxGraphics context
gfx_coord_txLeft edge (the track is 8px wide)
gfx_coord_tyTop edge
uint16_theightTrack height in pixels
uint16_tposZero-based index of the selected item
uint16_ttotalNumber of items; 0 draws the empty track
void ui_draw_frame(gfx_t* gfx, gfx_coord_t x, gfx_coord_t y, uint16_t w, uint16_t h, uint16_t r, bool active)

Rounded outline, with a double ring when selected

gfx_t*gfxGraphics context
gfx_coord_txLeft edge
gfx_coord_tyTop edge
uint16_twWidth in pixels
uint16_thHeight in pixels
uint16_trCorner radius
boolactivetrue adds two outer rings - the firmware's selection cue. They grow *outward*, so leave 2px of margin around the frame.
void ui_draw_value_bar(gfx_t* gfx, gfx_coord_t x, gfx_coord_t y, uint16_t w, uint16_t h, uint32_t val, uint32_t min, uint32_t max)

Horizontal bar meter over an integer range

gfx_t*gfxGraphics context
gfx_coord_txLeft edge
gfx_coord_tyTop edge
uint16_twOuter width in pixels
uint16_thOuter height in pixels
uint32_tvalCurrent value
uint32_tminRange minimum
uint32_tmaxRange maximum
void ui_draw_value_bar_smallf(gfx_t* gfx, gfx_coord_t x, gfx_coord_t y, uint16_t w, uint16_t h, float val, float min, float max)

Slim float bar meter, drawn in the lower half of its box

gfx_t*gfxGraphics context
gfx_coord_txLeft edge
gfx_coord_tyTop edge
uint16_twOuter width in pixels
uint16_thOuter height in pixels - the bar itself is about an eighth of it
floatvalCurrent value
floatminRange minimum
floatmaxRange maximum
struct ui_roll_text_t

Mechanical rolling-TEXT state - split-flap style label animation.

char[UI_ROLL_TEXT_MAX]from
char[UI_ROLL_TEXT_MAX]tgt
float[UI_ROLL_TEXT_MAX]phase
uint8_tlen
uint8_tinited
bool ui_roll_text_draw(gfx_t* gfx, gfx_coord_t x_right, gfx_coord_t y, ui_roll_text_t* c, const char* value)

Draw a rolling label, right edge at x_right, baseline at y

gfx_t*gfx
gfx_coord_tx_right
gfx_coord_ty
ui_roll_text_t*c
const char*value

Uses the CURRENTLY-SET gfx font and color. Self-clocked: call once per frame from redraw() with the desired string - changed characters roll toward it, mid-flight changes re-aim without a jump. The first-ever draw seeds silently.

Returns — true while any character is still rolling

Note — This call advances the roll as it paints, so it only moves on painted frames - tick() must keep returning true until it reports false.

void ui_roll_text_snap(ui_roll_text_t* c, const char* value)
ui_roll_text_t*c
const char*value

Set the label instantly, no roll (e.g. when the thing being named changes identity).