use crate::{color::Color, css, unit::*, StyleUpdater};
use derive_rich::Rich;
#[derive(Rich, Clone, Debug, PartialEq, Default)]
pub struct Border {
#[rich(write(rename = left), write(style = compose))]
pub left: Side,
#[rich(write(rename = top), write(style = compose))]
pub top: Side,
#[rich(write(rename = right), write(style = compose))]
pub right: Side,
#[rich(write(rename = bottom), write(style = compose))]
pub bottom: Side,
#[rich(write(rename = top_left), write(option, rename = try_top_left))]
pub top_left: Option<Radius>,
#[rich(write(rename = top_right), write(option, rename = try_top_right))]
pub top_right: Option<Radius>,
#[rich(write(rename = bottom_left), write(option, rename = try_bottom_left))]
pub bottom_left: Option<Radius>,
#[rich(write(rename = bottom_right), write(option, rename = try_bottom_right))]
pub bottom_right: Option<Radius>,
}
impl StyleUpdater for Border {
fn update_style(self, style: crate::Style) -> crate::Style {
style
.try_insert("border-left-color", self.left.color)
.try_insert("border-left-width", self.left.width)
.try_insert("border-left-style", self.left.style)
.try_insert("border-top-color", self.top.color)
.try_insert("border-top-width", self.top.width)
.try_insert("border-top-style", self.top.style)
.try_insert("border-right-color", self.right.color)
.try_insert("border-right-width", self.right.width)
.try_insert("border-right-style", self.right.style)
.try_insert("border-bottom-color", self.bottom.color)
.try_insert("border-bottom-width", self.bottom.width)
.try_insert("border-bottom-style", self.bottom.style)
.try_insert("border-top-left-radius", self.top_left)
.try_insert("border-top-right-radius", self.top_right)
.try_insert("border-bottom-left-radius", self.bottom_left)
.try_insert("border-bottom-right-radius", self.bottom_right)
}
}
impl<T: Into<Color>> From<T> for Border {
fn from(source: T) -> Self {
Self::default().color(source.into())
}
}
impl From<css::None> for Border {
fn from(_: css::None) -> Self {
Self::default().none()
}
}
macro_rules! sides_style_shortcut_functions {
( $( $fn:ident() $(,)? )* ) => {
$(
pub fn $fn(self) -> Self {
self.all_side(|side| side.$fn())
}
)*
}
}
impl Border {
pub fn all_side(self, value: impl Fn(Side) -> Side + Clone) -> Self {
self.and_left(value.clone())
.and_top(value.clone())
.and_right(value.clone())
.and_bottom(value)
}
pub fn style(self, style: impl Into<Style>) -> Self {
let style = style.into();
self.all_side(|side| side.style(style))
}
pub fn width(self, width: impl Into<Width>) -> Self {
let width = width.into();
self.all_side(|side| side.width(width.clone()))
}
pub fn color(self, color: impl Into<Color>) -> Self {
let color = color.into();
self.all_side(|side| side.color(color))
}
pub fn transparent(self) -> Self {
self.color(Color::Transparent)
}
pub fn radius(self, rad: impl Into<Radius>) -> Self {
let rad = rad.into();
self.top_left(rad.clone())
.top_right(rad.clone())
.bottom_left(rad.clone())
.bottom_right(rad)
}
sides_style_shortcut_functions! {
none(), hidden(), dotted(), dashed(), solid(), double(),
groove(), ridge(), inset(), outset(),
}
}
#[derive(Rich, Clone, Debug, PartialEq, From, Default)]
pub struct Side {
#[rich(write(rename = style), write(option, rename = try_style), value_fns = {
none = css::None,
hidden = css::Hidden,
dotted = css::Dotted,
dashed = css::Dashed,
solid = css::Solid,
double = css::Double,
groove = css::Groove,
ridge = css::Ridge,
inset = css::Inset,
outset = css::Outset,
initial_style = css::Initial,
inherit_style = css::Inherit,
})]
pub style: Option<Style>,
#[rich(write(rename = width), write(option, rename = try_width), value_fns = {
thick = css::Thick,
thin = css::Thin,
medium = css::Medium,
initial_width = css::Initial,
inherit_width = css::Inherit,
})]
pub width: Option<Width>,
#[rich(write(rename = color), write(option, rename = try_color))]
pub color: Option<Color>,
}
#[derive(Clone, Copy, Debug, PartialEq, Display, From)]
pub enum Style {
None(css::None),
Hidden(css::Hidden),
Dotted(css::Dotted),
Dashed(css::Dashed),
Solid(css::Solid),
Double(css::Double),
Groove(css::Groove),
Ridge(css::Ridge),
Inset(css::Inset),
Outset(css::Outset),
Initial(css::Initial),
Inherit(css::Inherit),
}
#[derive(Clone, Debug, PartialEq, Display, From)]
pub enum Width {
Length(Length),
Thin(css::Thin),
Medium(css::Medium),
Thick(css::Thick),
Initial(css::Initial),
Inherit(css::Inherit),
}
#[derive(Clone, Debug, PartialEq, Display, From)]
pub enum Radius {
#[from]
Length(Length),
#[from(forward)]
Percent(Percent),
#[from]
Initial(css::Initial),
#[from]
Inherit(css::Inherit),
}