feat(l2): light theme reworked - a tint for selected, grey values, quiet edges

The light theme read as the dark one inverted. Now something selected (a
tab, a segment, a tile, Fav) is a tint of the accent with the accent's text
(SEL_*), the full accent fill stays for the primary action; setting values
read in grey (VALUE); popups, the banner and the toast have a quiet grey edge
(EDGE), the toast is a dark pill; neutral greys the RGB565 panel keeps
neutral; the big clock graphite.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-10-14 23:24:46 +02:00
co-authored by Claude Opus 5.5
parent 76e96f7eaa
commit 743500761a
7 changed files with 71 additions and 38 deletions
@@ -100,9 +100,9 @@ void UITask::channelMenu(int idx) {
}; };
for (auto& b : btns) { for (auto& b : btns) {
if (b.act == A_READ && !unread) continue; if (b.act == A_READ && !unread) continue;
lv_obj_t* bt = barButton(acts, b.text, onChanAction, b.act, b.act == A_FAV && chanctl::favourite(_prefs, idx)); lv_obj_t* bt = barButton(acts, b.text, onChanAction, b.act);
if (b.act == A_DELETE) s_del_lbl = lv_obj_get_child(bt, 0); if (b.act == A_DELETE) s_del_lbl = lv_obj_get_child(bt, 0);
if (b.act == A_FAV) s_fav_btn = bt; if (b.act == A_FAV) { s_fav_btn = bt; styleSelected(bt, chanctl::favourite(_prefs, idx)); }
} }
} }
@@ -124,7 +124,7 @@ void UITask::channelAction(uint8_t act) {
bool on = !chanctl::favourite(_prefs, idx); bool on = !chanctl::favourite(_prefs, idx);
chanctl::setFavourite(_prefs, idx, on); chanctl::setFavourite(_prefs, idx, on);
prefsSave(); prefsSave();
if (s_fav_btn) barButtonOn(s_fav_btn, on); if (s_fav_btn) styleSelected(s_fav_btn, on);
showToast(on ? "Added to favourites" : "Removed from favourites", 1200); showToast(on ? "Added to favourites" : "Removed from favourites", 1200);
if (_screen == SCR_CHATS) { buildChats(); channelMenu(idx); } // list order / star if (_screen == SCR_CHATS) { buildChats(); channelMenu(idx); } // list order / star
break; break;
@@ -185,7 +185,8 @@ void UITask::conversationMenu(const uint8_t* pub_key) {
} }
lv_obj_t* acts = buttonBar(panel); lv_obj_t* acts = buttonBar(panel);
s_fav_btn = barButton(acts, UI_SYMBOL_STAR " Fav", onConvAction, A_FAV, contactctl::favourite(ci)); s_fav_btn = barButton(acts, UI_SYMBOL_STAR " Fav", onConvAction, A_FAV);
styleSelected(s_fav_btn, contactctl::favourite(ci));
if (!room && _core->dmUnread(ci.id.pub_key) > 0) barButton(acts, LV_SYMBOL_OK " Read", onConvAction, A_READ, false); if (!room && _core->dmUnread(ci.id.pub_key) > 0) barButton(acts, LV_SYMBOL_OK " Read", onConvAction, A_READ, false);
barButton(acts, UI_SYMBOL_TACK, onConvAction, A_PIN, favslots::findContact(_prefs, ci.id.pub_key) >= 0); barButton(acts, UI_SYMBOL_TACK, onConvAction, A_PIN, favslots::findContact(_prefs, ci.id.pub_key) >= 0);
if (room) { if (room) {
@@ -208,7 +209,7 @@ void UITask::conversationAction(uint8_t act) {
case A_FAV: { case A_FAV: {
bool on = !contactctl::favourite(ci); bool on = !contactctl::favourite(ci);
if (!contactctl::setFavourite(ci.id.pub_key, on)) break; if (!contactctl::setFavourite(ci.id.pub_key, on)) break;
if (s_fav_btn) barButtonOn(s_fav_btn, on); if (s_fav_btn) styleSelected(s_fav_btn, on);
showToast(on ? "Added to favourites" : "Removed from favourites", 1200); showToast(on ? "Added to favourites" : "Removed from favourites", 1200);
if (_screen == SCR_CHATS) { buildChats(); conversationMenu(s_key); } // star / filter if (_screen == SCR_CHATS) { buildChats(); conversationMenu(s_key); } // star / filter
break; break;
@@ -419,7 +419,7 @@ void UITask::setAccent(int idx) {
theme::setAccent(idx); theme::setAccent(idx);
lvport::saveAccent(theme::s_accent); lvport::saveAccent(theme::s_accent);
theme::install(lv_display_get_default()); theme::install(lv_display_get_default());
if (_toast) lv_obj_set_style_border_color(_toast, lv_color_hex(theme::ACCENT), 0); if (_toast) lv_obj_set_style_border_color(_toast, lv_color_hex(theme::EDGE), 0);
_status_sig[0] = '\0'; // icons in the accent rebuilt _status_sig[0] = '\0'; // icons in the accent rebuilt
refreshStatusBar(); refreshStatusBar();
pinRowRefresh(); // the page, kept at its bottom where this row is pinRowRefresh(); // the page, kept at its bottom where this row is
@@ -99,15 +99,15 @@ static void onPagesScrolled(lv_event_t* e) {
dotsSet(lv_obj_get_scroll_x(s_pages) > lv_obj_get_width(s_pages) / 2); dotsSet(lv_obj_get_scroll_x(s_pages) > lv_obj_get_width(s_pages) / 2);
} }
// A tile's look: on in the accent with dark text, off on the surface; // A tile's look: on in SEL_BG / SEL_FG (Theme.h), off on the surface;
// `dim`: nothing to switch on this device. // `dim`: nothing to switch on this device.
static void tileSet(int t, const char* icon, const char* cap, bool on, bool dim = false) { static void tileSet(int t, const char* icon, const char* cap, bool on, bool dim = false) {
const uint32_t fg = on ? theme::ON_ACCENT : dim ? theme::TEXT_MUTED : theme::TEXT; const uint32_t fg = on ? theme::SEL_FG : dim ? theme::TEXT_MUTED : theme::TEXT;
const uint8_t look = 1 | (on ? 2 : 0); const uint8_t look = 1 | (on ? 2 : 0);
if (s_look[t] != look) { // LVGL restyles, and redraws, on every set (the refresh is each second) if (s_look[t] != look) { // LVGL restyles, and redraws, on every set (the refresh is each second)
s_look[t] = look; s_look[t] = look;
lv_obj_set_style_bg_color(s_tile[t], lv_color_hex(on ? theme::ACCENT : theme::SURFACE), 0); lv_obj_set_style_bg_color(s_tile[t], lv_color_hex(on ? theme::SEL_BG : theme::SURFACE), 0);
lv_obj_set_style_bg_color(s_tile[t], lv_color_hex(on ? theme::mix(theme::ACCENT, theme::BG, 75) : theme::SURFACE_2), LV_STATE_PRESSED); lv_obj_set_style_bg_color(s_tile[t], lv_color_hex(on ? theme::SEL_PRESS : theme::SURFACE_2), LV_STATE_PRESSED);
} }
setText(s_icon[t], icon); setText(s_icon[t], icon);
setText(s_cap[t], cap); setText(s_cap[t], cap);
+30 -6
View File
@@ -14,7 +14,10 @@
// //
// Two themes, dark (the default) and light (Settings > Display > Theme). The // Two themes, dark (the default) and light (Settings > Display > Theme). The
// colours are set once, before anything is built (setLight()), so changing // colours are set once, before anything is built (setLight()), so changing
// the theme restarts the device. // the theme restarts the device. The light one isn't the dark one inverted:
// something selected is a tint of the accent with the accent's text (SEL_*),
// not a full accent fill -- that stays for the primary action and own
// bubbles -- values read in grey, and popups and banners have a quiet edge.
#include <src/themes/lv_theme_private.h> // lv_theme_t's fields, to layer a theme #include <src/themes/lv_theme_private.h> // lv_theme_t's fields, to layer a theme
namespace theme { namespace theme {
@@ -28,6 +31,12 @@ namespace theme {
static uint32_t TEXT_MUTED= 0x9A958C; static uint32_t TEXT_MUTED= 0x9A958C;
static uint32_t OK = 0x6FCF6F; // delivered / relayed static uint32_t OK = 0x6FCF6F; // delivered / relayed
static uint32_t FAIL = 0xE5534B; // not delivered static uint32_t FAIL = 0xE5534B; // not delivered
// Set from those by setAccent():
static uint32_t SEL_BG = 0xFFB000; // something selected / on: a tab, a segment, a tile
static uint32_t SEL_FG = 0x0B0B0D; // its text and icons
static uint32_t SEL_PRESS = 0xC08400; // it pressed
static uint32_t VALUE = 0xFFB000; // a setting's value (a choice, a typed value)
static uint32_t EDGE = 0xFFB000; // the edge of a popup, the banner, the toast
static bool s_light = false; static bool s_light = false;
// Spacing (px) // Spacing (px)
@@ -96,20 +105,34 @@ namespace theme {
if (idx < 0 || idx >= ACCENT_COUNT) idx = 0; if (idx < 0 || idx >= ACCENT_COUNT) idx = 0;
s_accent = idx; s_accent = idx;
ACCENT = s_light ? ACCENTS[idx].light : ACCENTS[idx].col; ACCENT = s_light ? ACCENTS[idx].light : ACCENTS[idx].col;
if (s_light) {
SEL_BG = mix(ACCENT, SURFACE, 20);
SEL_FG = mix(ACCENT, 0x000000, 78);
SEL_PRESS = mix(ACCENT, SURFACE, 32);
VALUE = TEXT_MUTED;
EDGE = SURFACE_2;
} else {
SEL_BG = ACCENT;
SEL_FG = ON_ACCENT;
SEL_PRESS = mix(ACCENT, BG, 75);
VALUE = ACCENT;
EDGE = ACCENT;
}
} }
// Before anything is built (the colours are copied into what is). // Before anything is built (the colours are copied into what is).
static void setLight(bool on) { static void setLight(bool on) {
s_light = on; s_light = on;
if (on) { if (on) {
BG = 0xF2F0EC; SURFACE = 0xFFFFFF; SURFACE_2 = 0xE2DFD9; // Neutral greys the panel's RGB565 keeps neutral (0xF3F3F1 came out pink).
ON_ACCENT = 0xFFFFFF; TEXT = 0x1C1B19; TEXT_MUTED = 0x6E6A62; BG = 0xEFEFEF; SURFACE = 0xFFFFFF; SURFACE_2 = 0xDEDEDE;
ON_ACCENT = 0xFFFFFF; TEXT = 0x1C1C1C; TEXT_MUTED = 0x6B6D6B;
OK = 0x2E9A3E; FAIL = 0xD23A32; OK = 0x2E9A3E; FAIL = 0xD23A32;
} }
setAccent(s_accent); setAccent(s_accent);
} }
// Over LVGL's default theme, for every widget: a checked button is // Over LVGL's default theme, for every widget: a checked button is
// "selected" (the accent, ON_ACCENT text), buttons // "selected" (SEL_BG, SEL_FG text), buttons
// have the card radius and give a little under the finger (the default // have the card radius and give a little under the finger (the default
// theme's transitions animate it both ways). Scrollbars are thin and hug // theme's transitions animate it both ways). Scrollbars are thin and hug
// the edge, inside the padding every panel and list has, instead of the // the edge, inside the padding every panel and list has, instead of the
@@ -137,7 +160,7 @@ namespace theme {
lv_style_set_transform_width(&s_press, -2); lv_style_set_transform_width(&s_press, -2);
lv_style_set_transform_height(&s_press, -2); lv_style_set_transform_height(&s_press, -2);
lv_style_init(&s_checked); lv_style_init(&s_checked);
lv_style_set_text_color(&s_checked, lv_color_hex(ON_ACCENT));
lv_style_init(&s_sbar); lv_style_init(&s_sbar);
lv_style_set_width(&s_sbar, 3); lv_style_set_width(&s_sbar, 3);
lv_style_set_pad_right(&s_sbar, 2); // vertical bar: 2 px off the edge lv_style_set_pad_right(&s_sbar, 2); // vertical bar: 2 px off the edge
@@ -145,7 +168,8 @@ namespace theme {
lv_style_set_pad_top(&s_sbar, RADIUS / 2); lv_style_set_pad_top(&s_sbar, RADIUS / 2);
lv_style_set_pad_left(&s_sbar, RADIUS / 2); lv_style_set_pad_left(&s_sbar, RADIUS / 2);
} }
lv_style_set_bg_color(&s_checked, lv_color_hex(ACCENT)); lv_style_set_bg_color(&s_checked, lv_color_hex(SEL_BG));
lv_style_set_text_color(&s_checked, lv_color_hex(SEL_FG));
lv_theme_t* base = lv_theme_default_init(disp, lv_color_hex(ACCENT), lv_color_hex(ACCENT), !s_light, THEME_FONT_BODY); lv_theme_t* base = lv_theme_default_init(disp, lv_color_hex(ACCENT), lv_color_hex(ACCENT), !s_light, THEME_FONT_BODY);
s_theme = *base; s_theme = *base;
lv_theme_set_parent(&s_theme, base); lv_theme_set_parent(&s_theme, base);
+10 -8
View File
@@ -524,14 +524,15 @@ static void bannerBuild() {
lv_obj_remove_flag(s_banner, LV_OBJ_FLAG_GESTURE_BUBBLE); lv_obj_remove_flag(s_banner, LV_OBJ_FLAG_GESTURE_BUBBLE);
lv_obj_set_size(s_banner, w - 12, LV_SIZE_CONTENT); lv_obj_set_size(s_banner, w - 12, LV_SIZE_CONTENT);
lv_obj_align(s_banner, LV_ALIGN_TOP_MID, 0, theme::STATUS_H + 2); lv_obj_align(s_banner, LV_ALIGN_TOP_MID, 0, theme::STATUS_H + 2);
lv_obj_set_style_bg_color(s_banner, lv_color_hex(theme::SURFACE_2), 0); // Raised off the page: lighter than it on the dark theme, white on the light.
lv_obj_set_style_bg_color(s_banner, lv_color_hex(theme::SURFACE), LV_STATE_PRESSED); lv_obj_set_style_bg_color(s_banner, lv_color_hex(theme::s_light ? theme::SURFACE : theme::SURFACE_2), 0);
lv_obj_set_style_border_color(s_banner, lv_color_hex(theme::ACCENT), 0); lv_obj_set_style_bg_color(s_banner, lv_color_hex(theme::s_light ? theme::SURFACE_2 : theme::SURFACE), LV_STATE_PRESSED);
lv_obj_set_style_border_color(s_banner, lv_color_hex(theme::EDGE), 0);
lv_obj_set_style_border_width(s_banner, 1, 0); lv_obj_set_style_border_width(s_banner, 1, 0);
lv_obj_set_style_radius(s_banner, theme::RADIUS, 0); lv_obj_set_style_radius(s_banner, theme::RADIUS, 0);
lv_obj_set_style_shadow_width(s_banner, 12, 0); lv_obj_set_style_shadow_width(s_banner, 12, 0);
lv_obj_set_style_shadow_color(s_banner, lv_color_hex(0x000000), 0); lv_obj_set_style_shadow_color(s_banner, lv_color_hex(0x000000), 0);
lv_obj_set_style_shadow_opa(s_banner, LV_OPA_60, 0); lv_obj_set_style_shadow_opa(s_banner, theme::s_light ? LV_OPA_20 : LV_OPA_60, 0);
lv_obj_set_style_pad_all(s_banner, 8, 0); lv_obj_set_style_pad_all(s_banner, 8, 0);
lv_obj_set_style_pad_column(s_banner, 10, 0); lv_obj_set_style_pad_column(s_banner, 10, 0);
lv_obj_set_flex_flow(s_banner, LV_FLEX_FLOW_ROW); lv_obj_set_flex_flow(s_banner, LV_FLEX_FLOW_ROW);
@@ -644,14 +645,15 @@ void UITask::buildStatusBar() {
lv_obj_remove_flag(_toast, LV_OBJ_FLAG_SCROLLABLE); lv_obj_remove_flag(_toast, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_remove_flag(_toast, LV_OBJ_FLAG_CLICKABLE); lv_obj_remove_flag(_toast, LV_OBJ_FLAG_CLICKABLE);
lv_obj_set_size(_toast, LV_SIZE_CONTENT, LV_SIZE_CONTENT); lv_obj_set_size(_toast, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
lv_obj_set_style_bg_color(_toast, lv_color_hex(theme::SURFACE_2), 0); // On the light theme a dark pill, as a phone's: a light one was lost on the page.
lv_obj_set_style_border_color(_toast, lv_color_hex(theme::ACCENT), 0); lv_obj_set_style_bg_color(_toast, lv_color_hex(theme::s_light ? theme::TEXT : theme::SURFACE_2), 0);
lv_obj_set_style_border_width(_toast, 1, 0); lv_obj_set_style_border_color(_toast, lv_color_hex(theme::EDGE), 0);
lv_obj_set_style_border_width(_toast, theme::s_light ? 0 : 1, 0);
lv_obj_set_style_radius(_toast, theme::RADIUS, 0); lv_obj_set_style_radius(_toast, theme::RADIUS, 0);
lv_obj_set_style_pad_hor(_toast, 12, 0); lv_obj_set_style_pad_hor(_toast, 12, 0);
lv_obj_set_style_pad_ver(_toast, 6, 0); lv_obj_set_style_pad_ver(_toast, 6, 0);
lv_obj_align(_toast, LV_ALIGN_TOP_MID, 0, theme::STATUS_H + 4); // slides down from under the status bar lv_obj_align(_toast, LV_ALIGN_TOP_MID, 0, theme::STATUS_H + 4); // slides down from under the status bar
lv_obj_t* tl = label(_toast, "", THEME_FONT_BODY, theme::TEXT); lv_obj_t* tl = label(_toast, "", THEME_FONT_BODY, theme::s_light ? theme::SURFACE : theme::TEXT);
lv_label_set_long_mode(tl, LV_LABEL_LONG_WRAP); // long texts wrap instead of running off the screen lv_label_set_long_mode(tl, LV_LABEL_LONG_WRAP); // long texts wrap instead of running off the screen
lv_obj_set_style_max_width(tl, lv_display_get_horizontal_resolution(NULL) - 40, 0); lv_obj_set_style_max_width(tl, lv_display_get_horizontal_resolution(NULL) - 40, 0);
lv_obj_set_style_text_align(tl, LV_TEXT_ALIGN_CENTER, 0); lv_obj_set_style_text_align(tl, LV_TEXT_ALIGN_CENTER, 0);
+20 -14
View File
@@ -346,7 +346,7 @@ static lv_obj_t* popupOpen(lv_obj_t* parent, PopFit fit, lv_obj_t*& overlay, int
} }
if (fit != POP_FIT) lv_obj_remove_flag(panel, LV_OBJ_FLAG_SCROLLABLE); if (fit != POP_FIT) lv_obj_remove_flag(panel, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_set_style_bg_color(panel, lv_color_hex(theme::BG), 0); lv_obj_set_style_bg_color(panel, lv_color_hex(theme::BG), 0);
lv_obj_set_style_border_color(panel, lv_color_hex(theme::ACCENT), 0); lv_obj_set_style_border_color(panel, lv_color_hex(theme::EDGE), 0);
lv_obj_set_style_border_width(panel, 1, 0); lv_obj_set_style_border_width(panel, 1, 0);
lv_obj_set_style_radius(panel, theme::RADIUS, 0); lv_obj_set_style_radius(panel, theme::RADIUS, 0);
lv_obj_set_style_pad_all(panel, theme::PAD, 0); lv_obj_set_style_pad_all(panel, theme::PAD, 0);
@@ -855,7 +855,7 @@ static lv_obj_t* choiceCreate(lv_obj_t* parent, const char* opts, int sel, const
Choice* ch = (Choice*)lv_malloc(sizeof(Choice)); Choice* ch = (Choice*)lv_malloc(sizeof(Choice));
memset(ch, 0, sizeof(*ch)); memset(ch, 0, sizeof(*ch));
snprintf(ch->title, sizeof(ch->title), "%s", title ? title : ""); snprintf(ch->title, sizeof(ch->title), "%s", title ? title : "");
ch->value = label(c, "", THEME_FONT_BODY, theme::ACCENT); ch->value = label(c, "", THEME_FONT_BODY, theme::VALUE);
lv_obj_set_style_max_width(ch->value, 140, 0); // a long value wraps (LONG_DOT mis-sizes with SIZE_CONTENT) lv_obj_set_style_max_width(ch->value, 140, 0); // a long value wraps (LONG_DOT mis-sizes with SIZE_CONTENT)
lv_obj_set_style_text_align(ch->value, LV_TEXT_ALIGN_RIGHT, 0); lv_obj_set_style_text_align(ch->value, LV_TEXT_ALIGN_RIGHT, 0);
label(c, LV_SYMBOL_DOWN, THEME_FONT_SMALL, theme::TEXT_MUTED); label(c, LV_SYMBOL_DOWN, THEME_FONT_SMALL, theme::TEXT_MUTED);
@@ -917,7 +917,7 @@ static lv_obj_t* rowValue(lv_obj_t* row, const char* text, lv_event_cb_t cb, voi
lv_obj_add_flag(c, LV_OBJ_FLAG_CLICKABLE); lv_obj_add_flag(c, LV_OBJ_FLAG_CLICKABLE);
lv_obj_set_ext_click_area(c, 10); lv_obj_set_ext_click_area(c, 10);
lv_obj_set_style_opa(c, LV_OPA_60, LV_STATE_PRESSED); lv_obj_set_style_opa(c, LV_OPA_60, LV_STATE_PRESSED);
label(c, text, THEME_FONT_BODY, theme::ACCENT); label(c, text, THEME_FONT_BODY, theme::VALUE);
label(c, LV_SYMBOL_EDIT, THEME_FONT_SMALL, theme::TEXT_MUTED); label(c, LV_SYMBOL_EDIT, THEME_FONT_SMALL, theme::TEXT_MUTED);
lv_obj_add_event_cb(c, cb, LV_EVENT_CLICKED, user); lv_obj_add_event_cb(c, cb, LV_EVENT_CLICKED, user);
return c; return c;
@@ -970,9 +970,9 @@ static lv_obj_t* segmented(lv_obj_t* parent, const char** map, int sel, int w, i
lv_obj_set_style_bg_opa(m, LV_OPA_TRANSP, 0); lv_obj_set_style_bg_opa(m, LV_OPA_TRANSP, 0);
lv_obj_set_style_border_width(m, 0, 0); lv_obj_set_style_border_width(m, 0, 0);
lv_obj_set_style_bg_color(m, lv_color_hex(item), LV_PART_ITEMS); lv_obj_set_style_bg_color(m, lv_color_hex(item), LV_PART_ITEMS);
lv_obj_set_style_bg_color(m, lv_color_hex(theme::ACCENT), LV_PART_ITEMS | LV_STATE_CHECKED); lv_obj_set_style_bg_color(m, lv_color_hex(theme::SEL_BG), LV_PART_ITEMS | LV_STATE_CHECKED);
lv_obj_set_style_text_color(m, lv_color_hex(theme::TEXT), LV_PART_ITEMS); lv_obj_set_style_text_color(m, lv_color_hex(theme::TEXT), LV_PART_ITEMS);
lv_obj_set_style_text_color(m, lv_color_hex(theme::ON_ACCENT), LV_PART_ITEMS | LV_STATE_CHECKED); lv_obj_set_style_text_color(m, lv_color_hex(theme::SEL_FG), LV_PART_ITEMS | LV_STATE_CHECKED);
lv_obj_set_style_text_font(m, THEME_FONT_SMALL, LV_PART_ITEMS); lv_obj_set_style_text_font(m, THEME_FONT_SMALL, LV_PART_ITEMS);
lv_obj_set_style_shadow_width(m, 0, LV_PART_ITEMS); lv_obj_set_style_shadow_width(m, 0, LV_PART_ITEMS);
lv_obj_set_style_radius(m, theme::RADIUS, LV_PART_ITEMS); lv_obj_set_style_radius(m, theme::RADIUS, LV_PART_ITEMS);
@@ -1024,8 +1024,8 @@ static void stylePrimary(lv_obj_t* b) {
lv_obj_set_style_text_color(lv_obj_get_child(b, i), lv_color_hex(theme::ON_ACCENT), 0); lv_obj_set_style_text_color(lv_obj_get_child(b, i), lv_color_hex(theme::ON_ACCENT), 0);
} }
// Something selected / on (a tab, a chip, a row): the accent with ON_ACCENT // Something selected / on (a tab, a chip, a row): SEL_BG with SEL_FG text
// text, or back to the surface with TEXT. Every label under it follows. // (Theme.h), or back to the surface with TEXT. Every label under it follows.
static void textUnder(lv_obj_t* o, uint32_t col) { static void textUnder(lv_obj_t* o, uint32_t col) {
for (uint32_t i = 0; i < lv_obj_get_child_count(o); i++) { for (uint32_t i = 0; i < lv_obj_get_child_count(o); i++) {
lv_obj_t* c = lv_obj_get_child(o, i); lv_obj_t* c = lv_obj_get_child(o, i);
@@ -1034,14 +1034,15 @@ static void textUnder(lv_obj_t* o, uint32_t col) {
} }
} }
static void styleSelected(lv_obj_t* b, bool on) { static void styleSelected(lv_obj_t* b, bool on) {
lv_obj_set_style_bg_color(b, lv_color_hex(on ? theme::ACCENT : theme::SURFACE), 0); lv_obj_set_style_bg_color(b, lv_color_hex(on ? theme::SEL_BG : theme::SURFACE), 0);
lv_obj_set_style_bg_color(b, lv_color_hex(on ? theme::mix(theme::ACCENT, theme::BG, 75) : theme::SURFACE_2), LV_STATE_PRESSED); lv_obj_set_style_bg_color(b, lv_color_hex(on ? theme::SEL_PRESS : theme::SURFACE_2), LV_STATE_PRESSED);
textUnder(b, on ? theme::ON_ACCENT : theme::TEXT); textUnder(b, on ? theme::SEL_FG : theme::TEXT);
} }
// A row of equal buttons at the foot of a popup or screen: buttonBar(), then // A row of equal buttons at the foot of a popup or screen: buttonBar(), then
// barButton() for each -- `accent` for the main action or one that's on // barButton() for each -- `accent` for the main action, in the full accent
// (barButtonOn() flips it later). Returns the button; its label is child 0. // (barButtonOn() flips it later; a button that is on, as Fav, takes
// styleSelected() instead). Returns the button; its label is child 0.
static lv_obj_t* buttonBar(lv_obj_t* parent) { static lv_obj_t* buttonBar(lv_obj_t* parent) {
lv_obj_t* bar = lv_obj_create(parent); lv_obj_t* bar = lv_obj_create(parent);
styleSurface(bar, theme::BG); styleSurface(bar, theme::BG);
@@ -1051,7 +1052,11 @@ static lv_obj_t* buttonBar(lv_obj_t* parent) {
lv_obj_set_style_pad_column(bar, theme::GAP, 0); lv_obj_set_style_pad_column(bar, theme::GAP, 0);
return bar; return bar;
} }
static void barButtonOn(lv_obj_t* b, bool on) { styleSelected(b, on); } static void barButtonOn(lv_obj_t* b, bool on) {
lv_obj_set_style_bg_color(b, lv_color_hex(on ? theme::ACCENT : theme::SURFACE), 0);
lv_obj_set_style_bg_color(b, lv_color_hex(on ? theme::mix(theme::ACCENT, theme::BG, 75) : theme::SURFACE_2), LV_STATE_PRESSED);
textUnder(b, on ? theme::ON_ACCENT : theme::TEXT);
}
static lv_obj_t* barButton(lv_obj_t* bar, const char* text, lv_event_cb_t cb, uintptr_t user, bool accent = false) { static lv_obj_t* barButton(lv_obj_t* bar, const char* text, lv_event_cb_t cb, uintptr_t user, bool accent = false) {
lv_obj_t* b = lv_button_create(bar); lv_obj_t* b = lv_button_create(bar);
lv_obj_set_height(b, 40); lv_obj_set_height(b, 40);
@@ -1264,7 +1269,8 @@ static lv_obj_t* create(lv_obj_t* parent) {
lv_obj_t* o = lv_obj_create(parent); lv_obj_t* o = lv_obj_create(parent);
lv_obj_remove_style_all(o); lv_obj_remove_style_all(o);
lv_obj_remove_flag(o, LV_OBJ_FLAG_CLICKABLE); lv_obj_remove_flag(o, LV_OBJ_FLAG_CLICKABLE);
lv_obj_set_style_text_color(o, lv_color_hex(theme::TEXT), 0); // Graphite on the light theme: that much black, that big, was heavy.
lv_obj_set_style_text_color(o, lv_color_hex(theme::s_light ? theme::mix(theme::TEXT, theme::BG, 80) : theme::TEXT), 0);
Text* t = (Text*)lv_malloc(sizeof(Text)); Text* t = (Text*)lv_malloc(sizeof(Text));
if (t) { snprintf(t->hm, sizeof(t->hm), "--:--"); t->sec[0] = 0; } if (t) { snprintf(t->hm, sizeof(t->hm), "--:--"); t->sec[0] = 0; }
lv_obj_set_user_data(o, t); lv_obj_set_user_data(o, t);