1use crate::{bindings::*, Declaration};
2
3#[derive(Debug, Clone, Copy)]
5#[repr(u8)]
6pub enum SizingType {
7 Fit = Clay__SizingType_CLAY__SIZING_TYPE_FIT,
9 Grow = Clay__SizingType_CLAY__SIZING_TYPE_GROW,
11 Percent = Clay__SizingType_CLAY__SIZING_TYPE_PERCENT,
13 Fixed = Clay__SizingType_CLAY__SIZING_TYPE_FIXED,
15}
16
17#[derive(Debug, Clone, Copy)]
19pub enum Sizing {
20 Fit(f32, f32),
22 Grow(f32, f32),
24 Fixed(f32),
26 Percent(f32),
28}
29
30impl From<Sizing> for Clay_SizingAxis {
32 fn from(value: Sizing) -> Self {
33 match value {
34 Sizing::Fit(min, max) => Self {
35 type_: SizingType::Fit as _,
36 size: Clay_SizingAxis__bindgen_ty_1 {
37 minMax: Clay_SizingMinMax { min, max },
38 },
39 },
40 Sizing::Grow(min, max) => Self {
41 type_: SizingType::Grow as _,
42 size: Clay_SizingAxis__bindgen_ty_1 {
43 minMax: Clay_SizingMinMax { min, max },
44 },
45 },
46 Sizing::Fixed(size) => Self {
47 type_: SizingType::Fixed as _,
48 size: Clay_SizingAxis__bindgen_ty_1 {
49 minMax: Clay_SizingMinMax {
50 min: size,
51 max: size,
52 },
53 },
54 },
55 Sizing::Percent(percent) => Self {
56 type_: SizingType::Percent as _,
57 size: Clay_SizingAxis__bindgen_ty_1 { percent },
58 },
59 }
60 }
61}
62
63#[derive(Debug, Default)]
65pub struct Padding {
66 pub left: u16,
68 pub right: u16,
70 pub top: u16,
72 pub bottom: u16,
74}
75
76impl Padding {
77 pub fn new(left: u16, right: u16, top: u16, bottom: u16) -> Self {
79 Self {
80 left,
81 right,
82 top,
83 bottom,
84 }
85 }
86
87 pub fn all(value: u16) -> Self {
89 Self::new(value, value, value, value)
90 }
91
92 pub fn horizontal(value: u16) -> Self {
95 Self::new(value, value, 0, 0)
96 }
97
98 pub fn vertical(value: u16) -> Self {
101 Self::new(0, 0, value, value)
102 }
103}
104
105#[derive(Debug, Clone, Copy)]
107#[repr(u8)]
108pub enum LayoutAlignmentX {
109 Left = Clay_LayoutAlignmentX_CLAY_ALIGN_X_LEFT,
111 Center = Clay_LayoutAlignmentX_CLAY_ALIGN_X_CENTER,
113 Right = Clay_LayoutAlignmentX_CLAY_ALIGN_X_RIGHT,
115}
116
117#[derive(Debug, Clone, Copy)]
119#[repr(u8)]
120pub enum LayoutAlignmentY {
121 Top = Clay_LayoutAlignmentY_CLAY_ALIGN_Y_TOP,
123 Center = Clay_LayoutAlignmentY_CLAY_ALIGN_Y_CENTER,
125 Bottom = Clay_LayoutAlignmentY_CLAY_ALIGN_Y_BOTTOM,
127}
128
129#[derive(Debug, Copy, Clone)]
131pub struct Alignment {
132 pub x: LayoutAlignmentX,
133 pub y: LayoutAlignmentY,
134}
135
136impl Alignment {
137 pub fn new(x: LayoutAlignmentX, y: LayoutAlignmentY) -> Self {
139 Self { x, y }
140 }
141}
142
143#[derive(Debug, Clone, Copy)]
145#[repr(u8)]
146pub enum LayoutDirection {
147 LeftToRight = Clay_LayoutDirection_CLAY_LEFT_TO_RIGHT,
149 TopToBottom = Clay_LayoutDirection_CLAY_TOP_TO_BOTTOM,
151}
152
153pub struct LayoutBuilder<
155 'declaration,
156 'render,
157 ImageElementData: 'render,
158 CustomElementData: 'render,
159> {
160 parent: &'declaration mut Declaration<'render, ImageElementData, CustomElementData>,
161}
162
163impl<'declaration, 'render, ImageElementData: 'render, CustomElementData: 'render>
164 LayoutBuilder<'declaration, 'render, ImageElementData, CustomElementData>
165{
166 #[inline]
168 pub fn new(
169 parent: &'declaration mut Declaration<'render, ImageElementData, CustomElementData>,
170 ) -> Self {
171 LayoutBuilder { parent }
172 }
173
174 #[inline]
176 pub fn width(&mut self, width: Sizing) -> &mut Self {
177 self.parent.inner.layout.sizing.width = width.into();
178 self
179 }
180
181 #[inline]
183 pub fn height(&mut self, height: Sizing) -> &mut Self {
184 self.parent.inner.layout.sizing.height = height.into();
185 self
186 }
187
188 #[inline]
190 pub fn padding(&mut self, padding: Padding) -> &mut Self {
191 self.parent.inner.layout.padding.left = padding.left;
192 self.parent.inner.layout.padding.right = padding.right;
193 self.parent.inner.layout.padding.top = padding.top;
194 self.parent.inner.layout.padding.bottom = padding.bottom;
195 self
196 }
197
198 #[inline]
200 pub fn child_gap(&mut self, child_gap: u16) -> &mut Self {
201 self.parent.inner.layout.childGap = child_gap;
202 self
203 }
204
205 #[inline]
207 pub fn child_alignment(&mut self, child_alignment: Alignment) -> &mut Self {
208 self.parent.inner.layout.childAlignment.x = child_alignment.x as _;
209 self.parent.inner.layout.childAlignment.y = child_alignment.y as _;
210 self
211 }
212
213 #[inline]
215 pub fn direction(&mut self, direction: LayoutDirection) -> &mut Self {
216 self.parent.inner.layout.layoutDirection = direction as _;
217 self
218 }
219
220 #[inline]
222 pub fn end(&mut self) -> &mut Declaration<'render, ImageElementData, CustomElementData> {
223 self.parent
224 }
225}
226
227#[macro_export]
229macro_rules! fit {
230 ($min:expr, $max:expr) => {
231 $crate::layout::Sizing::Fit($min, $max)
232 };
233 ($min:expr) => {
234 fit!($min, f32::MAX)
235 };
236 () => {
237 fit!(0.0)
238 };
239}
240
241#[macro_export]
243macro_rules! grow {
244 ($min:expr, $max:expr) => {
245 $crate::layout::Sizing::Grow($min, $max)
246 };
247 ($min:expr) => {
248 grow!($min, f32::MAX)
249 };
250 () => {
251 grow!(0.0)
252 };
253}
254
255#[macro_export]
257macro_rules! fixed {
258 ($val:expr) => {
259 $crate::layout::Sizing::Fixed($val)
260 };
261}
262
263#[macro_export]
266macro_rules! percent {
267 ($percent:expr) => {{
268 const _: () = assert!(
269 $percent >= 0.0 && $percent <= 1.0,
270 "Percent value must be between 0.0 and 1.0 inclusive!"
271 );
272 $crate::layout::Sizing::Percent($percent)
273 }};
274}
275
276#[cfg(test)]
277mod test {
278 use super::*;
279 use crate::{fit, fixed, grow, percent};
280
281 #[test]
282 fn fit_macro() {
283 let both_args = fit!(12.0, 34.0);
284 assert!(matches!(both_args, Sizing::Fit(12.0, 34.0)));
285
286 let one_arg = fit!(12.0);
287 assert!(matches!(one_arg, Sizing::Fit(12.0, f32::MAX)));
288
289 let zero_args = fit!();
290 assert!(matches!(zero_args, Sizing::Fit(0.0, f32::MAX)));
291 }
292
293 #[test]
294 fn grow_macro() {
295 let both_args = grow!(12.0, 34.0);
296 assert!(matches!(both_args, Sizing::Grow(12.0, 34.0)));
297
298 let one_arg = grow!(12.0);
299 assert!(matches!(one_arg, Sizing::Grow(12.0, f32::MAX)));
300
301 let zero_args = grow!();
302 assert!(matches!(zero_args, Sizing::Grow(0.0, f32::MAX)));
303 }
304
305 #[test]
306 fn fixed_macro() {
307 let value = fixed!(123.0);
308 assert!(matches!(value, Sizing::Fixed(123.0)));
309 }
310
311 #[test]
312 fn percent_macro() {
313 let value = percent!(0.5);
314 assert!(matches!(value, Sizing::Percent(0.5)));
315 }
316}