From 159e057a2881dd27c6a94fe1d1317b98eb4ef895 Mon Sep 17 00:00:00 2001 From: debarghaya <175645893+GhostMitra@users.noreply.github.com> Date: Mon, 12 Oct 2026 00:51:23 +0530 Subject: [PATCH] Web & UI: resolve system theme preference and default web to system theme --- apps/gridcraft-web/src/web.rs | 1 + contributors/people.toml | 4 ++++ crates/ui-egui/src/theme.rs | 15 +++++++++++++++ crates/ui-egui/src/widgets.rs | 28 ++++++++++++++++++++++++++++ 4 files changed, 48 insertions(+) diff --git a/apps/gridcraft-web/src/web.rs b/apps/gridcraft-web/src/web.rs index 8b1e51d..a8b597d 100644 --- a/apps/gridcraft-web/src/web.rs +++ b/apps/gridcraft-web/src/web.rs @@ -38,6 +38,7 @@ pub fn start() { let _ = session.execute("file.new", serde_json::json!({"sample": "sales"})); } let mut app = SheetApp::new(session, services(inbox.clone(), cc.egui_ctx.clone())); + app.ui.system_theme = true; // Follow the browser's language, except a CJK one: the web build has no system // CJK fonts (none are bundled), so that interface would render as tofu. let browser = gridcraft_ui_egui::i18n::Language::system(); diff --git a/contributors/people.toml b/contributors/people.toml index 7b69da3..681a4dd 100644 --- a/contributors/people.toml +++ b/contributors/people.toml @@ -50,3 +50,7 @@ sync_github_name = false [people.Losminek] sync_github_name = true + +[people.GhostMitra] +sync_github_name = true + diff --git a/crates/ui-egui/src/theme.rs b/crates/ui-egui/src/theme.rs index 6774154..e408a29 100644 --- a/crates/ui-egui/src/theme.rs +++ b/crates/ui-egui/src/theme.rs @@ -142,6 +142,21 @@ impl Tokens { } } +/// Resolves an [`egui::ThemePreference`] against the context's system theme. +pub fn resolve_theme(pref: egui::ThemePreference, ctx: &egui::Context) -> egui::Theme { + match pref { + egui::ThemePreference::System => { + if ctx.input(|i| i.raw.system_theme == Some(egui::Theme::Dark)) { + egui::Theme::Dark + } else { + egui::Theme::Light + } + } + egui::ThemePreference::Light => egui::Theme::Light, + egui::ThemePreference::Dark => egui::Theme::Dark, + } +} + pub const UI: &str = "ui"; pub const UI_BOLD: &str = "ui-bold"; pub const CELL: &str = "cell"; diff --git a/crates/ui-egui/src/widgets.rs b/crates/ui-egui/src/widgets.rs index a006c6b..5220f04 100644 --- a/crates/ui-egui/src/widgets.rs +++ b/crates/ui-egui/src/widgets.rs @@ -284,3 +284,31 @@ pub fn notice_bar(app: &mut SheetApp, ui: &mut Ui) { app.notice = None; } } + +/// Turn a monochrome image (black on white) into an alpha mask tinted with the active text color. +pub fn raster_to_alpha_mask(pixels: &mut [egui::Color32]) { + for p in pixels.iter_mut() { + // Darkness of source becomes the opacity + let darkness = 255u8.saturating_sub(p.r()); + // Pure white glyph with variable alpha + *p = egui::Color32::from_rgba_unmultiplied(255, 255, 255, darkness); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_raster_to_alpha_mask() { + let mut pixels = vec![ + egui::Color32::WHITE, // r=255 -> darkness=0 -> alpha=0 + egui::Color32::BLACK, // r=0 -> darkness=255 -> alpha=255 + egui::Color32::from_rgb(100, 100, 100), // r=100 -> darkness=155 -> alpha=155 + ]; + raster_to_alpha_mask(&mut pixels); + assert_eq!(pixels[0], egui::Color32::from_rgba_unmultiplied(255, 255, 255, 0)); + assert_eq!(pixels[1], egui::Color32::from_rgba_unmultiplied(255, 255, 255, 255)); + assert_eq!(pixels[2], egui::Color32::from_rgba_unmultiplied(255, 255, 255, 155)); + } +}