use crate::theme::{Theme, ThemeColors, ThemeKind, ThemeSpacing, ThemeVisuals, Typography};
use crate::visuals::*;
use egui::{
Color32, CornerRadius, Frame, Margin, Shadow, Spacing, Stroke, Style, Visuals,
style::{Selection, WidgetVisuals, Widgets},
vec2,
};
const STORM: Color32 = Color32::from_rgba_premultiplied(214, 216, 223, 255);
const PAPER: Color32 = Color32::from_rgba_premultiplied(230, 231, 237, 255);
const HAZE: Color32 = Color32::from_rgba_premultiplied(200, 203, 214, 255);
const INK: Color32 = Color32::from_rgba_premultiplied(42, 47, 74, 255);
const MUTED: Color32 = Color32::from_rgba_premultiplied(61, 69, 102, 255);
const TEAL: Color32 = Color32::from_rgba_premultiplied(10, 90, 110, 255);
const IRIS: Color32 = Color32::from_rgba_premultiplied(85, 32, 168, 255);
const AMBER: Color32 = Color32::from_rgba_premultiplied(138, 61, 0, 255);
const WINE: Color32 = Color32::from_rgba_premultiplied(155, 32, 54, 255);
const PINE: Color32 = Color32::from_rgba_premultiplied(13, 92, 64, 255);
const MIST: Color32 = Color32::from_rgba_premultiplied(193, 194, 199, 255);
const FADED_MIST: Color32 = Color32::from_rgba_premultiplied(193, 194, 199, 118);
const HIGHLIGHT: Color32 = Color32::from_rgba_premultiplied(172, 176, 191, 255);
const DUSK: Color32 = Color32::from_rgba_premultiplied(122, 133, 168, 255);
const TITLE_BAR: Color32 = STORM;
const MAIN_BG: Color32 = STORM;
const WIDGET_BG: Color32 = PAPER;
const HOVER: Color32 = HAZE;
const TEXT: Color32 = INK;
const TEXT_MUTED: Color32 = MUTED;
const BORDER: Color32 = MIST;
const ACCENT: Color32 = TEAL;
const ERROR: Color32 = WINE;
const WARNING: Color32 = AMBER;
const SUCCESS: Color32 = PINE;
const INFO: Color32 = IRIS;
const CORNER_RADIUS: u8 = 6;
const INNER_MARGIN: i8 = 10;
const OUTER_MARGIN: i8 = 5;
pub fn theme() -> Theme {
Theme {
dark: false,
image_tint_recommended: false,
kind: ThemeKind::TokyoNightLight,
colors: colors(),
typography: typography(),
spacing: ThemeSpacing::default(),
window_frame: window_frame(&colors()),
frame1: frame1(&colors()),
frame2: frame2(&colors()),
visuals: theme_visuals(),
corner_radius: CORNER_RADIUS,
inner_margin: INNER_MARGIN,
outer_margin: OUTER_MARGIN,
button_padding: vec2(10.0, 8.0),
#[cfg(feature = "elegance")]
elegance_key: None,
}
}
fn colors() -> ThemeColors {
ThemeColors {
title_bar: TITLE_BAR,
bg: MAIN_BG,
widget_bg: WIDGET_BG,
hover: HOVER,
text: TEXT,
text_muted: TEXT_MUTED,
highlight: HIGHLIGHT,
border: BORDER,
accent: ACCENT,
error: ERROR,
warning: WARNING,
success: SUCCESS,
info: INFO,
}
}
fn typography() -> Typography {
Typography {
very_small: 12.0,
small: 14.0,
normal: 16.0,
large: 18.0,
very_large: 20.0,
heading: 26.0,
}
}
pub fn window_frame(colors: &ThemeColors) -> Frame {
let shadow = Shadow {
offset: (0, 0).into(),
blur: 3,
spread: 0,
color: colors.border,
};
Frame {
corner_radius: CornerRadius::same(CORNER_RADIUS),
inner_margin: Margin::same(INNER_MARGIN),
fill: colors.bg,
stroke: Stroke::new(1.0, colors.border),
shadow: shadow,
..Default::default()
}
}
pub fn frame1(colors: &ThemeColors) -> Frame {
let shadow = Shadow {
offset: (0, 0).into(),
blur: 2,
spread: 0,
color: colors.border,
};
Frame {
corner_radius: CornerRadius::same(CORNER_RADIUS),
inner_margin: Margin::same(INNER_MARGIN),
fill: colors.widget_bg,
stroke: Stroke::NONE,
shadow: shadow,
..Default::default()
}
}
pub fn frame1_visuals(colors: &ThemeColors) -> FrameVisuals {
FrameVisuals {
bg: colors.widget_bg,
bg_hover: colors.hover,
bg_click: colors.widget_bg,
bg_selected: colors.highlight,
border: Stroke::NONE,
border_hover: Stroke::new(0.0, colors.highlight),
border_click: Stroke::new(0.0, colors.highlight),
corner_radius: CornerRadius::same(CORNER_RADIUS),
shadow: Shadow {
offset: (0, 0).into(),
blur: 2,
spread: 0,
color: colors.border,
},
}
}
pub fn frame2(colors: &ThemeColors) -> Frame {
let shadow = Shadow {
offset: (0, 0).into(),
blur: 2,
spread: 0,
color: colors.border,
};
Frame {
corner_radius: CornerRadius::same(CORNER_RADIUS),
inner_margin: Margin::same(INNER_MARGIN),
fill: colors.bg,
stroke: Stroke::NONE,
shadow: shadow,
..Default::default()
}
}
pub fn frame2_visuals(colors: &ThemeColors) -> FrameVisuals {
FrameVisuals {
bg: colors.bg,
bg_hover: colors.hover,
bg_click: colors.bg,
bg_selected: colors.highlight,
border: Stroke::NONE,
border_hover: Stroke::new(0.0, colors.highlight),
border_click: Stroke::new(0.0, colors.highlight),
corner_radius: CornerRadius::same(CORNER_RADIUS),
shadow: Shadow {
offset: (0, 0).into(),
blur: 2,
spread: 0,
color: colors.border,
},
}
}
pub fn button_visuals() -> ButtonVisuals {
ButtonVisuals {
text: TEXT,
bg: WIDGET_BG,
bg_hover: HOVER,
bg_click: WIDGET_BG,
bg_selected: HIGHLIGHT,
border: Stroke::new(1.0, Color32::TRANSPARENT),
border_hover: Stroke::new(1.0, DUSK),
border_click: Stroke::new(1.0, Color32::TRANSPARENT),
corner_radius: CornerRadius::same(3),
shadow: Shadow {
offset: (0, 0).into(),
blur: 2,
spread: 1,
color: MIST,
},
}
}
pub fn combo_box_visuals() -> ComboBoxVisuals {
ComboBoxVisuals {
bg: WIDGET_BG,
icon: TEXT,
bg_hover: HOVER,
bg_open: WIDGET_BG,
border: Stroke::new(1.0, Color32::TRANSPARENT),
border_hover: Stroke::new(1.0, DUSK),
border_open: Stroke::new(1.0, Color32::TRANSPARENT),
corner_radius: CornerRadius::same(CORNER_RADIUS),
shadow: Shadow {
offset: (0, 0).into(),
blur: 2,
spread: 1,
color: MIST,
},
}
}
pub fn label_visuals() -> ButtonVisuals {
ButtonVisuals {
bg: Color32::TRANSPARENT,
border: Stroke::new(1.0, Color32::TRANSPARENT),
border_hover: Stroke::new(1.0, Color32::TRANSPARENT),
border_click: Stroke::new(1.0, Color32::TRANSPARENT),
..button_visuals()
}
}
pub fn text_edit_visuals() -> TextEditVisuals {
TextEditVisuals {
text: TEXT,
bg: WIDGET_BG,
border: Stroke::new(1.0, BORDER),
border_hover: Stroke::new(1.0, TEAL),
border_open: Stroke::new(1.0, TEAL),
corner_radius: CornerRadius::same(CORNER_RADIUS),
shadow: Shadow::NONE,
}
}
pub fn style() -> Style {
let widgets = widgets(colors());
let visuals = visuals(widgets, &colors());
let spacing = Spacing {
window_margin: Margin::same(10),
..Default::default()
};
Style {
visuals,
animation_time: 0.3,
spacing,
..Default::default()
}
}
fn theme_visuals() -> ThemeVisuals {
ThemeVisuals {
button_visuals: button_visuals(),
label_visuals: label_visuals(),
combo_box_visuals: combo_box_visuals(),
text_edit_visuals: text_edit_visuals(),
frame1_visuals: frame1_visuals(&colors()),
frame2_visuals: frame2_visuals(&colors()),
}
}
fn visuals(widgets: Widgets, colors: &ThemeColors) -> Visuals {
Visuals {
dark_mode: false,
override_text_color: Some(colors.text),
widgets,
selection: Selection {
bg_fill: colors.highlight, stroke: Stroke::new(1.0, colors.accent), },
hyperlink_color: colors.info,
faint_bg_color: colors.bg,
extreme_bg_color: colors.widget_bg,
code_bg_color: colors.bg,
warn_fg_color: colors.warning,
error_fg_color: colors.error,
window_corner_radius: CornerRadius::same(CORNER_RADIUS),
window_shadow: Shadow {
offset: (0, 0).into(),
blur: 3,
spread: 0,
color: FADED_MIST,
},
window_fill: colors.bg,
window_stroke: Stroke::new(1.0, Color32::TRANSPARENT),
panel_fill: colors.bg,
..Default::default()
}
}
fn widgets(colors: ThemeColors) -> Widgets {
let base_visuals = WidgetVisuals {
bg_fill: colors.widget_bg,
weak_bg_fill: colors.bg,
bg_stroke: Stroke::new(1.0, colors.border),
corner_radius: CornerRadius::same(CORNER_RADIUS),
fg_stroke: Stroke::new(1.0, colors.text),
expansion: 0.0,
};
let mut non_interactive_base = base_visuals.clone();
non_interactive_base.bg_stroke.width = 1.0;
let mut inactive_visuals = base_visuals.clone();
inactive_visuals.bg_fill = colors.highlight;
Widgets {
noninteractive: non_interactive_base,
inactive: inactive_visuals,
hovered: WidgetVisuals {
bg_fill: colors.widget_bg,
weak_bg_fill: colors.hover,
bg_stroke: Stroke::new(1.0, colors.hover),
..base_visuals
},
active: WidgetVisuals {
bg_fill: colors.widget_bg,
weak_bg_fill: colors.widget_bg,
bg_stroke: Stroke::new(1.0, colors.border),
..base_visuals
},
open: WidgetVisuals {
bg_fill: colors.widget_bg,
weak_bg_fill: colors.widget_bg,
bg_stroke: Stroke::new(1.0, colors.border),
..base_visuals
},
}
}