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