use crate::{unit::*, Color, Style, StyleUpdater};
use derive_rich::Rich;
use std::fmt;
#[derive(Clone, Debug, PartialEq, From, Display)]
pub enum BoxShadow {
One(ShadowValue),
#[display(
fmt = "{}",
"_0.iter().map(|s| s.to_string()).collect::<Vec<_>>().join(\", \")"
)]
Multiple(Vec<ShadowValue>),
#[display(fmt = "initial")]
Initial,
#[display(fmt = "inherit")]
Inherit,
#[display(fmt = "none")]
None,
#[display(fmt = "unset")]
Unset,
}
impl Default for BoxShadow {
fn default() -> Self {
BoxShadow::Multiple(vec![])
}
}
impl StyleUpdater for BoxShadow {
fn update_style(self, style: Style) -> Style {
style.insert("box-shadow", self)
}
}
impl BoxShadow {
fn shadow(mut self, conf: impl FnOnce(ShadowValue) -> ShadowValue) -> Self {
self = match self {
Self::One(shadow) => Self::One(conf(shadow)),
Self::Multiple(shadows) => Self::One(conf(
shadows
.into_iter()
.next()
.unwrap_or_else(ShadowValue::default),
)),
_ => Self::One(conf(ShadowValue::default())),
};
self
}
pub fn new() -> Self {
BoxShadow::Multiple(vec![])
}
pub fn x(self, val: impl Into<Length>) -> Self {
self.shadow(|sh| sh.x(val))
}
pub fn y(self, val: impl Into<Length>) -> Self {
self.shadow(|sh| sh.y(val))
}
pub fn blur(self, val: impl Into<Length>) -> Self {
self.shadow(|sh| sh.blur(val))
}
pub fn try_blur(self, val: Option<impl Into<Length>>) -> Self {
self.shadow(|sh| sh.try_blur(val))
}
pub fn spread(self, val: impl Into<Length>) -> Self {
self.shadow(|sh| sh.spread(val))
}
pub fn try_spread(self, val: Option<impl Into<Length>>) -> Self {
self.shadow(|sh| sh.try_spread(val))
}
pub fn color(self, val: impl Into<Color>) -> Self {
self.shadow(|sh| sh.color(val))
}
pub fn try_color(self, val: Option<impl Into<Color>>) -> Self {
self.shadow(|sh| sh.try_color(val))
}
pub fn inset(self) -> Self {
self.shadow(|sh| sh.inset())
}
pub fn outset(self) -> Self {
self.shadow(|sh| sh.outset())
}
pub fn push(mut self, get_val: impl FnOnce(ShadowValue) -> ShadowValue) -> Self {
let val = get_val(ShadowValue::default());
self = match self {
Self::Multiple(mut vec) => {
vec.push(val);
Self::Multiple(vec)
}
_ => Self::Multiple(vec![val]),
};
self
}
}
#[derive(Rich, Clone, Debug, PartialEq)]
pub struct ShadowValue {
#[rich(write)]
x: Length,
#[rich(write)]
y: Length,
#[rich(write, write(option))]
blur: Option<Length>,
#[rich(write, write(option))]
spread: Option<Length>,
#[rich(write, write(option))]
color: Option<Color>,
#[rich(value_fns = { inset = true, outset = false })]
inset: bool,
}
impl fmt::Display for ShadowValue {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.inset {
write!(f, "inset ")?;
}
write!(f, "{} {}", self.x, self.y)?;
match (self.blur.as_ref(), self.spread.as_ref()) {
(Some(blur), Some(spread)) => write!(f, " {} {}", blur, spread)?,
(Some(blur), None) => write!(f, " {}", blur)?,
(None, Some(spread)) => write!(f, " {} {}", px(0), spread)?,
(None, None) => {}
};
if let Some(color) = self.color {
write!(f, " {}", color)?;
}
Ok(())
}
}
impl Default for ShadowValue {
fn default() -> Self {
Self {
x: px(0),
y: px(0),
blur: None,
spread: None,
color: None,
inset: false,
}
}
}