159 lines
7.2 KiB
Rust
Executable File
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) } |