domi-egui 0.1.0

DOMicile 15-primitive widget library for egui (Phase 3c).
use egui::Color32;

include!(concat!(env!("OUT_DIR"), "/generated/tokens.rs"));

#[derive(Clone, Debug)]
pub struct PrimaryTheme {
    pub gradient_stops: Vec<Color32>,
    pub angle: String,
}

#[derive(Clone, Debug)]
pub struct Theme {
    pub primary: PrimaryTheme,
    pub text_default: Color32,
    pub text_muted: Color32,
    pub text_inverse: Color32,
    pub surface_glass: Color32,
    pub surface_glass_strong: Color32,
    pub radius: (f32, f32, f32, f32),
    pub space: (f32, f32, f32, f32, f32),
    pub body_font: egui::FontFamily,
    pub display_font: egui::FontFamily,
}

impl Default for Theme {
    fn default() -> Self {
        let stops = COLOR_PRIMARY_GRADIENT
            .iter()
            .map(|hex| parse_hex(hex).expect("hex from tokens.json"))
            .collect();
        let primary = PrimaryTheme {
            gradient_stops: stops,
            angle: COLOR_PRIMARY_ANGLE.to_string(),
        };

        Self {
            primary,
            text_default: parse_hex(TEXT_DEFAULT).expect("TEXT_DEFAULT hex"),
            text_muted: parse_hex(TEXT_MUTED).expect("TEXT_MUTED hex"),
            text_inverse: parse_hex(TEXT_INVERSE).expect("TEXT_INVERSE hex"),
            surface_glass: parse_hex(SURFACE_GLASS).expect("SURFACE_GLASS hex"),
            surface_glass_strong: parse_hex(SURFACE_GLASS_STRONG)
                .expect("SURFACE_GLASS_STRONG hex"),
            radius: (RADIUS_SM, RADIUS_MD, RADIUS_LG, RADIUS_PILL),
            space: (SPACE_XS, SPACE_SM, SPACE_MD, SPACE_LG, SPACE_XL),
            body_font: egui::FontFamily::Monospace,
            display_font: egui::FontFamily::Proportional,
        }
    }
}

pub fn parse_hex(hex: &str) -> Option<Color32> {
    let body = hex.trim_start_matches('#');
    if body.len() == 6 {
        let r = u8::from_str_radix(&body[0..2], 16).ok()?;
        let g = u8::from_str_radix(&body[2..4], 16).ok()?;
        let b = u8::from_str_radix(&body[4..6], 16).ok()?;
        Some(Color32::from_rgb(r, g, b))
    } else if body.len() == 8 {
        let r = u8::from_str_radix(&body[0..2], 16).ok()?;
        let g = u8::from_str_radix(&body[2..4], 16).ok()?;
        let b = u8::from_str_radix(&body[4..6], 16).ok()?;
        let a = u8::from_str_radix(&body[6..8], 16).ok()?;
        Some(Color32::from_rgba_unmultiplied(r, g, b, a))
    } else {
        None
    }
}