use crate::CooljapanTheme;
use oxiui_core::{Color, FontSpec, Palette, Theme};
#[derive(Clone, Debug, Default)]
pub struct PartialTheme {
pub background: Option<Color>,
pub surface: Option<Color>,
pub primary: Option<Color>,
pub on_primary: Option<Color>,
pub text_primary: Option<Color>,
pub text_secondary: Option<Color>,
pub font_family: Option<String>,
pub font_size: Option<f32>,
pub font_weight: Option<u16>,
}
pub fn overlay(base: &dyn Theme, overrides: &PartialTheme) -> CooljapanTheme {
let bp = base.palette();
let bf = base.font();
let palette = Palette {
background: overrides.background.unwrap_or(bp.background),
surface: overrides.surface.unwrap_or(bp.surface),
primary: overrides.primary.unwrap_or(bp.primary),
on_primary: overrides.on_primary.unwrap_or(bp.on_primary),
text: overrides.text_primary.unwrap_or(bp.text),
muted: overrides.text_secondary.unwrap_or(bp.muted),
};
let font = FontSpec::new(
overrides.font_family.as_deref().unwrap_or(&bf.family),
overrides.font_size.unwrap_or(bf.size),
overrides.font_weight.unwrap_or(bf.weight),
);
CooljapanTheme::new(palette, font)
}
#[cfg(test)]
mod tests {
use super::*;
use oxiui_core::Theme;
fn base_theme() -> Box<dyn Theme> {
crate::dark()
}
#[test]
fn overlay_override_precedence() {
let base = base_theme();
let red = Color(200, 0, 0, 255);
let overrides = PartialTheme {
background: Some(red),
..PartialTheme::default()
};
let result = overlay(base.as_ref(), &overrides);
assert_eq!(
result.palette().background,
red,
"overlay must apply the override background"
);
}
#[test]
fn overlay_none_fields_keep_base() {
let base = base_theme();
let original_bg = base.palette().background;
let overrides = PartialTheme::default(); let result = overlay(base.as_ref(), &overrides);
assert_eq!(
result.palette().background,
original_bg,
"empty overlay must preserve base"
);
assert_eq!(result.palette().surface, base.palette().surface);
assert_eq!(result.palette().text, base.palette().text);
}
#[test]
fn overlay_multiple_fields() {
let base = base_theme();
let new_text = Color(0, 255, 0, 255);
let new_primary = Color(0, 0, 255, 255);
let overrides = PartialTheme {
text_primary: Some(new_text),
primary: Some(new_primary),
..PartialTheme::default()
};
let result = overlay(base.as_ref(), &overrides);
assert_eq!(result.palette().text, new_text);
assert_eq!(result.palette().primary, new_primary);
assert_eq!(result.palette().background, base.palette().background);
}
}