faststep 0.1.0

UIKit-inspired embedded UI framework built on embedded-graphics
Documentation
use embedded_graphics::{pixelcolor::Rgb565, prelude::RgbColor};

use crate::FsTheme;

use super::ButtonKind;

pub(super) fn background(kind: ButtonKind, theme: &FsTheme, highlighted: bool) -> Rgb565 {
    let base = match kind {
        ButtonKind::Primary => theme.accent,
        ButtonKind::Secondary => theme.surface_alt,
        ButtonKind::Destructive => theme.danger,
        ButtonKind::Ghost => theme.surface,
    };
    if highlighted {
        match kind {
            ButtonKind::Ghost => lighten(theme.surface_alt, 280),
            _ => lighten(base, 180),
        }
    } else {
        base
    }
}

pub(super) fn border(kind: ButtonKind, theme: &FsTheme, highlighted: bool) -> Rgb565 {
    let base = match kind {
        ButtonKind::Ghost => theme.surface_alt,
        _ => background(kind, theme, false),
    };
    if highlighted {
        match kind {
            ButtonKind::Ghost => lighten(theme.accent, 120),
            _ => lighten(base, 260),
        }
    } else {
        base
    }
}

pub(super) fn foreground(kind: ButtonKind, theme: &FsTheme, highlighted: bool) -> Rgb565 {
    match kind {
        ButtonKind::Ghost if highlighted => lighten(theme.text_primary, 120),
        ButtonKind::Ghost => theme.text_primary,
        ButtonKind::Primary => theme.text_on_accent,
        ButtonKind::Secondary => theme.text_primary,
        ButtonKind::Destructive => theme.text_on_danger,
    }
}

fn lighten(color: Rgb565, permille: u16) -> Rgb565 {
    Rgb565::new(
        lift(color.r(), 31, permille),
        lift(color.g(), 63, permille),
        lift(color.b(), 31, permille),
    )
}

fn lift(value: u8, max: u8, permille: u16) -> u8 {
    let value = u32::from(value);
    let max = u32::from(max);
    let permille = u32::from(permille.min(1000));
    (value + (((max - value) * permille) / 1000)) as u8
}