use crate::geometry::Color;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum BackgroundPattern {
None,
Solid,
Dots,
Lines,
DiagonalForward,
CrossStitch,
}
impl BackgroundPattern {
pub const ALL: [BackgroundPattern; 6] = [
Self::None,
Self::Solid,
Self::Dots,
Self::Lines,
Self::DiagonalForward,
Self::CrossStitch,
];
pub fn name(self) -> &'static str {
match self {
Self::None => "none",
Self::Solid => "solid",
Self::Dots => "dots",
Self::Lines => "lines",
Self::DiagonalForward => "diagonal",
Self::CrossStitch => "cross-stitch",
}
}
pub fn from_name(s: &str) -> Option<Self> {
let key = s.trim().to_ascii_lowercase().replace('_', "-");
Self::ALL.into_iter().find(|p| p.name() == key)
}
pub fn next(self) -> Self {
let i = Self::ALL.iter().position(|&p| p == self).unwrap_or(0);
Self::ALL[(i + 1) % Self::ALL.len()]
}
}
pub const PATTERN_COLORS: [(&str, Color); 4] = [
("superlight", Color::rgb(0xEE, 0xEE, 0xEE)),
("light", Color::rgb(0xC0, 0xC0, 0xC0)),
("dark", Color::rgb(0x40, 0x40, 0x40)),
("black", Color::rgb(0x00, 0x00, 0x00)),
];
pub fn pattern_color(name: &str) -> Option<Color> {
let key = name.trim().to_ascii_lowercase();
PATTERN_COLORS
.iter()
.find(|(n, _)| *n == key)
.map(|(_, c)| *c)
}
pub(crate) struct BackgroundState {
pub pattern: BackgroundPattern,
pub color: Color,
}
impl BackgroundState {
pub fn from_env() -> Self {
let pattern = match std::env::var("SAUDADE_WINDOW_PATTERN") {
Ok(v) => BackgroundPattern::from_name(&v).unwrap_or_else(|| {
eprintln!("[saudade] ignoring unknown SAUDADE_WINDOW_PATTERN={v:?}");
BackgroundPattern::DiagonalForward
}),
Err(_) => BackgroundPattern::DiagonalForward,
};
let color = match std::env::var("SAUDADE_WINDOW_PATTERN_COLOR") {
Ok(v) => pattern_color(&v).unwrap_or_else(|| {
eprintln!("[saudade] ignoring unknown SAUDADE_WINDOW_PATTERN_COLOR={v:?}");
PATTERN_COLORS[0].1
}),
Err(_) => PATTERN_COLORS[0].1,
};
Self { pattern, color }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn pattern_names_round_trip() {
for p in BackgroundPattern::ALL {
assert_eq!(BackgroundPattern::from_name(p.name()), Some(p));
}
}
#[test]
fn pattern_from_name_is_lenient_but_strict() {
assert_eq!(
BackgroundPattern::from_name(" DIAGONAL "),
Some(BackgroundPattern::DiagonalForward)
);
assert_eq!(
BackgroundPattern::from_name("cross_stitch"),
Some(BackgroundPattern::CrossStitch)
);
assert_eq!(BackgroundPattern::from_name("dots2"), None);
assert_eq!(BackgroundPattern::from_name(""), None);
}
#[test]
fn color_lookup_by_name() {
assert_eq!(pattern_color("superlight"), Some(PATTERN_COLORS[0].1));
assert_eq!(pattern_color("BLACK"), Some(Color::rgb(0, 0, 0)));
assert_eq!(pattern_color("chartreuse"), None);
}
}