use chrono::Timelike;
use egui::{Color32, Margin, Visuals};
pub struct UiTheme;
#[derive(Debug, Clone, Copy, PartialEq, serde::Deserialize, serde::Serialize)]
pub enum ThemeMode {
Auto,
Light,
Dark,
}
impl UiTheme {
pub const PADDING: f32 = 20.0;
pub const SPACING: f32 = 12.0;
pub const ROUNDING: u8 = 12; pub const BUTTON_HEIGHT: f32 = 36.0;
pub const ICON_SIZE: f32 = 18.0;
pub const PRIMARY: Color32 = Color32::from_rgb(0, 120, 215);
pub const SUCCESS: Color32 = Color32::from_rgb(16, 124, 16);
pub const ERROR: Color32 = Color32::from_rgb(209, 52, 56);
pub fn standard_margin() -> Margin {
Margin {
left: Self::PADDING as i8,
right: Self::PADDING as i8,
top: Self::PADDING as i8,
bottom: Self::PADDING as i8,
}
}
pub fn apply_master_visuals(ctx: &egui::Context, mode: ThemeMode) {
let is_dark = match mode {
ThemeMode::Light => false,
ThemeMode::Dark => true,
ThemeMode::Auto => {
let hour = chrono::Local::now().hour();
!(6..18).contains(&hour) }
};
let mut visuals = if is_dark {
let mut v = Visuals::dark();
v.panel_fill = Color32::from_rgb(18, 20, 24);
v.widgets.noninteractive.bg_fill = Color32::from_rgb(30, 33, 37);
v.widgets.noninteractive.weak_bg_fill = Color32::from_rgb(40, 44, 49);
v.extreme_bg_color = Color32::from_rgb(12, 14, 16);
v.widgets.noninteractive.fg_stroke.color = Color32::from_gray(200);
v.widgets.noninteractive.bg_stroke.color = Color32::from_gray(50);
v.widgets.inactive.corner_radius = 12.0.into();
v.widgets.hovered.corner_radius = 12.0.into();
v.widgets.active.corner_radius = 12.0.into();
v
} else {
let mut v = Visuals::light();
v.panel_fill = Color32::from_rgb(248, 249, 250);
v.widgets.noninteractive.bg_fill = Color32::from_rgb(240, 242, 245);
v.widgets.noninteractive.weak_bg_fill = Color32::from_rgb(255, 255, 255);
v.extreme_bg_color = Color32::from_rgb(230, 233, 237);
v.widgets.noninteractive.fg_stroke.color = Color32::from_rgb(45, 45, 45); v.widgets.noninteractive.bg_stroke.color = Color32::from_gray(200);
v.widgets.inactive.corner_radius = 12.0.into();
v.widgets.hovered.corner_radius = 12.0.into();
v.widgets.active.corner_radius = 12.0.into();
v
};
visuals.window_corner_radius = 15.0.into();
visuals.selection.bg_fill = Self::PRIMARY;
ctx.set_visuals(visuals);
}
pub fn center_content<R>(
ui: &mut egui::Ui,
add_contents: impl FnOnce(&mut egui::Ui) -> R,
) -> R {
ui.vertical_centered(|ui| {
ui.add_space(ui.available_height() / 3.0);
add_contents(ui)
})
.inner
}
}