cryptnox-pos 1.0.0
Standalone USDC payment terminal firmware (ESP32 + Cryptnox smart card)
Loading...
Searching...
No Matches
ui_theme.cpp
Go to the documentation of this file.
1/*
2 * SPDX-License-Identifier: LGPL-3.0-or-later
3 * Copyright (c) 2026 Cryptnox SA
4 */
5
11
12#include "ui_internal.h"
13
14/******************************************************************
15 * 3a. LVGL theme — extends the built-in default rather than replacing it
16 *
17 * Restyles the widgets not styled by hand (tab bar as a segmented control,
18 * thin scrollbars, sliders, fields, keys) to match the hand-drawn pills. A
19 * theme applies at creation, so every future tabview gets it too.
20 *
21 * Deliberately narrow: buttons, pills and cards are styled explicitly at each
22 * call site, and a theme fighting an explicit style depends on which ran last.
23 ******************************************************************/
24#define TAB_SEG_INSET 5 /* pill inset inside the 42px bar, top+bottom */
25#define TAB_SEG_GAP 4 /* gap between segments */
26#define SCROLLBAR_W 4 /* hairline, not the default block */
27
28static lv_theme_t s_theme;
29static lv_style_t s_st_tabbar; /* the bar the segments sit on */
30static lv_style_t s_st_tab; /* one segment, not selected */
31static lv_style_t s_st_tab_sel; /* the selected segment */
32static lv_style_t s_st_tabview; /* the tabview container itself */
33static lv_style_t s_st_scrollbar;
34static lv_style_t s_st_track; /* slider/arc/spinner background */
35static lv_style_t s_st_ink; /* their filled part and knob */
36static lv_style_t s_st_field; /* text entry */
37static lv_style_t s_st_key; /* one key of the keyboard */
38
39static void theme_styles_init(void)
40{
41 /* The bar stays white: the selected pill is the only ink. */
42 lv_style_init(&s_st_tabbar);
43 lv_style_set_bg_color(&s_st_tabbar, COL_BG);
44 lv_style_set_bg_opa(&s_st_tabbar, LV_OPA_COVER);
45 lv_style_set_border_width(&s_st_tabbar, 0);
46 lv_style_set_pad_ver(&s_st_tabbar, TAB_SEG_INSET);
47 lv_style_set_pad_hor(&s_st_tabbar, TAB_SEG_GAP);
48 lv_style_set_pad_column(&s_st_tabbar, TAB_SEG_GAP);
49
50 lv_style_init(&s_st_tab);
51 lv_style_set_bg_opa(&s_st_tab, LV_OPA_TRANSP);
52 lv_style_set_border_width(&s_st_tab, 0);
53 lv_style_set_radius(&s_st_tab, BTN_RADIUS);
54 lv_style_set_text_color(&s_st_tab, COL_DIM);
55 lv_style_set_text_font(&s_st_tab, &font_inter_14_medium);
56
57 /* Filled pill, same shape and colour (COL_ACTION) as the admin panel's
58 * action buttons. */
59 lv_style_init(&s_st_tab_sel);
60 lv_style_set_bg_color(&s_st_tab_sel, COL_ACTION);
61 lv_style_set_bg_opa(&s_st_tab_sel, LV_OPA_COVER);
62 lv_style_set_radius(&s_st_tab_sel, BTN_RADIUS);
63 lv_style_set_text_color(&s_st_tab_sel, COL_BG);
64 lv_style_set_border_width(&s_st_tab_sel, 0);
65
66 lv_style_init(&s_st_tabview);
67 lv_style_set_bg_color(&s_st_tabview, COL_BG);
68 lv_style_set_bg_opa(&s_st_tabview, LV_OPA_COVER);
69 lv_style_set_border_width(&s_st_tabview, 0);
70
71 lv_style_init(&s_st_scrollbar);
72 lv_style_set_bg_color(&s_st_scrollbar, COL_BORDER);
73 lv_style_set_bg_opa(&s_st_scrollbar, LV_OPA_COVER);
74 lv_style_set_radius(&s_st_scrollbar, LV_RADIUS_CIRCLE);
75 lv_style_set_width(&s_st_scrollbar, SCROLLBAR_W);
76 lv_style_set_pad_right(&s_st_scrollbar, 2);
77
78 /* Colour and radius only from here down — no size, pad or length: these
79 * widgets sit in hand-positioned layouts that moved geometry would break. */
80 lv_style_init(&s_st_track);
81 lv_style_set_bg_color(&s_st_track, COL_BORDER);
82 lv_style_set_bg_opa(&s_st_track, LV_OPA_COVER);
83 lv_style_set_radius(&s_st_track, LV_RADIUS_CIRCLE);
84 lv_style_set_arc_color(&s_st_track, COL_BORDER);
85
86 lv_style_init(&s_st_ink);
87 lv_style_set_bg_color(&s_st_ink, COL_ACCENT);
88 lv_style_set_bg_opa(&s_st_ink, LV_OPA_COVER);
89 lv_style_set_radius(&s_st_ink, LV_RADIUS_CIRCLE);
90 lv_style_set_arc_color(&s_st_ink, COL_ACCENT);
91 lv_style_set_border_width(&s_st_ink, 0);
92 lv_style_set_shadow_width(&s_st_ink, 0); /* software-rendered: not free */
93
94 /* A field is a filled grey rounded box, the pills' and cards' surface. */
95 lv_style_init(&s_st_field);
96 lv_style_set_bg_color(&s_st_field, COL_SURFACE);
97 lv_style_set_bg_opa(&s_st_field, LV_OPA_COVER);
98 lv_style_set_radius(&s_st_field, 10);
99 lv_style_set_border_width(&s_st_field, 0);
100 lv_style_set_text_color(&s_st_field, COL_TEXT);
101
102 /* White rounded keys on the grey field. */
103 lv_style_init(&s_st_key);
104 lv_style_set_bg_color(&s_st_key, COL_BG);
105 lv_style_set_bg_opa(&s_st_key, LV_OPA_COVER);
106 lv_style_set_radius(&s_st_key, 8);
107 lv_style_set_border_width(&s_st_key, 0);
108 lv_style_set_text_color(&s_st_key, COL_TEXT);
109}
110
111static void theme_apply(lv_theme_t *th, lv_obj_t *obj)
112{
113 LV_UNUSED(th);
114
115 lv_obj_add_style(obj, &s_st_scrollbar, LV_PART_SCROLLBAR);
116
117 if (lv_obj_check_type(obj, &lv_tabview_class)) {
118 lv_obj_add_style(obj, &s_st_tabview, LV_PART_MAIN);
119 return;
120 }
121
122 /* The tab bar is a button matrix, and so is the PIN pad; the parent tells
123 * them apart, so the keypad does not become a segmented control. */
124 if (lv_obj_check_type(obj, &lv_btnmatrix_class)) {
125 lv_obj_t *parent = lv_obj_get_parent(obj);
126 if ((parent != NULL) && lv_obj_check_type(parent, &lv_tabview_class)) {
127 lv_obj_add_style(obj, &s_st_tabbar, LV_PART_MAIN);
128 lv_obj_add_style(obj, &s_st_tab, LV_PART_ITEMS);
129 lv_obj_add_style(obj, &s_st_tab_sel,
130 LV_PART_ITEMS | LV_STATE_CHECKED);
131 }
132 return;
133 }
134
135 if (lv_obj_check_type(obj, &lv_slider_class)) {
136 lv_obj_add_style(obj, &s_st_track, LV_PART_MAIN);
137 lv_obj_add_style(obj, &s_st_ink, LV_PART_INDICATOR);
138 lv_obj_add_style(obj, &s_st_ink, LV_PART_KNOB);
139 } else if (lv_obj_check_type(obj, &lv_arc_class)
140 || lv_obj_check_type(obj, &lv_spinner_class)) {
141 lv_obj_add_style(obj, &s_st_track, LV_PART_MAIN);
142 lv_obj_add_style(obj, &s_st_ink, LV_PART_INDICATOR);
143 } else if (lv_obj_check_type(obj, &lv_textarea_class)) {
144 lv_obj_add_style(obj, &s_st_field, LV_PART_MAIN);
145 } else if (lv_obj_check_type(obj, &lv_keyboard_class)) {
146 lv_obj_add_style(obj, &s_st_field, LV_PART_MAIN);
147 lv_obj_add_style(obj, &s_st_key, LV_PART_ITEMS);
148 }
149}
150
157void theme_init(void)
158{
160
161 /* Re-initialised with the UI font: the one LVGL built it with is a
162 * Kconfig built-in, and every widget not styled by hand inherits it. */
163 lv_theme_t *base = lv_disp_get_theme(NULL);
164 base = lv_theme_default_init(NULL, base->color_primary, base->color_secondary,
165 LV_THEME_DEFAULT_DARK, &font_inter_14);
166 s_theme = *base;
167 lv_theme_set_parent(&s_theme, base);
168 lv_theme_set_apply_cb(&s_theme, theme_apply);
169 lv_disp_set_theme(NULL, &s_theme);
170}
lv_font_t font_inter_14
lv_font_t font_inter_14_medium
Private to the ui*.cpp files: the state and helpers they share.
#define COL_SURFACE
#define COL_DIM
#define BTN_RADIUS
#define COL_TEXT
#define COL_ACCENT
#define COL_BG
#define COL_ACTION
#define COL_BORDER
static lv_style_t s_st_ink
Definition ui_theme.cpp:35
static lv_style_t s_st_track
Definition ui_theme.cpp:34
static lv_style_t s_st_key
Definition ui_theme.cpp:37
static void theme_styles_init(void)
Definition ui_theme.cpp:39
static lv_style_t s_st_tab_sel
Definition ui_theme.cpp:31
static void theme_apply(lv_theme_t *th, lv_obj_t *obj)
Definition ui_theme.cpp:111
#define TAB_SEG_INSET
Definition ui_theme.cpp:24
static lv_theme_t s_theme
Definition ui_theme.cpp:28
#define SCROLLBAR_W
Definition ui_theme.cpp:26
static lv_style_t s_st_scrollbar
Definition ui_theme.cpp:33
static lv_style_t s_st_tabview
Definition ui_theme.cpp:32
static lv_style_t s_st_tab
Definition ui_theme.cpp:30
static lv_style_t s_st_tabbar
Definition ui_theme.cpp:29
static lv_style_t s_st_field
Definition ui_theme.cpp:36
void theme_init(void)
Install the theme. After lv_disp_drv_register(), before any object.
Definition ui_theme.cpp:157
#define TAB_SEG_GAP
Definition ui_theme.cpp:25