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 render_z_index: Option<f32>,
72 pub hit_passthrough: bool,
74 pub input_blocker: bool,
76 pub repaint_boundary: bool,
77 pub click: bool,
78 pub on_scroll: Option<Rc<dyn Fn(Vec2) -> Vec2>>,
79 pub on_pointer_down: Option<Rc<dyn Fn(PointerEvent)>>,
80 pub on_pointer_move: Option<Rc<dyn Fn(PointerEvent)>>,
81 pub on_pointer_up: Option<Rc<dyn Fn(PointerEvent)>>,
82 pub on_pointer_enter: Option<Rc<dyn Fn(PointerEvent)>>,
83 pub on_pointer_leave: Option<Rc<dyn Fn(PointerEvent)>>,
84 pub semantics: Option<crate::Semantics>,
85 pub alpha: Option<f32>,
86 pub transform: Option<Transform>,
87 pub grid: Option<GridConfig>,
88 pub grid_col_span: Option<u16>,
89 pub grid_row_span: Option<u16>,
90 pub position_type: Option<PositionType>,
91 pub offset_left: Option<f32>,
92 pub offset_right: Option<f32>,
93 pub offset_top: Option<f32>,
94 pub offset_bottom: Option<f32>,
95 pub margin_left: Option<f32>,
96 pub margin_right: Option<f32>,
97 pub margin_top: Option<f32>,
98 pub margin_bottom: Option<f32>,
99 pub aspect_ratio: Option<f32>,
100 pub painter: Option<Rc<dyn Fn(&mut crate::Scene, crate::Rect)>>,
101
102 pub on_drag_start: Option<Rc<dyn Fn(crate::dnd::DragStart) -> Option<crate::dnd::DragPayload>>>,
104 pub on_drag_end: Option<Rc<dyn Fn(crate::dnd::DragEnd)>>,
105 pub on_drag_enter: Option<Rc<dyn Fn(crate::dnd::DragOver)>>,
106 pub on_drag_over: Option<Rc<dyn Fn(crate::dnd::DragOver)>>,
107 pub on_drag_leave: Option<Rc<dyn Fn(crate::dnd::DragOver)>>,
108 pub on_drop: Option<Rc<dyn Fn(crate::dnd::DropEvent) -> bool>>,
109
110 pub on_action: Option<Rc<dyn Fn(crate::shortcuts::Action) -> bool>>,
111
112 pub cursor: Option<crate::CursorIcon>,
114}
115
116impl std::fmt::Debug for Modifier {
117 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
118 f.debug_struct("Modifier")
119 .field("key", &self.key)
120 .field("size", &self.size)
121 .field("width", &self.width)
122 .field("height", &self.height)
123 .field("fill_max", &self.fill_max)
124 .field("fill_max_w", &self.fill_max_w)
125 .field("fill_max_h", &self.fill_max_h)
126 .field("padding", &self.padding)
127 .field("padding_values", &self.padding_values)
128 .field("min_width", &self.min_width)
129 .field("min_height", &self.min_height)
130 .field("max_width", &self.max_width)
131 .field("max_height", &self.max_height)
132 .field("background", &self.background)
133 .field("border", &self.border)
134 .field("flex_grow", &self.flex_grow)
135 .field("flex_shrink", &self.flex_shrink)
136 .field("flex_basis", &self.flex_basis)
137 .field("align_self", &self.align_self)
138 .field("justify_content", &self.justify_content)
139 .field("align_items_container", &self.align_items_container)
140 .field("align_content", &self.align_content)
141 .field("clip_rounded", &self.clip_rounded)
142 .field("z_index", &self.z_index)
143 .field("render_z_index", &self.render_z_index)
144 .field("hit_passthrough", &self.hit_passthrough)
145 .field("input_blocker", &self.input_blocker)
146 .field("repaint_boundary", &self.repaint_boundary)
147 .field("click", &self.click)
148 .field("on_scroll", &self.on_scroll.as_ref().map(|_| "..."))
149 .field(
150 "on_pointer_down",
151 &self.on_pointer_down.as_ref().map(|_| "..."),
152 )
153 .field(
154 "on_pointer_move",
155 &self.on_pointer_move.as_ref().map(|_| "..."),
156 )
157 .field("on_pointer_up", &self.on_pointer_up.as_ref().map(|_| "..."))
158 .field(
159 "on_pointer_enter",
160 &self.on_pointer_enter.as_ref().map(|_| "..."),
161 )
162 .field(
163 "on_pointer_leave",
164 &self.on_pointer_leave.as_ref().map(|_| "..."),
165 )
166 .field("semantics", &self.semantics)
167 .field("alpha", &self.alpha)
168 .field("transform", &self.transform)
169 .field("grid", &self.grid)
170 .field("grid_col_span", &self.grid_col_span)
171 .field("grid_row_span", &self.grid_row_span)
172 .field("position_type", &self.position_type)
173 .field("offset_left", &self.offset_left)
174 .field("offset_right", &self.offset_right)
175 .field("offset_top", &self.offset_top)
176 .field("offset_bottom", &self.offset_bottom)
177 .field("aspect_ratio", &self.aspect_ratio)
178 .field("painter", &self.painter.as_ref().map(|_| "..."))
179 .field("on_drag_start", &self.on_drag_start.as_ref().map(|_| "..."))
180 .field("on_drag_end", &self.on_drag_end.as_ref().map(|_| "..."))
181 .field("on_drag_enter", &self.on_drag_enter.as_ref().map(|_| "..."))
182 .field("on_drag_over", &self.on_drag_over.as_ref().map(|_| "..."))
183 .field("on_drag_leave", &self.on_drag_leave.as_ref().map(|_| "..."))
184 .field("on_drop", &self.on_drop.as_ref().map(|_| "..."))
185 .field("on_action", &self.on_action.as_ref().map(|_| "..."))
186 .finish()
187 }
188}
189
190impl Modifier {
191 pub fn new() -> Self {
192 Self::default()
193 }
194
195 pub fn key(mut self, key: u64) -> Self {
198 self.key = Some(key);
199 self
200 }
201
202 pub fn size(mut self, w: f32, h: f32) -> Self {
203 self.size = Some(Size {
204 width: w,
205 height: h,
206 });
207 self
208 }
209 pub fn width(mut self, w: f32) -> Self {
210 self.width = Some(w);
211 self
212 }
213 pub fn height(mut self, h: f32) -> Self {
214 self.height = Some(h);
215 self
216 }
217 pub fn fill_max_size(mut self) -> Self {
218 self.fill_max = true;
219 self
220 }
221 pub fn fill_max_width(mut self) -> Self {
222 self.fill_max_w = true;
223 self
224 }
225 pub fn fill_max_height(mut self) -> Self {
226 self.fill_max_h = true;
227 self
228 }
229 pub fn padding(mut self, v: f32) -> Self {
230 self.padding = Some(v);
231 self
232 }
233 pub fn padding_values(mut self, padding: PaddingValues) -> Self {
234 self.padding_values = Some(padding);
235 self
236 }
237 pub fn min_size(mut self, w: f32, h: f32) -> Self {
238 self.min_width = Some(w);
239 self.min_height = Some(h);
240 self
241 }
242 pub fn max_size(mut self, w: f32, h: f32) -> Self {
243 self.max_width = Some(w);
244 self.max_height = Some(h);
245 self
246 }
247 pub fn min_width(mut self, w: f32) -> Self {
248 self.min_width = Some(w);
249 self
250 }
251 pub fn min_height(mut self, h: f32) -> Self {
252 self.min_height = Some(h);
253 self
254 }
255 pub fn max_width(mut self, w: f32) -> Self {
256 self.max_width = Some(w);
257 self
258 }
259 pub fn max_height(mut self, h: f32) -> Self {
260 self.max_height = Some(h);
261 self
262 }
263 pub fn background(mut self, color: Color) -> Self {
265 self.background = Some(Brush::Solid(color));
266 self
267 }
268 pub fn background_brush(mut self, brush: Brush) -> Self {
270 self.background = Some(brush);
271 self
272 }
273 pub fn border(mut self, width: f32, color: Color, radius: f32) -> Self {
274 self.border = Some(Border {
275 width,
276 color,
277 radius,
278 });
279 self
280 }
281 pub fn flex_grow(mut self, v: f32) -> Self {
282 self.flex_grow = Some(v);
283 self
284 }
285 pub fn flex_shrink(mut self, v: f32) -> Self {
286 self.flex_shrink = Some(v);
287 self
288 }
289 pub fn flex_basis(mut self, v: f32) -> Self {
290 self.flex_basis = Some(v);
291 self
292 }
293 pub fn flex_wrap(mut self, w: FlexWrap) -> Self {
294 self.flex_wrap = Some(w);
295 self
296 }
297 pub fn flex_dir(mut self, d: FlexDirection) -> Self {
298 self.flex_dir = Some(d);
299 self
300 }
301 pub fn align_self(mut self, a: AlignSelf) -> Self {
302 self.align_self = Some(a);
303 self
304 }
305 pub fn align_self_center(mut self) -> Self {
306 self.align_self = Some(AlignSelf::Center);
307 self
308 }
309 pub fn justify_content(mut self, j: JustifyContent) -> Self {
310 self.justify_content = Some(j);
311 self
312 }
313 pub fn align_items(mut self, a: AlignItems) -> Self {
314 self.align_items_container = Some(a);
315 self
316 }
317 pub fn align_content(mut self, a: AlignContent) -> Self {
318 self.align_content = Some(a);
319 self
320 }
321 pub fn clip_rounded(mut self, radius: f32) -> Self {
322 self.clip_rounded = Some(radius);
323 self
324 }
325 pub fn z_index(mut self, z: f32) -> Self {
326 self.z_index = z;
327 self
328 }
329
330 pub fn render_z_index(mut self, z: f32) -> Self {
333 self.render_z_index = Some(z);
334 self
335 }
336
337 pub fn input_blocker(mut self) -> Self {
339 self.input_blocker = true;
340 self
341 }
342
343 pub fn hit_passthrough(mut self) -> Self {
344 self.hit_passthrough = true;
345 self
346 }
347 pub fn clickable(mut self) -> Self {
348 self.click = true;
349 self
350 }
351 pub fn on_scroll(mut self, f: impl Fn(Vec2) -> Vec2 + 'static) -> Self {
352 self.on_scroll = Some(Rc::new(f));
353 self
354 }
355 pub fn on_pointer_down(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
356 self.on_pointer_down = Some(Rc::new(f));
357 self
358 }
359 pub fn on_pointer_move(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
360 self.on_pointer_move = Some(Rc::new(f));
361 self
362 }
363 pub fn on_pointer_up(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
364 self.on_pointer_up = Some(Rc::new(f));
365 self
366 }
367 pub fn on_pointer_enter(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
368 self.on_pointer_enter = Some(Rc::new(f));
369 self
370 }
371 pub fn on_pointer_leave(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
372 self.on_pointer_leave = Some(Rc::new(f));
373 self
374 }
375 pub fn semantics(mut self, s: crate::Semantics) -> Self {
376 self.semantics = Some(s);
377 self
378 }
379 pub fn alpha(mut self, a: f32) -> Self {
380 self.alpha = Some(a);
381 self
382 }
383 pub fn transform(mut self, t: Transform) -> Self {
384 self.transform = Some(t);
385 self
386 }
387 pub fn grid(mut self, columns: usize, row_gap: f32, column_gap: f32) -> Self {
388 self.grid = Some(GridConfig {
389 columns,
390 row_gap,
391 column_gap,
392 });
393 self
394 }
395 pub fn grid_span(mut self, col_span: u16, row_span: u16) -> Self {
396 self.grid_col_span = Some(col_span);
397 self.grid_row_span = Some(row_span);
398 self
399 }
400 pub fn absolute(mut self) -> Self {
401 self.position_type = Some(PositionType::Absolute);
402 self
403 }
404 pub fn offset(
405 mut self,
406 left: Option<f32>,
407 top: Option<f32>,
408 right: Option<f32>,
409 bottom: Option<f32>,
410 ) -> Self {
411 self.offset_left = left;
412 self.offset_top = top;
413 self.offset_right = right;
414 self.offset_bottom = bottom;
415 self
416 }
417 pub fn offset_left(mut self, v: f32) -> Self {
418 self.offset_left = Some(v);
419 self
420 }
421 pub fn offset_right(mut self, v: f32) -> Self {
422 self.offset_right = Some(v);
423 self
424 }
425 pub fn offset_top(mut self, v: f32) -> Self {
426 self.offset_top = Some(v);
427 self
428 }
429 pub fn offset_bottom(mut self, v: f32) -> Self {
430 self.offset_bottom = Some(v);
431 self
432 }
433
434 pub fn margin(mut self, v: f32) -> Self {
435 self.margin_left = Some(v);
436 self.margin_right = Some(v);
437 self.margin_top = Some(v);
438 self.margin_bottom = Some(v);
439 self
440 }
441
442 pub fn margin_horizontal(mut self, v: f32) -> Self {
443 self.margin_left = Some(v);
444 self.margin_right = Some(v);
445 self
446 }
447
448 pub fn margin_vertical(mut self, v: f32) -> Self {
449 self.margin_top = Some(v);
450 self.margin_bottom = Some(v);
451 self
452 }
453 pub fn aspect_ratio(mut self, ratio: f32) -> Self {
454 self.aspect_ratio = Some(ratio);
455 self
456 }
457 pub fn painter(mut self, f: impl Fn(&mut crate::Scene, crate::Rect) + 'static) -> Self {
458 self.painter = Some(Rc::new(f));
459 self
460 }
461 pub fn scale(self, s: f32) -> Self {
462 self.scale2(s, s)
463 }
464 pub fn scale2(mut self, sx: f32, sy: f32) -> Self {
465 let mut t = self.transform.unwrap_or_else(Transform::identity);
466 t.scale_x *= sx;
467 t.scale_y *= sy;
468 self.transform = Some(t);
469 self
470 }
471 pub fn translate(mut self, x: f32, y: f32) -> Self {
472 let t = self.transform.unwrap_or_else(Transform::identity);
473 self.transform = Some(t.combine(&Transform::translate(x, y)));
474 self
475 }
476 pub fn rotate(mut self, radians: f32) -> Self {
477 let mut t = self.transform.unwrap_or_else(Transform::identity);
478 t.rotate += radians;
479 self.transform = Some(t);
480 self
481 }
482 pub fn weight(mut self, w: f32) -> Self {
483 let w = w.max(0.0);
484 self.flex_grow = Some(w);
485 self.flex_shrink = Some(1.0);
486 self.flex_basis = Some(0.0);
488 self
489 }
490 pub fn repaint_boundary(mut self) -> Self {
494 self.repaint_boundary = true;
495 self
496 }
497 pub fn on_action(mut self, f: impl Fn(crate::shortcuts::Action) -> bool + 'static) -> Self {
498 self.on_action = Some(Rc::new(f));
499 self
500 }
501
502 pub fn on_drag_start(
504 mut self,
505 f: impl Fn(crate::dnd::DragStart) -> Option<crate::dnd::DragPayload> + 'static,
506 ) -> Self {
507 self.on_drag_start = Some(Rc::new(f));
508 self
509 }
510
511 pub fn on_drag_end(mut self, f: impl Fn(crate::dnd::DragEnd) + 'static) -> Self {
513 self.on_drag_end = Some(Rc::new(f));
514 self
515 }
516
517 pub fn on_drag_enter(mut self, f: impl Fn(crate::dnd::DragOver) + 'static) -> Self {
519 self.on_drag_enter = Some(Rc::new(f));
520 self
521 }
522
523 pub fn on_drag_over(mut self, f: impl Fn(crate::dnd::DragOver) + 'static) -> Self {
525 self.on_drag_over = Some(Rc::new(f));
526 self
527 }
528
529 pub fn on_drag_leave(mut self, f: impl Fn(crate::dnd::DragOver) + 'static) -> Self {
531 self.on_drag_leave = Some(Rc::new(f));
532 self
533 }
534
535 pub fn on_drop(mut self, f: impl Fn(crate::dnd::DropEvent) -> bool + 'static) -> Self {
538 self.on_drop = Some(Rc::new(f));
539 self
540 }
541
542 pub fn cursor(mut self, c: crate::CursorIcon) -> Self {
544 self.cursor = Some(c);
545 self
546 }
547}