use std::sync::atomic::{AtomicU8, Ordering};
use egui::Color32;
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
pub enum Theme {
#[default]
Dark,
Light,
}
impl Theme {
pub fn as_str(self) -> &'static str {
match self {
Theme::Dark => "dark",
Theme::Light => "light",
}
}
pub fn from_str(s: &str) -> Theme {
if s.trim().eq_ignore_ascii_case("light") {
Theme::Light
} else {
Theme::Dark
}
}
pub fn label(self) -> &'static str {
match self {
Theme::Dark => "Dark",
Theme::Light => "Light",
}
}
}
pub struct Palette {
pub accent: Color32,
pub encrypted: Color32,
pub success: Color32,
pub warn: Color32,
pub error: Color32,
pub text: Color32,
pub text_dim: Color32,
pub bg: Color32,
pub panel: Color32,
pub select: Color32,
}
static DARK: Palette = Palette {
accent: Color32::from_rgb(0x4c, 0xc2, 0xff),
encrypted: Color32::from_rgb(0xc9, 0x8b, 0xff),
success: Color32::from_rgb(0x4a, 0xde, 0x80),
warn: Color32::from_rgb(0xfa, 0xcc, 0x15),
error: Color32::from_rgb(0xff, 0x6b, 0x6b),
text: Color32::from_rgb(0xf2, 0xf3, 0xf5),
text_dim: Color32::from_rgb(0xb4, 0xb8, 0xc4),
bg: Color32::from_rgb(0x0b, 0x0b, 0x0f),
panel: Color32::from_rgb(0x15, 0x16, 0x1c),
select: Color32::from_rgb(0x26, 0x31, 0x4a),
};
static LIGHT: Palette = Palette {
accent: Color32::from_rgb(0x03, 0x69, 0xa1),
encrypted: Color32::from_rgb(0x7e, 0x22, 0xce),
success: Color32::from_rgb(0x15, 0x80, 0x3d),
warn: Color32::from_rgb(0xb4, 0x53, 0x09),
error: Color32::from_rgb(0xb9, 0x1c, 0x1c),
text: Color32::from_rgb(0x14, 0x15, 0x1a),
text_dim: Color32::from_rgb(0x52, 0x55, 0x5e),
bg: Color32::from_rgb(0xf4, 0xf5, 0xf7),
panel: Color32::from_rgb(0xff, 0xff, 0xff),
select: Color32::from_rgb(0xcf, 0xe4, 0xff),
};
static CURRENT: AtomicU8 = AtomicU8::new(0);
pub fn current() -> Theme {
match CURRENT.load(Ordering::Relaxed) {
1 => Theme::Light,
_ => Theme::Dark,
}
}
pub fn set_theme(t: Theme) {
CURRENT.store(
match t {
Theme::Dark => 0,
Theme::Light => 1,
},
Ordering::Relaxed,
);
}
pub fn palette() -> &'static Palette {
match current() {
Theme::Dark => &DARK,
Theme::Light => &LIGHT,
}
}
pub fn install(ctx: &egui::Context) {
let theme = current();
let p = palette();
let mut v = match theme {
Theme::Dark => egui::Visuals::dark(),
Theme::Light => egui::Visuals::light(),
};
v.panel_fill = p.panel;
v.window_fill = p.panel;
v.extreme_bg_color = p.bg;
v.faint_bg_color = match theme {
Theme::Dark => Color32::from_rgb(0x1c, 0x1c, 0x24),
Theme::Light => Color32::from_rgb(0xec, 0xee, 0xf2),
};
v.override_text_color = Some(p.text);
v.hyperlink_color = p.accent;
v.selection.bg_fill = p.select;
v.selection.stroke = egui::Stroke::new(1.0, p.accent);
v.widgets.hovered.bg_fill = match theme {
Theme::Dark => Color32::from_rgb(0x22, 0x26, 0x33),
Theme::Light => Color32::from_rgb(0xe3, 0xe7, 0xef),
};
v.widgets.active.bg_fill = p.select;
ctx.set_visuals(v);
let mut style = (*ctx.global_style()).clone();
style.spacing.item_spacing = egui::vec2(8.0, 6.0);
style.spacing.button_padding = egui::vec2(8.0, 4.0);
style.spacing.window_margin = egui::Margin::same(10);
ctx.set_global_style(style);
}