Fix percentage height to be based on container height
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 perform_layout: bool,
215
216 pub result: algo::ComputeResult,
217}
218
219pub struct Node {
220 pub display: Display,
221
222 pub position_type: PositionType,
223 pub direction: Direction,
224 pub flex_direction: FlexDirection,
225
226 pub flex_wrap: FlexWrap,
227 pub overflow: Overflow,
228
229 pub align_items: AlignItems,
230 pub align_self: AlignSelf,
231 pub align_content: AlignContent,
232
233 pub justify_content: JustifyContent,
234
235 pub position: Rect<Dimension>,
236 pub margin: Rect<Dimension>,
237 pub padding: Rect<Dimension>,
238 pub border: Rect<Dimension>,
239
240 pub flex_grow: f32,
241 pub flex_shrink: f32,
242 pub flex_basis: Dimension,
243
244 pub size: Size<Dimension>,
245 pub min_size: Size<Dimension>,
246 pub max_size: Size<Dimension>,
247
248 pub aspect_ratio: Number,
249 pub measure: Option<MeasureFunc>,
250
251 pub children: Vec<Node>,
252
253 pub layout_cache: core::cell::RefCell<Option<LayoutCache>>,
254}
255
256impl Default for Node {
257 fn default() -> Node {
258 Node {
259 display: Default::default(),
260
261 position_type: Default::default(),
262 direction: Default::default(),
263 flex_direction: Default::default(),
264
265 flex_wrap: Default::default(),
266 overflow: Default::default(),
267
268 align_items: Default::default(),
269 align_self: Default::default(),
270 align_content: Default::default(),
271
272 justify_content: Default::default(),
273
274 position: Default::default(),
275 margin: Default::default(),
276 padding: Default::default(),
277 border: Default::default(),
278
279 flex_grow: 0.0,
280 flex_shrink: 1.0,
281 flex_basis: Dimension::Auto,
282
283 size: Default::default(),
284 min_size: Default::default(),
285 max_size: Default::default(),
286
287 aspect_ratio: Default::default(),
288 measure: None,
289
290 children: vec![],
291
292 layout_cache: core::cell::RefCell::new(None),
293 }
294 }
295}
296
297impl Node {
298 pub(crate) fn min_main_size(&self, direction: FlexDirection) -> Dimension {
299 match direction {
300 FlexDirection::Row | FlexDirection::RowReverse => self.min_size.width,
301 FlexDirection::Column | FlexDirection::ColumnReverse => self.min_size.height,
302 }
303 }
304
305 pub(crate) fn max_main_size(&self, direction: FlexDirection) -> Dimension {
306 match direction {
307 FlexDirection::Row | FlexDirection::RowReverse => self.max_size.width,
308 FlexDirection::Column | FlexDirection::ColumnReverse => self.max_size.height,
309 }
310 }
311
312 pub(crate) fn main_margin_start(&self, direction: FlexDirection) -> Dimension {
313 match direction {
314 FlexDirection::Row | FlexDirection::RowReverse => self.margin.start,
315 FlexDirection::Column | FlexDirection::ColumnReverse => self.margin.top,
316 }
317 }
318
319 pub(crate) fn main_margin_end(&self, direction: FlexDirection) -> Dimension {
320 match direction {
321 FlexDirection::Row | FlexDirection::RowReverse => self.margin.end,
322 FlexDirection::Column | FlexDirection::ColumnReverse => self.margin.bottom,
323 }
324 }
325
326 pub(crate) fn cross_size(&self, direction: FlexDirection) -> Dimension {
327 match direction {
328 FlexDirection::Row | FlexDirection::RowReverse => self.size.height,
329 FlexDirection::Column | FlexDirection::ColumnReverse => self.size.width,
330 }
331 }
332
333 pub(crate) fn min_cross_size(&self, direction: FlexDirection) -> Dimension {
334 match direction {
335 FlexDirection::Row | FlexDirection::RowReverse => self.min_size.height,
336 FlexDirection::Column | FlexDirection::ColumnReverse => self.min_size.width,
337 }
338 }
339
340 pub(crate) fn max_cross_size(&self, direction: FlexDirection) -> Dimension {
341 match direction {
342 FlexDirection::Row | FlexDirection::RowReverse => self.max_size.height,
343 FlexDirection::Column | FlexDirection::ColumnReverse => self.max_size.width,
344 }
345 }
346
347 pub(crate) fn cross_margin_start(&self, direction: FlexDirection) -> Dimension {
348 match direction {
349 FlexDirection::Row | FlexDirection::RowReverse => self.margin.top,
350 FlexDirection::Column | FlexDirection::ColumnReverse => self.margin.start,
351 }
352 }
353
354 pub(crate) fn cross_margin_end(&self, direction: FlexDirection) -> Dimension {
355 match direction {
356 FlexDirection::Row | FlexDirection::RowReverse => self.margin.bottom,
357 FlexDirection::Column | FlexDirection::ColumnReverse => self.margin.end,
358 }
359 }
360
361 pub(crate) fn align_self(&self, parent: &Node) -> AlignSelf {
362 if self.align_self == AlignSelf::Auto {
363 match parent.align_items {
364 AlignItems::FlexStart => AlignSelf::FlexStart,
365 AlignItems::FlexEnd => AlignSelf::FlexEnd,
366 AlignItems::Center => AlignSelf::Center,
367 AlignItems::Baseline => AlignSelf::Baseline,
368 AlignItems::Stretch => AlignSelf::Stretch,
369 }
370 } else {
371 self.align_self
372 }
373 }
374}