mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-11-01 10:21:59 +00:00
feat(l2): light theme
Settings > Display > Theme: Dark / Light (NVS mc_ui/light). The colour tokens are set once before anything is built, so a change restarts the device. Text on an accent fill is the new ON_ACCENT (it was BG, white in the light theme); each accent has a deeper hand-picked light variant that reads on white and takes white text. The map's empty-tile fill and grid and the areas' outlines follow the theme too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -68,14 +68,14 @@ static void onCalendarDraw(lv_event_t* e) {
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "%d", day);
|
||||
td.text = buf;
|
||||
td.color = lv_color_hex(today ? theme::BG : k % 7 >= 5 ? theme::TEXT_MUTED : theme::TEXT);
|
||||
td.color = lv_color_hex(today ? theme::ON_ACCENT : k % 7 >= 5 ? theme::TEXT_MUTED : theme::TEXT);
|
||||
lv_area_t la = { cx, cy + (ch - fh) / 2, cx + cw - 1, cy + (ch + fh) / 2 };
|
||||
lv_draw_label(layer, &td, &la);
|
||||
if (s_cal_marks & (1UL << (day - 1))) { // under the number
|
||||
lv_draw_rect_dsc_t md;
|
||||
lv_draw_rect_dsc_init(&md);
|
||||
md.radius = 1;
|
||||
md.bg_color = lv_color_hex(today ? theme::BG : theme::ACCENT);
|
||||
md.bg_color = lv_color_hex(today ? theme::ON_ACCENT : theme::ACCENT);
|
||||
lv_area_t ma = { cx + cw / 2 - 6, cy + ch - 2, cx + cw / 2 + 6, cy + ch - 1 };
|
||||
lv_draw_rect(layer, &md, &ma);
|
||||
}
|
||||
|
||||
@@ -404,12 +404,12 @@ void UITask::accentRow(lv_obj_t* body) { // a row of a group: the label over t
|
||||
lv_obj_t* sw = lv_button_create(row);
|
||||
lv_obj_set_size(sw, 32, 32);
|
||||
lv_obj_set_style_radius(sw, LV_RADIUS_CIRCLE, 0);
|
||||
lv_obj_set_style_bg_color(sw, lv_color_hex(theme::ACCENTS[i].col), 0);
|
||||
lv_obj_set_style_bg_color(sw, lv_color_hex(theme::s_light ? theme::ACCENTS[i].light : theme::ACCENTS[i].col), 0);
|
||||
bool cur = i == theme::s_accent;
|
||||
lv_obj_set_style_border_width(sw, cur ? 3 : 0, 0);
|
||||
lv_obj_set_style_border_color(sw, lv_color_hex(theme::TEXT), 0);
|
||||
lv_obj_add_event_cb(sw, onAccent, LV_EVENT_CLICKED, (void*)(uintptr_t)i);
|
||||
if (cur) lv_obj_center(label(sw, LV_SYMBOL_OK, THEME_FONT_SMALL, theme::BG));
|
||||
if (cur) lv_obj_center(label(sw, LV_SYMBOL_OK, THEME_FONT_SMALL, theme::ON_ACCENT));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -372,7 +372,7 @@ static void editTile(lv_obj_t* box, int pos) {
|
||||
lv_obj_set_style_bg_opa(b, LV_OPA_COVER, 0);
|
||||
lv_obj_set_style_bg_color(b, lv_color_hex(on ? theme::SURFACE_2 : theme::ACCENT), 0);
|
||||
lv_obj_align(b, LV_ALIGN_TOP_RIGHT, 2, -2);
|
||||
lv_obj_center(label(b, on ? LV_SYMBOL_MINUS : LV_SYMBOL_PLUS, THEME_FONT_SMALL, on ? theme::TEXT : theme::BG));
|
||||
lv_obj_center(label(b, on ? LV_SYMBOL_MINUS : LV_SYMBOL_PLUS, THEME_FONT_SMALL, on ? theme::TEXT : theme::ON_ACCENT));
|
||||
}
|
||||
} // namespace home
|
||||
|
||||
@@ -479,7 +479,7 @@ void UITask::buildHome() {
|
||||
lv_obj_set_style_bg_color(b, lv_color_hex(theme::ACCENT), 0);
|
||||
lv_obj_align(b, LV_ALIGN_BOTTOM_RIGHT, 0, 24);
|
||||
lv_obj_add_event_cb(b, home::onEditDone, LV_EVENT_CLICKED, NULL);
|
||||
lv_obj_center(label(b, "Done", THEME_FONT_SMALL, theme::BG));
|
||||
lv_obj_center(label(b, "Done", THEME_FONT_SMALL, theme::ON_ACCENT));
|
||||
}
|
||||
setHomePage(home::s_page);
|
||||
}
|
||||
@@ -635,7 +635,7 @@ void UITask::buildHomeMap(lv_obj_t* box) {
|
||||
using namespace home::mini;
|
||||
lv_obj_set_layout(box, LV_LAYOUT_NONE);
|
||||
s_area = lv_obj_create(box);
|
||||
styleSurface(s_area, 0x1A1A1E); // unloaded / missing tiles
|
||||
styleSurface(s_area, theme::SURFACE); // unloaded / missing tiles
|
||||
lv_obj_set_size(s_area, LV_PCT(100), LV_PCT(100));
|
||||
lv_obj_set_style_radius(s_area, theme::RADIUS, 0);
|
||||
lv_obj_set_style_clip_corner(s_area, true, 0);
|
||||
|
||||
@@ -1010,6 +1010,9 @@ static void setVectorOn(bool on) { nvs::putBool("mc_ui", "vector", on); }
|
||||
// Accent colour (Settings > Display): an index into theme::ACCENTS.
|
||||
static int loadAccent() { return nvs::getU8("mc_ui", "accent", 0); }
|
||||
static void saveAccent(int idx) { nvs::putU8("mc_ui", "accent", idx); }
|
||||
// Settings > Display > Theme: light (else dark), applied at start.
|
||||
static bool loadLight() { return nvs::getU8("mc_ui", "light", 0) != 0; }
|
||||
static void saveLight(bool on) { nvs::putU8("mc_ui", "light", on ? 1 : 0); }
|
||||
// Settings > Storage > Kept per conversation (an index into histstore::KEEP).
|
||||
static int loadHistKeep() { return nvs::getI8("mc_ui", "hkeep", -1); }
|
||||
static void saveHistKeep(int idx) { nvs::putI8("mc_ui", "hkeep", idx); }
|
||||
|
||||
@@ -119,7 +119,7 @@ static void drawLayer(lv_event_t* e) {
|
||||
lv_draw_rect_dsc_init(&d);
|
||||
d.bg_opa = LV_OPA_TRANSP;
|
||||
d.border_width = i == s_show ? 2 : 1;
|
||||
d.border_color = lv_color_hex(i == s_show ? theme::ACCENT : 0x9A958C);
|
||||
d.border_color = lv_color_hex(i == s_show ? theme::ACCENT : theme::TEXT_MUTED);
|
||||
d.border_opa = LV_OPA_COVER;
|
||||
lv_draw_rect(layer, &d, &r);
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ static void drawGrid(lv_event_t* e) {
|
||||
lv_obj_get_coords(o, &a);
|
||||
lv_draw_line_dsc_t d;
|
||||
lv_draw_line_dsc_init(&d);
|
||||
d.color = lv_color_hex(0x3C3C46);
|
||||
d.color = lv_color_hex(theme::SURFACE_2);
|
||||
d.width = 1;
|
||||
lv_layer_t* layer = lv_event_get_layer(e);
|
||||
int w = lv_area_get_width(&a), h = lv_area_get_height(&a);
|
||||
@@ -555,7 +555,7 @@ static void drawMarks(lv_event_t* e) {
|
||||
lv_draw_label_dsc_t bl;
|
||||
lv_draw_label_dsc_init(&bl);
|
||||
bl.font = THEME_FONT_SMALL;
|
||||
bl.color = lv_color_hex(theme::BG);
|
||||
bl.color = lv_color_hex(theme::ON_ACCENT);
|
||||
bl.align = LV_TEXT_ALIGN_CENTER;
|
||||
for (int k = 0; k < s_mark_count; k++) {
|
||||
const Mark& m = s_marks[k];
|
||||
@@ -759,7 +759,7 @@ void UITask::buildMap() {
|
||||
lv_obj_set_layout(body, LV_LAYOUT_NONE);
|
||||
lv_obj_set_style_pad_all(body, 0, 0);
|
||||
lv_obj_remove_flag(body, LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_set_style_bg_color(body, lv_color_hex(0x1A1A1E), 0); // unloaded / missing tiles
|
||||
lv_obj_set_style_bg_color(body, lv_color_hex(theme::SURFACE), 0); // unloaded / missing tiles
|
||||
lv_obj_set_style_bg_opa(body, LV_OPA_COVER, 0);
|
||||
lv_obj_add_event_cb(body, mapview::drawGrid, LV_EVENT_DRAW_MAIN_END, &mapview::s_grid);
|
||||
lv_obj_add_event_cb(body, mapview::tiledCovers, LV_EVENT_COVER_CHECK, &mapview::s_grid);
|
||||
|
||||
@@ -102,7 +102,7 @@ static void onPagesScrolled(lv_event_t* e) {
|
||||
// A tile's look: on in the accent with dark text, off on the surface;
|
||||
// `dim`: nothing to switch on this device.
|
||||
static void tileSet(int t, const char* icon, const char* cap, bool on, bool dim = false) {
|
||||
const uint32_t fg = on ? theme::BG : dim ? theme::TEXT_MUTED : theme::TEXT;
|
||||
const uint32_t fg = on ? theme::ON_ACCENT : dim ? theme::TEXT_MUTED : theme::TEXT;
|
||||
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)
|
||||
s_look[t] = look;
|
||||
|
||||
@@ -127,6 +127,14 @@ void UITask::setBrightnessPct(uint8_t pct, bool save) {
|
||||
if (save) prefsSave();
|
||||
}
|
||||
|
||||
// Every screen is built in the theme's colours: a new one starts afresh.
|
||||
static void onThemeChoice(lv_event_t* e) {
|
||||
const bool light = choiceSelected((lv_obj_t*)lv_event_get_target(e)) == 1;
|
||||
if (light == theme::s_light) return;
|
||||
lvport::saveLight(light);
|
||||
restartScreen(light ? "Starting in the light theme." : "Starting in the dark theme.");
|
||||
}
|
||||
|
||||
static void onTapWake(lv_event_t* e) {
|
||||
s_ui->setTapWake(lv_obj_has_state((lv_obj_t*)lv_event_get_target(e), LV_STATE_CHECKED));
|
||||
}
|
||||
@@ -158,7 +166,9 @@ void UITask::buildSchemaSettings() {
|
||||
g = group(body, "LOCK");
|
||||
schemaRow(g, SETTING(auto_lock));
|
||||
listRow(g, "Screen PIN", pinSet() ? "On - asked when the screen wakes" : "Off", onPinSetup, NULL);
|
||||
accentRow(group(body, "LOOK")); // DeviceScreen.h
|
||||
g = group(body, "LOOK");
|
||||
choiceRow(g, "Theme", "Changing it restarts the device", "Dark\nLight", theme::s_light ? 1 : 0, onThemeChoice);
|
||||
accentRow(g); // DeviceScreen.h
|
||||
return;
|
||||
}
|
||||
case PG_POWER: {
|
||||
|
||||
@@ -39,8 +39,8 @@ static void styleCell(int i, bool sel) {
|
||||
const bool hl = i == s_hl;
|
||||
lv_obj_set_style_bg_color(s_cells[i], lv_color_hex(hl ? theme::ACCENT : theme::SURFACE), 0);
|
||||
lv_obj_set_style_border_width(s_cells[i], sel ? 2 : 0, 0);
|
||||
setTextColor(lv_obj_get_child(s_cells[i], 0), hl ? theme::BG : theme::TEXT);
|
||||
setTextColor(lv_obj_get_child(s_cells[i], 1), hl ? theme::BG : theme::TEXT_MUTED);
|
||||
setTextColor(lv_obj_get_child(s_cells[i], 0), hl ? theme::ON_ACCENT : theme::TEXT);
|
||||
setTextColor(lv_obj_get_child(s_cells[i], 1), hl ? theme::ON_ACCENT : theme::TEXT_MUTED);
|
||||
}
|
||||
|
||||
// Moves the "sounding" light to note `idx` (-1: none).
|
||||
|
||||
@@ -462,7 +462,7 @@ static void usbPanel(const char* title, const char* text, bool buttons) {
|
||||
lv_obj_set_style_radius(b, theme::RADIUS, 0);
|
||||
lv_obj_set_style_bg_color(b, lv_color_hex(i ? theme::ACCENT : theme::SURFACE_2), 0);
|
||||
lv_obj_add_event_cb(b, onUsbTap, LV_EVENT_CLICKED, i ? (void*)1 : nullptr);
|
||||
lv_obj_center(label(b, i ? "USB drive" : "Keep card", THEME_FONT_BODY, i ? theme::BG : theme::TEXT));
|
||||
lv_obj_center(label(b, i ? "USB drive" : "Keep card", THEME_FONT_BODY, i ? theme::ON_ACCENT : theme::TEXT));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,25 +4,31 @@
|
||||
//
|
||||
// The accent (amber by default; Settings > Display > Accent colour)
|
||||
// on near-black, soft corners. The accent means one of three things:
|
||||
// - ACCENT fill, dark text: the primary action of a screen or popup
|
||||
// - ACCENT fill, ON_ACCENT text: the primary action of a screen or popup
|
||||
// (Download, Install, Save, Go) -- stylePrimary() in UITask.cpp -- and
|
||||
// something selected / on (a tab, a chip, a segment, a mode that is
|
||||
// running, own bubbles) -- styleSelected();
|
||||
// - ACCENT text or icon: a name, a count, a background mode, a value.
|
||||
// No accent mixed toward black for "selected": it came out brown.
|
||||
// Everything else is BG / SURFACE / SURFACE_2 with TEXT or TEXT_MUTED.
|
||||
//
|
||||
// Two themes, dark (the default) and light (Settings > Display > Theme). The
|
||||
// colours are set once, before anything is built (setLight()), so changing
|
||||
// the theme restarts the device.
|
||||
#include <src/themes/lv_theme_private.h> // lv_theme_t's fields, to layer a theme
|
||||
|
||||
namespace theme {
|
||||
// Colours (0xRRGGBB)
|
||||
static const uint32_t BG = 0x0B0B0D; // screen background
|
||||
static const uint32_t SURFACE = 0x1A1A1F; // cards, rows, bubbles (incoming)
|
||||
static const uint32_t SURFACE_2 = 0x27272E; // pressed / raised
|
||||
static uint32_t ACCENT = 0xFFB000; // primary actions, names, badges, modes (setAccent)
|
||||
static const uint32_t TEXT = 0xF2EEE6;
|
||||
static const uint32_t TEXT_MUTED= 0x9A958C;
|
||||
static const uint32_t OK = 0x6FCF6F; // delivered / relayed
|
||||
static const uint32_t FAIL = 0xE5534B; // not delivered
|
||||
// Colours (0xRRGGBB), the dark theme's; setLight() sets the light one's.
|
||||
static uint32_t BG = 0x0B0B0D; // screen background
|
||||
static uint32_t SURFACE = 0x1A1A1F; // cards, rows, bubbles (incoming)
|
||||
static uint32_t SURFACE_2 = 0x27272E; // pressed / raised
|
||||
static uint32_t ACCENT = 0xFFB000; // primary actions, names, badges, modes (setAccent)
|
||||
static uint32_t ON_ACCENT = 0x0B0B0D; // text and icons on an ACCENT fill
|
||||
static uint32_t TEXT = 0xF2EEE6;
|
||||
static uint32_t TEXT_MUTED= 0x9A958C;
|
||||
static uint32_t OK = 0x6FCF6F; // delivered / relayed
|
||||
static uint32_t FAIL = 0xE5534B; // not delivered
|
||||
static bool s_light = false;
|
||||
|
||||
// Spacing (px)
|
||||
static const int PAD = 8;
|
||||
@@ -67,11 +73,12 @@ namespace theme {
|
||||
#define UI_SYMBOL_SUN "\xEF\x86\x85" // U+F185, quick panel: brightness
|
||||
#define UI_SYMBOL_BULB "\xEF\x83\xAB" // U+F0EB, Flashlight
|
||||
|
||||
// Accent choices; the fill is the colour at 42% over the background.
|
||||
struct Accent { const char* name; uint32_t col; };
|
||||
// Accent choices: on the dark theme, and deeper on the light one, to read
|
||||
// as text on white and take white text on it.
|
||||
struct Accent { const char* name; uint32_t col, light; };
|
||||
static const Accent ACCENTS[] = {
|
||||
{ "Amber", 0xFFB000 }, { "Orange", 0xFF7A2E }, { "Coral", 0xFF6B7A },
|
||||
{ "Violet", 0xB18CFF }, { "Cyan", 0x3CC8E8 }, { "Lime", 0xB5E04A },
|
||||
{ "Amber", 0xFFB000, 0xC77800 }, { "Orange", 0xFF7A2E, 0xD9561A }, { "Coral", 0xFF6B7A, 0xD9455A },
|
||||
{ "Violet", 0xB18CFF, 0x7A55E0 }, { "Cyan", 0x3CC8E8, 0x0E8AA8 }, { "Lime", 0xB5E04A, 0x5E8A12 },
|
||||
};
|
||||
static const int ACCENT_COUNT = sizeof(ACCENTS) / sizeof(ACCENTS[0]);
|
||||
static int s_accent = 0;
|
||||
@@ -88,11 +95,21 @@ namespace theme {
|
||||
static void setAccent(int idx) {
|
||||
if (idx < 0 || idx >= ACCENT_COUNT) idx = 0;
|
||||
s_accent = idx;
|
||||
ACCENT = ACCENTS[idx].col;
|
||||
ACCENT = s_light ? ACCENTS[idx].light : ACCENTS[idx].col;
|
||||
}
|
||||
// Before anything is built (the colours are copied into what is).
|
||||
static void setLight(bool on) {
|
||||
s_light = on;
|
||||
if (on) {
|
||||
BG = 0xF2F0EC; SURFACE = 0xFFFFFF; SURFACE_2 = 0xE2DFD9;
|
||||
ON_ACCENT = 0xFFFFFF; TEXT = 0x1C1B19; TEXT_MUTED = 0x6E6A62;
|
||||
OK = 0x2E9A3E; FAIL = 0xD23A32;
|
||||
}
|
||||
setAccent(s_accent);
|
||||
}
|
||||
|
||||
// Over LVGL's default theme, for every widget: a checked button is
|
||||
// "selected" (the accent, dark text), buttons
|
||||
// "selected" (the accent, ON_ACCENT text), buttons
|
||||
// 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
|
||||
// the edge, inside the padding every panel and list has, instead of the
|
||||
@@ -120,7 +137,7 @@ namespace theme {
|
||||
lv_style_set_transform_width(&s_press, -2);
|
||||
lv_style_set_transform_height(&s_press, -2);
|
||||
lv_style_init(&s_checked);
|
||||
lv_style_set_text_color(&s_checked, lv_color_hex(BG));
|
||||
lv_style_set_text_color(&s_checked, lv_color_hex(ON_ACCENT));
|
||||
lv_style_init(&s_sbar);
|
||||
lv_style_set_width(&s_sbar, 3);
|
||||
lv_style_set_pad_right(&s_sbar, 2); // vertical bar: 2 px off the edge
|
||||
@@ -129,7 +146,7 @@ namespace theme {
|
||||
lv_style_set_pad_left(&s_sbar, RADIUS / 2);
|
||||
}
|
||||
lv_style_set_bg_color(&s_checked, lv_color_hex(ACCENT));
|
||||
lv_theme_t* base = lv_theme_default_init(disp, lv_color_hex(ACCENT), lv_color_hex(ACCENT), true, 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;
|
||||
lv_theme_set_parent(&s_theme, base);
|
||||
lv_theme_set_apply_cb(&s_theme, applyTheme);
|
||||
|
||||
@@ -289,9 +289,9 @@ static void msgLocButton(lv_obj_t* parent, const char* text, bool save, bool acc
|
||||
lv_obj_set_style_radius(b, theme::RADIUS, 0);
|
||||
lv_obj_set_style_shadow_width(b, 0, 0);
|
||||
// on our own amber bubble the main one goes dark instead
|
||||
lv_obj_set_style_bg_color(b, lv_color_hex(accent ? (own ? theme::BG : theme::ACCENT) : theme::SURFACE_2), 0);
|
||||
lv_obj_set_style_bg_color(b, lv_color_hex(accent ? (own ? theme::ON_ACCENT : theme::ACCENT) : theme::SURFACE_2), 0);
|
||||
lv_obj_add_event_cb(b, onMsgLoc, LV_EVENT_CLICKED, (void*)(uintptr_t)(save ? 1 : 0));
|
||||
lv_obj_center(label(b, text, THEME_FONT_SMALL, accent ? (own ? theme::ACCENT : theme::BG) : theme::TEXT));
|
||||
lv_obj_center(label(b, text, THEME_FONT_SMALL, accent ? (own ? theme::ACCENT : theme::ON_ACCENT) : theme::TEXT));
|
||||
}
|
||||
|
||||
// A message's text, wrapped at `max_w` and shrunk to fit. "@[nick]" mentions
|
||||
@@ -300,7 +300,7 @@ static void msgLocButton(lv_obj_t* parent, const char* text, bool save, bool acc
|
||||
// ours (*mentions_me set). Plain text stays a label.
|
||||
static lv_obj_t* msgText(lv_obj_t* parent, const char* text, bool own, int max_w, bool* mentions_me) {
|
||||
*mentions_me = false;
|
||||
const uint32_t col = own ? theme::BG : theme::TEXT;
|
||||
const uint32_t col = own ? theme::ON_ACCENT : theme::TEXT;
|
||||
if (!strstr(text, "@[")) {
|
||||
lv_obj_t* t = label(parent, text, THEME_FONT_BODY, col);
|
||||
lv_label_set_long_mode(t, LV_LABEL_LONG_WRAP);
|
||||
@@ -337,7 +337,7 @@ static lv_obj_t* msgText(lv_obj_t* parent, const char* text, bool own, int max_w
|
||||
lv_span_t* sp = lv_spangroup_new_span(sg);
|
||||
lv_span_set_text(sp, part);
|
||||
lv_style_t* st = lv_span_get_style(sp);
|
||||
lv_style_set_text_color(st, lv_color_hex(own ? theme::BG : theme::ACCENT));
|
||||
lv_style_set_text_color(st, lv_color_hex(own ? theme::ON_ACCENT : theme::ACCENT));
|
||||
if (mine) { lv_style_set_text_decor(st, LV_TEXT_DECOR_UNDERLINE); *mentions_me = true; }
|
||||
p = close + 1;
|
||||
}
|
||||
@@ -377,7 +377,7 @@ static lv_obj_t* bubble(lv_obj_t* list, const char* from, const char* text, bool
|
||||
lv_obj_set_size(b, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
|
||||
lv_obj_set_style_max_width(b, 250, 0);
|
||||
lv_obj_set_style_bg_color(b, lv_color_hex(own ? theme::ACCENT : theme::SURFACE), 0);
|
||||
const uint32_t muted = own ? theme::mix(theme::BG, theme::ACCENT, 60) : theme::TEXT_MUTED;
|
||||
const uint32_t muted = own ? theme::mix(theme::ON_ACCENT, theme::ACCENT, 60) : theme::TEXT_MUTED;
|
||||
lv_obj_set_style_border_width(b, 0, 0);
|
||||
lv_obj_set_style_radius(b, theme::RADIUS, 0);
|
||||
lv_obj_set_style_pad_all(b, 6, 0);
|
||||
@@ -394,7 +394,7 @@ static lv_obj_t* bubble(lv_obj_t* list, const char* from, const char* text, bool
|
||||
if (from && from[0]) {
|
||||
lv_obj_t* hdr = flexBox(b, LV_FLEX_FLOW_ROW);
|
||||
lv_obj_set_style_pad_column(hdr, 8, 0);
|
||||
label(hdr, from, THEME_FONT_SMALL, own ? theme::BG : theme::ACCENT); // names are <= 31 chars: fits the bubble
|
||||
label(hdr, from, THEME_FONT_SMALL, own ? theme::ON_ACCENT : theme::ACCENT); // names are <= 31 chars: fits the bubble
|
||||
if (meta_in_header) *age_out = label(hdr, meta, THEME_FONT_SMALL, muted);
|
||||
}
|
||||
bool mentions_me;
|
||||
@@ -427,11 +427,11 @@ static lv_obj_t* bubble(lv_obj_t* list, const char* from, const char* text, bool
|
||||
lv_obj_set_style_bg_opa(c, LV_OPA_COVER, 0);
|
||||
lv_obj_set_style_bg_color(c, lv_color_hex(theme::OK), 0);
|
||||
lv_obj_set_style_radius(c, LV_RADIUS_CIRCLE, 0);
|
||||
lv_obj_t* n = label(c, "", THEME_FONT_SMALL, theme::BG);
|
||||
lv_obj_t* n = label(c, "", THEME_FONT_SMALL, theme::ON_ACCENT);
|
||||
lv_label_set_text_fmt(n, "%d", relays);
|
||||
lv_obj_center(n);
|
||||
} else if (status && status[0]) {
|
||||
label(line, status, THEME_FONT_SMALL, own ? theme::BG : status_col);
|
||||
label(line, status, THEME_FONT_SMALL, own ? theme::ON_ACCENT : status_col);
|
||||
}
|
||||
}
|
||||
return row;
|
||||
|
||||
@@ -177,6 +177,7 @@ void UITask::begin(DisplayDriver* display_drv, SensorManager* sensors, NodePrefs
|
||||
return;
|
||||
}
|
||||
theme::setAccent(lvport::loadAccent());
|
||||
theme::setLight(lvport::loadLight());
|
||||
theme::install(lv_display_get_default());
|
||||
lv_display_add_event_cb(lv_display_get_default(), [](lv_event_t*) { rowsFitPending(); }, LV_EVENT_REFR_START, NULL);
|
||||
|
||||
|
||||
@@ -972,7 +972,7 @@ static lv_obj_t* segmented(lv_obj_t* parent, const char** map, int sel, int w, i
|
||||
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_text_color(m, lv_color_hex(theme::TEXT), LV_PART_ITEMS);
|
||||
lv_obj_set_style_text_color(m, lv_color_hex(theme::BG), LV_PART_ITEMS | LV_STATE_CHECKED);
|
||||
lv_obj_set_style_text_color(m, lv_color_hex(theme::ON_ACCENT), LV_PART_ITEMS | LV_STATE_CHECKED);
|
||||
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_radius(m, theme::RADIUS, LV_PART_ITEMS);
|
||||
@@ -1016,16 +1016,16 @@ static void onByteCapInsert(lv_event_t* e) {
|
||||
if (ins && strlen(lv_textarea_get_text(ta)) + strlen(ins) > cap) lv_textarea_set_insert_replace(ta, "");
|
||||
}
|
||||
|
||||
// The primary action of a screen or popup: full amber, dark text (Theme.h);
|
||||
// The primary action of a screen or popup: full accent, ON_ACCENT text (Theme.h);
|
||||
// call after its label is made.
|
||||
static void stylePrimary(lv_obj_t* b) {
|
||||
lv_obj_set_style_bg_color(b, lv_color_hex(theme::ACCENT), 0);
|
||||
for (uint32_t i = 0; i < lv_obj_get_child_count(b); i++)
|
||||
lv_obj_set_style_text_color(lv_obj_get_child(b, i), lv_color_hex(theme::BG), 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 dark text,
|
||||
// or back to the surface with light text. Every label under it follows.
|
||||
// Something selected / on (a tab, a chip, a row): the accent with ON_ACCENT
|
||||
// text, or back to the surface with TEXT. Every label under it follows.
|
||||
static void textUnder(lv_obj_t* o, uint32_t col) {
|
||||
for (uint32_t i = 0; i < lv_obj_get_child_count(o); i++) {
|
||||
lv_obj_t* c = lv_obj_get_child(o, i);
|
||||
@@ -1036,7 +1036,7 @@ static void textUnder(lv_obj_t* o, uint32_t col) {
|
||||
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::mix(theme::ACCENT, theme::BG, 75) : theme::SURFACE_2), LV_STATE_PRESSED);
|
||||
textUnder(b, on ? theme::BG : theme::TEXT);
|
||||
textUnder(b, on ? theme::ON_ACCENT : theme::TEXT);
|
||||
}
|
||||
|
||||
// A row of equal buttons at the foot of a popup or screen: buttonBar(), then
|
||||
@@ -1137,7 +1137,7 @@ static void badge(lv_obj_t* parent, int n, bool overflow) {
|
||||
lv_obj_set_style_pad_hor(b, 7, 0);
|
||||
lv_obj_set_style_pad_ver(b, 0, 0);
|
||||
lv_obj_align(b, LV_ALIGN_RIGHT_MID, -theme::PAD, 0);
|
||||
lv_obj_t* l = label(b, "", THEME_FONT_SMALL, theme::BG);
|
||||
lv_obj_t* l = label(b, "", THEME_FONT_SMALL, theme::ON_ACCENT);
|
||||
lv_label_set_text_fmt(l, "%d%s", n, overflow ? "+" : "");
|
||||
lv_obj_center(l);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user