Skip to main content

ply_engine/
elements.rs

1use crate::align::{AlignX, AlignY};
2use crate::id::Id;
3use crate::{color::Color, Vector2, engine};
4
5/// Specifies how pointer capture should behave for floating elements.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
7#[repr(u8)]
8pub enum PointerCaptureMode {
9    /// Captures all pointer input.
10    #[default]
11    Capture,
12    /// Allows pointer input to pass through.
13    Passthrough,
14}
15
16/// Defines how a floating element is attached to other elements.
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
18#[repr(u8)]
19pub enum FloatingAttachToElement {
20    /// The floating element is not attached to any other element.
21    #[default]
22    None,
23    /// The floating element is attached to its parent element.
24    Parent,
25    /// The floating element is attached to a specific element identified by an ID.
26    ElementWithId,
27    /// The floating element is attached to the root of the layout.
28    Root,
29}
30
31/// Defines how a floating element is clipped.
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
33#[repr(u8)]
34pub enum FloatingClipToElement {
35    /// The floating element is not clipped.
36    #[default]
37    None,
38    /// The floating element is clipped to the attached parent.
39    AttachedParent,
40}
41
42/// Builder for configuring floating element properties using a closure.
43pub struct FloatingBuilder {
44    pub(crate) config: engine::FloatingConfig,
45}
46
47impl FloatingBuilder {
48    /// Sets the floating element's offset.
49    #[inline]
50    pub fn offset(&mut self, x: f32, y: f32) -> &mut Self {
51        self.config.offset = Vector2::new(x, y);
52        self
53    }
54
55    /// Sets the floating element's Z-index.
56    #[inline]
57    pub fn z_index(&mut self, z_index: i16) -> &mut Self {
58        self.config.z_index = z_index;
59        self
60    }
61
62    /// Sets the attachment points of the floating element and its parent.
63    ///
64    /// Each tuple is `(AlignX, AlignY)` — the first for the element, the second for the parent.
65    /// ```ignore
66    /// .floating(|f| f.anchor((CenterX, Bottom), (CenterX, Top)))
67    /// ```
68    #[inline]
69    pub fn anchor(
70        &mut self,
71        element: (AlignX, AlignY),
72        parent: (AlignX, AlignY),
73    ) -> &mut Self {
74        self.config.attach_points.element_x = element.0;
75        self.config.attach_points.element_y = element.1;
76        self.config.attach_points.parent_x = parent.0;
77        self.config.attach_points.parent_y = parent.1;
78        self
79    }
80
81    /// Attaches this floating element to its parent element (default behavior).
82    #[inline]
83    pub fn attach_parent(&mut self) -> &mut Self {
84        self.config.attach_to = FloatingAttachToElement::Parent;
85        self
86    }
87
88    /// Attaches this floating element to the root of the layout.
89    #[inline]
90    pub fn attach_root(&mut self) -> &mut Self {
91        self.config.attach_to = FloatingAttachToElement::Root;
92        self
93    }
94
95    /// Attaches this floating element to a specific element by ID.
96    #[inline]
97    pub fn attach_id(&mut self, id: impl Into<Id>) -> &mut Self {
98        self.config.attach_to = FloatingAttachToElement::ElementWithId;
99        self.config.parent_id = id.into().id;
100        self
101    }
102
103    /// Clips this floating element to its parent's bounds.
104    #[inline]
105    pub fn clip_by_parent(&mut self) -> &mut Self {
106        self.config.clip_to = FloatingClipToElement::AttachedParent;
107        self
108    }
109
110    /// Sets pointer capture mode to Passthrough.
111    #[inline]
112    pub fn passthrough(&mut self) -> &mut Self {
113        self.config.pointer_capture_mode = PointerCaptureMode::Passthrough;
114        self
115    }
116}
117
118/// Builder for configuring overflow (clip/scroll) properties using a closure.
119pub struct OverflowBuilder {
120    pub(crate) config: engine::ClipConfig,
121}
122
123impl OverflowBuilder {
124    /// Clips horizontal overflow without enabling scrolling.
125    #[inline]
126    pub fn clip_x(&mut self) -> &mut Self {
127        self.config.horizontal = true;
128        self
129    }
130
131    /// Clips vertical overflow without enabling scrolling.
132    #[inline]
133    pub fn clip_y(&mut self) -> &mut Self {
134        self.config.vertical = true;
135        self
136    }
137
138    /// Clips both axes without enabling scrolling.
139    #[inline]
140    pub fn clip(&mut self) -> &mut Self {
141        self.config.horizontal = true;
142        self.config.vertical = true;
143        self
144    }
145
146    /// Enables horizontal scrolling (implies clip on this axis).
147    #[inline]
148    pub fn scroll_x(&mut self) -> &mut Self {
149        self.config.horizontal = true;
150        self.config.scroll_x = true;
151        self
152    }
153
154    /// Enables vertical scrolling (implies clip on this axis).
155    #[inline]
156    pub fn scroll_y(&mut self) -> &mut Self {
157        self.config.vertical = true;
158        self.config.scroll_y = true;
159        self
160    }
161
162    /// Enables scrolling on both axes (implies clip on both axes).
163    #[inline]
164    pub fn scroll(&mut self) -> &mut Self {
165        self.config.horizontal = true;
166        self.config.vertical = true;
167        self.config.scroll_x = true;
168        self.config.scroll_y = true;
169        self
170    }
171}
172
173/// Builder for configuring border properties using a closure.
174pub struct BorderBuilder {
175    pub(crate) config: engine::BorderConfig,
176}
177
178impl BorderBuilder {
179    /// Sets the border color.
180    #[inline]
181    pub fn color(&mut self, color: impl Into<Color>) -> &mut Self {
182        self.config.color = color.into();
183        self
184    }
185
186    /// Set the same border width for all sides.
187    #[inline]
188    pub fn all(&mut self, width: u16) -> &mut Self {
189        self.config.width.left = width;
190        self.config.width.right = width;
191        self.config.width.top = width;
192        self.config.width.bottom = width;
193        self
194    }
195
196    /// Sets the left border width.
197    #[inline]
198    pub fn left(&mut self, width: u16) -> &mut Self {
199        self.config.width.left = width;
200        self
201    }
202
203    /// Sets the right border width.
204    #[inline]
205    pub fn right(&mut self, width: u16) -> &mut Self {
206        self.config.width.right = width;
207        self
208    }
209
210    /// Sets the top border width.
211    #[inline]
212    pub fn top(&mut self, width: u16) -> &mut Self {
213        self.config.width.top = width;
214        self
215    }
216
217    /// Sets the bottom border width.
218    #[inline]
219    pub fn bottom(&mut self, width: u16) -> &mut Self {
220        self.config.width.bottom = width;
221        self
222    }
223
224    /// Sets the spacing between child elements.
225    #[inline]
226    pub fn between_children(&mut self, width: u16) -> &mut Self {
227        self.config.width.between_children = width;
228        self
229    }
230}
231
232/// Builder for configuring visual rotation (render-target based).
233pub struct VisualRotationBuilder {
234    pub(crate) config: engine::VisualRotationConfig,
235}
236
237impl VisualRotationBuilder {
238    /// Sets the rotation angle in degrees.
239    #[inline]
240    pub fn degrees(&mut self, degrees: f32) -> &mut Self {
241        self.config.rotation_radians = degrees.to_radians();
242        self
243    }
244
245    /// Sets the rotation angle in radians.
246    #[inline]
247    pub fn radians(&mut self, radians: f32) -> &mut Self {
248        self.config.rotation_radians = radians;
249        self
250    }
251
252    /// Sets the rotation pivot as normalized coordinates (0.0–1.0).
253    /// Default is (0.5, 0.5) = center of the element.
254    /// (0.0, 0.0) = top-left corner.
255    #[inline]
256    pub fn pivot(&mut self, x: f32, y: f32) -> &mut Self {
257        self.config.pivot_x = x;
258        self.config.pivot_y = y;
259        self
260    }
261
262    /// Flips the element horizontally (mirror across the vertical axis).
263    #[inline]
264    pub fn flip_x(&mut self) -> &mut Self {
265        self.config.flip_x = true;
266        self
267    }
268
269    /// Flips the element vertically (mirror across the horizontal axis).
270    #[inline]
271    pub fn flip_y(&mut self) -> &mut Self {
272        self.config.flip_y = true;
273        self
274    }
275}
276
277/// Builder for configuring shape rotation (vertex-level).
278pub struct ShapeRotationBuilder {
279    pub(crate) config: engine::ShapeRotationConfig,
280}
281
282impl ShapeRotationBuilder {
283    /// Sets the rotation angle in degrees.
284    #[inline]
285    pub fn degrees(&mut self, degrees: f32) -> &mut Self {
286        self.config.rotation_radians = degrees.to_radians();
287        self
288    }
289
290    /// Sets the rotation angle in radians.
291    #[inline]
292    pub fn radians(&mut self, radians: f32) -> &mut Self {
293        self.config.rotation_radians = radians;
294        self
295    }
296
297    /// Flips the shape horizontally (applied before rotation).
298    #[inline]
299    pub fn flip_x(&mut self) -> &mut Self {
300        self.config.flip_x = true;
301        self
302    }
303
304    /// Flips the shape vertically (applied before rotation).
305    #[inline]
306    pub fn flip_y(&mut self) -> &mut Self {
307        self.config.flip_y = true;
308        self
309    }
310}