темы ST7789LCDDisplay: палитры вынесены в общий ColorThemes.h

This commit is contained in:
2026-10-08 20:52:23 +03:00
parent 28e802dcf0
commit db05d5f5bc
4 changed files with 150 additions and 89 deletions
+84
View File
@@ -0,0 +1,84 @@
#pragma once
// Общие палитры цветных TFT-драйверов: ST7735Display и ST7789LCDDisplay.
//
// Таблица живёт в заголовке, а не в отдельном .cpp, чтобы оба драйвера
// использовали одну и ту же палитру. В сборке всегда включён ровно один
// драйвер (выбор по DISPLAY_CLASS), поэтому копий таблицы в прошивке нет.
//
// Значения — RGB565. CLASSIC — официальная светлая схема MeshCore
// (белый фон, чёрный текст), взятая из upstream.
#include <stdint.h>
#include "DisplayDriver.h"
// Две темы сразу — почти наверняка ошибка в env
#if (defined(ST7735_THEME_CLASSIC) + defined(ST7735_THEME_AMBER) + defined(ST7735_THEME_TEAL) + defined(ST7735_THEME_SIGNAL) + defined(ST7735_THEME_NEON) + \
defined(ST7789_THEME_CLASSIC) + defined(ST7789_THEME_AMBER) + defined(ST7789_THEME_TEAL) + defined(ST7789_THEME_SIGNAL) + defined(ST7789_THEME_NEON)) > 1
#error "ColorThemes: выбрана более чем одна тема *_THEME_*"
#endif
struct ColorTheme {
const char* name;
ColorVal window_bkg, title_bkg, title_txt, primary_txt,
secondary_txt, warning_txt, popup_bkg, popup_txt, corp_blue;
};
// Порядок в таблице = порядок в меню выбора темы
static constexpr ColorTheme UI_THEMES[] = {
{ "amber", 0x1082, 0x2146, 0xF79E, 0xFFDF, 0x9493, 0xFD84, 0xFD84, 0x10A3, 0x551F }, // #101010 / #202830 / #FFB020
{ "teal", 0x0883, 0x1187, 0xEFDF, 0xF7DF, 0x8515, 0xFE4A, 0x1696, 0x0881, 0x45DF }, // #081018 / #103038 / #10D0B0
{ "signal", 0x0000, 0xEB07, 0x1082, 0xFFDF, 0x9D15, 0xFE8C, 0xFB46, 0x1082, 0x5D5F }, // #000000 / #E86038 / #FF6830
{ "neon", 0x0000, 0x0000, 0xEF5D, 0xFFFF, 0x8C52, 0xFEA0, 0x18C3, 0xFEA0, 0x555F }, // #000000 / #000000 / #FFD400
{ "classic", 0xFFFF, 0x001F, 0xFFFF, 0x0000, 0x9492, 0xFD20, 0x07FF, 0x0000, 0x001A }, // официальная светлая
};
#define UI_THEME_COUNT ((uint8_t)(sizeof(UI_THEMES) / sizeof(UI_THEMES[0])))
// Тема по умолчанию: AMBER для Heltec T096, для остальных плат — официальная
// CLASSIC. Флаги *_THEME_* в platformio.ini варианта переопределяют выбор.
static constexpr uint8_t ui_default_theme_index() {
#if defined(ST7735_THEME_CLASSIC) || defined(ST7789_THEME_CLASSIC)
return 4;
#elif defined(ST7735_THEME_TEAL) || defined(ST7789_THEME_TEAL)
return 1;
#elif defined(ST7735_THEME_SIGNAL) || defined(ST7789_THEME_SIGNAL)
return 2;
#elif defined(ST7735_THEME_NEON) || defined(ST7789_THEME_NEON)
return 3;
#elif defined(ST7735_THEME_AMBER) || defined(ST7789_THEME_AMBER) || defined(HELTEC_T096)
return 0;
#else
return 4;
#endif
}
static inline const char* ui_theme_name(uint8_t i) {
return i < UI_THEME_COUNT ? UI_THEMES[i].name : "";
}
static inline ColorVal ui_theme_color(uint8_t theme, uint8_t role) {
if (theme >= UI_THEME_COUNT) return 0;
const ColorTheme* t = &UI_THEMES[theme];
switch (role) {
case DisplayDriver::THEME_COLOR_WINDOW: return t->window_bkg;
case DisplayDriver::THEME_COLOR_TITLE: return t->title_bkg;
case DisplayDriver::THEME_COLOR_POPUP: return t->popup_bkg;
case DisplayDriver::THEME_COLOR_ACCENT: return t->warning_txt;
default: return t->primary_txt;
}
}
// Применить палитру к глобальным цветам интерфейса
static inline void ui_apply_theme(uint8_t i) {
if (i >= UI_THEME_COUNT) return;
const ColorTheme* t = &UI_THEMES[i];
UIColor::window_bkg = t->window_bkg;
UIColor::title_bkg = t->title_bkg;
UIColor::title_txt = t->title_txt;
UIColor::primary_txt = t->primary_txt;
UIColor::secondary_txt = t->secondary_txt;
UIColor::warning_txt = t->warning_txt;
UIColor::popup_bkg = t->popup_bkg;
UIColor::popup_txt = t->popup_txt;
UIColor::corp_blue = t->corp_blue;
}
+20 -80
View File
@@ -1,4 +1,5 @@
#include "ST7735Display.h"
#include "ColorThemes.h"
#ifdef OLED_RU
#include "glcdfont6x8.h"
#endif
@@ -422,80 +423,36 @@ bool ST7735Display::i2c_probe(TwoWire& wire, uint8_t addr) {
// Color scheme
//
// Палитры вынесены в таблицу, поэтому тема переключается в рантайме (UIColor::* —
// обычные статические переменные, не const). Выбранная тема хранится в prefs по имени
// и применяется при старте; в меню ui-new есть страница THEME с живым предпросмотром.
// Палитры общие с ST7789LCDDisplay и лежат в src/helpers/ui/ColorThemes.h, поэтому
// тема переключается в рантайме (UIColor::* — обычные статические переменные, не const).
// Выбранная тема хранится в prefs по имени и применяется при старте; в меню ui-new
// есть страница THEME с живым предпросмотром.
//
// Тема по умолчанию зависит от платы:
// - Heltec T096 — AMBER (графит + янтарь);
// - остальные платы на этом драйвере (heltec_t1 / tracker / tracker_v2) —
// официальная схема MeshCore (CLASSIC).
// Флаг ST7735_THEME_* в platformio.ini варианта переопределяет этот дефолт.
//
// CLASSIC взята из upstream: github.com/meshcore-dev/MeshCore, ветка main,
// src/helpers/ui/ST7735Display.cpp — светлая схема (белый фон, чёрный текст).
// В форке она была перекрашена в тёмную вручную, здесь восстановлен оригинал.
#if (defined(ST7735_THEME_CLASSIC) + defined(ST7735_THEME_AMBER) + defined(ST7735_THEME_TEAL) + defined(ST7735_THEME_SIGNAL) + defined(ST7735_THEME_NEON)) > 1
#error "ST7735Display: выбрана более чем одна тема ST7735_THEME_*"
#endif
#define MC_CLASSIC_SECONDARY_TXT ((18 << 11) | (36 << 5) | 18) // mid-gray
struct ColorTheme {
const char* name;
ColorVal window_bkg, title_bkg, title_txt, primary_txt,
secondary_txt, warning_txt, popup_bkg, popup_txt, corp_blue;
};
// Порядок в таблице = порядок в меню выбора темы.
// constexpr — чтобы палитра инициализировалась статически (иначе значения уехали бы
// в .bss и заполнялись динамической инициализацией C++).
static constexpr ColorTheme THEMES[] = {
{ "amber", 0x1082, 0x2146, 0xF79E, 0xFFDF, 0x9493, 0xFD84, 0xFD84, 0x10A3, 0x551F }, // #101010 / #202830 / #FFB020
{ "teal", 0x0883, 0x1187, 0xEFDF, 0xF7DF, 0x8515, 0xFE4A, 0x1696, 0x0881, 0x45DF }, // #081018 / #103038 / #10D0B0
{ "signal", 0x0000, 0xEB07, 0x1082, 0xFFDF, 0x9D15, 0xFE8C, 0xFB46, 0x1082, 0x5D5F }, // #000000 / #E86038 / #FF6830
{ "neon", 0x0000, 0x0000, 0xEF5D, 0xFFFF, 0x8C52, 0xFEA0, 0x18C3, 0xFEA0, 0x555F }, // #000000 / #000000 / #FFD400
{ "classic", ST77XX_WHITE, ST77XX_BLUE, ST77XX_WHITE, ST77XX_BLACK, MC_CLASSIC_SECONDARY_TXT,
ST77XX_ORANGE, ST77XX_CYAN, ST77XX_BLACK, 0x001A }, // официальная светлая
};
#define THEME_COUNT ((uint8_t)(sizeof(THEMES) / sizeof(THEMES[0])))
static constexpr uint8_t default_theme_index() {
#if defined(ST7735_THEME_CLASSIC)
return 4;
#elif defined(ST7735_THEME_TEAL)
return 1;
#elif defined(ST7735_THEME_SIGNAL)
return 2;
#elif defined(ST7735_THEME_NEON)
return 3;
#elif defined(ST7735_THEME_AMBER) || defined(HELTEC_T096)
return 0;
#else
return 4; // остальные платы: официальная схема MeshCore
#endif
}
static constexpr uint8_t DEFAULT_THEME = default_theme_index();
static constexpr uint8_t DEFAULT_THEME = ui_default_theme_index();
static uint8_t active_theme = DEFAULT_THEME;
ColorVal UIColor::window_bkg = THEMES[DEFAULT_THEME].window_bkg;
ColorVal UIColor::title_bkg = THEMES[DEFAULT_THEME].title_bkg;
ColorVal UIColor::title_txt = THEMES[DEFAULT_THEME].title_txt;
ColorVal UIColor::primary_txt = THEMES[DEFAULT_THEME].primary_txt;
ColorVal UIColor::secondary_txt = THEMES[DEFAULT_THEME].secondary_txt;
ColorVal UIColor::warning_txt = THEMES[DEFAULT_THEME].warning_txt;
ColorVal UIColor::popup_bkg = THEMES[DEFAULT_THEME].popup_bkg;
ColorVal UIColor::popup_txt = THEMES[DEFAULT_THEME].popup_txt;
ColorVal UIColor::corp_blue = THEMES[DEFAULT_THEME].corp_blue;
ColorVal UIColor::window_bkg = UI_THEMES[DEFAULT_THEME].window_bkg;
ColorVal UIColor::title_bkg = UI_THEMES[DEFAULT_THEME].title_bkg;
ColorVal UIColor::title_txt = UI_THEMES[DEFAULT_THEME].title_txt;
ColorVal UIColor::primary_txt = UI_THEMES[DEFAULT_THEME].primary_txt;
ColorVal UIColor::secondary_txt = UI_THEMES[DEFAULT_THEME].secondary_txt;
ColorVal UIColor::warning_txt = UI_THEMES[DEFAULT_THEME].warning_txt;
ColorVal UIColor::popup_bkg = UI_THEMES[DEFAULT_THEME].popup_bkg;
ColorVal UIColor::popup_txt = UI_THEMES[DEFAULT_THEME].popup_txt;
ColorVal UIColor::corp_blue = UI_THEMES[DEFAULT_THEME].corp_blue;
uint8_t ST7735Display::getThemeCount() {
return THEME_COUNT;
return UI_THEME_COUNT;
}
const char* ST7735Display::getThemeName(uint8_t i) {
return i < THEME_COUNT ? THEMES[i].name : "";
return ui_theme_name(i);
}
uint8_t ST7735Display::getTheme() {
@@ -503,30 +460,13 @@ uint8_t ST7735Display::getTheme() {
}
void ST7735Display::setTheme(uint8_t i) {
if (i >= THEME_COUNT) return;
const ColorTheme* t = &THEMES[i];
UIColor::window_bkg = t->window_bkg;
UIColor::title_bkg = t->title_bkg;
UIColor::title_txt = t->title_txt;
UIColor::primary_txt = t->primary_txt;
UIColor::secondary_txt = t->secondary_txt;
UIColor::warning_txt = t->warning_txt;
UIColor::popup_bkg = t->popup_bkg;
UIColor::popup_txt = t->popup_txt;
UIColor::corp_blue = t->corp_blue;
if (i >= UI_THEME_COUNT) return;
ui_apply_theme(i);
active_theme = i;
}
ColorVal ST7735Display::getThemeColor(uint8_t theme, uint8_t role) {
if (theme >= THEME_COUNT) return 0;
const ColorTheme* t = &THEMES[theme];
switch (role) {
case THEME_COLOR_WINDOW: return t->window_bkg;
case THEME_COLOR_TITLE: return t->title_bkg;
case THEME_COLOR_POPUP: return t->popup_bkg;
case THEME_COLOR_ACCENT: return t->warning_txt;
default: return t->primary_txt;
}
return ui_theme_color(theme, role);
}
bool ST7735Display::begin() {
+39 -9
View File
@@ -1,4 +1,5 @@
#include "ST7789LCDDisplay.h"
#include "ColorThemes.h"
#ifdef OLED_RU
#include "glcdfont6x8.h"
#endif
@@ -27,15 +28,44 @@ bool ST7789LCDDisplay::i2c_probe(TwoWire& wire, uint8_t addr) {
}
// Color scheme
ColorVal UIColor::window_bkg = ST77XX_WHITE;
ColorVal UIColor::title_bkg = ST77XX_BLUE;
ColorVal UIColor::title_txt = ST77XX_WHITE;
ColorVal UIColor::primary_txt = ST77XX_BLACK;
ColorVal UIColor::secondary_txt = (18 << 11) | (36 << 5) | 18; // mid-gray
ColorVal UIColor::warning_txt = ST77XX_ORANGE;
ColorVal UIColor::popup_bkg = ST77XX_CYAN;
ColorVal UIColor::popup_txt = ST77XX_BLACK;
ColorVal UIColor::corp_blue = 0x001A;
//
// Палитры общие с ST7735Display (src/helpers/ui/ColorThemes.h), поэтому тема
// переключается в рантайме и одинаково выглядит на обоих TFT-драйверах.
// Дефолт для этих плат (heltec_v4 / tdeck) — официальная светлая CLASSIC.
static constexpr uint8_t DEFAULT_THEME = ui_default_theme_index();
static uint8_t active_theme = DEFAULT_THEME;
ColorVal UIColor::window_bkg = UI_THEMES[DEFAULT_THEME].window_bkg;
ColorVal UIColor::title_bkg = UI_THEMES[DEFAULT_THEME].title_bkg;
ColorVal UIColor::title_txt = UI_THEMES[DEFAULT_THEME].title_txt;
ColorVal UIColor::primary_txt = UI_THEMES[DEFAULT_THEME].primary_txt;
ColorVal UIColor::secondary_txt = UI_THEMES[DEFAULT_THEME].secondary_txt;
ColorVal UIColor::warning_txt = UI_THEMES[DEFAULT_THEME].warning_txt;
ColorVal UIColor::popup_bkg = UI_THEMES[DEFAULT_THEME].popup_bkg;
ColorVal UIColor::popup_txt = UI_THEMES[DEFAULT_THEME].popup_txt;
ColorVal UIColor::corp_blue = UI_THEMES[DEFAULT_THEME].corp_blue;
uint8_t ST7789LCDDisplay::getThemeCount() {
return UI_THEME_COUNT;
}
const char* ST7789LCDDisplay::getThemeName(uint8_t i) {
return ui_theme_name(i);
}
uint8_t ST7789LCDDisplay::getTheme() {
return active_theme;
}
void ST7789LCDDisplay::setTheme(uint8_t i) {
if (i >= UI_THEME_COUNT) return;
ui_apply_theme(i);
active_theme = i;
}
ColorVal ST7789LCDDisplay::getThemeColor(uint8_t theme, uint8_t role) {
return ui_theme_color(theme, role);
}
bool ST7789LCDDisplay::begin() {
if (!_isOn) {
+7
View File
@@ -73,4 +73,11 @@ public:
void drawXbm(int x, int y, const uint8_t* bits, int w, int h) override;
uint16_t getTextWidth(const char* str) override;
void endFrame() override;
// Темы (палитры общие с ST7735Display — src/helpers/ui/ColorThemes.h)
uint8_t getThemeCount() override;
const char* getThemeName(uint8_t i) override;
uint8_t getTheme() override;
void setTheme(uint8_t i) override;
ColorVal getThemeColor(uint8_t theme, uint8_t role) override;
};