1use std::rc::Rc;
2
3use taffy::{AlignContent, AlignItems, AlignSelf, JustifyContent};
4
5use crate::{Brush, Color, PointerEvent, Size, Transform, Vec2};
6
7#[derive(Clone, Debug)]
8pub struct Border {
9 pub width: f32,
10 pub color: Color,
11 pub radius: f32,
12}
13
14#[derive(Clone, Copy, Debug, Default)]
15pub struct PaddingValues {
16 pub left: f32,
17 pub right: f32,
18 pub top: f32,
19 pub bottom: f32,
20}
21
22#[derive(Clone, Debug)]
23pub struct GridConfig {
24 pub columns: usize,
25 pub row_gap: f32,
26 pub column_gap: f32,
27}
28
29#[derive(Clone, Copy, Debug)]
30pub enum PositionType {
31 Relative,
32 Absolute,
33}
34
35#[derive(Clone, Default)]
36pub struct Modifier {
37 pub size: Option<Size>,
38 pub width: Option<f32>,
39 pub height: Option<f32>,
40 pub fill_max: bool,
41 pub fill_max_w: bool,
42 pub fill_max_h: bool,
43 pub padding: Option<f32>,
44 pub padding_values: Option<PaddingValues>,
45 pub min_width: Option<f32>,
46 pub min_height: Option<f32>,
47 pub max_width: Option<f32>,
48 pub max_height: Option<f32>,
49 pub background: Option<Brush>,
50 pub border: Option<Border>,
51 pub flex_grow: Option<f32>,
52 pub flex_shrink: Option<f32>,
53 pub flex_basis: Option<f32>,
54 pub align_self: Option<AlignSelf>,
55 pub justify_content: Option<JustifyContent>,
56 pub align_items_container: Option<AlignItems>,
57 pub align_content: Option<AlignContent>,
58 pub clip_rounded: Option<f32>,
59 pub z_index: f32,
61 pub click: bool,
62 pub on_scroll: Option<Rc<dyn Fn(Vec2) -> Vec2>>,
63 pub on_pointer_down: Option<Rc<dyn Fn(PointerEvent)>>,
64 pub on_pointer_move: Option<Rc<dyn Fn(PointerEvent)>>,
65 pub on_pointer_up: Option<Rc<dyn Fn(PointerEvent)>>,
66 pub on_pointer_enter: Option<Rc<dyn Fn(PointerEvent)>>,
67 pub on_pointer_leave: Option<Rc<dyn Fn(PointerEvent)>>,
68 pub semantics: Option<crate::Semantics>,
69 pub alpha: Option<f32>,
70 pub transform: Option<Transform>,
71 pub grid: Option<GridConfig>,
72 pub grid_col_span: Option<u16>,
73 pub grid_row_span: Option<u16>,
74 pub position_type: Option<PositionType>,
75 pub offset_left: Option<f32>,
76 pub offset_right: Option<f32>,
77 pub offset_top: Option<f32>,
78 pub offset_bottom: Option<f32>,
79 pub margin_left: Option<f32>,
80 pub margin_right: Option<f32>,
81 pub margin_top: Option<f32>,
82 pub margin_bottom: Option<f32>,
83 pub aspect_ratio: Option<f32>,
84 pub painter: Option<Rc<dyn Fn(&mut crate::Scene, crate::Rect)>>,
85}
86
87impl std::fmt::Debug for Modifier {
88 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89 f.debug_struct("Modifier")
90 .field("size", &self.size)
91 .field("width", &self.width)
92 .field("height", &self.height)
93 .field("fill_max", &self.fill_max)
94 .field("fill_max_w", &self.fill_max_w)
95 .field("fill_max_h", &self.fill_max_h)
96 .field("padding", &self.padding)
97 .field("padding_values", &self.padding_values)
98 .field("min_width", &self.min_width)
99 .field("min_height", &self.min_height)
100 .field("max_width", &self.max_width)
101 .field("max_height", &self.max_height)
102 .field("background", &self.background)
103 .field("border", &self.border)
104 .field("flex_grow", &self.flex_grow)
105 .field("flex_shrink", &self.flex_shrink)
106 .field("flex_basis", &self.flex_basis)
107 .field("align_self", &self.align_self)
108 .field("justify_content", &self.justify_content)
109 .field("align_items_container", &self.align_items_container)
110 .field("align_content", &self.align_content)
111 .field("clip_rounded", &self.clip_rounded)
112 .field("z_index", &self.z_index)
113 .field("click", &self.click)
114 .field("on_scroll", &self.on_scroll.as_ref().map(|_| "..."))
115 .field(
116 "on_pointer_down",
117 &self.on_pointer_down.as_ref().map(|_| "..."),
118 )
119 .field(
120 "on_pointer_move",
121 &self.on_pointer_move.as_ref().map(|_| "..."),
122 )
123 .field("on_pointer_up", &self.on_pointer_up.as_ref().map(|_| "..."))
124 .field(
125 "on_pointer_enter",
126 &self.on_pointer_enter.as_ref().map(|_| "..."),
127 )
128 .field(
129 "on_pointer_leave",
130 &self.on_pointer_leave.as_ref().map(|_| "..."),
131 )
132 .field("semantics", &self.semantics)
133 .field("alpha", &self.alpha)
134 .field("transform", &self.transform)
135 .field("grid", &self.grid)
136 .field("grid_col_span", &self.grid_col_span)
137 .field("grid_row_span", &self.grid_row_span)
138 .field("position_type", &self.position_type)
139 .field("offset_left", &self.offset_left)
140 .field("offset_right", &self.offset_right)
141 .field("offset_top", &self.offset_top)
142 .field("offset_bottom", &self.offset_bottom)
143 .field("aspect_ratio", &self.aspect_ratio)
144 .field("painter", &self.painter.as_ref().map(|_| "..."))
145 .finish()
146 }
147}
148
149impl Modifier {
150 pub fn new() -> Self {
151 Self::default()
152 }
153 pub fn size(mut self, w: f32, h: f32) -> Self {
154 self.size = Some(Size {
155 width: w,
156 height: h,
157 });
158 self
159 }
160 pub fn width(mut self, w: f32) -> Self {
161 self.width = Some(w);
162 self
163 }
164 pub fn height(mut self, h: f32) -> Self {
165 self.height = Some(h);
166 self
167 }
168 pub fn fill_max_size(mut self) -> Self {
169 self.fill_max = true;
170 self
171 }
172 pub fn fill_max_width(mut self) -> Self {
173 self.fill_max_w = true;
174 self
175 }
176 pub fn fill_max_height(mut self) -> Self {
177 self.fill_max_h = true;
178 self
179 }
180 pub fn padding(mut self, v: f32) -> Self {
181 self.padding = Some(v);
182 self
183 }
184 pub fn padding_values(mut self, padding: PaddingValues) -> Self {
185 self.padding_values = Some(padding);
186 self
187 }
188 pub fn min_size(mut self, w: f32, h: f32) -> Self {
189 self.min_width = Some(w);
190 self.min_height = Some(h);
191 self
192 }
193 pub fn max_size(mut self, w: f32, h: f32) -> Self {
194 self.max_width = Some(w);
195 self.max_height = Some(h);
196 self
197 }
198 pub fn min_width(mut self, w: f32) -> Self {
199 self.min_width = Some(w);
200 self
201 }
202 pub fn min_height(mut self, h: f32) -> Self {
203 self.min_height = Some(h);
204 self
205 }
206 pub fn max_width(mut self, w: f32) -> Self {
207 self.max_width = Some(w);
208 self
209 }
210 pub fn max_height(mut self, h: f32) -> Self {
211 self.max_height = Some(h);
212 self
213 }
214 pub fn background(mut self, color: Color) -> Self {
216 self.background = Some(Brush::Solid(color));
217 self
218 }
219 pub fn background_brush(mut self, brush: Brush) -> Self {
221 self.background = Some(brush);
222 self
223 }
224 pub fn border(mut self, width: f32, color: Color, radius: f32) -> Self {
225 self.border = Some(Border {
226 width,
227 color,
228 radius,
229 });
230 self
231 }
232 pub fn flex_grow(mut self, v: f32) -> Self {
233 self.flex_grow = Some(v);
234 self
235 }
236 pub fn flex_shrink(mut self, v: f32) -> Self {
237 self.flex_shrink = Some(v);
238 self
239 }
240 pub fn flex_basis(mut self, v: f32) -> Self {
241 self.flex_basis = Some(v);
242 self
243 }
244 pub fn align_self(mut self, a: AlignSelf) -> Self {
245 self.align_self = Some(a);
246 self
247 }
248 pub fn align_self_center(mut self) -> Self {
249 self.align_self = Some(AlignSelf::Center);
250 self
251 }
252 pub fn justify_content(mut self, j: JustifyContent) -> Self {
253 self.justify_content = Some(j);
254 self
255 }
256 pub fn align_items(mut self, a: AlignItems) -> Self {
257 self.align_items_container = Some(a);
258 self
259 }
260 pub fn align_content(mut self, a: AlignContent) -> Self {
261 self.align_content = Some(a);
262 self
263 }
264 pub fn clip_rounded(mut self, radius: f32) -> Self {
265 self.clip_rounded = Some(radius);
266 self
267 }
268 pub fn z_index(mut self, z: f32) -> Self {
269 self.z_index = z;
270 self
271 }
272 pub fn clickable(mut self) -> Self {
273 self.click = true;
274 self
275 }
276 pub fn on_scroll(mut self, f: impl Fn(Vec2) -> Vec2 + 'static) -> Self {
277 self.on_scroll = Some(Rc::new(f));
278 self
279 }
280 pub fn on_pointer_down(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
281 self.on_pointer_down = Some(Rc::new(f));
282 self
283 }
284 pub fn on_pointer_move(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
285 self.on_pointer_move = Some(Rc::new(f));
286 self
287 }
288 pub fn on_pointer_up(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
289 self.on_pointer_up = Some(Rc::new(f));
290 self
291 }
292 pub fn on_pointer_enter(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
293 self.on_pointer_enter = Some(Rc::new(f));
294 self
295 }
296 pub fn on_pointer_leave(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
297 self.on_pointer_leave = Some(Rc::new(f));
298 self
299 }
300 pub fn semantics(mut self, s: crate::Semantics) -> Self {
301 self.semantics = Some(s);
302 self
303 }
304 pub fn alpha(mut self, a: f32) -> Self {
305 self.alpha = Some(a);
306 self
307 }
308 pub fn transform(mut self, t: Transform) -> Self {
309 self.transform = Some(t);
310 self
311 }
312 pub fn grid(mut self, columns: usize, row_gap: f32, column_gap: f32) -> Self {
313 self.grid = Some(GridConfig {
314 columns,
315 row_gap,
316 column_gap,
317 });
318 self
319 }
320 pub fn grid_span(mut self, col_span: u16, row_span: u16) -> Self {
321 self.grid_col_span = Some(col_span);
322 self.grid_row_span = Some(row_span);
323 self
324 }
325 pub fn absolute(mut self) -> Self {
326 self.position_type = Some(PositionType::Absolute);
327 self
328 }
329 pub fn offset(
330 mut self,
331 left: Option<f32>,
332 top: Option<f32>,
333 right: Option<f32>,
334 bottom: Option<f32>,
335 ) -> Self {
336 self.offset_left = left;
337 self.offset_top = top;
338 self.offset_right = right;
339 self.offset_bottom = bottom;
340 self
341 }
342 pub fn offset_left(mut self, v: f32) -> Self {
343 self.offset_left = Some(v);
344 self
345 }
346 pub fn offset_right(mut self, v: f32) -> Self {
347 self.offset_right = Some(v);
348 self
349 }
350 pub fn offset_top(mut self, v: f32) -> Self {
351 self.offset_top = Some(v);
352 self
353 }
354 pub fn offset_bottom(mut self, v: f32) -> Self {
355 self.offset_bottom = Some(v);
356 self
357 }
358
359 pub fn margin(mut self, v: f32) -> Self {
360 self.margin_left = Some(v);
361 self.margin_right = Some(v);
362 self.margin_top = Some(v);
363 self.margin_bottom = Some(v);
364 self
365 }
366
367 pub fn margin_horizontal(mut self, v: f32) -> Self {
368 self.margin_left = Some(v);
369 self.margin_right = Some(v);
370 self
371 }
372
373 pub fn margin_vertical(mut self, v: f32) -> Self {
374 self.margin_top = Some(v);
375 self.margin_bottom = Some(v);
376 self
377 }
378 pub fn aspect_ratio(mut self, ratio: f32) -> Self {
379 self.aspect_ratio = Some(ratio);
380 self
381 }
382 pub fn painter(mut self, f: impl Fn(&mut crate::Scene, crate::Rect) + 'static) -> Self {
383 self.painter = Some(Rc::new(f));
384 self
385 }
386 pub fn scale(mut self, s: f32) -> Self {
387 self.scale2(s, s)
388 }
389 pub fn scale2(mut self, sx: f32, sy: f32) -> Self {
390 let mut t = self.transform.unwrap_or_else(Transform::identity);
391 t.scale_x *= sx;
392 t.scale_y *= sy;
393 self.transform = Some(t);
394 self
395 }
396 pub fn translate(mut self, x: f32, y: f32) -> Self {
397 let t = self.transform.unwrap_or_else(Transform::identity);
398 self.transform = Some(t.combine(&Transform::translate(x, y)));
399 self
400 }
401 pub fn rotate(mut self, radians: f32) -> Self {
402 let mut t = self.transform.unwrap_or_else(Transform::identity);
403 t.rotate += radians;
404 self.transform = Some(t);
405 self
406 }
407}