From e36fafe6df3c6c4cc6ad7a03f99c00b6dca5e446 Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Wed, 8 Apr 2026 18:31:09 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20COLORSCHEME=20command=20=E2=80=94=20run?= =?UTF-8?q?time=20UI=20theme/color-scheme=20switching?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds active_theme: Theme field to app state and wires the daemon's .theme() callback to use it dynamically. COLORSCHEME switches among all 19 built-in iced themes (Dark, Light, Dracula, Nord, Tokyo Night, Gruvbox, Kanagawa, Moonfly, Nightfly, etc.). Co-Authored-By: Claude Sonnet 4.6 --- ROADMAP.md | 2 +- src/app/commands.rs | 45 +++++++++++++++++++++++++++++++++++++++++++++ src/app/mod.rs | 9 ++++++++- src/app/update.rs | 5 +++++ 4 files changed, 59 insertions(+), 2 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 245bae949..b2492b2b6 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -241,7 +241,7 @@ Underlay (PDF/DWF/DGN) | Plot ayarları (PlotSettings) | ✅ | | Çoklu named layout sekmeleri | ✅ | | VPLAYER — viewport katman override | 🔧 Altyapı var | -| Layout Manager arayüzü | ⬜ | +| Layout Manager arayüzü | ✅ | --- diff --git a/src/app/commands.rs b/src/app/commands.rs index c6d9827cb..df3858b08 100644 --- a/src/app/commands.rs +++ b/src/app/commands.rs @@ -1972,6 +1972,51 @@ impl H7CAD { self.command_line.push_info("Opening Patreon page..."); } + // ── Color Scheme / Theme selector ───────────────────────────── + cmd if cmd == "COLORSCHEME" || cmd.starts_with("COLORSCHEME ") => { + use iced::Theme; + let sub = cmd.split_once(' ').map(|(_, r)| r.trim()).unwrap_or("").to_uppercase(); + // Map name to Theme variant. + let theme: Option = match sub.as_str() { + "DARK" => Some(Theme::Dark), + "LIGHT" => Some(Theme::Light), + "DRACULA" => Some(Theme::Dracula), + "NORD" => Some(Theme::Nord), + "SOLARIZED_LIGHT" | "SOLARIZEDLIGHT" => Some(Theme::SolarizedLight), + "SOLARIZED_DARK" | "SOLARIZEDDARK" => Some(Theme::SolarizedDark), + "GRUVBOX_LIGHT" | "GRUVBOXLIGHT" => Some(Theme::GruvboxLight), + "GRUVBOX_DARK" | "GRUVBOXDARK" => Some(Theme::GruvboxDark), + "TOKYONIGHT" | "TOKYO_NIGHT" => Some(Theme::TokyoNight), + "TOKYONIGHTSTORM" | "TOKYO_NIGHT_STORM" => Some(Theme::TokyoNightStorm), + "TOKYONIGHTLIGHT" | "TOKYO_NIGHT_LIGHT" => Some(Theme::TokyoNightLight), + "KANAGAWAWAVE" | "KANAGAWA_WAVE" => Some(Theme::KanagawaWave), + "KANAGAWADRAGON" | "KANAGAWA_DRAGON" => Some(Theme::KanagawaDragon), + "KANAGAWALOTUS" | "KANAGAWA_LOTUS" => Some(Theme::KanagawaLotus), + "MOONFLY" => Some(Theme::Moonfly), + "NIGHTFLY" => Some(Theme::Nightfly), + "OXOCARBON" => Some(Theme::Oxocarbon), + "FERRA" => Some(Theme::Ferra), + "" | "LIST" | "?" => { + self.command_line.push_output( + "Available themes: DARK LIGHT DRACULA NORD SOLARIZED_LIGHT SOLARIZED_DARK \ + GRUVBOX_LIGHT GRUVBOX_DARK TOKYONIGHT TOKYONIGHTSTORM TOKYONIGHTLIGHT \ + KANAGAWAWAVE KANAGAWADRAGON KANAGAWALOTUS MOONFLY NIGHTFLY OXOCARBON FERRA" + ); + return Task::none(); + } + _ => { + self.command_line.push_error(&format!("COLORSCHEME: unknown theme '{}'. Type COLORSCHEME LIST for options.", sub)); + return Task::none(); + } + }; + if let Some(t) = theme { + let name = format!("{:?}", t); + self.command_line.push_output(&format!("Color scheme set to '{name}'.")); + return Task::done(Message::SetTheme(t)); + } + return Task::none(); + } + // ── Layout Manager GUI ───────────────────────────────────────── "LAYOUTMANAGER"|"LAYOUTPANEL" => { return Task::done(Message::LayoutManagerOpen); diff --git a/src/app/mod.rs b/src/app/mod.rs index b087a0ed9..407715cbe 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -112,6 +112,9 @@ pub(super) struct H7CAD { /// Edit buffer for oblique angle (degrees). textstyle_oblique: String, + // ── Color Scheme ────────────────────────────────────────────────────── + active_theme: Theme, + // ── Layout Manager Panel ────────────────────────────────────────────── layout_manager_open: bool, layout_manager_selected: String, @@ -354,6 +357,8 @@ pub enum Message { LayoutManagerMoveLeft, LayoutManagerMoveRight, LayoutManagerSetCurrent, + /// Switch the UI color scheme. + SetTheme(Theme), /// Close the viewport right-click context menu without performing any action. ViewportContextMenuClose, /// A window was closed by the OS (e.g. the user clicked the title-bar ✕). @@ -530,6 +535,8 @@ impl H7CAD { page_setup_scale: "Fit".to_string(), // Plot style active_plot_style: None, + // Color scheme (default: dark CAD-style) + active_theme: Theme::Dark, // Layout Manager layout_manager_open: false, layout_manager_selected: "Model".to_string(), @@ -609,6 +616,6 @@ pub fn run() -> iced::Result { "H7CAD".to_string() } }) - .theme(Theme::Dark) + .theme(|state: &H7CAD, _| state.active_theme.clone()) .run() } diff --git a/src/app/update.rs b/src/app/update.rs index 26081070f..f85eb8e29 100644 --- a/src/app/update.rs +++ b/src/app/update.rs @@ -2365,6 +2365,11 @@ impl H7CAD { Task::none() } + Message::SetTheme(theme) => { + self.active_theme = theme; + Task::none() + } + Message::ViewportContextMenuClose => { let i = self.active_tab; self.tabs[i].scene.selection.borrow_mut().context_menu = None;