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