1use std::rc::Rc;
2
3use taffy::AlignSelf;
4
5use crate::{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, Default)]
23pub struct Modifier {
24 pub padding: Option<f32>,
25 pub padding_values: Option<PaddingValues>,
26 pub size: Option<Size>,
27 pub fill_max: bool,
28 pub fill_max_w: bool,
29 pub fill_max_h: bool,
30 pub width: Option<f32>,
31 pub height: Option<f32>,
32 pub min_width: Option<f32>,
33 pub min_height: Option<f32>,
34 pub max_width: Option<f32>,
35 pub max_height: Option<f32>,
36 pub background: Option<Color>,
37 pub border: Option<Border>,
38 pub flex_grow: Option<f32>,
39 pub flex_shrink: Option<f32>,
40 pub flex_basis: Option<f32>,
41 pub align_self: Option<AlignSelf>,
42 pub aspect_ratio: Option<f32>, pub position_type: Option<PositionType>,
44 pub offset_left: Option<f32>,
45 pub offset_right: Option<f32>,
46 pub offset_top: Option<f32>,
47 pub offset_bottom: Option<f32>,
48 pub grid: Option<GridConfig>,
49 pub grid_col_span: Option<u16>,
50 pub grid_row_span: Option<u16>,
51 pub click: bool,
52 pub semantics_label: Option<String>,
53 pub z_index: f32,
55 pub clip_rounded: Option<f32>,
56 pub on_scroll: Option<Rc<dyn Fn(Vec2) -> Vec2>>,
57
58 pub on_pointer_down: Option<Rc<dyn Fn(PointerEvent)>>,
60 pub on_pointer_move: Option<Rc<dyn Fn(PointerEvent)>>,
61 pub on_pointer_up: Option<Rc<dyn Fn(PointerEvent)>>,
62 pub on_pointer_enter: Option<Rc<dyn Fn(PointerEvent)>>,
63 pub on_pointer_leave: Option<Rc<dyn Fn(PointerEvent)>>,
64
65 pub alpha: Option<f32>,
66 pub transform: Option<Transform>,
67
68 pub painter: Option<Rc<dyn Fn(&mut crate::Scene, crate::Rect)>>,
69}
70
71#[derive(Clone, Copy, Debug)]
72pub enum PositionType {
73 Relative,
74 Absolute,
75}
76
77#[derive(Clone, Copy, Debug)]
78pub struct GridConfig {
79 pub columns: usize, pub row_gap: f32,
81 pub column_gap: f32,
82}
83
84impl Default for Border {
85 fn default() -> Self {
86 Border {
87 width: 1.0,
88 color: Color::WHITE,
89 radius: 0.0,
90 }
91 }
92}
93
94impl std::fmt::Debug for Modifier {
95 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
96 f.debug_struct("Modifier")
97 .field("padding", &self.padding)
98 .field("padding_values", &self.padding_values)
99 .field("size", &self.size)
100 .field("max_height", &self.max_height)
101 .field("max_width", &self.max_width)
102 .field("min_height", &self.min_height)
103 .field("min_width", &self.min_width)
104 .field("fill_max", &self.fill_max)
105 .field("background", &self.background)
106 .field("border", &self.border)
107 .field("click", &self.click)
108 .field("semantics_label", &self.semantics_label)
109 .field("z_index", &self.z_index)
110 .field("clip_rounded", &self.clip_rounded)
111 .field("alpha", &self.alpha)
112 .finish()
113 }
114}
115
116impl Modifier {
117 pub fn new() -> Self {
118 Self::default()
119 }
120 pub fn padding(mut self, px: f32) -> Self {
121 self.padding = Some(px);
122 self
123 }
124 pub fn padding_values(mut self, pv: PaddingValues) -> Self {
125 self.padding_values = Some(pv);
126 self
127 }
128 pub fn size(mut self, w: f32, h: f32) -> Self {
129 self.size = Some(Size {
130 width: w,
131 height: h,
132 });
133 self
134 }
135 pub fn fill_max_size(mut self) -> Self {
136 self.fill_max = true;
137 self
138 }
139 pub fn width(mut self, w: f32) -> Self {
140 self.width = Some(w);
141 self
142 }
143 pub fn height(mut self, h: f32) -> Self {
144 self.height = Some(h);
145 self
146 }
147 pub fn fill_max_width(mut self) -> Self {
148 self.fill_max_w = true;
149 self
150 }
151 pub fn fill_max_height(mut self) -> Self {
152 self.fill_max_h = true;
153 self
154 }
155 pub fn min_size(mut self, w: f32, h: f32) -> Self {
156 self.min_width = Some(w.max(0.0));
157 self.min_height = Some(h.max(0.0));
158 self
159 }
160 pub fn max_size(mut self, w: f32, h: f32) -> Self {
161 self.max_width = Some(w.max(0.0));
162 self.max_height = Some(h.max(0.0));
163 self
164 }
165 pub fn min_width(mut self, w: f32) -> Self {
166 self.min_width = Some(w.max(0.0));
167 self
168 }
169 pub fn min_height(mut self, h: f32) -> Self {
170 self.min_height = Some(h.max(0.0));
171 self
172 }
173 pub fn max_width(mut self, w: f32) -> Self {
174 self.max_width = Some(w.max(0.0));
175 self
176 }
177 pub fn max_height(mut self, h: f32) -> Self {
178 self.max_height = Some(h.max(0.0));
179 self
180 }
181 pub fn background(mut self, color: Color) -> Self {
182 self.background = Some(color);
183 self
184 }
185 pub fn border(mut self, width: f32, color: Color, radius: f32) -> Self {
186 self.border = Some(Border {
187 width,
188 color,
189 radius,
190 });
191 self
192 }
193 pub fn clickable(mut self) -> Self {
194 self.click = true;
195 self
196 }
197 pub fn semantics(mut self, label: impl Into<String>) -> Self {
198 self.semantics_label = Some(label.into());
199 self
200 }
201 pub fn z_index(mut self, z: f32) -> Self {
202 self.z_index = z;
203 self
204 }
205 pub fn clip_rounded(mut self, r: f32) -> Self {
206 self.clip_rounded = Some(r);
207 self
208 }
209
210 pub fn on_pointer_down(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
211 self.on_pointer_down = Some(Rc::new(f));
212 self
213 }
214 pub fn on_pointer_move(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
215 self.on_pointer_move = Some(Rc::new(f));
216 self
217 }
218 pub fn on_pointer_up(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
219 self.on_pointer_up = Some(Rc::new(f));
220 self
221 }
222 pub fn on_pointer_enter(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
223 self.on_pointer_enter = Some(Rc::new(f));
224 self
225 }
226 pub fn on_pointer_leave(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
227 self.on_pointer_leave = Some(Rc::new(f));
228 self
229 }
230 pub fn flex_grow(mut self, g: f32) -> Self {
231 self.flex_grow = Some(g);
232 self
233 }
234 pub fn flex_shrink(mut self, s: f32) -> Self {
235 self.flex_shrink = Some(s);
236 self
237 }
238 pub fn flex_basis(mut self, px: f32) -> Self {
239 self.flex_basis = Some(px);
240 self
241 }
242 pub fn align_self_baseline(mut self) -> Self {
243 self.align_self = Some(AlignSelf::Baseline);
244 self
245 }
246 pub fn align_self_center(mut self) -> Self {
247 self.align_self = Some(AlignSelf::Center);
248 self
249 }
250 pub fn align_self(mut self, align: AlignSelf) -> Self {
251 self.align_self = Some(align);
252 self
253 }
254 pub fn aspect_ratio(mut self, ratio: f32) -> Self {
255 self.aspect_ratio = Some(ratio.max(0.0));
256 self
257 }
258 pub fn absolute(mut self) -> Self {
259 self.position_type = Some(PositionType::Absolute);
260 self
261 }
262 pub fn offset(
263 mut self,
264 left: Option<f32>,
265 top: Option<f32>,
266 right: Option<f32>,
267 bottom: Option<f32>,
268 ) -> Self {
269 self.offset_left = left;
270 self.offset_top = top;
271 self.offset_right = right;
272 self.offset_bottom = bottom;
273 self
274 }
275 pub fn grid(mut self, columns: usize, row_gap: f32, column_gap: f32) -> Self {
276 self.grid = Some(GridConfig {
277 columns: columns.max(1),
278 row_gap,
279 column_gap,
280 });
281 self
282 }
283 pub fn grid_span(mut self, col_span: u16, row_span: u16) -> Self {
284 self.grid_col_span = Some(col_span.max(1));
285 self.grid_row_span = Some(row_span.max(1));
286 self
287 }
288
289 pub fn alpha(mut self, a: f32) -> Self {
290 self.alpha = Some(a.clamp(0.0, 1.0));
291 self
292 }
293 pub fn translate(mut self, x: f32, y: f32) -> Self {
295 let t = self.transform.unwrap_or_else(Transform::identity);
296 self.transform = Some(t.combine(&Transform::translate(x, y)));
297 self
298 }
299 pub fn scale(mut self, s: f32) -> Self {
300 self.scale2(s, s)
301 }
302 pub fn scale2(mut self, sx: f32, sy: f32) -> Self {
303 let mut t = self.transform.unwrap_or_else(Transform::identity);
304 t.scale_x *= sx;
305 t.scale_y *= sy;
306 self.transform = Some(t);
307 self
308 }
309 pub fn rotate(mut self, radians: f32) -> Self {
310 let mut t = self.transform.unwrap_or_else(Transform::identity);
311 t.rotate += radians;
312 self.transform = Some(t);
313 self
314 }
315 pub fn on_scroll(mut self, f: impl Fn(Vec2) -> Vec2 + 'static) -> Self {
316 self.on_scroll = Some(Rc::new(f));
317 self
318 }
319
320 pub fn painter(mut self, f: impl Fn(&mut crate::Scene, crate::Rect) + 'static) -> Self {
321 self.painter = Some(Rc::new(f));
322 self
323 }
324}