repose_core/
modifier.rs

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    /// Works for hit-testing only, draw order is not changed.
60    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    /// Set a solid color background.
215    pub fn background(mut self, color: Color) -> Self {
216        self.background = Some(Brush::Solid(color));
217        self
218    }
219    /// Set a brush (solid, gradient, etc.) background.
220    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}