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