repose_core/
modifier.rs

1use std::rc::Rc;
2
3use taffy::AlignSelf;
4
5use crate::{Color, PointerEvent, Size};
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, Default)]
15pub struct Modifier {
16    pub padding: Option<f32>,
17    pub size: Option<Size>,
18    pub fill_max: bool,
19    pub background: Option<Color>,
20    pub border: Option<Border>,
21    pub flex_grow: Option<f32>,
22    pub flex_shrink: Option<f32>,
23    pub flex_basis: Option<f32>,
24    pub align_self: Option<AlignSelf>,
25    pub aspect_ratio: Option<f32>, // width/height
26    pub position_type: Option<PositionType>,
27    pub offset_left: Option<f32>,
28    pub offset_right: Option<f32>,
29    pub offset_top: Option<f32>,
30    pub offset_bottom: Option<f32>,
31    pub grid: Option<GridConfig>,
32    pub grid_col_span: Option<u16>,
33    pub grid_row_span: Option<u16>,
34    pub click: bool,
35    pub semantics_label: Option<String>,
36    pub z_index: f32,
37    pub clip_rounded: Option<f32>,
38    // (desktop/mobile gestures build on top later)
39    pub on_pointer_down: Option<Rc<dyn Fn(PointerEvent)>>,
40    pub on_pointer_move: Option<Rc<dyn Fn(PointerEvent)>>,
41    pub on_pointer_up: Option<Rc<dyn Fn(PointerEvent)>>,
42    pub on_pointer_enter: Option<Rc<dyn Fn(PointerEvent)>>,
43    pub on_pointer_leave: Option<Rc<dyn Fn(PointerEvent)>>,
44}
45
46#[derive(Clone, Copy, Debug)]
47pub enum PositionType {
48    Relative,
49    Absolute,
50}
51
52#[derive(Clone, Copy, Debug)]
53pub struct GridConfig {
54    pub columns: usize, // e.g. 3 (auto 1fr tracks)
55    pub row_gap: f32,
56    pub column_gap: f32,
57}
58
59impl Default for Border {
60    fn default() -> Self {
61        Border {
62            width: 1.0,
63            color: Color::WHITE,
64            radius: 0.0,
65        }
66    }
67}
68
69impl std::fmt::Debug for Modifier {
70    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71        f.debug_struct("Modifier")
72            .field("padding", &self.padding)
73            .field("size", &self.size)
74            .field("fill_max", &self.fill_max)
75            .field("background", &self.background)
76            .field("border", &self.border)
77            .field("click", &self.click)
78            .field("semantics_label", &self.semantics_label)
79            .field("z_index", &self.z_index)
80            .field("clip_rounded", &self.clip_rounded)
81            .finish()
82    }
83}
84
85impl Modifier {
86    pub fn new() -> Self {
87        Self::default()
88    }
89    pub fn padding(mut self, px: f32) -> Self {
90        self.padding = Some(px);
91        self
92    }
93    pub fn size(mut self, w: f32, h: f32) -> Self {
94        self.size = Some(Size {
95            width: w,
96            height: h,
97        });
98        self
99    }
100    pub fn fill_max_size(mut self) -> Self {
101        self.fill_max = true;
102        self
103    }
104    pub fn background(mut self, color: Color) -> Self {
105        self.background = Some(color);
106        self
107    }
108    pub fn border(mut self, width: f32, color: Color, radius: f32) -> Self {
109        self.border = Some(Border {
110            width,
111            color,
112            radius,
113        });
114        self
115    }
116    pub fn clickable(mut self) -> Self {
117        self.click = true;
118        self
119    }
120    pub fn semantics(mut self, label: impl Into<String>) -> Self {
121        self.semantics_label = Some(label.into());
122        self
123    }
124    pub fn z_index(mut self, z: f32) -> Self {
125        self.z_index = z;
126        self
127    }
128    pub fn clip_rounded(mut self, r: f32) -> Self {
129        self.clip_rounded = Some(r);
130        self
131    }
132
133    pub fn on_pointer_down(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
134        self.on_pointer_down = Some(Rc::new(f));
135        self
136    }
137    pub fn on_pointer_move(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
138        self.on_pointer_move = Some(Rc::new(f));
139        self
140    }
141    pub fn on_pointer_up(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
142        self.on_pointer_up = Some(Rc::new(f));
143        self
144    }
145    pub fn on_pointer_enter(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
146        self.on_pointer_enter = Some(Rc::new(f));
147        self
148    }
149    pub fn on_pointer_leave(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
150        self.on_pointer_leave = Some(Rc::new(f));
151        self
152    }
153    pub fn flex_grow(mut self, g: f32) -> Self {
154        self.flex_grow = Some(g);
155        self
156    }
157    pub fn flex_shrink(mut self, s: f32) -> Self {
158        self.flex_shrink = Some(s);
159        self
160    }
161    pub fn flex_basis(mut self, px: f32) -> Self {
162        self.flex_basis = Some(px);
163        self
164    }
165    pub fn align_self_baseline(mut self) -> Self {
166        self.align_self = Some(taffy::style::AlignSelf::Baseline);
167        self
168    }
169    pub fn align_self_center(mut self) -> Self {
170        self.align_self = Some(taffy::style::AlignSelf::Center);
171        self
172    }
173    pub fn aspect_ratio(mut self, ratio: f32) -> Self {
174        self.aspect_ratio = Some(ratio.max(0.0));
175        self
176    }
177    pub fn absolute(mut self) -> Self {
178        self.position_type = Some(PositionType::Absolute);
179        self
180    }
181    pub fn offset(
182        mut self,
183        left: Option<f32>,
184        top: Option<f32>,
185        right: Option<f32>,
186        bottom: Option<f32>,
187    ) -> Self {
188        self.offset_left = left;
189        self.offset_top = top;
190        self.offset_right = right;
191        self.offset_bottom = bottom;
192        self
193    }
194    pub fn grid(mut self, columns: usize, row_gap: f32, column_gap: f32) -> Self {
195        self.grid = Some(GridConfig {
196            columns: columns.max(1),
197            row_gap,
198            column_gap,
199        });
200        self
201    }
202    pub fn grid_span(mut self, col_span: u16, row_span: u16) -> Self {
203        self.grid_col_span = Some(col_span.max(1));
204        self.grid_row_span = Some(row_span.max(1));
205        self
206    }
207}