122 lines
5.2 KiB
Rust
122 lines
5.2 KiB
Rust
use eframe::egui;
|
|
|
|
#[derive(Clone, Copy)]
|
|
pub struct AppTheme {
|
|
pub bg: egui::Color32,
|
|
pub panel: egui::Color32,
|
|
pub panel_strong: egui::Color32,
|
|
pub panel_deep: egui::Color32,
|
|
pub border: egui::Color32,
|
|
pub border_soft: egui::Color32,
|
|
pub text: egui::Color32,
|
|
pub text_dim: egui::Color32,
|
|
pub accent: egui::Color32,
|
|
pub accent_hot: egui::Color32,
|
|
pub radius: u8,
|
|
}
|
|
|
|
pub const ONE_DARK_PRO: AppTheme = AppTheme {
|
|
bg: egui::Color32::from_rgb(40, 44, 52), // #282C34 editor background
|
|
panel: egui::Color32::from_rgb(33, 37, 43), // #21252B sidebar/darker
|
|
panel_strong: egui::Color32::from_rgb(44, 49, 58), // #2C313A slightly lighter
|
|
panel_deep: egui::Color32::from_rgb(27, 31, 39), // #1B1F27 darkest
|
|
border: egui::Color32::from_rgb(62, 68, 81), // #3E4451 border
|
|
border_soft: egui::Color32::from_rgb(44, 49, 58), // #2C313A soft border
|
|
text: egui::Color32::from_rgb(171, 178, 191), // #ABB2BF default text
|
|
text_dim: egui::Color32::from_rgb(92, 99, 112), // #5C6370 dimmed text
|
|
accent: egui::Color32::from_rgb(198, 120, 221), // #C678DD purple (signature)
|
|
accent_hot: egui::Color32::from_rgb(229, 192, 123), // #E5C07B yellow/gold
|
|
radius: 3,
|
|
};
|
|
|
|
// Additional One Dark Pro accent colors (standalone constants)
|
|
pub const ACCENT_GREEN: egui::Color32 = egui::Color32::from_rgb(152, 195, 121); // #98C379
|
|
pub const ACCENT_RED: egui::Color32 = egui::Color32::from_rgb(224, 108, 117); // #E06C75
|
|
pub const ACCENT_BLUE: egui::Color32 = egui::Color32::from_rgb(97, 175, 239); // #61AFEF
|
|
pub const ACCENT_CYAN: egui::Color32 = egui::Color32::from_rgb(86, 182, 194); // #56B6C2
|
|
pub const ACCENT_ORANGE: egui::Color32 = egui::Color32::from_rgb(209, 154, 102); // #D19A66
|
|
|
|
pub fn apply_theme(ctx: &egui::Context, theme: &AppTheme) {
|
|
let mut visuals = egui::Visuals::dark();
|
|
visuals.override_text_color = Some(theme.text);
|
|
visuals.panel_fill = theme.bg;
|
|
visuals.window_fill = theme.panel;
|
|
visuals.window_stroke = egui::Stroke::new(1.0, theme.border);
|
|
visuals.extreme_bg_color = theme.panel_deep;
|
|
visuals.faint_bg_color = theme.panel_strong;
|
|
visuals.code_bg_color = theme.panel_deep;
|
|
visuals.warn_fg_color = theme.accent_hot;
|
|
visuals.error_fg_color = ACCENT_RED;
|
|
|
|
visuals.widgets.noninteractive.bg_fill = theme.panel_strong;
|
|
visuals.widgets.noninteractive.bg_stroke = egui::Stroke::new(1.0, theme.border_soft);
|
|
visuals.widgets.noninteractive.fg_stroke = egui::Stroke::new(1.0, theme.text);
|
|
visuals.widgets.inactive.bg_fill = theme.panel_strong;
|
|
visuals.widgets.inactive.bg_stroke = egui::Stroke::new(1.0, theme.border_soft);
|
|
visuals.widgets.inactive.fg_stroke = egui::Stroke::new(1.0, theme.text);
|
|
visuals.widgets.hovered.bg_fill = egui::Color32::from_rgb(55, 61, 72);
|
|
visuals.widgets.hovered.bg_stroke = egui::Stroke::new(1.0, theme.border);
|
|
visuals.widgets.hovered.fg_stroke = egui::Stroke::new(1.0, theme.text);
|
|
visuals.widgets.active.bg_fill = theme.accent;
|
|
visuals.widgets.active.bg_stroke = egui::Stroke::new(1.0, theme.accent_hot);
|
|
visuals.widgets.active.fg_stroke = egui::Stroke::new(1.0, egui::Color32::WHITE);
|
|
visuals.widgets.open.bg_fill = egui::Color32::from_rgb(50, 56, 66);
|
|
visuals.widgets.open.bg_stroke = egui::Stroke::new(1.0, theme.border);
|
|
visuals.widgets.open.fg_stroke = egui::Stroke::new(1.0, theme.text);
|
|
|
|
visuals.selection.bg_fill = theme.accent;
|
|
visuals.selection.stroke = egui::Stroke::new(1.0, egui::Color32::WHITE);
|
|
visuals.hyperlink_color = theme.accent_hot;
|
|
ctx.set_visuals(visuals);
|
|
|
|
let mut style = (*ctx.global_style()).clone();
|
|
style.spacing.item_spacing = egui::vec2(7.0, 5.0);
|
|
style.spacing.window_margin = egui::Margin::same(7);
|
|
style.visuals.window_corner_radius = egui::CornerRadius::same(theme.radius);
|
|
style.visuals.menu_corner_radius = egui::CornerRadius::same(2);
|
|
style.visuals.window_shadow = egui::epaint::Shadow {
|
|
offset: [0, 12],
|
|
blur: 24,
|
|
spread: 0,
|
|
color: egui::Color32::from_black_alpha(110),
|
|
};
|
|
ctx.set_global_style(style);
|
|
}
|
|
|
|
pub fn panel_frame(ctx: &egui::Context) -> egui::Frame {
|
|
let style = ctx.global_style();
|
|
egui::Frame::window(&style)
|
|
.fill(ONE_DARK_PRO.panel)
|
|
.stroke(egui::Stroke::new(1.0, ONE_DARK_PRO.border))
|
|
.corner_radius(egui::CornerRadius::same(ONE_DARK_PRO.radius))
|
|
.shadow(egui::epaint::Shadow {
|
|
offset: [0, 12],
|
|
blur: 26,
|
|
spread: 0,
|
|
color: egui::Color32::from_black_alpha(120),
|
|
})
|
|
}
|
|
|
|
pub fn group_frame() -> egui::Frame {
|
|
egui::Frame::new()
|
|
.fill(ONE_DARK_PRO.panel_deep)
|
|
.stroke(egui::Stroke::new(1.0, ONE_DARK_PRO.border_soft))
|
|
.corner_radius(egui::CornerRadius::same(2))
|
|
.inner_margin(egui::Margin::symmetric(6, 5))
|
|
}
|
|
|
|
pub fn tag_button(label: impl Into<egui::WidgetText>) -> egui::Button<'static> {
|
|
egui::Button::new(label)
|
|
.fill(ONE_DARK_PRO.panel_strong)
|
|
.stroke(egui::Stroke::new(1.0, ONE_DARK_PRO.border))
|
|
.corner_radius(egui::CornerRadius::same(2))
|
|
}
|
|
|
|
pub fn dim_text() -> egui::Color32 {
|
|
ONE_DARK_PRO.text_dim
|
|
}
|
|
|
|
pub fn accent_text() -> egui::Color32 {
|
|
ONE_DARK_PRO.accent_hot
|
|
}
|