1use crate::{color::Color, unit::*, Style, StyleUpdater};
2use derive_rich::Rich;
3
4#[derive(Rich, Clone, Debug, PartialEq, Default)]
15pub struct Background {
16 #[rich(write)]
17 pub color: Option<Color>,
18 #[rich(write, value_fns = { empty = Image::None })]
20 pub image: Option<Image>,
21 #[rich(value_fns = {
22 repeat_x = Repeat::RepeatX,
23 repeat_y = Repeat::RepeatY,
24 repeat = Repeat::Repeat,
25 repeat_with_space = Repeat::Space,
26 repeat_round = Repeat::Round,
27 no_repeat = Repeat::NoRepeat,
28 initial_repeat = Repeat::Initial,
29 inherit_repeat = Repeat::Inherit,
30 })]
31 pub repeat: Option<Repeat>,
32 #[rich(write(rename = attachment), value_fns = {
33 scroll = Attachment::Scroll,
34 fixed = Attachment::Fixed,
35 local = Attachment::Local,
36 initial_attachment = Attachment::Initial,
37 inherit_attachment = Attachment::Inherit,
38 })]
39 pub attachment: Option<Attachment>,
49 #[rich(write(rename = position), value_fns = {
50 center_top = (Horizontal::Center, Vertical::Top(None)),
51 center = (Horizontal::Center, Vertical::Center),
52 center_bottom = (Horizontal::Center, Vertical::Bottom(None)),
53 left_top = (Horizontal::Left(None), Vertical::Top(None)),
54 left_center = (Horizontal::Left(None), Vertical::Center),
55 left_bottom = (Horizontal::Left(None), Vertical::Bottom(None)),
56 right_top = (Horizontal::Right(None), Vertical::Top(None)),
57 right_center = (Horizontal::Right(None), Vertical::Center),
58 right_bottom = (Horizontal::Right(None), Vertical::Bottom(None)),
59 })]
60 pub position: Option<Position>,
61 #[rich(write(rename = clip), value_fns = {
62 fill_under_border = Clip::BorderBox,
63 fill_inside_border = Clip::PaddingBox,
64 fill_under_content = Clip::ContentBox,
65 })]
66 pub clip: Option<Clip>,
67 #[rich(write(rename = origin), value_fns = {
68 image_fill_under_border = Origin::BorderBox,
69 image_inside_border = Origin::PaddingBox,
70 image_under_content = Origin::ContentBox,
71 })]
72 pub origin: Option<Origin>,
73 #[rich(write(rename = size), value_fns = {
74 full = (1.0, 1.0),
75 half = (0.5, 0.5),
76 quarter = (0.25, 0.25),
77 auto_size = Size::Auto,
78 cover = Size::Cover,
79 contain = Size::Contain,
80 })]
81 pub size: Option<Size>,
82}
83
84impl<T: Into<Color>> From<T> for Background {
85 fn from(source: T) -> Self {
86 Background::default().color(source.into())
87 }
88}
89
90impl StyleUpdater for Background {
91 fn update_style(self, style: Style) -> Style {
92 style
93 .try_insert("background-color", self.color)
94 .try_insert("background-image", self.image.as_ref())
95 .try_insert("background-repeat", self.repeat)
96 .try_insert("background-attachment", self.attachment)
97 .try_insert("background-position", self.position)
98 }
99}
100
101#[derive(Clone, Debug, PartialEq, Display, From)]
102pub enum Image {
103 #[display(fmt = "none")]
104 None,
105 #[display(fmt = "url({})", _0)]
106 #[from(forward)]
107 Url(String),
108}
109
110#[derive(Clone, Copy, Debug, PartialEq, Display, From)]
111pub enum Repeat {
112 #[display(fmt = "repeat-x")]
113 RepeatX,
114 #[display(fmt = "repeat-y")]
115 RepeatY,
116 #[display(fmt = "repeat")]
117 Repeat,
118 #[display(fmt = "space")]
119 Space,
120 #[display(fmt = "round")]
121 Round,
122 #[display(fmt = "no-repeat")]
123 NoRepeat,
124 #[display(fmt = "initial")]
125 Initial,
126 #[display(fmt = "inherit")]
127 Inherit,
128}
129
130#[derive(Clone, Copy, Debug, PartialEq, Display, From)]
131pub enum Attachment {
132 #[display(fmt = "scroll")]
133 Scroll,
134 #[display(fmt = "fixed")]
135 Fixed,
136 #[display(fmt = "local")]
137 Local,
138 #[display(fmt = "initial")]
139 Initial,
140 #[display(fmt = "inherit")]
141 Inherit,
142}
143
144fn display_helper(v: &Option<impl ToString>) -> String {
145 v.as_ref()
146 .map_or("".into(), |s| format!(" {}", s.to_string()))
147}
148
149#[derive(Clone, Debug, PartialEq, Display)]
150pub enum Horizontal {
151 #[display(fmt = "center")]
152 Center,
153 #[display(fmt = "left{}", "display_helper(_0)")]
154 Left(Option<Length>),
155 #[display(fmt = "right{}", "display_helper(_0)")]
156 Right(Option<Length>),
157}
158
159#[derive(Clone, Debug, PartialEq, Display)]
160pub enum Vertical {
161 #[display(fmt = "center")]
162 Center,
163 #[display(fmt = "top{}", "display_helper(_0)")]
164 Top(Option<Length>),
165 #[display(fmt = "bottom{}", "display_helper(_0)")]
166 Bottom(Option<Length>),
167}
168
169#[derive(Clone, Debug, PartialEq, Display, From)]
170pub enum Position {
171 #[display(fmt = "{} {}", _0, _1)]
172 #[from]
173 Percent(Percent, Percent),
174 #[display(fmt = "{} {}", _0, _1)]
175 #[from]
176 Placement(Horizontal, Vertical),
177}
178
179impl From<(f32, f32)> for Position {
180 fn from((hor, ver): (f32, f32)) -> Self {
181 Position::Percent(hor.into(), ver.into())
182 }
183}
184
185#[derive(Clone, Copy, Debug, PartialEq, Display, From)]
186pub enum Box {
187 #[display(fmt = "border-box")]
188 BorderBox,
189 #[display(fmt = "padding-box")]
190 PaddingBox,
191 #[display(fmt = "content-box")]
192 ContentBox,
193 #[display(fmt = "initial")]
194 Initial,
195 #[display(fmt = "inherit")]
196 Inherit,
197}
198
199pub type Clip = Box;
200pub type Origin = Box;
201
202#[derive(Clone, Debug, PartialEq, Display, From)]
203pub enum Size {
204 #[display(fmt = "{} {}", _0, _1)]
205 WidthHeight(LengthPercent, LengthPercent),
206 #[display(fmt = "auto")]
207 Auto,
208 #[display(fmt = "cover")]
209 Cover,
210 #[display(fmt = "contain")]
211 Contain,
212 #[display(fmt = "initial")]
213 Initial,
214}
215
216impl From<(f32, f32)> for Size {
217 fn from((width, height): (f32, f32)) -> Self {
218 Self::WidthHeight(width.into(), height.into())
219 }
220}