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