Scitano/src/theme.rs

159 lines
7.2 KiB
Rust
Executable File

use iced::widget::{button, container};
use iced::{Background, Border, Color, Shadow, Theme};
// ── VS Code Dark+ palette ──────────────────────────────────────────
pub const BG_EDITOR: Color = Color::from_rgb(0.06, 0.06, 0.06); // #0F0F0F
pub const BG_PANEL: Color = Color::from_rgb(0.12, 0.12, 0.12); // #1E1E1E
pub const BG_SIDEBAR: Color = Color::from_rgb(0.10, 0.10, 0.10); // #1A1A1A
pub const BG_ACTIVE_TAB: Color = Color::from_rgb(0.18, 0.18, 0.18); // #2D2D2D
pub const BG_INPUT: Color = Color::from_rgb(0.05, 0.05, 0.05); // #0D0D0D
pub const BG_STATUS: Color = Color::from_rgb(0.06, 0.06, 0.06); // #0F0F0F
pub const BG_FOOTER: Color = Color::from_rgb(0.08, 0.08, 0.08); // #141414
pub const BG_HOVER: Color = Color::from_rgb(0.16, 0.16, 0.16); // #292929
pub const BORDER_COLOR: Color = Color::from_rgb(0.20, 0.20, 0.20); // #333333
pub const BORDER_SUBTLE: Color = Color::from_rgb(0.12, 0.12, 0.12); // #1F1F1F
pub const ACCENT_BLUE: Color = Color::from_rgb(0.00, 0.48, 0.67); // #007ACC
pub const ACCENT_GREEN: Color = Color::from_rgb(0.40, 0.70, 0.40); // #66B366
pub const ACCENT_YELLOW: Color = Color::from_rgb(0.95, 0.85, 0.40); // #F2D966
pub const ACCENT_RED: Color = Color::from_rgb(0.90, 0.40, 0.40); // #E66666
pub const TEXT_PRIMARY: Color = Color::from_rgb(0.83, 0.83, 0.83); // #D4D4D4
pub const TEXT_SECONDARY: Color = Color::from_rgb(0.60, 0.60, 0.60); // #999999
pub const TEXT_MUTED: Color = Color::from_rgb(0.40, 0.40, 0.40); // #666666
pub const TEXT_DIM: Color = Color::from_rgb(0.25, 0.25, 0.25); // #404040
// Traffic light colors
pub const TL_RED: Color = Color::from_rgb(0.96, 0.40, 0.40); // #F56666
pub const TL_YELLOW: Color = Color::from_rgb(0.96, 0.84, 0.40); // #F5D766
pub const TL_GREEN: Color = Color::from_rgb(0.50, 0.87, 0.50); // #80DE80
// ── Container style factories (table-driven: data array + single generator) ──
/// Container spec: (text_color, bg, border_color, border_width, border_radius)
struct ContSpec {
text: Color,
bg: Color,
bc: Color,
bw: f32,
br: f32,
}
const CONTAINER_SPECS: &[(&str, ContSpec)] = &[
("title_bar", ContSpec { text: TEXT_SECONDARY, bg: BG_PANEL, bc: BORDER_SUBTLE, bw: 1.0, br: 0.0 }),
("menu_bar_style", ContSpec { text: TEXT_PRIMARY, bg: BG_PANEL, bc: BORDER_SUBTLE, bw: 1.0, br: 0.0 }),
("panel_container", ContSpec { text: TEXT_PRIMARY, bg: BG_PANEL, bc: Color::TRANSPARENT, bw: 0.0, br: 0.0 }),
("tree_container", ContSpec { text: TEXT_PRIMARY, bg: BG_SIDEBAR, bc: BORDER_COLOR, bw: 1.0, br: 0.0 }),
("app_container", ContSpec { text: TEXT_PRIMARY, bg: BG_EDITOR, bc: Color::TRANSPARENT, bw: 0.0, br: 0.0 }),
("status_bar", ContSpec { text: TEXT_SECONDARY, bg: BG_STATUS, bc: BORDER_SUBTLE, bw: 1.0, br: 0.0 }),
("footer_bar", ContSpec { text: TEXT_MUTED, bg: BG_FOOTER, bc: BORDER_COLOR, bw: 1.0, br: 0.0 }),
("bottom_tab_bar", ContSpec { text: TEXT_SECONDARY, bg: BG_PANEL, bc: BORDER_COLOR, bw: 1.0, br: 0.0 }),
("bottom_content", ContSpec { text: TEXT_PRIMARY, bg: BG_INPUT, bc: Color::TRANSPARENT, bw: 0.0, br: 0.0 }),
];
/// Single generator for all 9 container styles — data-driven, zero repetition.
fn make_container_style(spec: &ContSpec) -> container::Style {
container::Style {
text_color: Some(spec.text),
background: Some(Background::Color(spec.bg)),
border: Border {
color: spec.bc,
width: spec.bw,
radius: spec.br.into(),
},
shadow: Shadow::default(),
}
}
// ── Public container style functions (thin wrappers over the table) ──
pub fn title_bar(_: &Theme) -> container::Style {
make_container_style(&CONTAINER_SPECS[0].1)
}
pub fn menu_bar_style(_: &Theme) -> container::Style {
make_container_style(&CONTAINER_SPECS[1].1)
}
pub fn panel_container(_: &Theme) -> container::Style {
make_container_style(&CONTAINER_SPECS[2].1)
}
pub fn tree_container(_: &Theme) -> container::Style {
make_container_style(&CONTAINER_SPECS[3].1)
}
pub fn app_container(_: &Theme) -> container::Style {
make_container_style(&CONTAINER_SPECS[4].1)
}
pub fn status_bar(_: &Theme) -> container::Style {
make_container_style(&CONTAINER_SPECS[5].1)
}
pub fn footer_bar(_: &Theme) -> container::Style {
make_container_style(&CONTAINER_SPECS[6].1)
}
pub fn bottom_tab_bar(_: &Theme) -> container::Style {
make_container_style(&CONTAINER_SPECS[7].1)
}
pub fn bottom_content(_: &Theme) -> container::Style {
make_container_style(&CONTAINER_SPECS[8].1)
}
// ── Button style factories ──
pub fn menu_button(_: &Theme, status: button::Status) -> button::Style {
let (bg, tc) = match status {
button::Status::Hovered => (BG_HOVER, TEXT_PRIMARY),
button::Status::Pressed => (BG_ACTIVE_TAB, TEXT_PRIMARY),
_ => (Color::TRANSPARENT, TEXT_PRIMARY),
};
button::Style { background: Some(Background::Color(bg)), text_color: tc, border: Border::default(), shadow: Shadow::default() }
}
pub fn active_tab_button(_: &Theme, _: button::Status) -> button::Style {
button::Style {
background: Some(Background::Color(BG_ACTIVE_TAB)),
text_color: TEXT_PRIMARY,
border: Border { color: BORDER_SUBTLE, width: 1.0, radius: 0.0.into() },
shadow: Shadow::default(),
}
}
pub fn inactive_tab_button(_: &Theme, status: button::Status) -> button::Style {
let (bg, tc) = match status {
button::Status::Hovered => (BG_HOVER, TEXT_SECONDARY),
_ => (Color::TRANSPARENT, TEXT_MUTED),
};
button::Style { background: Some(Background::Color(bg)), text_color: tc, border: Border::default(), shadow: Shadow::default() }
}
pub fn bottom_tab_active(_: &Theme, _: button::Status) -> button::Style {
button::Style {
background: Some(Background::Color(BG_ACTIVE_TAB)),
text_color: TEXT_PRIMARY,
border: Border { color: ACCENT_BLUE, width: 1.0, radius: 0.0.into() },
shadow: Shadow::default(),
}
}
pub fn bottom_tab_inactive(_: &Theme, status: button::Status) -> button::Style {
let (bg, tc) = match status {
button::Status::Hovered => (BG_HOVER, TEXT_SECONDARY),
_ => (Color::TRANSPARENT, TEXT_MUTED),
};
button::Style { background: Some(Background::Color(bg)), text_color: tc, border: Border::default(), shadow: Shadow::default() }
}
/// Traffic light styles — retained for optional platform-specific title bars.
#[allow(dead_code)]
fn traffic_light(_: &Theme, _: button::Status, color: Color) -> button::Style {
button::Style {
background: Some(Background::Color(color)),
text_color: Color::TRANSPARENT,
border: Border::default(),
shadow: Shadow::default(),
}
}
#[allow(dead_code)]
pub fn traffic_light_red(t: &Theme, s: button::Status) -> button::Style { traffic_light(t, s, TL_RED) }
#[allow(dead_code)]
pub fn traffic_light_yellow(t: &Theme, s: button::Status) -> button::Style { traffic_light(t, s, TL_YELLOW) }
#[allow(dead_code)]
pub fn traffic_light_green(t: &Theme, s: button::Status) -> button::Style { traffic_light(t, s, TL_GREEN) }