use crate::ConfigAction;
use crate::theme::ColorsSrgb;
use std::collections::BTreeMap;
use std::time::Duration;
#[derive(Clone, Debug)]
#[non_exhaustive]
pub enum ThemeConfigMsg {
SetActiveTheme(String),
SetActiveScheme(String),
AddScheme(String, ColorsSrgb),
RemoveScheme(String),
FadeDurationMs(u32),
}
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ThemeConfig {
#[cfg_attr(feature = "serde", serde(default))]
pub active_theme: String,
#[cfg_attr(feature = "serde", serde(default = "defaults::default_scheme"))]
pub active_scheme: String,
#[cfg_attr(feature = "serde", serde(default = "defaults::color_schemes"))]
pub color_schemes: BTreeMap<String, ColorsSrgb>,
#[cfg_attr(feature = "serde", serde(default = "defaults::cursor_blink_rate_ms"))]
pub cursor_blink_rate_ms: u32,
#[cfg_attr(feature = "serde", serde(default = "defaults::transition_fade_ms"))]
pub transition_fade_ms: u32,
}
impl Default for ThemeConfig {
fn default() -> Self {
ThemeConfig {
active_theme: "".to_string(),
active_scheme: defaults::default_scheme(),
color_schemes: defaults::color_schemes(),
cursor_blink_rate_ms: defaults::cursor_blink_rate_ms(),
transition_fade_ms: defaults::transition_fade_ms(),
}
}
}
impl ThemeConfig {
pub(super) fn change_config(&mut self, msg: ThemeConfigMsg) -> ConfigAction {
match msg {
ThemeConfigMsg::SetActiveTheme(theme) => self.set_active_theme(theme),
ThemeConfigMsg::SetActiveScheme(scheme) => self.set_active_scheme(scheme),
ThemeConfigMsg::AddScheme(scheme, colors) => self.add_scheme(scheme, colors),
ThemeConfigMsg::RemoveScheme(scheme) => self.remove_scheme(&scheme),
ThemeConfigMsg::FadeDurationMs(dur) => {
self.transition_fade_ms = dur;
ConfigAction::THEME
}
}
}
}
impl ThemeConfig {
pub fn set_active_theme(&mut self, theme: impl ToString) -> ConfigAction {
let theme = theme.to_string();
if self.active_theme == theme {
ConfigAction::empty()
} else {
self.active_theme = theme;
ConfigAction::THEME_SWITCH
}
}
#[inline]
pub fn active_scheme(&self) -> &str {
&self.active_scheme
}
pub fn set_active_scheme(&mut self, scheme: impl ToString) -> ConfigAction {
let scheme = scheme.to_string();
if self.color_schemes.keys().any(|k| *k == scheme) {
self.active_scheme = scheme.to_string();
ConfigAction::THEME
} else {
ConfigAction::empty()
}
}
#[inline]
pub fn color_schemes(&self) -> impl Iterator<Item = (&str, &ColorsSrgb)> {
self.color_schemes.iter().map(|(s, t)| (s.as_str(), t))
}
#[inline]
pub fn get_color_scheme(&self, name: &str) -> Option<&ColorsSrgb> {
self.color_schemes.get(name)
}
#[inline]
pub fn get_active_scheme(&self) -> &ColorsSrgb {
self.color_schemes
.get(&self.active_scheme)
.unwrap_or(&ColorsSrgb::LIGHT)
}
pub fn add_scheme(&mut self, scheme: impl ToString, colors: ColorsSrgb) -> ConfigAction {
self.color_schemes.insert(scheme.to_string(), colors);
ConfigAction::empty()
}
pub fn remove_scheme(&mut self, scheme: &str) -> ConfigAction {
self.color_schemes.remove(scheme);
if scheme == self.active_scheme {
ConfigAction::THEME
} else {
ConfigAction::empty()
}
}
#[inline]
pub fn cursor_blink_rate(&self) -> Duration {
Duration::from_millis(self.cursor_blink_rate_ms as u64)
}
#[inline]
pub fn transition_fade_duration(&self) -> Duration {
Duration::from_millis(self.transition_fade_ms as u64)
}
}
mod defaults {
use super::*;
pub fn default_scheme() -> String {
"light".to_string()
}
pub fn color_schemes() -> BTreeMap<String, ColorsSrgb> {
let mut schemes = BTreeMap::new();
schemes.insert("light".to_string(), ColorsSrgb::LIGHT);
schemes.insert("dark".to_string(), ColorsSrgb::DARK);
schemes.insert("blue".to_string(), ColorsSrgb::BLUE);
schemes
}
pub fn cursor_blink_rate_ms() -> u32 {
600
}
pub fn transition_fade_ms() -> u32 {
150
}
}