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