Skip to main content

torin/
node.rs

1pub use euclid::Rect;
2
3use crate::{
4    alignment::Alignment,
5    direction::Direction,
6    gaps::Gaps,
7    geometry::Length,
8    order::Order,
9    prelude::{
10        Content,
11        Position,
12        VisibleSize,
13    },
14    scaled::Scaled,
15    size::Size,
16};
17
18/// Node layout configuration
19#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
20#[derive(PartialEq, Clone, Debug, Default)]
21pub struct Node {
22    /// Dimensions
23    pub width: Size,
24    pub height: Size,
25
26    // Minimum dimensions
27    pub minimum_width: Size,
28    pub minimum_height: Size,
29
30    // Maximum dimensions
31    pub maximum_width: Size,
32    pub maximum_height: Size,
33
34    // Visible dimensions
35    pub visible_width: VisibleSize,
36    pub visible_height: VisibleSize,
37
38    // Axis alignments for the children
39    pub main_alignment: Alignment,
40    pub cross_alignment: Alignment,
41
42    /// Inner padding
43    pub padding: Gaps,
44
45    /// Inner margin
46    pub margin: Gaps,
47
48    /// Inner position offsets
49    pub offset_x: Length,
50    pub offset_y: Length,
51
52    /// Direction in which it's inner Nodes will be stacked
53    pub direction: Direction,
54
55    /// Order in which it's inner Nodes will be stacked along the direction axis
56    pub order: Order,
57
58    /// Position config
59    pub position: Position,
60
61    pub content: Content,
62
63    /// A Node might depend on inner sizes but have a fixed position, like scroll views.
64    pub has_layout_references: bool,
65
66    pub spacing: Length,
67
68    /// A Node might need to relayout when its children change even if its own size
69    /// is fixed, like paragraphs with inline elements.
70    pub depends_on_inner: bool,
71}
72
73impl Scaled for Node {
74    fn scale(&mut self, scale_factor: f32) {
75        self.width.scale(scale_factor);
76        self.height.scale(scale_factor);
77        self.minimum_width.scale(scale_factor);
78        self.minimum_height.scale(scale_factor);
79        self.maximum_width.scale(scale_factor);
80        self.maximum_height.scale(scale_factor);
81        self.margin.scale(scale_factor);
82        self.padding.scale(scale_factor);
83        self.offset_x *= scale_factor;
84        self.offset_y *= scale_factor;
85        self.position.scale(scale_factor);
86        self.spacing *= scale_factor;
87    }
88}
89
90impl Node {
91    /// Create a Node with the default values
92    pub fn new() -> Self {
93        Self::default()
94    }
95
96    pub fn self_layout_eq(&self, other: &Self) -> bool {
97        // Excludes offset_x and offset_y
98        self.width == other.width
99            && self.height == other.height
100            && self.minimum_width == other.minimum_width
101            && self.minimum_height == other.minimum_height
102            && self.maximum_width == other.maximum_width
103            && self.maximum_height == other.maximum_height
104            && self.visible_width == other.visible_width
105            && self.visible_height == other.visible_height
106            && self.main_alignment == other.main_alignment
107            && self.cross_alignment == other.cross_alignment
108            && self.padding == other.padding
109            && self.margin == other.margin
110            && self.direction == other.direction
111            && self.order == other.order
112            && self.position == other.position
113            && self.content == other.content
114            && self.has_layout_references == other.has_layout_references
115            && self.spacing == other.spacing
116            && self.depends_on_inner == other.depends_on_inner
117    }
118
119    pub fn inner_layout_eq(&self, other: &Self) -> bool {
120        // Excludes everything but offset_x and offset_y
121        self.offset_x == other.offset_x && self.offset_y == other.offset_y
122    }
123
124    /// Construct a new Node given a size and a direction
125    pub fn from_size_and_direction(width: Size, height: Size, direction: Direction) -> Self {
126        Self {
127            width,
128            height,
129            direction,
130            ..Default::default()
131        }
132    }
133
134    /// Construct a new Node given some sizes
135    pub fn from_sizes(
136        width: Size,
137        height: Size,
138        minimum_width: Size,
139        minimum_height: Size,
140        maximum_width: Size,
141        maximum_height: Size,
142    ) -> Self {
143        Self {
144            width,
145            height,
146            minimum_width,
147            minimum_height,
148            maximum_width,
149            maximum_height,
150            ..Default::default()
151        }
152    }
153
154    /// Construct a new Node given a size and a visible size
155    pub fn from_size_and_visible_size(
156        width: Size,
157        height: Size,
158        visible_width: VisibleSize,
159        visible_height: VisibleSize,
160    ) -> Self {
161        Self {
162            width,
163            height,
164            visible_width,
165            visible_height,
166            ..Default::default()
167        }
168    }
169
170    /// Construct a new Node given a size and some offsets
171    pub fn from_size_and_offset(
172        width: Size,
173        height: Size,
174        offset_x: Length,
175        offset_y: Length,
176    ) -> Self {
177        Self {
178            width,
179            height,
180            offset_x,
181            offset_y,
182            ..Default::default()
183        }
184    }
185
186    /// Construct a new Node given a size and padding
187    pub fn from_size_and_padding(width: Size, height: Size, padding: Gaps) -> Self {
188        Self {
189            width,
190            height,
191            padding,
192            ..Default::default()
193        }
194    }
195
196    /// Construct a new Node given a size, alignments and a direction
197    pub fn from_size_and_alignments_and_direction(
198        width: Size,
199        height: Size,
200        main_alignment: Alignment,
201        cross_alignment: Alignment,
202        direction: Direction,
203    ) -> Self {
204        Self {
205            width,
206            height,
207            main_alignment,
208            cross_alignment,
209            direction,
210            ..Default::default()
211        }
212    }
213
214    /// Construct a new Node given a size, alignments, direction and spacing
215    pub fn from_size_and_alignments_and_direction_and_spacing(
216        width: Size,
217        height: Size,
218        main_alignment: Alignment,
219        cross_alignment: Alignment,
220        direction: Direction,
221        spacing: Length,
222    ) -> Self {
223        Self {
224            width,
225            height,
226            main_alignment,
227            cross_alignment,
228            direction,
229            spacing,
230            ..Default::default()
231        }
232    }
233
234    /// Construct a new Node given a size and a direction
235    pub fn from_size_and_margin(width: Size, height: Size, margin: Gaps) -> Self {
236        Self {
237            width,
238            height,
239            margin,
240            ..Default::default()
241        }
242    }
243
244    /// Construct a new Node given a size and a direction and some margin,
245    pub fn from_size_and_direction_and_margin(
246        width: Size,
247        height: Size,
248        direction: Direction,
249        margin: Gaps,
250    ) -> Self {
251        Self {
252            width,
253            height,
254            margin,
255            direction,
256            ..Default::default()
257        }
258    }
259
260    /// Construct a new Node given a size, alignments and a direction
261    pub fn from_size_and_alignments_and_direction_and_padding(
262        width: Size,
263        height: Size,
264        main_alignment: Alignment,
265        cross_alignment: Alignment,
266        direction: Direction,
267        padding: Gaps,
268    ) -> Self {
269        Self {
270            width,
271            height,
272            main_alignment,
273            cross_alignment,
274            padding,
275            direction,
276            ..Default::default()
277        }
278    }
279
280    /// Construct a new Node given a size and a position
281    pub fn from_size_and_position(width: Size, height: Size, position: Position) -> Self {
282        Self {
283            width,
284            height,
285            position,
286            ..Default::default()
287        }
288    }
289
290    /// Construct a new Node given a size and content
291    pub fn from_size_and_content(width: Size, height: Size, content: Content) -> Self {
292        Self {
293            width,
294            height,
295            content,
296            ..Default::default()
297        }
298    }
299
300    /// Construct a new Node given a size and spacing
301    pub fn from_size_and_direction_and_spacing(
302        width: Size,
303        height: Size,
304        direction: Direction,
305        spacing: Length,
306    ) -> Self {
307        Self {
308            width,
309            height,
310            direction,
311            spacing,
312            ..Default::default()
313        }
314    }
315
316    /// Has properties that depend on the inner Nodes?
317    pub fn does_depend_on_inner(&self) -> bool {
318        self.width.inner_sized()
319            || self.height.inner_sized()
320            || self.depends_on_inner
321            || self.do_inner_depend_on_parent()
322    }
323
324    /// Has properties that make its children dependant on it?
325    pub fn do_inner_depend_on_parent(&self) -> bool {
326        self.cross_alignment.is_not_start()
327            || self.main_alignment.is_not_start()
328            || self.has_layout_references
329            || self.content == Content::Flex
330    }
331}