feat(theme): themes as files (theme crate: toml subset + ints, contrast check, wire); whimsy dark + light; display reads themes/, serves THEME/THEME_NAME, init SET_THEME -> THEME_CHANGED to all windows, bar themed; k-ui follows; settings appearance; init keeps choice in sealed users/<id>/settings/, reapplies at sign-in + display restart

This commit is contained in:
2026-10-28 13:36:57 +01:00
parent 29becf297c
commit 6827e1455d
43 changed files with 1140 additions and 179 deletions

View File

@@ -59,7 +59,7 @@ pub struct Ui<A: App> {
focus: usize,
/// How far down the view is scrolled, in pixels.
scroll: f32,
theme: &'static Theme,
theme: Theme,
}
/// The pre-order indices of every pressable element in `e`.
@@ -87,10 +87,15 @@ fn event_at<E: Clone>(e: &Element<E>, index: &mut usize, target: usize) -> Optio
}
impl<A: App> Ui<A> {
pub fn new(theme: &'static Theme) -> Self {
pub fn new(theme: Theme) -> Self {
Self { app: A::init(), focus: 0, scroll: 0.0, theme }
}
/// A new theme: everything is drawn in it from the next frame.
pub fn set_theme(&mut self, theme: Theme) {
self.theme = theme;
}
fn pressables(&self, view: &Element<A::Event>) -> Vec<usize> {
let mut out = Vec::new();
pressables(view, &mut 0, &mut out);
@@ -143,10 +148,10 @@ impl<A: App> Ui<A> {
pub fn draw(&mut self, pm: &mut PixmapMut, fonts: &Fonts) {
let view = self.app.view();
let (w, h) = (pm.width() as f32, pm.height() as f32);
let measurer = Measurer { fonts, theme: self.theme };
let measurer = Measurer { fonts, theme: &self.theme };
// As tall as it needs: what does not fit is scrolled to.
let tall = layout::natural(&view, &measurer, self.theme).1.max(h);
let mut rects = layout::layout(&view, Rect { x: 0.0, y: 0.0, w, h: tall }, &measurer, self.theme);
let tall = layout::natural(&view, &measurer, &self.theme).1.max(h);
let mut rects = layout::layout(&view, Rect { x: 0.0, y: 0.0, w, h: tall }, &measurer, &self.theme);
let focused = self.pressables(&view).get(self.focus).copied();
if let Some(r) = focused.and_then(|i| rects.get(i)) {
self.scroll = keep_in_sight(self.scroll, r.y, r.h, h, tall);
@@ -154,7 +159,7 @@ impl<A: App> Ui<A> {
for r in &mut rects {
r.y -= self.scroll;
}
render::render(pm, &view, &rects, fonts, self.theme, focused);
render::render(pm, &view, &rects, fonts, &self.theme, focused);
}
}