Slider Widget¶
The Slider is a draggable value control — a track with a knob, or a
min..max RANGE with two knobs. Init installs a theme-tracked 0..100 VALUE
slider at a default 200×44 size, wired for touch (drag or tap-to-set)
and keypad (focus + LEFT/RIGHT step) with no extra event wiring.
set_value() / set_range() drive the value and its scale;
ext->type = UGUI_SLIDER_TYPE_RANGE switches to a two-knob range control;
ext->orient = UGUI_SLIDER_VERT flips the whole layout to vertical,
remapping the keys automatically; colour and size are plain ext fields (no
dedicated setters), so a handful of assignments after init restyle the stock
widget completely.
Every example below is complete — the file-scope storage, the callbacks and
the build calls — beside the exact frame it renders on a 480×320 panel. Each
compiles against nothing but the released library: drop it into the
Application Skeleton and it runs as-is. The icons come from
inc/icons/, the lexend fonts from inc/fonts/ — both ship with the library.
Examples¶
Default Slider¶
Two calls make a working control: ugui_widget_slider_init() installs the whole look, size and event mask, and set_callback() hooks the value change. Tapping anywhere on the track sets the value directly; the live readout below tracks on_change()'s value.

/* --- widget IDs: only need to be unique within the screen (10+ leaves
* room for the IDs your app already uses, e.g. the root's) --- */
enum {
WDGT_ID_DEMO = 10, WDGT_ID_VALUE
};
/* --- fonts: each is DEFINED in inc/fonts/<name>.h — #include that
* header in exactly one .c of your app; elsewhere just: --- */
extern const ugui_font_t lexend_14pt_2bpp;
/* --- file-scope storage --- */
#if defined(UGUI_WIDGET_ENABLE_SLIDER)
static ugui_screen_t s_screen;
static ugui_widget_t s_root;
static ugui_widget_t s_slider;
static ugui_slider_ext_t s_slider_ext;
static ugui_widget_t s_value; /* live value readout under the slider */
static ugui_label_ext_t s_value_ext;
static char s_value_buf[16];
#endif
/* --- local helpers & event callbacks --- */
static void on_change(int16_t val_lo, int16_t val_hi, void* ctx)
{
(void)val_hi; (void)ctx;
printf("[slider.default] value -> %d\n", (int)val_lo);
(void)snprintf(s_value_buf, sizeof(s_value_buf), "%d", (int)val_lo);
ugui_label_set_text(&s_value, s_value_buf);
}
/* --- build it (in your screen's init) --- */
ugui_widget_slider_init(&s_root, &s_slider, &s_slider_ext);
ugui_widget_set_align(&s_slider, UGUI_ALIGN_CENTER, 0, -10);
ugui_widget_set_id(&s_slider, WDGT_ID_DEMO);
ugui_widget_slider_set_callback(&s_slider, on_change, NULL);
ugui_screen_add_widget(&s_screen, &s_slider);
#if UGUI_ENABLE_KEYPAD
ugui_screen_add_focus(&s_screen, &s_slider);
#endif
/* Live value readout, centred just below the slider. */
ugui_widget_label_init(&s_root, &s_value, &s_value_ext);
ugui_widget_set_area(&s_value, 0, (int16_t)((UGUI_SCREEN_H / 2) + 30),
(int16_t)UGUI_SCREEN_W, 22);
ugui_widget_set_id(&s_value, WDGT_ID_VALUE);
ugui_widget_label_set_style(&s_value, false, UGUI_THEME_BG, "0",
&lexend_14pt_2bpp, UGUI_THEME_TEXT, UGUI_ALIGN_CENTER, 1u);
ugui_screen_add_widget(&s_screen, &s_value);
Value vs Range, Vertical, Disabled¶
Left column: a plain VALUE slider, a RANGE slider (two knobs via set_value() + set_value_hi()), and a disabled row locked at a fixed value with a muted fill. Right column: the SAME value slider with ext->orient = UGUI_SLIDER_VERT — one field flips the whole layout.

/* --- widget IDs: only need to be unique within the screen (10+ leaves
* room for the IDs your app already uses, e.g. the root's) --- */
enum {
WDGT_ID_SLOT0 = 10, WDGT_ID_SLOT4, WDGT_ID_STATUS,
WDGT_ID_SLOT3, WDGT_ID_SLOT7, WDGT_ID_SLOT10
};
/* --- fonts: each is DEFINED in inc/fonts/<name>.h — #include that
* header in exactly one .c of your app; elsewhere just: --- */
extern const ugui_font_t lexend_14pt_2bpp;
/* --- file-scope storage --- */
#if defined(UGUI_WIDGET_ENABLE_SLIDER)
static ugui_screen_t s_screen;
static ugui_widget_t s_root;
static ugui_widget_t s_status; /* live readout */
static ugui_label_ext_t s_status_ext;
#define ROW_N 3u
static ugui_widget_t s_row_w [ROW_N];
static ugui_slider_ext_t s_row_ext[ROW_N];
static ugui_widget_t s_row_lbl[ROW_N];
static ugui_label_ext_t s_row_lbl_ext[ROW_N];
static const char* const k_row_label[ROW_N] = {
"Value 0..100", "Range 0..100", "Disabled (locked 70)"
};
static ugui_widget_t s_vert_w;
static ugui_slider_ext_t s_vert_ext;
static ugui_widget_t s_vert_lbl;
static ugui_label_ext_t s_vert_lbl_ext;
static ugui_widget_t s_vert_val;
static ugui_label_ext_t s_vert_val_ext;
#define ROW_X 10
#define ROW_W 280
#define LBL_H 18
#define SLD_H 40
#define ROW_STEP 72 /* LBL_H + SLD_H + 14px gap */
#define ROW0_Y ((int16_t)(38 + 4))
#define VCOL_X ((int16_t)(ROW_X + ROW_W + 40))
#define VCOL_W 44
#define VCOL_LBL_Y ROW0_Y
#define VCOL_SLD_Y ((int16_t)(VCOL_LBL_Y + LBL_H + 4))
#define VCOL_SLD_H 170
#define VCOL_VAL_Y ((int16_t)(VCOL_SLD_Y + VCOL_SLD_H + 6))
#define STATUS_H 26
#define STATUS_Y ((int16_t)(UGUI_SCREEN_H - STATUS_H - 10))
static char s_status_buf[48];
static char s_vert_buf[8];
#endif
/* --- local helpers & event callbacks --- */
static void on_row_change(int16_t val_lo, int16_t val_hi, void* ctx)
{
const char* name = (const char*)ctx;
if (val_hi != val_lo) {
(void)snprintf(s_status_buf, sizeof(s_status_buf), "%s: %d - %d",
name, (int)val_lo, (int)val_hi);
} else {
(void)snprintf(s_status_buf, sizeof(s_status_buf), "%s: %d", name, (int)val_lo);
}
ugui_label_set_text(&s_status, s_status_buf);
}
static void on_vert_change(int16_t val_lo, int16_t val_hi, void* ctx)
{
(void)val_hi; (void)ctx;
(void)snprintf(s_vert_buf, sizeof(s_vert_buf), "%d", (int)val_lo);
ugui_label_set_text(&s_vert_val, s_vert_buf);
}
static void add_label(ugui_widget_t* w, ugui_label_ext_t* ext, uint8_t id,
int16_t x, int16_t y, int16_t cw, int16_t ch,
const char* str, ugui_align_t align)
{
ugui_widget_label_init(&s_root, w, ext);
ugui_widget_set_area(w, x, y, cw, ch);
ugui_widget_set_id (w, id);
ugui_widget_label_set_style(w, false, UGUI_THEME_BG, str,
&lexend_14pt_2bpp, UGUI_THEME_TEXT, align, 1u);
ugui_screen_add_widget(&s_screen, w);
}
/* --- build it (in your screen's init) --- */
uint8_t i;
for (i = 0u; i < ROW_N; i++) {
int16_t lbl_y = (int16_t)(ROW0_Y + (int16_t)i * ROW_STEP);
int16_t sld_y = (int16_t)(lbl_y + LBL_H);
add_label(&s_row_lbl[i], &s_row_lbl_ext[i], (uint8_t)(WDGT_ID_SLOT0 + i),
ROW_X, lbl_y, ROW_W, LBL_H, k_row_label[i], UGUI_ALIGN_LEFT);
ugui_widget_slider_init(&s_root, &s_row_w[i], &s_row_ext[i]);
ugui_widget_set_area(&s_row_w[i], ROW_X, sld_y, ROW_W, SLD_H);
ugui_widget_set_id(&s_row_w[i], (uint8_t)(WDGT_ID_SLOT4 + i));
switch (i) {
case 1u: /* Range */
s_row_ext[i].type = (uint8_t)UGUI_SLIDER_TYPE_RANGE;
ugui_widget_slider_set_value(&s_row_w[i], 20);
ugui_widget_slider_set_value_hi(&s_row_w[i], 75);
ugui_widget_slider_set_callback(&s_row_w[i], on_row_change,
(void*)k_row_label[i]);
#if UGUI_ENABLE_KEYPAD
ugui_screen_add_focus(&s_screen, &s_row_w[i]);
#endif
break;
case 2u: /* Disabled, locked at 70 — muted colour signals the lock */
ugui_widget_slider_set_value(&s_row_w[i], 70);
s_row_ext[i].color_track_fill = UGUI_COLOR_GRAY;
ugui_widget_set_enabled(&s_row_w[i], false);
break;
default: /* case 0: plain default Value slider */
ugui_widget_slider_set_callback(&s_row_w[i], on_row_change,
(void*)k_row_label[i]);
#if UGUI_ENABLE_KEYPAD
ugui_screen_add_focus(&s_screen, &s_row_w[i]);
#endif
break;
}
ugui_screen_add_widget(&s_screen, &s_row_w[i]);
}
/* Live status bar across the foot. */
(void)snprintf(s_status_buf, sizeof(s_status_buf), "drag Value or Range - state lands here");
ugui_widget_label_init(&s_root, &s_status, &s_status_ext);
ugui_widget_set_area(&s_status, 10, STATUS_Y, (int16_t)(UGUI_SCREEN_W - 20), STATUS_H);
ugui_widget_set_id(&s_status, WDGT_ID_STATUS);
ugui_widget_label_set_style(&s_status, false, UGUI_THEME_BG, s_status_buf,
&lexend_14pt_2bpp, UGUI_THEME_ACCENT, UGUI_ALIGN_CENTER, 1u);
ugui_screen_add_widget(&s_screen, &s_status);
/* Right column: same VALUE slider, vertical orientation. */
add_label(&s_vert_lbl, &s_vert_lbl_ext, WDGT_ID_SLOT3,
VCOL_X, VCOL_LBL_Y, 90, LBL_H, "Vertical", UGUI_ALIGN_LEFT);
ugui_widget_slider_init(&s_root, &s_vert_w, &s_vert_ext);
ugui_widget_set_area(&s_vert_w, VCOL_X, VCOL_SLD_Y, VCOL_W, VCOL_SLD_H);
ugui_widget_set_id(&s_vert_w, WDGT_ID_SLOT7);
s_vert_ext.orient = (uint8_t)UGUI_SLIDER_VERT;
ugui_widget_slider_set_value(&s_vert_w, 50);
ugui_widget_slider_set_callback(&s_vert_w, on_vert_change, NULL);
ugui_screen_add_widget(&s_screen, &s_vert_w);
#if UGUI_ENABLE_KEYPAD
ugui_screen_add_focus(&s_screen, &s_vert_w);
#endif
add_label(&s_vert_val, &s_vert_val_ext, WDGT_ID_SLOT10,
(int16_t)(VCOL_X - 20), VCOL_VAL_Y, 90, 20, "50", UGUI_ALIGN_LEFT);
Colours, Sizes & Labels¶
Left: six sliders restyled through plain ext fields (there is no set_colors() helper) — fill colour, a custom deselected-track colour, and a custom knob colour each get a row. Right: the same widget at three knob/track sizes. Bottom: show_labels = 1 turns on the built-in min/max/current-value text under the track.

/* --- widget IDs: only need to be unique within the screen (10+ leaves
* room for the IDs your app already uses, e.g. the root's) --- */
enum {
WDGT_ID_SLOT0 = 10, WDGT_ID_SLOT18, WDGT_ID_SLOT8,
WDGT_ID_SLOT11, WDGT_ID_SLOT17
};
/* --- fonts: each is DEFINED in inc/fonts/<name>.h — #include that
* header in exactly one .c of your app; elsewhere just: --- */
extern const ugui_font_t lexend_14pt_2bpp;
/* --- file-scope storage --- */
#if defined(UGUI_WIDGET_ENABLE_SLIDER)
static ugui_screen_t s_screen;
static ugui_widget_t s_root;
#define COL_N 6u
static ugui_widget_t s_col_w [COL_N];
static ugui_slider_ext_t s_col_ext[COL_N];
static ugui_widget_t s_col_lbl[COL_N];
static ugui_label_ext_t s_col_lbl_ext[COL_N];
static const char* const k_col_name[COL_N] = {
"Accent", "Success", "Caution", "Alert", "Custom track", "Custom knob"
};
#define SIZE_N 3u
static ugui_widget_t s_size_w [SIZE_N];
static ugui_slider_ext_t s_size_ext[SIZE_N];
static ugui_widget_t s_size_lbl[SIZE_N];
static ugui_label_ext_t s_size_lbl_ext[SIZE_N];
static const char* const k_size_name [SIZE_N] = { "Small", "Medium", "Large" };
static const uint8_t k_size_kr [SIZE_N] = { 6u, 9u, 14u };
static const uint8_t k_size_delta[SIZE_N] = { 2u, 3u, 5u };
static const uint8_t k_size_thick[SIZE_N] = { 3u, 4u, 6u };
static const int16_t k_size_h [SIZE_N] = { 24, 32, 44 };
static ugui_widget_t s_lbl_w;
static ugui_slider_ext_t s_lbl_ext;
#define HDR_Y 38
#define COL_LBL_X 10
#define COL_LBL_W 74
#define COL_SLD_X ((int16_t)(COL_LBL_X + COL_LBL_W + 4))
#define COL_SLD_W 120
#define COL_SLD_H 26
#define COL_ROW0 ((int16_t)(HDR_Y + 24))
#define COL_STEP 34
#define SIZE_LBL_X ((int16_t)(COL_SLD_X + COL_SLD_W + 30))
#define SIZE_LBL_W 62
#define SIZE_SLD_X ((int16_t)(SIZE_LBL_X + SIZE_LBL_W + 4))
#define SIZE_SLD_W 140
#define LBL_DEMO_Y 260
#define LBL_DEMO_SLD_Y ((int16_t)(LBL_DEMO_Y + 18))
#define LBL_DEMO_W ((int16_t)(UGUI_SCREEN_W - 2 * 10))
#define LBL_DEMO_H 34
#endif
/* --- local helpers & event callbacks --- */
static void add_label(ugui_widget_t* w, ugui_label_ext_t* ext, uint8_t id,
int16_t x, int16_t y, int16_t cw, int16_t ch,
const char* str, ugui_align_t align)
{
ugui_widget_label_init(&s_root, w, ext);
ugui_widget_set_area(w, x, y, cw, ch);
ugui_widget_set_id (w, id);
ugui_widget_label_set_style(w, false, UGUI_THEME_BG, str,
&lexend_14pt_2bpp, UGUI_THEME_TEXT, align, 1u);
ugui_screen_add_widget(&s_screen, w);
}
/* --- build it (in your screen's init) --- */
ugui_color_t fill_col[COL_N];
ugui_color_t bg_col [COL_N];
ugui_color_t knob_col[COL_N];
int16_t init_val[COL_N];
fill_col[0] = UGUI_THEME_ACCENT; bg_col[0] = UGUI_THEME_BORDER; knob_col[0] = UGUI_THEME_ACCENT; init_val[0] = 65; /* Accent */
fill_col[1] = UGUI_THEME_OK; bg_col[1] = UGUI_THEME_BORDER; knob_col[1] = UGUI_THEME_ACCENT; init_val[1] = 65; /* Success */
fill_col[2] = ugui_color_hex(0xF5A623u); bg_col[2] = UGUI_THEME_BORDER; knob_col[2] = UGUI_THEME_ACCENT; init_val[2] = 65; /* Caution */
fill_col[3] = UGUI_THEME_CANCEL; bg_col[3] = UGUI_THEME_BORDER; knob_col[3] = UGUI_THEME_ACCENT; init_val[3] = 65; /* Alert */
/* Custom deselect: track_bg = slate blue, fill = cyan, shown mostly OFF. */
fill_col[4] = ugui_color_hex(0x22B8E6u);
bg_col [4] = ugui_color_hex(0x3A4A63u);
knob_col[4] = UGUI_THEME_ACCENT;
init_val[4] = 25;
/* Custom knob: gold knob on the plain Accent track. */
fill_col[5] = UGUI_THEME_ACCENT;
bg_col [5] = UGUI_THEME_BORDER;
knob_col[5] = ugui_color_hex(0xFFD24Du);
init_val[5] = 65;
uint8_t i;
for (i = 0u; i < COL_N; i++) {
int16_t row_y = (int16_t)(COL_ROW0 + (int16_t)i * COL_STEP);
add_label(&s_col_lbl[i], &s_col_lbl_ext[i], (uint8_t)(WDGT_ID_SLOT0 + i),
COL_LBL_X, row_y, COL_LBL_W, COL_SLD_H,
k_col_name[i], (ugui_align_t)(UGUI_ALIGN_LEFT | UGUI_ALIGN_V_CENTER));
ugui_widget_slider_init(&s_root, &s_col_w[i], &s_col_ext[i]);
ugui_widget_set_area(&s_col_w[i], COL_SLD_X, row_y, COL_SLD_W, COL_SLD_H);
ugui_widget_set_id(&s_col_w[i], (uint8_t)(WDGT_ID_SLOT18 + i));
s_col_ext[i].color_track_fill = fill_col[i];
s_col_ext[i].color_track_bg = bg_col[i];
s_col_ext[i].color_knob = knob_col[i];
ugui_widget_slider_set_value(&s_col_w[i], init_val[i]);
ugui_screen_add_widget(&s_screen, &s_col_w[i]);
#if UGUI_ENABLE_KEYPAD
ugui_screen_add_focus(&s_screen, &s_col_w[i]);
#endif
}
int16_t size_y = COL_ROW0;
for (i = 0u; i < SIZE_N; i++) {
int16_t row_h = k_size_h[i];
add_label(&s_size_lbl[i], &s_size_lbl_ext[i], (uint8_t)(WDGT_ID_SLOT8 + i),
SIZE_LBL_X, size_y, SIZE_LBL_W, row_h,
k_size_name[i], (ugui_align_t)(UGUI_ALIGN_LEFT | UGUI_ALIGN_V_CENTER));
ugui_widget_slider_init(&s_root, &s_size_w[i], &s_size_ext[i]);
ugui_widget_set_area(&s_size_w[i], SIZE_SLD_X, size_y, SIZE_SLD_W, row_h);
ugui_widget_set_id(&s_size_w[i], (uint8_t)(WDGT_ID_SLOT11 + i));
s_size_ext[i].knob_radius = k_size_kr[i];
s_size_ext[i].knob_press_delta = k_size_delta[i];
s_size_ext[i].track_thickness = k_size_thick[i];
ugui_widget_slider_set_value(&s_size_w[i], 55);
ugui_screen_add_widget(&s_screen, &s_size_w[i]);
#if UGUI_ENABLE_KEYPAD
ugui_screen_add_focus(&s_screen, &s_size_w[i]);
#endif
size_y = (int16_t)(size_y + row_h + 8);
}
ugui_widget_slider_init(&s_root, &s_lbl_w, &s_lbl_ext);
ugui_widget_set_area(&s_lbl_w, 10, LBL_DEMO_SLD_Y, LBL_DEMO_W, LBL_DEMO_H);
ugui_widget_set_id(&s_lbl_w, WDGT_ID_SLOT17);
s_lbl_ext.show_labels = 1u;
s_lbl_ext.label_font = &lexend_14pt_2bpp;
ugui_widget_slider_set_value(&s_lbl_w, 42);
ugui_screen_add_widget(&s_screen, &s_lbl_w);
#if UGUI_ENABLE_KEYPAD
ugui_screen_add_focus(&s_screen, &s_lbl_w);
#endif
Mixer Form¶
The realistic case: a card panel of five labeled faders (Volume, Bass, Treble, Balance — VALUE — and Crossover — RANGE), each carrying its row name as callback context so ONE handler formats every drag into the status bar at the foot.

/* --- widget IDs: only need to be unique within the screen (10+ leaves
* room for the IDs your app already uses, e.g. the root's) --- */
enum {
WDGT_ID_PANEL = 10, WDGT_ID_SLOT5, WDGT_ID_SLOT0,
WDGT_ID_STATUS
};
/* --- fonts: each is DEFINED in inc/fonts/<name>.h — #include that
* header in exactly one .c of your app; elsewhere just: --- */
extern const ugui_font_t lexend_14pt_2bpp;
/* --- file-scope storage --- */
#if defined(UGUI_WIDGET_ENABLE_SLIDER)
static ugui_screen_t s_screen;
static ugui_widget_t s_root;
static ugui_widget_t s_panel; /* card behind the rows */
static ugui_box_ext_t s_panel_ext;
static ugui_widget_t s_status; /* live readout */
static ugui_label_ext_t s_status_ext;
#define ROW_N 5u
static ugui_widget_t s_slider_w [ROW_N];
static ugui_slider_ext_t s_slider_ext[ROW_N];
static ugui_widget_t s_label [ROW_N];
static ugui_label_ext_t s_label_ext [ROW_N];
static const char* const k_row_label[ROW_N] = {
"Master Volume", "Bass", "Treble", "Balance", "Crossover"
};
static const uint8_t k_row_is_range[ROW_N] = { 0u, 0u, 0u, 0u, 1u };
static const int16_t k_row_min [ROW_N] = { 0, -12, -12, -50, 0 };
static const int16_t k_row_max [ROW_N] = { 100, 12, 12, 50, 100 };
static const int16_t k_row_init_lo [ROW_N] = { 70, 0, 0, 0, 30 };
static const int16_t k_row_init_hi [ROW_N] = { 70, 0, 0, 0, 70 };
#define STATUS_H 26
#define STATUS_Y ((int16_t)(UGUI_SCREEN_H - STATUS_H - 10))
#define PANEL_X 10
#define PANEL_Y ((int16_t)(38 + 4))
#define PANEL_W ((int16_t)(UGUI_SCREEN_W - 2 * 10))
#define PANEL_H ((int16_t)(STATUS_Y - PANEL_Y - 8))
#define ROW_STEP ((int16_t)(PANEL_H / (int16_t)ROW_N))
#define SLD_H 30
#define LBL_X ((int16_t)(PANEL_X + 12))
#define LBL_W 110
#define SLD_X ((int16_t)(LBL_X + LBL_W + 8))
#define SLD_W ((int16_t)(PANEL_X + PANEL_W - SLD_X - 12))
static char s_status_buf[48];
#endif
/* --- local helpers & event callbacks --- */
static void on_change(int16_t val_lo, int16_t val_hi, void* ctx)
{
const char* name = (const char*)ctx;
if (val_hi != val_lo) {
(void)snprintf(s_status_buf, sizeof(s_status_buf), "%s: %d - %d",
name, (int)val_lo, (int)val_hi);
} else {
(void)snprintf(s_status_buf, sizeof(s_status_buf), "%s: %d", name, (int)val_lo);
}
ugui_label_set_text(&s_status, s_status_buf);
}
static void add_label(ugui_widget_t* w, ugui_label_ext_t* ext, uint8_t id,
int16_t x, int16_t y, int16_t cw, int16_t ch,
const char* str, ugui_align_t align)
{
ugui_widget_label_init(&s_root, w, ext);
ugui_widget_set_area(w, x, y, cw, ch);
ugui_widget_set_id (w, id);
ugui_widget_label_set_style(w, false, UGUI_THEME_SURFACE, str,
&lexend_14pt_2bpp, UGUI_THEME_TEXT, align, 1u);
ugui_screen_add_widget(&s_screen, w);
}
/* --- build it (in your screen's init) --- */
/* Card panel behind the rows (display-only, added first so it sits under
* the sliders). */
ugui_widget_box_init(&s_root, &s_panel, &s_panel_ext);
ugui_widget_set_area(&s_panel, PANEL_X, PANEL_Y, PANEL_W, PANEL_H);
ugui_widget_set_id(&s_panel, WDGT_ID_PANEL);
ugui_widget_box_set_style(&s_panel, true, 6u, 1u, UGUI_THEME_SURFACE, UGUI_THEME_ACCENT);
ugui_widget_set_enabled(&s_panel, false);
ugui_screen_add_widget(&s_screen, &s_panel);
uint8_t i;
for (i = 0u; i < ROW_N; i++) {
int16_t row_y = (int16_t)(PANEL_Y + (int16_t)i * ROW_STEP
+ (ROW_STEP - SLD_H) / 2);
add_label(&s_label[i], &s_label_ext[i], (uint8_t)(WDGT_ID_SLOT5 + i),
LBL_X, row_y, LBL_W, SLD_H,
k_row_label[i], (ugui_align_t)(UGUI_ALIGN_LEFT | UGUI_ALIGN_V_CENTER));
ugui_widget_slider_init(&s_root, &s_slider_w[i], &s_slider_ext[i]);
ugui_widget_set_area(&s_slider_w[i], SLD_X, row_y, SLD_W, SLD_H);
ugui_widget_set_id(&s_slider_w[i], (uint8_t)(WDGT_ID_SLOT0 + i));
ugui_widget_slider_set_range(&s_slider_w[i], k_row_min[i], k_row_max[i]);
if (k_row_is_range[i] != 0u) {
s_slider_ext[i].type = (uint8_t)UGUI_SLIDER_TYPE_RANGE;
}
ugui_widget_slider_set_value(&s_slider_w[i], k_row_init_lo[i]);
if (k_row_is_range[i] != 0u) {
ugui_widget_slider_set_value_hi(&s_slider_w[i], k_row_init_hi[i]);
}
ugui_widget_slider_set_callback(&s_slider_w[i], on_change, (void*)k_row_label[i]);
ugui_screen_add_widget(&s_screen, &s_slider_w[i]);
#if UGUI_ENABLE_KEYPAD
ugui_screen_add_focus(&s_screen, &s_slider_w[i]);
#endif
}
/* Live status line across the foot. */
(void)snprintf(s_status_buf, sizeof(s_status_buf), "drag a fader to see it here");
ugui_widget_label_init(&s_root, &s_status, &s_status_ext);
ugui_widget_set_area(&s_status, 10, STATUS_Y, (int16_t)(UGUI_SCREEN_W - 20), STATUS_H);
ugui_widget_set_id(&s_status, WDGT_ID_STATUS);
ugui_widget_label_set_style(&s_status, false, UGUI_THEME_BG, s_status_buf,
&lexend_14pt_2bpp, UGUI_THEME_ACCENT, UGUI_ALIGN_CENTER, 1u);
ugui_screen_add_widget(&s_screen, &s_status);
From this widget to a working app
Everything above is the widget-specific code. The scaffolding it drops into — storage, HAL, main loop, display-mode bring-up — is the same for every app: copy it from the Application Skeleton.