1use crate::{ChromeRefinement, Space};
2
3pub trait RefineStyle: Sized {
4 fn refine_style(self, style: ChromeRefinement) -> Self;
5}
6
7pub trait Stylable: Sized {
8 fn apply_style(self, style: ChromeRefinement) -> Self;
9}
10
11impl<T: RefineStyle> Stylable for T {
12 fn apply_style(self, style: ChromeRefinement) -> Self {
13 RefineStyle::refine_style(self, style)
14 }
15}
16
17pub struct Styled<T> {
18 inner: T,
19 style: ChromeRefinement,
20}
21
22impl<T> Styled<T> {
23 pub fn new(inner: T) -> Self {
24 Self {
25 inner,
26 style: ChromeRefinement::default(),
27 }
28 }
29
30 pub fn refine_style(mut self, style: ChromeRefinement) -> Self {
31 self.style = self.style.merge(style);
32 self
33 }
34
35 pub fn px_1(mut self) -> Self {
36 self.style = self.style.px_1();
37 self
38 }
39
40 pub fn px_0p5(mut self) -> Self {
41 self.style = self.style.px_0p5();
42 self
43 }
44
45 pub fn px_0(mut self) -> Self {
46 self.style = self.style.px_0();
47 self
48 }
49
50 pub fn px_1p5(mut self) -> Self {
51 self.style = self.style.px_1p5();
52 self
53 }
54
55 pub fn px_2(mut self) -> Self {
56 self.style = self.style.px_2();
57 self
58 }
59
60 pub fn px_2p5(mut self) -> Self {
61 self.style = self.style.px_2p5();
62 self
63 }
64
65 pub fn px_3(mut self) -> Self {
66 self.style = self.style.px_3();
67 self
68 }
69
70 pub fn px_4(mut self) -> Self {
71 self.style = self.style.px_4();
72 self
73 }
74
75 pub fn py_1(mut self) -> Self {
76 self.style = self.style.py_1();
77 self
78 }
79
80 pub fn py_0p5(mut self) -> Self {
81 self.style = self.style.py_0p5();
82 self
83 }
84
85 pub fn py_0(mut self) -> Self {
86 self.style = self.style.py_0();
87 self
88 }
89
90 pub fn py_1p5(mut self) -> Self {
91 self.style = self.style.py_1p5();
92 self
93 }
94
95 pub fn py_2(mut self) -> Self {
96 self.style = self.style.py_2();
97 self
98 }
99
100 pub fn py_2p5(mut self) -> Self {
101 self.style = self.style.py_2p5();
102 self
103 }
104
105 pub fn py_3(mut self) -> Self {
106 self.style = self.style.py_3();
107 self
108 }
109
110 pub fn py_4(mut self) -> Self {
111 self.style = self.style.py_4();
112 self
113 }
114
115 pub fn pt(mut self, space: Space) -> Self {
116 self.style = self.style.pt(space);
117 self
118 }
119
120 pub fn pr(mut self, space: Space) -> Self {
121 self.style = self.style.pr(space);
122 self
123 }
124
125 pub fn pb(mut self, space: Space) -> Self {
126 self.style = self.style.pb(space);
127 self
128 }
129
130 pub fn pl(mut self, space: Space) -> Self {
131 self.style = self.style.pl(space);
132 self
133 }
134
135 pub fn p_1(mut self) -> Self {
136 self.style = self.style.p_1();
137 self
138 }
139
140 pub fn p_0(mut self) -> Self {
141 self.style = self.style.p_0();
142 self
143 }
144
145 pub fn p_0p5(mut self) -> Self {
146 self.style = self.style.p_0p5();
147 self
148 }
149
150 pub fn p_1p5(mut self) -> Self {
151 self.style = self.style.p_1p5();
152 self
153 }
154
155 pub fn p_2(mut self) -> Self {
156 self.style = self.style.p_2();
157 self
158 }
159
160 pub fn p_2p5(mut self) -> Self {
161 self.style = self.style.p_2p5();
162 self
163 }
164
165 pub fn p_3(mut self) -> Self {
166 self.style = self.style.p_3();
167 self
168 }
169
170 pub fn p_4(mut self) -> Self {
171 self.style = self.style.p_4();
172 self
173 }
174
175 pub fn rounded_md(mut self) -> Self {
176 self.style = self.style.rounded_md();
177 self
178 }
179
180 pub fn border_1(mut self) -> Self {
181 self.style = self.style.border_1();
182 self
183 }
184}
185
186impl<T: Stylable> Styled<T> {
187 pub fn finish(self) -> T {
188 self.inner.apply_style(self.style)
189 }
190}
191
192pub trait StyledExt: RefineStyle + Sized {
193 fn styled(self) -> Styled<Self> {
194 Styled::new(self)
195 }
196}
197
198impl<T: RefineStyle> StyledExt for T {}
199
200#[cfg(test)]
204mod tests {
205 use super::*;
206 use crate::{MetricRef, Space};
207
208 #[derive(Debug, Default, Clone)]
209 struct Dummy {
210 style: ChromeRefinement,
211 }
212
213 impl RefineStyle for Dummy {
214 fn refine_style(mut self, style: ChromeRefinement) -> Self {
215 self.style = style;
216 self
217 }
218 }
219
220 #[test]
221 fn styled_ext_builds_a_refinement_chain() {
222 let dummy = Dummy::default()
223 .styled()
224 .px_3()
225 .py_2()
226 .border_1()
227 .rounded_md()
228 .finish();
229
230 let padding = dummy.style.padding.expect("expected padding refinement");
231 match padding.left {
232 Some(MetricRef::Token { key, .. }) => assert_eq!(key, Space::N3.token_key()),
233 _ => panic!("expected left padding token"),
234 }
235 match padding.right {
236 Some(MetricRef::Token { key, .. }) => assert_eq!(key, Space::N3.token_key()),
237 _ => panic!("expected right padding token"),
238 }
239 match padding.top {
240 Some(MetricRef::Token { key, .. }) => assert_eq!(key, Space::N2.token_key()),
241 _ => panic!("expected top padding token"),
242 }
243 match padding.bottom {
244 Some(MetricRef::Token { key, .. }) => assert_eq!(key, Space::N2.token_key()),
245 _ => panic!("expected bottom padding token"),
246 }
247 assert!(dummy.style.border_width.is_some());
248 assert!(dummy.style.radius.is_some());
249 }
250}