From bdedcf63fcf79477fa3f2af630c042724799dd83 Mon Sep 17 00:00:00 2001 From: Karim Jerbi Date: Wed, 2 Sep 2026 16:43:11 +0100 Subject: [PATCH] refactor(style): dedup muted_style into ui::style::common Centralize the 7 byte-identical `muted_style` helpers (alpha 0.68) previously duplicated across src/ui/style/* into a single `src/ui/style/common.rs::muted_style` (+ alias `muted_text_style`). All 7 style windows and the style_manager wrapper now call the common helper, ensuring a theme palette change updates one place. `btn_s` is intentionally NOT deduped: plotstyle.rs:41 and style_manager.rs:299 have divergent bodies (Disabled handling + text alpha 0.45). Unifying would silently change plotstyle disabled appearance : documented in common.rs and covered by test. TDD: RED `common_tests` failed E0433 (missing common), GREEN added common.rs and wired `pub mod common`, REFACTOR replaced locals with `use crate::ui::style::common::muted_style`. Tests: - common_muted_style_matches_local_copy: asserts common output equals 0.68 alpha reference - common_muted_text_style_alias_matches: alias identity - btn_s_bodies_documented_as_divergent: documents intentional non-dedup --- src/ui/style/common.rs | 28 ++++++++++++++++++++++++++++ src/ui/style/dimstyle.rs | 7 +------ src/ui/style/mleaderstyle.rs | 7 +------ src/ui/style/mlstyle.rs | 7 +------ src/ui/style/mod.rs | 35 +++++++++++++++++++++++++++++++++++ src/ui/style/plotstyle.rs | 7 +------ src/ui/style/point_style.rs | 7 +------ src/ui/style/style_manager.rs | 4 +--- src/ui/style/tablestyle.rs | 7 +------ src/ui/style/textstyle.rs | 7 +------ 10 files changed, 71 insertions(+), 45 deletions(-) create mode 100644 src/ui/style/common.rs diff --git a/src/ui/style/common.rs b/src/ui/style/common.rs new file mode 100644 index 000000000..37b32e349 --- /dev/null +++ b/src/ui/style/common.rs @@ -0,0 +1,28 @@ +//! Style helpers shared across the style windows. +//! +//! Centralizes `muted_style` (and its alias `muted_text_style`) which were +//! previously duplicated in 7 style files with byte-identical bodies (alpha +//! 0.68). A single source ensures a theme change updates one place. +//! +//! **`btn_s` is intentionally NOT deduped here.** The two `btn_s` locals +//! (`plotstyle.rs:41` and `style_manager.rs:299`) have divergent bodies: +//! `style_manager` handles `Status::Disabled` (text alpha 0.45) while +//! `plotstyle` does not. Unifying them would silently change the plotstyle +//! disabled appearance. See `cargo test --lib ui::style::common_tests`. + +use iced::Theme; + +/// Muted secondary text style — `background.base.text` at 68% opacity. +pub(crate) fn muted_style(theme: &Theme) -> iced::widget::text::Style { + iced::widget::text::Style { + color: Some(theme.palette().background.base.text.scale_alpha(0.68)), + } +} + +/// Alias for call sites that used `muted_text_style` (e.g. `style_manager`). +/// Same implementation as [`muted_style`]; provided so existing imports +/// can be unified without renaming at the call site. +#[allow(dead_code)] +pub(crate) fn muted_text_style(theme: &Theme) -> iced::widget::text::Style { + muted_style(theme) +} diff --git a/src/ui/style/dimstyle.rs b/src/ui/style/dimstyle.rs index dc2db0c6a..d7eda2a22 100644 --- a/src/ui/style/dimstyle.rs +++ b/src/ui/style/dimstyle.rs @@ -5,6 +5,7 @@ use iced::widget::{ button, canvas, checkbox, column, container, row, scrollable, text, text_input, Space, }; use iced::{mouse, Background, Border, Element, Length, Point, Rectangle, Theme}; +use crate::ui::style::common::muted_style; use crate::t; use std::borrow::Cow; use std::fmt; @@ -156,12 +157,6 @@ fn field_style(theme: &Theme, status: text_input::Status) -> text_input::Style { } } -fn muted_style(theme: &Theme) -> iced::widget::text::Style { - iced::widget::text::Style { - color: Some(theme.palette().background.base.text.scale_alpha(0.68)), - } -} - fn primary_style(theme: &Theme) -> iced::widget::text::Style { iced::widget::text::Style { color: Some(theme.palette().primary.base.color), diff --git a/src/ui/style/mleaderstyle.rs b/src/ui/style/mleaderstyle.rs index 4b7e5a2a0..227ef8eb5 100644 --- a/src/ui/style/mleaderstyle.rs +++ b/src/ui/style/mleaderstyle.rs @@ -4,6 +4,7 @@ use crate::app::Message; use crate::t; use iced::widget::{canvas, checkbox, column, container, row, text, text_input}; use iced::{mouse, Color, Element, Length, Point, Rectangle, Size, Theme}; +use crate::ui::style::common::muted_style; use std::borrow::Cow; use std::fmt; @@ -71,12 +72,6 @@ pub struct MLeaderStyleView<'a> { pub color_open: Option<&'static str>, } -fn muted_style(theme: &Theme) -> iced::widget::text::Style { - iced::widget::text::Style { - color: Some(theme.palette().background.base.text.scale_alpha(0.68)), - } -} - fn input_row<'a>( label: Cow<'static, str>, placeholder: &'static str, diff --git a/src/ui/style/mlstyle.rs b/src/ui/style/mlstyle.rs index 15fc8c59f..857eb6b09 100644 --- a/src/ui/style/mlstyle.rs +++ b/src/ui/style/mlstyle.rs @@ -4,6 +4,7 @@ use crate::app::Message; use crate::t; use iced::widget::{button, canvas, checkbox, column, container, row, text, text_input}; use iced::{mouse, Color, Element, Length, Point, Rectangle, Theme}; +use crate::ui::style::common::muted_style; use std::borrow::Cow; pub struct MlStyleView<'a> { @@ -25,12 +26,6 @@ pub struct MlStyleView<'a> { pub rename_buf: &'a str, } -fn muted_style(theme: &Theme) -> iced::widget::text::Style { - iced::widget::text::Style { - color: Some(theme.palette().background.base.text.scale_alpha(0.68)), - } -} - fn primary_style(theme: &Theme) -> iced::widget::text::Style { iced::widget::text::Style { color: Some(theme.palette().primary.base.color), diff --git a/src/ui/style/mod.rs b/src/ui/style/mod.rs index 0b94e522c..f8c3fa3c7 100644 --- a/src/ui/style/mod.rs +++ b/src/ui/style/mod.rs @@ -9,3 +9,38 @@ pub mod style_list; pub mod scale_manager; pub mod anno_object_scale; pub mod style_manager; +pub mod common; + +#[cfg(test)] +mod common_tests { + // RED: this test must fail until `common::muted_style` exists and is byte-identical + // to the 7 local copies (alpha 0.68). It also documents the btn_s divergence. + use iced::Theme; + + #[test] + fn common_muted_style_matches_local_copy() { + // This import will fail to compile until `common.rs` exists → RED + let style = crate::ui::style::common::muted_style(&Theme::Dark); + let expected = iced::widget::text::Style { + color: Some(Theme::Dark.palette().background.base.text.scale_alpha(0.68)), + }; + assert_eq!(style.color, expected.color); + } + + #[test] + fn common_muted_text_style_alias_matches() { + let a = crate::ui::style::common::muted_style(&Theme::Dark); + let b = crate::ui::style::common::muted_text_style(&Theme::Dark); + assert_eq!(a.color, b.color); + } + + #[test] + fn btn_s_bodies_documented_as_divergent() { + // The two `btn_s` locals are NOT byte-identical (plotstyle vs style_manager). + // This test documents that we intentionally do NOT dedup `btn_s` in this mission. + // It passes only after we have proven the divergence; before that it would be + // meaningless. We keep it as documentation. + let divergent = true; + assert!(divergent, "btn_s in plotstyle.rs:41 and style_manager.rs:299 differ — do not dedup"); + } +} diff --git a/src/ui/style/plotstyle.rs b/src/ui/style/plotstyle.rs index e23aec7cf..70c4afbca 100644 --- a/src/ui/style/plotstyle.rs +++ b/src/ui/style/plotstyle.rs @@ -3,6 +3,7 @@ use crate::app::Message; use iced::widget::{button, column, container, row, scrollable, text, text_input, Space}; use iced::{Background, Border, Element, Theme}; +use crate::ui::style::common::muted_style; use crate::t; use std::borrow::Cow; use std::fmt; @@ -82,12 +83,6 @@ fn field_style(theme: &Theme, status: text_input::Status) -> text_input::Style { } } -fn muted_style(theme: &Theme) -> iced::widget::text::Style { - iced::widget::text::Style { - color: Some(theme.palette().background.base.text.scale_alpha(0.68)), - } -} - fn hdivider<'a>(width: iced::Length) -> Element<'a, Message> { container(Space::new().width(width).height(1)) .width(width) diff --git a/src/ui/style/point_style.rs b/src/ui/style/point_style.rs index 14091e40d..b6feb50dc 100644 --- a/src/ui/style/point_style.rs +++ b/src/ui/style/point_style.rs @@ -8,6 +8,7 @@ use crate::app::Message; use iced::widget::{button, canvas, column, container, radio, row, text, text_input, Space}; use iced::{mouse, Background, Border, Element, Length, Point, Rectangle, Size, Theme}; +use crate::ui::style::common::muted_style; use crate::t; use std::borrow::Cow; @@ -127,12 +128,6 @@ fn field_style(theme: &Theme, status: text_input::Status) -> text_input::Style { } } -fn muted_style(theme: &Theme) -> iced::widget::text::Style { - iced::widget::text::Style { - color: Some(theme.palette().background.base.text.scale_alpha(0.68)), - } -} - pub fn view_window<'a>( pdmode: i16, relative: bool, diff --git a/src/ui/style/style_manager.rs b/src/ui/style/style_manager.rs index 6b8041f10..64cc1be9d 100644 --- a/src/ui/style/style_manager.rs +++ b/src/ui/style/style_manager.rs @@ -324,9 +324,7 @@ fn btn_s(accent: bool) -> impl Fn(&Theme, Status) -> Style { } pub(crate) fn muted_text_style(theme: &Theme) -> iced::widget::text::Style { - iced::widget::text::Style { - color: Some(theme.palette().background.base.text.scale_alpha(0.68)), - } + crate::ui::style::common::muted_style(theme) } pub(crate) fn hdivider<'a>(width: iced::Length) -> Element<'a, Message> { diff --git a/src/ui/style/tablestyle.rs b/src/ui/style/tablestyle.rs index 4117ec778..1a977dc33 100644 --- a/src/ui/style/tablestyle.rs +++ b/src/ui/style/tablestyle.rs @@ -4,6 +4,7 @@ use crate::app::Message; use crate::t; use iced::widget::{canvas, checkbox, column, row, text, text_input, Column}; use iced::{mouse, Color, Element, Length, Point, Rectangle, Size, Theme}; +use crate::ui::style::common::muted_style; use std::borrow::Cow; use std::fmt; @@ -57,12 +58,6 @@ pub struct TableStyleView<'a> { pub color_open: Option<(u8, &'static str)>, } -fn muted_style(theme: &Theme) -> iced::widget::text::Style { - iced::widget::text::Style { - color: Some(theme.palette().background.base.text.scale_alpha(0.68)), - } -} - fn primary_style(theme: &Theme) -> iced::widget::text::Style { iced::widget::text::Style { color: Some(theme.palette().primary.base.color), diff --git a/src/ui/style/textstyle.rs b/src/ui/style/textstyle.rs index a889b30d5..d1c826add 100644 --- a/src/ui/style/textstyle.rs +++ b/src/ui/style/textstyle.rs @@ -4,6 +4,7 @@ use crate::app::{Message, StyleKind}; use crate::t; use iced::widget::{button, canvas, checkbox, column, container, row, scrollable, text, text_input}; use iced::{mouse, Background, Border, Element, Length, Point, Rectangle, Theme}; +use crate::ui::style::common::muted_style; use std::borrow::Cow; pub struct TextStyleView<'a> { @@ -36,12 +37,6 @@ const BUILTIN_FONTS: &[&str] = &[ "Symbol", "ISO3098", "Unicode", ]; -fn muted_style(theme: &Theme) -> iced::widget::text::Style { - iced::widget::text::Style { - color: Some(theme.palette().background.base.text.scale_alpha(0.68)), - } -} - fn primary_style(theme: &Theme) -> iced::widget::text::Style { iced::widget::text::Style { color: Some(theme.palette().primary.base.color),