wireman-theme 0.2.0

Theme for wireman
Documentation
use crate::{skin, Config};
use logger::Logger;
use once_cell::sync::OnceCell;
use ratatui::{style::Style, widgets::BorderType};

pub static THEME: OnceCell<Theme> = OnceCell::new();

#[derive(Debug, Default, Clone)]
pub struct Theme {
    pub base: Base,
    pub list: List,
    pub border: Border,
    pub navbar: Navbar,
    pub editor: Editor,
    pub history: History,
    pub headers: Headers,
    pub footer: Footer,
    pub help_dialog: HelpDialog,
}

impl Theme {
    pub(crate) fn update_from_skin(&mut self, skin: &skin::Skin) {
        skin.apply_to(self);
    }
}

#[derive(Debug, Clone, Default)]
pub struct Base {
    pub style: Style,
}

#[derive(Debug, Clone)]
pub struct Border {
    pub border: (Style, Style),
    pub text: (Style, Style),
    pub border_type: (BorderType, BorderType),
}

impl Default for Border {
    fn default() -> Self {
        Self {
            border: (Style::default(), Style::default()),
            text: (Style::default(), Style::default()),
            border_type: (BorderType::Plain, BorderType::Double),
        }
    }
}

#[derive(Debug, Clone, Default)]
pub struct Navbar {
    pub title: Style,
    pub tabs: (Style, Style),
}

#[derive(Debug, Clone, Default)]
pub struct List {
    pub text: Style,
    pub focused: Style,
}

#[derive(Debug, Clone, Default)]
pub struct Editor {
    pub text: Style,
    pub cursor: Style,
    pub selection: Style,
    pub status_text: Style,
    pub status_line: Style,
    pub hide_status_line: bool,
}

#[derive(Debug, Clone, Default)]
pub struct History {
    pub active: (Style, Style),
    pub inactive: (Style, Style),
}

#[derive(Debug, Clone, Default)]
pub struct Headers {
    pub titles: Style,
    pub tabs: (Style, Style),
}

#[derive(Debug, Clone, Default)]
pub struct Footer {
    pub tabs: Style,
    pub text: Style,
    pub hide: bool,
}

#[derive(Debug, Clone, Default)]
pub struct HelpDialog {
    pub style: Style,
}

impl Theme {
    /// Initializes the `Theme` from a config.
    pub fn init(config: &Config) {
        let mut theme = Theme::default();

        if let Some(skin_file_path) = &config.skin {
            match skin::Skin::from_file(skin_file_path) {
                Ok(skin) => {
                    theme.update_from_skin(&skin);
                }
                Err(err) => {
                    Logger::debug(format!(
                        "Failed read skin from file {skin_file_path}, err: {err}"
                    ));
                    let default_skin = skin::Skin::default();
                    theme.update_from_skin(&default_skin);
                }
            }
        } else {
            let default_skin = skin::Skin::default();
            theme.update_from_skin(&default_skin);
        }

        let _ = THEME.set(theme.clone());
    }

    /// Gets the globally shared theme data
    #[must_use]
    pub fn global() -> &'static Theme {
        THEME.get_or_init(|| {
            Logger::debug("Theme was not initialized. Fallback to default.");
            Theme::default()
        })
    }
}