UI: seven themes, each dark and light, chosen in the Settings

Settings > Theme and Settings > Light or dark pick the colours of every
screen (issue #10): roro9stack (the website's, the default), Catppuccin,
Dracula, Nord, ANSI terminal, Gruvbox and Solarized.

- A palette is 14 roles (lib/ui/src/palette.h). theme::kText and the
  others are now references into the one in use, so the Apps are
  unchanged; the main loop applies it when a Setting changes.
- Every colour is one the RGB332 frame buffer holds exactly: the themes'
  own were rounded, and those that fell together or lost contrast were
  picked by hand. test_palette checks exactness and 18 contrast ratios
  for each palette.
- The Sky view's constellation colours come from the theme.
- `theme [0-6] [light|dark]` on the consoles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0162FokPdvY2KsS4NBfwyWPk
This commit is contained in:
2026-10-10 00:11:52 +02:00
co-authored by Claude Opus 5.5
parent 10627e6e18
commit 37335b4829
17 changed files with 336 additions and 24 deletions
+2
View File
@@ -14,6 +14,8 @@ class Screen {
// Takes over the screen while a Firmware Update is received or about to restart.
void renderUpdate(const std::string& title, const std::string& detail, int percent);
Canvas& canvas() { return canvas_; }
// The colours changed: an App that keeps what it drew has to draw it all again.
void invalidate() { lost_ = true; }
private:
Canvas canvas_;
+23 -14
View File
@@ -2,22 +2,31 @@
#include <cstdint>
#include "palette.h"
namespace roro::theme {
// The website's palette (site/static/css/site.css, its dark side), as RGB565. Every one is a colour
// the 8-bit frame buffer (RGB332) holds exactly, so what is asked for is what is shown.
constexpr uint16_t kBackground = 0x0000;
constexpr uint16_t kText = 0xFFFF;
constexpr uint16_t kAccent = 0x06DF; // cyan, #00dbff: what is chosen, what is live
constexpr uint16_t kOnAccent = 0x000A; // dark blue, #000055: text and pictures on a cyan fill
constexpr uint16_t kSelection = kAccent; // behind a selected row, whose text is kOnAccent
constexpr uint16_t kMuted = 0x9495; // grey, #9292aa: between the website's two
constexpr uint16_t kFaint = 0x4A4A; // slate, #494955: grid lines, what stays behind
constexpr uint16_t kBar = kFaint; // Status Bar background
constexpr uint16_t kBarMuted = 0xB5B5; // light grey, #b6b6aa: what is idle, on the bar
constexpr uint16_t kWarning = 0xFC80; // orange, #ff9200
constexpr uint16_t kMessage = 0xFC9F; // pink, #ff92ff: someone wrote
constexpr uint16_t kGood = 0x4ECA; // green, #49db55: a Fix, the best of a set (not on the website)
// The colours every screen draws with: the theme chosen in the Settings (issue #10, lib/ui's
// palette.h), set at boot and whenever it changes. They read as constants, and are references into
// the palette in use, so a draw after apply() is in the new colours.
inline ui::Palette current = ui::palette(0, false);
inline void apply(const ui::Palette& p) { current = p; }
inline const uint16_t& kBackground = current.background;
inline const uint16_t& kText = current.text;
inline const uint16_t& kAccent = current.accent; // what is chosen, what is live
inline const uint16_t& kOnAccent = current.onAccent; // text and pictures on an accent fill
inline const uint16_t& kSelection = current.accent; // behind a selected row, whose text is kOnAccent
inline const uint16_t& kMuted = current.muted;
inline const uint16_t& kFaint = current.faint; // grid lines, what stays behind
inline const uint16_t& kBar = current.bar; // Status Bar background
inline const uint16_t& kBarMuted = current.barMuted; // what is idle, on the bar
inline const uint16_t& kWarning = current.warning;
inline const uint16_t& kMessage = current.message; // someone wrote
inline const uint16_t& kGood = current.good; // a Fix, the best of a set
inline const uint16_t& kRed = current.red; // these three: to tell things apart
inline const uint16_t& kYellow = current.yellow;
inline const uint16_t& kViolet = current.violet;
constexpr int kWidth = 240;
constexpr int kHeight = 135;