wireman_theme/
theme.rs

1use crate::{skin, Config};
2use logger::Logger;
3use once_cell::sync::OnceCell;
4use ratatui::{style::Style, widgets::BorderType};
5
6pub static THEME: OnceCell<Theme> = OnceCell::new();
7
8#[derive(Debug, Default, Clone)]
9pub struct Theme {
10    pub base: Base,
11    pub highlight: Highlight,
12    pub border: Border,
13    pub title: Title,
14    pub hide_footer: bool,
15    pub hide_status: bool,
16}
17
18impl Theme {
19    pub(crate) fn update_from_skin(&mut self, skin: &skin::Skin) {
20        skin.apply_to(self);
21    }
22}
23
24#[derive(Debug, Clone, Default)]
25pub struct Base {
26    pub focused: Style,
27    pub unfocused: Style,
28}
29
30#[derive(Debug, Clone, Default)]
31pub struct Highlight {
32    pub focused: Style,
33    pub unfocused: Style,
34}
35
36#[derive(Debug, Clone, Default)]
37pub struct Title {
38    pub focused: Style,
39    pub unfocused: Style,
40}
41
42#[allow(clippy::struct_field_names)]
43#[derive(Debug, Clone)]
44pub struct Border {
45    pub focused: Style,
46    pub unfocused: Style,
47    pub border_type: BorderType,
48}
49
50impl Default for Border {
51    fn default() -> Self {
52        Self {
53            focused: Style::default(),
54            unfocused: Style::default(),
55            border_type: BorderType::Rounded,
56        }
57    }
58}
59
60impl Theme {
61    /// Initializes the `Theme` from a config.
62    pub fn init(config: &Config) {
63        let skin = config
64            .skin
65            .as_deref()
66            .and_then(|skin_file| match skin::Skin::from_file(skin_file) {
67                Ok(skin) => Some(skin),
68                Err(err) => {
69                    Logger::debug(format!(
70                        "Failed to read skin from file {skin_file}, err: {err}"
71                    ));
72                    None
73                }
74            })
75            .unwrap_or_default();
76
77        let mut theme = Theme::default();
78        theme.update_from_skin(&skin);
79
80        let _ = THEME.set(theme.clone());
81    }
82
83    /// Gets the globally shared theme data
84    #[must_use]
85    pub fn global() -> &'static Theme {
86        THEME.get_or_init(|| {
87            Logger::debug("Theme was not initialized. Fallback to default.");
88            Theme::default()
89        })
90    }
91}