1#[cfg(not(feature = "std"))]
2use alloc::boxed::Box;
3#[cfg(not(feature = "std"))]
4use alloc::{vec, vec::Vec};
5
6use crate::algo;
7use crate::geometry::{Rect, Size};
8use crate::number::Number;
9
10#[derive(Copy, Clone, PartialEq, Debug)]
11pub enum AlignItems {
12 FlexStart,
13 FlexEnd,
14 Center,
15 Baseline,
16 Stretch,
17}
18
19impl Default for AlignItems {
20 fn default() -> AlignItems {
21 AlignItems::Stretch
22 }
23}
24
25#[derive(Copy, Clone, PartialEq, Debug)]
26pub enum AlignSelf {
27 Auto,
28 FlexStart,
29 FlexEnd,
30 Center,
31 Baseline,
32 Stretch,
33}
34
35impl Default for AlignSelf {
36 fn default() -> AlignSelf {
37 AlignSelf::Auto
38 }
39}
40
41#[derive(Copy, Clone, PartialEq, Debug)]
42pub enum AlignContent {
43 FlexStart,
44 FlexEnd,
45 Center,
46 Stretch,
47 SpaceBetween,
48 SpaceAround,
49}
50
51impl Default for AlignContent {
52 fn default() -> AlignContent {
53 AlignContent::Stretch
54 }
55}
56
57#[derive(Copy, Clone, PartialEq, Debug)]
58pub enum Direction {
59 Inherit,
60 LTR,
61 RTL,
62}
63
64impl Default for Direction {
65 fn default() -> Direction {
66 Direction::Inherit
67 }
68}
69
70#[derive(Copy, Clone, PartialEq, Debug)]
71pub enum Display {
72 Flex,
73 None,
74}
75
76impl Default for Display {
77 fn default() -> Display {
78 Display::Flex
79 }
80}
81
82#[derive(Copy, Clone, PartialEq, Debug)]
83pub enum FlexDirection {
84 Row,
85 Column,
86 RowReverse,
87 ColumnReverse,
88}
89
90impl Default for FlexDirection {
91 fn default() -> FlexDirection {
92 FlexDirection::Row
93 }
94}
95
96impl FlexDirection {
97 pub(crate) fn is_row(self) -> bool {
98 self == FlexDirection::Row || self == FlexDirection::RowReverse
99 }
100
101 pub(crate) fn is_column(self) -> bool {
102 self == FlexDirection::Column || self == FlexDirection::ColumnReverse
103 }
104
105 pub(crate) fn is_reverse(self) -> bool {
106 self == FlexDirection::RowReverse || self == FlexDirection::ColumnReverse
107 }
108}
109
110#[derive(Copy, Clone, PartialEq, Debug)]
111pub enum JustifyContent {
112 FlexStart,
113 FlexEnd,
114 Center,
115 SpaceBetween,
116 SpaceAround,
117 SpaceEvenly,
118}
119
120impl Default for JustifyContent {
121 fn default() -> JustifyContent {
122 JustifyContent::FlexStart
123 }
124}
125
126#[derive(Copy, Clone, PartialEq, Debug)]
127pub enum Overflow {
128 Visible,
129 Hidden,
130 Scroll,
131}
132
133impl Default for Overflow {
134 fn default() -> Overflow {
135 Overflow::Visible
136 }
137}
138
139#[derive(Copy, Clone, PartialEq, Debug)]
140pub enum PositionType {
141 Relative,
142 Absolute,
143}
144
145impl Default for PositionType {
146 fn default() -> PositionType {
147 PositionType::Relative
148 }
149}
150
151#[derive(Copy, Clone, PartialEq, Debug)]
152pub enum FlexWrap {
153 NoWrap,
154 Wrap,
155 WrapReverse,
156}
157
158impl Default for FlexWrap {
159 fn default() -> FlexWrap {
160 FlexWrap::NoWrap
161 }
162}
163
164#[derive(Copy, Clone, PartialEq, Debug)]
165pub enum Dimension {
166 Undefined,
167 Auto,
168 Points(f32),
169 Percent(f32),
170}
171
172impl Default for Dimension {
173 fn default() -> Dimension {
174 Dimension::Undefined
175 }
176}
177
178impl Dimension {
179 pub(crate) fn resolve(self, parent_width: Number) -> Number {
180 match self {
181 Dimension::Points(points) => Number::Defined(points),
182 Dimension::Percent(percent) => parent_width * percent,
183 _ => Number::Undefined,
184 }
185 }
186
187 pub(crate) fn is_defined(self) -> bool {
188 match self {
189 Dimension::Points(_) => true,
190 Dimension::Percent(_) => true,
191 _ => false,
192 }
193 }
194}
195
196impl Default for Rect<Dimension> {
197 fn default() -> Rect<Dimension> {
198 Rect { start: Default::default(), end: Default::default(), top: Default::default(), bottom: Default::default() }
199 }
200}
201
202impl Default for Size<Dimension> {
203 fn default() -> Size<Dimension> {
204 Size { width: Dimension::Auto, height: Dimension::Auto }
205 }
206}
207
208type MeasureFunc = Box<Fn(Size<Number>) -> Size<f32>>;
209
210#[derive(Debug, Clone)]
211pub struct LayoutCache {
212 pub node_size: Size<Number>,
213 pub parent_size: Size<Number>,
214 pub percent_calc_base: Number,
215 pub perform_layout: bool,
216
217 pub result: algo::ComputeResult,
218}
219
220pub struct Node {
221 pub display: Display,
222
223 pub position_type: PositionType,
224 pub direction: Direction,
225 pub flex_direction: FlexDirection,
226
227 pub flex_wrap: FlexWrap,
228 pub overflow: Overflow,
229
230 pub align_items: AlignItems,
231 pub align_self: AlignSelf,
232 pub align_content: AlignContent,
233
234 pub justify_content: JustifyContent,
235
236 pub position: Rect<Dimension>,
237 pub margin: Rect<Dimension>,
238 pub padding: Rect<Dimension>,
239 pub border: Rect<Dimension>,
240
241 pub flex_grow: f32,
242 pub flex_shrink: f32,
243 pub flex_basis: Dimension,
244
245 pub size: Size<Dimension>,
246 pub min_size: Size<Dimension>,
247 pub max_size: Size<Dimension>,
248
249 pub aspect_ratio: Number,
250 pub measure: Option<MeasureFunc>,
251
252 pub children: Vec<Node>,
253
254 pub layout_cache: core::cell::RefCell<Option<LayoutCache>>,
255}
256
257impl Default for Node {
258 fn default() -> Node {
259 Node {
260 display: Default::default(),
261
262 position_type: Default::default(),
263 direction: Default::default(),
264 flex_direction: Default::default(),
265
266 flex_wrap: Default::default(),
267 overflow: Default::default(),
268
269 align_items: Default::default(),
270 align_self: Default::default(),
271 align_content: Default::default(),
272
273 justify_content: Default::default(),
274
275 position: Default::default(),
276 margin: Default::default(),
277 padding: Default::default(),
278 border: Default::default(),
279
280 flex_grow: 0.0,
281 flex_shrink: 1.0,
282 flex_basis: Dimension::Auto,
283
284 size: Default::default(),
285 min_size: Default::default(),
286 max_size: Default::default(),
287
288 aspect_ratio: Default::default(),
289 measure: None,
290
291 children: vec![],
292
293 layout_cache: core::cell::RefCell::new(None),
294 }
295 }
296}
297
298impl Node {
299 pub(crate) fn min_main_size(&self, direction: FlexDirection) -> Dimension {
300 match direction {
301 FlexDirection::Row | FlexDirection::RowReverse => self.min_size.width,
302 FlexDirection::Column | FlexDirection::ColumnReverse => self.min_size.height,
303 }
304 }
305
306 pub(crate) fn max_main_size(&self, direction: FlexDirection) -> Dimension {
307 match direction {
308 FlexDirection::Row | FlexDirection::RowReverse => self.max_size.width,
309 FlexDirection::Column | FlexDirection::ColumnReverse => self.max_size.height,
310 }
311 }
312
313 pub(crate) fn main_margin_start(&self, direction: FlexDirection) -> Dimension {
314 match direction {
315 FlexDirection::Row | FlexDirection::RowReverse => self.margin.start,
316 FlexDirection::Column | FlexDirection::ColumnReverse => self.margin.top,
317 }
318 }
319
320 pub(crate) fn main_margin_end(&self, direction: FlexDirection) -> Dimension {
321 match direction {
322 FlexDirection::Row | FlexDirection::RowReverse => self.margin.end,
323 FlexDirection::Column | FlexDirection::ColumnReverse => self.margin.bottom,
324 }
325 }
326
327 pub(crate) fn cross_size(&self, direction: FlexDirection) -> Dimension {
328 match direction {
329 FlexDirection::Row | FlexDirection::RowReverse => self.size.height,
330 FlexDirection::Column | FlexDirection::ColumnReverse => self.size.width,
331 }
332 }
333
334 pub(crate) fn min_cross_size(&self, direction: FlexDirection) -> Dimension {
335 match direction {
336 FlexDirection::Row | FlexDirection::RowReverse => self.min_size.height,
337 FlexDirection::Column | FlexDirection::ColumnReverse => self.min_size.width,
338 }
339 }
340
341 pub(crate) fn max_cross_size(&self, direction: FlexDirection) -> Dimension {
342 match direction {
343 FlexDirection::Row | FlexDirection::RowReverse => self.max_size.height,
344 FlexDirection::Column | FlexDirection::ColumnReverse => self.max_size.width,
345 }
346 }
347
348 pub(crate) fn cross_margin_start(&self, direction: FlexDirection) -> Dimension {
349 match direction {
350 FlexDirection::Row | FlexDirection::RowReverse => self.margin.top,
351 FlexDirection::Column | FlexDirection::ColumnReverse => self.margin.start,
352 }
353 }
354
355 pub(crate) fn cross_margin_end(&self, direction: FlexDirection) -> Dimension {
356 match direction {
357 FlexDirection::Row | FlexDirection::RowReverse => self.margin.bottom,
358 FlexDirection::Column | FlexDirection::ColumnReverse => self.margin.end,
359 }
360 }
361
362 pub(crate) fn align_self(&self, parent: &Node) -> AlignSelf {
363 if self.align_self == AlignSelf::Auto {
364 match parent.align_items {
365 AlignItems::FlexStart => AlignSelf::FlexStart,
366 AlignItems::FlexEnd => AlignSelf::FlexEnd,
367 AlignItems::Center => AlignSelf::Center,
368 AlignItems::Baseline => AlignSelf::Baseline,
369 AlignItems::Stretch => AlignSelf::Stretch,
370 }
371 } else {
372 self.align_self
373 }
374 }
375}