1use bumpalo::Bump;
2use paste::paste;
3
4use crate::Container;
5
6use super::{Calc, font::FontMetrics};
7
8#[derive(Debug, Clone, Copy)]
9pub struct CalculatorDefaults {
10 pub font_size: f32,
11 pub font_margin_top: f32,
12 pub font_margin_bottom: f32,
13 pub h1_font_size: f32,
14 pub h1_font_margin_top: f32,
15 pub h1_font_margin_bottom: f32,
16 pub h2_font_size: f32,
17 pub h2_font_margin_top: f32,
18 pub h2_font_margin_bottom: f32,
19 pub h3_font_size: f32,
20 pub h3_font_margin_top: f32,
21 pub h3_font_margin_bottom: f32,
22 pub h4_font_size: f32,
23 pub h4_font_margin_top: f32,
24 pub h4_font_margin_bottom: f32,
25 pub h5_font_size: f32,
26 pub h5_font_margin_top: f32,
27 pub h5_font_margin_bottom: f32,
28 pub h6_font_size: f32,
29 pub h6_font_margin_top: f32,
30 pub h6_font_margin_bottom: f32,
31}
32
33pub struct Calculator<F: FontMetrics> {
34 font_metrics: F,
35 defaults: CalculatorDefaults,
36}
37
38impl<F: FontMetrics> Calculator<F> {
39 pub const fn new(font_metrics: F, defaults: CalculatorDefaults) -> Self {
40 Self {
41 font_metrics,
42 defaults,
43 }
44 }
45}
46
47#[cfg(feature = "benchmark")]
48macro_rules! time {
49 ($label:tt, $expr:expr $(,)?) => {{
50 let before = gimbal_time::now();
51 let ret = $expr;
52 let duration = gimbal_time::now().duration_since(before).unwrap();
53 log::info!("{}: took {}µs", $label, duration.as_micros());
54 ret
55 }};
56}
57
58#[cfg(not(feature = "benchmark"))]
59macro_rules! time {
60 ($label:tt, $expr:expr $(,)?) => {
61 $expr
62 };
63}
64
65macro_rules! update_changed {
66 ($changed:ident, $($reason:tt)+) => {{
67 if std::option_env!("LOG_ON_CHANGED") == Some("1") {
68 let reason = format!($($reason)*);
69 log::info!("change triggered because {reason}");
70 }
71 $changed = true;
72 }};
73}
74
75#[cfg_attr(feature = "profiling", profiling::all_functions)]
76impl<F: FontMetrics> Calc for Calculator<F> {
77 #[allow(clippy::let_and_return, clippy::cognitive_complexity)]
78 fn calc(&self, container: &mut Container) -> bool {
79 log::trace!("calc: container={container}");
80
81 time!("calc", {
82 let arena = time!("arena", Bump::new());
83 let context = arena.alloc(Container::default());
84 let bfs = time!("bfs", container.bfs());
85 time!("calc_widths", self.calc_widths(&bfs, container));
86 time!(
87 "calc_margin_and_padding",
88 self.calc_margin_and_padding(&bfs, container)
89 );
90 time!("flex_width", self.flex_width(&bfs, container));
91 time!("wrap_horizontal", self.wrap_horizontal(&bfs, container));
92 time!("calc_heights", self.calc_heights(&bfs, container));
93 time!("flex_height", self.flex_height(&bfs, container));
94 time!(
95 "position_elements",
96 self.position_elements(&arena, &bfs, container, context)
97 )
98 })
99 }
100}
101
102macro_rules! calc_size_on_axis {
103 (
104 $label:tt,
105 $self:ident,
106 $bfs:ident,
107 $container:ident,
108 $size:ident,
109 $axis:ident,
110 $cross_axis:ident,
111 $x:ident,
112 $y:ident,
113 $unit:ident,
114 $each_parent:expr,
115 $each_child:expr
116 $(,)?
117 ) => {{
118 use paste::paste;
119
120 use crate::{LayoutDirection, LayoutOverflow, Position, float_eq};
121
122 const LABEL: &str = $label;
123
124 log::trace!("{LABEL}:\n{}", $container);
125
126 let root_id = $container.id;
127 let defaults = $self.defaults;
128 let view_width = $container.calculated_width.expect("Missing view_width");
129 let view_height = $container.calculated_height.expect("Missing view_height");
130
131 $bfs.traverse_rev_with_parents_ref_mut(
132 true,
133 Container::default(),
134 $container,
135 |parent, mut context| {
136 if parent.id == root_id {
137 context.calculated_font_size = Some(defaults.font_size);
138 context.calculated_margin_top = Some(defaults.font_margin_top);
139 context.calculated_margin_bottom = Some(defaults.font_margin_bottom);
140 }
141
142 $each_parent(&mut *parent, view_width, view_height, &context, defaults);
143
144 macro_rules! set_prop_to_context {
145 ($prop:ident) => {
146 if let Some(value) = paste!(parent.[<calculated_ $prop>]) {
147 paste!(context.[<calculated_ $prop>]) = Some(value);
148 }
149 };
150 }
151
152 set_prop_to_context!(font_size);
153 set_prop_to_context!(margin_top);
154 set_prop_to_context!(margin_bottom);
155
156 context
157 },
158 |parent, context| {
159 let mut min_size = 0.0;
160 let mut preferred_size = 0.0;
161
162 if let Some(gap) = paste!(parent.[<$cross_axis:lower _gap>]).as_ref().and_then(crate::Number::as_fixed) {
163 let gap = gap.calc(0.0, view_width, view_height);
164 log::trace!("{LABEL}: setting gap={gap}");
165 paste!(parent.[<calculated_ $cross_axis:lower _gap>]) = Some(gap);
166 }
167
168 let direction = parent.direction;
169 let overflow = paste!(parent.[<overflow_ $unit>]);
170
171 for child in &mut parent.children {
172 log::trace!("{LABEL}: container:\n{child}");
173
174 $each_child(&mut *child, view_width, view_height, context, defaults);
175
176 if let Some(max) = paste!(child.[<max_ $size>]).as_ref().and_then(crate::Number::as_fixed) {
177 let size = max.calc(0.0, view_width, view_height);
178 log::trace!("{LABEL}: calculated_max_size={size}");
179 paste!(child.[<calculated_max_ $size>]) = Some(size);
180 }
181 if let Some(min) = paste!(child.[<min_ $size>]).as_ref().and_then(crate::Number::as_fixed) {
182 let size = min.calc(0.0, view_width, view_height);
183 log::trace!("{LABEL}: calculated_min_size={size}");
184 paste!(child.[<calculated_min_ $size>]) = Some(size);
185 }
186
187 let (mut min, mut preferred) = if let Some(size) = child.$size.as_ref().and_then(Number::as_fixed) {
188 let new_size = size.calc(0.0, view_width, view_height);
189
190 paste!(child.[<calculated_ $size>]) = Some(new_size);
191 (Some(new_size), new_size)
192 } else if let (LayoutDirection::Row, crate::Element::Raw { value }) = (LayoutDirection::$axis, &child.element) {
193 log::trace!("{LABEL}: measuring text={value}");
194 let bounds = $self.font_metrics.measure_text(
195 value,
196 context.calculated_font_size.expect("Missing calculated_font_size"),
197 f32::INFINITY
198 );
199 log::trace!("{LABEL}: measured bounds={bounds:?}");
200 let width = bounds.width();
201 let height = bounds.height();
202
203 child.calculated_width = Some(width);
204 child.calculated_height = Some(height);
205 child.calculated_preferred_height = Some(height);
206
207 (None, width)
208 } else if let Some(size) = paste!(child.[<calculated_preferred_ $size>]) {
209 paste!(child.[<calculated_ $size>]) = Some(size);
210 (paste!(child.[<calculated_child_min_ $size>]), size)
211 } else if let Some(size) = paste!(child.[<calculated_child_min_ $size>]) {
212 paste!(child.[<calculated_ $size>]) = Some(size);
213 (Some(size), size)
214 } else {
215 paste!(child.[<calculated_ $size>]) = Some(0.0);
216 (None, 0.0)
217 };
218
219 if let Some(calculated_max) = paste!(child.[<calculated_max_ $size>]) {
220 if let Some(existing) = &mut paste!(child.[<calculated_ $size>]) {
221 if *existing > calculated_max {
222 *existing = calculated_max;
223 preferred = calculated_max;
224 }
225 } else {
226 paste!(child.[<calculated_ $size>]) = Some(calculated_max);
227 preferred = calculated_max;
228 }
229 }
230 if let Some(calculated_min) = paste!(child.[<calculated_min_ $size>]) {
231 if let Some(existing) = &mut paste!(child.[<calculated_ $size>]) {
232 if *existing < calculated_min {
233 *existing = calculated_min;
234 preferred = calculated_min;
235 }
236 } else {
237 paste!(child.[<calculated_ $size>]) = Some(calculated_min);
238 preferred = calculated_min;
239 }
240 }
241
242 if let Some(margin) = paste!(child.[<margin_ $x>]).as_ref().and_then(crate::Number::as_fixed) {
243 let size = margin.calc(0.0, view_width, view_height);
244 paste!(child.[<calculated_margin_ $x>]) = Some(size);
245 preferred += size;
246 crate::layout::increase_opt(&mut min, size);
247 }
248 if let Some(margin) = paste!(child.[<margin_ $y>]).as_ref().and_then(crate::Number::as_fixed) {
249 let size = margin.calc(0.0, view_width, view_height);
250 paste!(child.[<calculated_margin_ $y>]) = Some(size);
251 preferred += size;
252 crate::layout::increase_opt(&mut min, size);
253 }
254 if let Some(padding) = paste!(child.[<padding_ $x>]).as_ref().and_then(crate::Number::as_fixed) {
255 let size = padding.calc(0.0, view_width, view_height);
256 paste!(child.[<calculated_padding_ $x>]) = Some(size);
257 preferred += size;
258 crate::layout::increase_opt(&mut min, size);
259 }
260 if let Some(padding) = paste!(child.[<padding_ $y>]).as_ref().and_then(crate::Number::as_fixed) {
261 let size = padding.calc(0.0, view_width, view_height);
262 paste!(child.[<calculated_padding_ $y>]) = Some(size);
263 preferred += size;
264 crate::layout::increase_opt(&mut min, size);
265 }
266 if let Some((&color, size)) = paste!(child.[<border_ $x>])
267 .as_ref()
268 .and_then(|(color, size)| size.as_fixed().map(|size| (color, size)))
269 {
270 let size = size.calc(0.0, view_width, view_height);
271 if let Some(calculated) = &mut paste!(child.[<calculated_border_ $x>]) {
272 if calculated.0 != color {
273 calculated.0 = color;
274 }
275 if !float_eq!(calculated.1, size) {
276 calculated.1 = size;
277 }
278 } else {
279 paste!(child.[<calculated_border_ $x>]) = Some((color, size));
280 }
281 }
282 if let Some((&color, size)) = paste!(child.[<border_ $y>])
283 .as_ref()
284 .and_then(|(color, size)| size.as_fixed().map(|size| (color, size)))
285 {
286 let size = size.calc(0.0, view_width, view_height);
287 if let Some(calculated) = &mut paste!(child.[<calculated_border_ $y>]) {
288 if calculated.0 != color {
289 calculated.0 = color;
290 }
291 if !float_eq!(calculated.1, size) {
292 calculated.1 = size;
293 }
294 } else {
295 paste!(child.[<calculated_border_ $y>]) = Some((color, size));
296 }
297 }
298
299 macro_rules! handle_auto_sizing {
300 ($value:ident, $output:ident) => {{
301 match child.position.unwrap_or_default() {
302 Position::Static | Position::Relative | Position::Sticky => match overflow {
303 LayoutOverflow::Auto
304 | LayoutOverflow::Scroll
305 | LayoutOverflow::Expand
306 | LayoutOverflow::Squash => {
307 match direction {
308 LayoutDirection::$axis => $output += $value,
309 LayoutDirection::$cross_axis => if $value > $output {
310 $output = $value;
311 },
312 }
313 }
314 LayoutOverflow::Wrap { .. } => {
315 if $value > $output {
316 $output = $value;
317 }
318 }
319 LayoutOverflow::Hidden => {}
320 },
321 Position::Absolute | Position::Fixed => {}
322 }
323 }};
324 }
325
326 paste!(child.[<calculated_preferred_ $size>]) = Some(preferred);
327 handle_auto_sizing!(preferred, preferred_size);
328
329 if let Some(size) = min {
330 paste!(child.[<calculated_child_min_ $size>]) = Some(size);
331 handle_auto_sizing!(size, min_size);
332 }
333 }
334
335 paste!(parent.[<calculated_child_min_ $size>]) = Some(min_size);
336 paste!(parent.[<calculated_preferred_ $size>]) = Some(preferred_size);
337 });
338 }};
339}
340
341macro_rules! flex_on_axis {
342 (
343 $label:tt,
344 $bfs:ident,
345 $container:ident,
346 $size:ident,
347 $axis:ident,
348 $cross_axis:ident,
349 $cell:ident,
350 $x:ident,
351 $y:ident,
352 $unit:ident
353 $(,)?
354 ) => {{
355 use paste::paste;
356
357 use crate::{Element, LayoutOverflow, float_eq, float_gt};
358
359 const LABEL: &str = $label;
360
361 log::trace!("{LABEL}:\n{}", $container);
362
363 let root_id = $container.id;
364 let view_width = $container.calculated_width.expect("Missing view_width");
365 let view_height = $container.calculated_height.expect("Missing view_height");
366 let mut rect = crate::layout::Rect::default();
367
368 #[allow(clippy::cognitive_complexity)]
369 $bfs.traverse_with_parents_ref_mut(
370 true,
371 &mut rect,
372 $container,
373 |parent, relative_container| {
374 if parent.id == root_id {
375 relative_container.x = 0.0;
376 relative_container.y = 0.0;
377 relative_container.width = view_width;
378 relative_container.height = view_height;
379 } else if parent.position == Some(Position::Relative) {
380 relative_container.x = 0.0;
381 relative_container.y = 0.0;
382 relative_container.width = view_width;
383 relative_container.height = view_height;
384 paste!(relative_container.[<$size>] = parent.[<calculated_ $size>].expect("Missing parent calculated size"));
385 }
386 },
387 |parent, relative_container| {
388 let direction = parent.direction;
389 let container_size = paste!(parent.[<calculated_ $size>]).expect("Missing container size");
390
391 if let Some(gap) = paste!(parent.[<$cross_axis:lower _gap>]).as_ref().and_then(crate::Number::as_dynamic) {
392 paste!(parent.[<calculated_ $cross_axis:lower _gap>]) =
393 Some(gap.calc(container_size, view_width, view_height));
394 }
395
396 for child in &mut parent.children {
397 log::trace!("{LABEL}: processing child\n{child}");
398 let calculated_size = paste!(child.[<calculated_ $size>]).as_mut().expect("Missing calculated size");
399 if let Some(min) = paste!(child.[<min_ $size>]).as_ref().and_then(crate::Number::as_dynamic) {
400 let size = min.calc(container_size, view_width, view_height);
401 log::trace!("{LABEL}: calculated_min_size={size}");
402 paste!(child.[<calculated_min_ $size>]) = Some(size);
403 }
404 if let Some(max) = paste!(child.[<max_ $size>]).as_ref().and_then(crate::Number::as_dynamic) {
405 let size = max.calc(container_size, view_width, view_height);
406 log::trace!("{LABEL}: calculated_max_size={size}");
407 paste!(child.[<calculated_max_ $size>]) = Some(size);
408
409 if size < *calculated_size {
410 *calculated_size = size;
411 }
412 }
413 if let Some(min) = paste!(child.[<calculated_min_ $size>]) {
414 if min > *calculated_size {
415 log::trace!("{LABEL}: setting size from={calculated_size} to min_size={min}");
416 *calculated_size = min;
417 }
418 }
419
420 if matches!(paste!(child.[<overflow_ $unit>]), LayoutOverflow::Auto | LayoutOverflow::Scroll) {
421 if let Some(min) = &mut paste!(child.[<calculated_min_ $size>]).or(paste!(child.[<calculated_child_min_ $size>])) {
422 log::trace!("{LABEL}: checking if min={min} > container_size={container_size}");
423 if *min > container_size {
424 *min = container_size;
425 paste!(child.[<calculated_ $size>]) = Some(container_size);
426 }
427 }
428 }
429
430 if let Some((&color, size)) = paste!(child.[<border_ $x>])
431 .as_ref()
432 .and_then(|(color, size)| size.as_dynamic().map(|size| (color, size)))
433 {
434 let size = size.calc(0.0, view_width, view_height);
435 if let Some(calculated) = &mut paste!(child.[<calculated_border_ $x>]) {
436 if calculated.0 != color {
437 calculated.0 = color;
438 }
439 if !float_eq!(calculated.1, size) {
440 calculated.1 = size;
441 }
442 } else {
443 paste!(child.[<calculated_border_ $x>]) = Some((color, size));
444 }
445 }
446 if let Some((&color, size)) = paste!(child.[<border_ $y>])
447 .as_ref()
448 .and_then(|(color, size)| size.as_dynamic().map(|size| (color, size)))
449 {
450 let size = size.calc(0.0, view_width, view_height);
451 if let Some(calculated) = &mut paste!(child.[<calculated_border_ $y>]) {
452 if calculated.0 != color {
453 calculated.0 = color;
454 }
455 if !float_eq!(calculated.1, size) {
456 calculated.1 = size;
457 }
458 } else {
459 paste!(child.[<calculated_border_ $y>]) = Some((color, size));
460 }
461 }
462 }
463
464 if parent.relative_positioned_elements().any(|x| x.$size.as_ref().is_none_or(crate::Number::is_dynamic)) {
465 let mut remaining_container_size = container_size;
466
467 for child in parent.relative_positioned_elements() {
469 match direction {
470 LayoutDirection::$axis => {
471 if let Some(size) = paste!(child.[<margin_ $unit>]()) {
472 log::trace!(
473 "{LABEL}: removing margin size={size} from remaining_container_size={remaining_container_size} ({})",
474 remaining_container_size - size
475 );
476 remaining_container_size -= size;
477 }
478 if let Some(size) = paste!(child.[<padding_ $unit>]()) {
479 log::trace!(
480 "{LABEL}: removing padding size={size} from remaining_container_size={remaining_container_size} ({})",
481 remaining_container_size - size
482 );
483 remaining_container_size -= size;
484 }
485 }
486 LayoutDirection::$cross_axis => {}
487 }
488 }
489
490 log::trace!("{LABEL}: container_size={container_size} remaining_container_size={remaining_container_size}");
491 let container_size = remaining_container_size;
492
493 for child in parent.relative_positioned_elements_mut() {
495 if let Some(size) = child.$size.as_ref().and_then(crate::Number::as_dynamic) {
496 let container_size = match direction {
497 LayoutDirection::$axis => container_size,
498 LayoutDirection::$cross_axis => {
499 container_size
500 - paste!(child.[<margin_ $unit>]()).unwrap_or_default()
501 - paste!(child.[<padding_ $unit>]()).unwrap_or_default()
502 }
503 };
504 log::trace!("{LABEL}: calculating dynamic size={size:?}");
505 let size = size.calc(container_size, view_width, view_height);
506 log::trace!("{LABEL}: calculated dynamic size={size}");
507 paste!(child.[<calculated_ $size>]) = Some(size);
508 }
509 }
510
511 if parent.relative_positioned_elements().any(|x| x.$size.is_none()) {
513 let mut remaining_size = container_size;
514 let mut last_cell = 0;
515 let mut max_cell_size = 0.0;
516
517 for child in parent.relative_positioned_elements() {
519 log::trace!("{LABEL}: calculating remaining size:\n{child}");
520
521 match direction {
522 LayoutDirection::$axis => {
523 if let Some(size) = paste!(child.[<calculated_ $size>]) {
524 log::trace!(
525 "{LABEL}: removing size={size} from remaining_size={remaining_size} ({})",
526 remaining_size - size
527 );
528 remaining_size -= size;
529 }
530 }
531 LayoutDirection::$cross_axis => {
532 if let Some(LayoutPosition::Wrap { $cell: cell, .. }) = child.calculated_position {
533 if cell != last_cell {
534 moosicbox_assert::assert!(cell > last_cell);
535 remaining_size -= max_cell_size;
536 max_cell_size = paste!(child.[<calculated_ $size>]).unwrap_or_default();
537 }
538 last_cell = cell;
539 }
540 }
541 }
542 }
543
544 let cell_count = last_cell + 1;
545 remaining_size -= max_cell_size;
546
547 if remaining_size < 0.0 {
548 remaining_size = 0.0;
549 }
550
551 log::trace!("{LABEL}: remaining_size={remaining_size}\n{parent}");
552
553 match direction {
555 LayoutDirection::$axis => {
556 if parent.is_flex_container() {
557 if float_gt!(remaining_size, 0.0)
558 && parent
559 .relative_positioned_elements()
560 .any(|x| x.$size.is_none() && x.is_expandable(parent))
561 {
562 loop {
563 let mut smallest = f32::INFINITY;
564 let mut target = f32::INFINITY;
565 let mut smallest_count = 0_u16;
566
567 for size in parent
568 .relative_positioned_elements()
569 .filter(|x| x.$size.is_none() && x.is_expandable(parent))
570 .filter_map(|x| paste!(x.[<calculated_ $size>]))
571 {
572 if smallest > size {
573 target = smallest;
574 smallest = size;
575 smallest_count = 1;
576 } else if float_eq!(smallest, size) {
577 smallest_count += 1;
578 } else if size < target {
579 target = size;
580 }
581 }
582
583 moosicbox_assert::assert!(smallest_count > 0, "expected at least one smallest item");
584 moosicbox_assert::assert!(smallest.is_finite(), "expected smallest to be finite");
585
586 let smallest_countf = f32::from(smallest_count);
587
588 let last_iteration = if target.is_infinite() {
589 log::trace!("{LABEL}: last iteration remaining_size={remaining_size}");
590 target = smallest + if smallest_count == 1 {
591 remaining_size
592 } else {
593 remaining_size / smallest_countf
594 };
595 remaining_size = 0.0;
596 true
597 } else if target > remaining_size {
598 log::trace!("{LABEL}: target={target} > remaining_size={remaining_size}");
599 target = if smallest_count == 1 {
600 remaining_size
601 } else {
602 remaining_size / smallest_countf
603 };
604 remaining_size = 0.0;
605 true
606 } else {
607 remaining_size -= (target - smallest) * smallest_countf;
608 float_eq!(remaining_size, 0.0)
609 };
610
611 log::trace!("{LABEL}: target={target} smallest={smallest} smallest_count={smallest_count} remaining_size={remaining_size} container_size={container_size}");
612
613 moosicbox_assert::assert!(target.is_finite(), "expected target to be finite");
614
615 let mut dynamic_child_size = false;
616
617 for child in parent
618 .relative_positioned_elements_mut()
619 .filter(|x| x.$size.is_none())
620 .filter(|x| paste!(x.[<calculated_ $size>]).is_some_and(|x| float_eq!(x, smallest)))
621 {
622 let mut clipped = false;
623 let mut target = target;
624
625 if let Some(min) = paste!(child.[<calculated_min_ $size>]) {
626 log::trace!("{LABEL}: calculated_min={min}");
627 let min = min - paste!(child.[<padding_ $unit>]()).unwrap_or_default() - paste!(child.[<margin_ $unit>]()).unwrap_or_default();
628 log::trace!("{LABEL}: calculated_min={min} without padding/margins");
629 if target < min {
630 remaining_size -= min - target;
631 target = min;
632 }
633 }
634 if direction == LayoutDirection::Row && child.is_raw() {
635 if let Some(preferred) = paste!(child.[<calculated_preferred_ $size>]) {
636 log::trace!("{LABEL}: calculated_preferred={preferred}");
637 let preferred = preferred - paste!(child.[<padding_ $unit>]()).unwrap_or_default() - paste!(child.[<margin_ $unit>]()).unwrap_or_default();
638 log::trace!("{LABEL}: calculated_preferred={preferred} without padding/margins");
639 if target > preferred {
640 remaining_size += target - preferred;
641 target = preferred;
642 clipped = true;
643 }
644 }
645 }
646
647 if !clipped {
648 dynamic_child_size = true;
649 }
650
651 let prev = paste!(child.[<calculated_ $size>]).unwrap();
652 paste!(child.[<calculated_ $size>]) = Some(target);
653 log::trace!("{LABEL}: increasing child size prev={prev} to target={target}:\n{child}");
654 }
655
656 if last_iteration || !dynamic_child_size {
657 break;
658 }
659 }
660 }
661 }
662 }
663 LayoutDirection::$cross_axis => {
664 log::trace!("{LABEL}: size_cross_axis\n{parent}");
665
666 let align_items = parent.align_items;
667
668 for child in parent.relative_positioned_elements_mut() {
669 if matches!(child.element, Element::Raw { .. }) {
670 continue;
671 }
672
673 if float_gt!(paste!(child.[<calculated_ $size>]).expect("Missing calculated_size"), container_size) {
674 set_float(
675 &mut paste!(child.[<calculated_ $size>]),
676 paste!(child.[<calculated_min_ $size>]).unwrap_or(container_size)
677 );
678 }
679
680 if align_items.is_none() {
681 log::trace!("{LABEL}: setting size to remaining_size={remaining_size}:\n{child}");
682 let mut remaining_container_size = remaining_size;
683
684 if let Some(size) = paste!(child.[<margin_ $unit>]()) {
685 log::trace!(
686 "{LABEL}: removing margin size={size} from remaining_container_size={remaining_container_size} ({})",
687 remaining_container_size - size
688 );
689 remaining_container_size -= size;
690 }
691 if let Some(size) = paste!(child.[<padding_ $unit>]()) {
692 log::trace!(
693 "{LABEL}: removing padding size={size} from remaining_container_size={remaining_container_size} ({})",
694 remaining_container_size - size
695 );
696 remaining_container_size -= size;
697 }
698
699 #[allow(clippy::cast_precision_loss)]
700 let mut new_size = remaining_container_size / (cell_count as f32);
701
702 if let Some(max) = paste!(child.[<calculated_max_ $size>]) {
703 if new_size > max {
704 log::trace!("{LABEL}: setting size to calculated_max={max}");
705 new_size = max;
706 }
707 }
708 if let Some(min) = paste!(child.[<calculated_min_ $size>]) {
709 if new_size < min {
710 log::trace!("{LABEL}: setting size to calculated_min={min}");
711 new_size = min;
712 }
713 } else if let Some(min) = paste!(child.[<calculated_child_min_ $size>]) {
714 if new_size < min
715 && paste!(child.[<calculated_max_ $size>]).is_none_or(|x| min < x)
716 && paste!(child.[<calculated_min_ $size>]).is_none_or(|x| min > x)
717 {
718 log::trace!("{LABEL}: setting size to calculated_child_min={min}");
719 new_size = min;
720 }
721 }
722
723 if new_size < 0.0 {
724 log::trace!("{LABEL}: clamping size to 0.0");
725 new_size = 0.0;
726 }
727
728 if child.$size.is_none() {
729 paste!(child.[<calculated_ $size>]) = Some(new_size);
730 }
731 }
732 }
733 }
734 }
735 }
736 }
737
738 let crate::layout::Rect { $size: relative_size, .. } = relative_container;
741
742 for child in parent.absolute_positioned_elements_mut() {
743 let mut remaining_container_size = *relative_size;
744
745 if let Some(size) = paste!(child.[<margin_ $unit>]()) {
746 log::trace!(
747 "{LABEL}: absolute removing margin size={size} from remaining_container_size={remaining_container_size} ({})",
748 remaining_container_size - size
749 );
750 remaining_container_size -= size;
751 }
752 if let Some(size) = paste!(child.[<padding_ $unit>]()) {
753 log::trace!(
754 "{LABEL}: absolute removing padding size={size} from remaining_container_size={remaining_container_size} ({})",
755 remaining_container_size - size
756 );
757 remaining_container_size -= size;
758 }
759
760 if let Some(size) = &child.$size {
761 log::trace!("{LABEL}: calculating absolute child size={size:?}");
762 let size = size.calc(remaining_container_size, view_width, view_height);
763 log::trace!("{LABEL}: calculated absolute child size={size}");
764 paste!(child.[<calculated_ $size>]) = Some(size);
765 } else {
766 paste!(child.[<calculated_ $size>]) = Some(remaining_container_size);
767 }
768 }
769
770 for child in parent.fixed_positioned_elements_mut() {
771 let mut remaining_container_size = *relative_size;
772
773 if let Some(size) = paste!(child.[<margin_ $unit>]()) {
774 log::trace!(
775 "{LABEL}: fixed removing margin size={size} from remaining_container_size={remaining_container_size} ({})",
776 remaining_container_size - size
777 );
778 remaining_container_size -= size;
779 }
780 if let Some(size) = paste!(child.[<padding_ $unit>]()) {
781 log::trace!(
782 "{LABEL}: fixed removing padding size={size} from remaining_container_size={remaining_container_size} ({})",
783 remaining_container_size - size
784 );
785 remaining_container_size -= size;
786 }
787
788 if let Some(size) = &child.$size {
789 log::trace!("{LABEL}: calculating fixed child size={size:?}");
790 let size = size.calc(remaining_container_size, view_width, view_height);
791 log::trace!("{LABEL}: calculated fixed child size={size}");
792 paste!(child.[<calculated_ $size>]) = Some(size);
793 }
794 }
795 });
796 }};
797}
798
799macro_rules! wrap_on_axis {
800 (
801 $label:tt,
802 $axis:ident,
803 $bfs:ident,
804 $container:ident,
805 $size:ident,
806 $overflow:ident,
807 $gap:ident,
808 $each_child:expr
809 $(,)?
810 ) => {{
811 use paste::paste;
812
813 use crate::models::{LayoutDirection, LayoutOverflow, LayoutPosition};
814
815 paste! {
816 const LABEL: &str = $label;
817
818 log::trace!("{LABEL}:\n{}", $container);
819
820 let view_width = $container.calculated_width.expect("Missing view_width");
821 let view_height = $container.calculated_height.expect("Missing view_height");
822
823 $bfs.traverse_mut($container, |parent| {
824 let container_width = parent.calculated_width.expect("Missing parent calculated_width");
825
826 for child in &mut parent.children {
827 $each_child(child, container_width, view_width, view_height);
828 }
829
830 if !matches!(parent.$overflow, LayoutOverflow::Wrap { .. }) {
831 return;
832 }
833
834 let container_size = paste!(parent.[<calculated_ $size>]).expect("Missing parent container_size");
835
836 let direction = parent.direction;
837 let mut pos = 0.0;
838 let mut row = 0;
839 let mut col = 0;
840 let gap = paste!(parent.[<calculated_ $gap>]);
841
842 for child in parent.relative_positioned_elements_mut() {
843 let child_size = paste!(child.[<bounding_calculated_ $size>]()).expect("Missing child calculated bounding size");
844
845 let mut position = LayoutPosition::Wrap { row, col };
846
847 if direction == LayoutDirection::$axis {
848 pos += child_size;
849
850 if pos > container_size {
851 log::trace!("{LABEL}: wrapping to next row");
852 pos = child_size + gap.unwrap_or_default();
853 col = 0;
854 row += 1;
855 position = LayoutPosition::Wrap { row, col };
856 } else if let Some(gap) = gap {
857 pos += gap;
858 }
859
860 col += 1;
861 }
862
863 if let LayoutPosition::Wrap { row, col } = position {
864 log::trace!("{LABEL}: positioning child ({row}, {col}) pos={pos} container_size={container_size}:\n{child}");
865 }
866
867 set_value(&mut child.calculated_position, position);
868 }
869 });
870 }
871 }};
872}
873
874mod pass_widths {
879 use paste::paste;
880
881 use crate::{
882 BfsPaths, Container, Element, HeaderSize, Number,
883 layout::{
884 calc::{Calculator, CalculatorDefaults},
885 font::FontMetrics,
886 set_float,
887 },
888 };
889
890 #[cfg_attr(feature = "profiling", profiling::all_functions)]
891 impl Container {
892 fn calculate_font_size(
893 &mut self,
894 view_width: f32,
895 view_height: f32,
896 context: &Self,
897 defaults: CalculatorDefaults,
898 ) {
899 if self.calculated_font_size.is_some() {
900 return;
901 }
902
903 macro_rules! default_heading_prop {
904 ($size:expr, $prop:ident $(,)?) => {
905 match $size {
906 HeaderSize::H1 => paste!(defaults.[<h1_ $prop>]),
907 HeaderSize::H2 => paste!(defaults.[<h2_ $prop>]),
908 HeaderSize::H3 => paste!(defaults.[<h3_ $prop>]),
909 HeaderSize::H4 => paste!(defaults.[<h4_ $prop>]),
910 HeaderSize::H5 => paste!(defaults.[<h5_ $prop>]),
911 HeaderSize::H6 => paste!(defaults.[<h6_ $prop>]),
912 }
913 };
914 }
915
916 self.calculated_font_size = self.font_size.as_ref().map_or_else(
917 || {
918 match self.element {
919 Element::Heading { size } => {
920 Some(default_heading_prop!(size, font_size))
921 }
922 _ => {
923 context.calculated_font_size
924 }
925 }
926 },
927 |font_size| {
928 let calculated_font_size = font_size.calc(
929 context
930 .calculated_font_size
931 .expect("Missing calculated_font_size"),
932 view_width,
933 view_height,
934 );
935 log::trace!("calculate_font_size: setting font_size={font_size} to calculated_font_size={calculated_font_size}");
936
937 Some(calculated_font_size)
938 },
939 );
940
941 if self.margin_top.is_none() {
942 if let Element::Heading { size } = self.element {
943 self.calculated_margin_top = Some(default_heading_prop!(size, font_margin_top));
944 }
945 }
946
947 if self.margin_bottom.is_none() {
948 if let Element::Heading { size } = self.element {
949 self.calculated_margin_bottom =
950 Some(default_heading_prop!(size, font_margin_bottom));
951 }
952 }
953 }
954
955 fn calc_fixed_properties(&mut self, view_width: f32, view_height: f32) -> bool {
956 macro_rules! update_prop {
957 ($value:expr, $prop:ident, $basis:expr $(,)?) => {{
958 let value = $value;
959 let size = value.calc($basis, view_width, view_height);
960 if set_float(&mut paste!(self.[<calculated_ $prop>]), size).is_some() {
961 log::trace!("calc_fixed_properties: updated from={value} to calculated_{}={size}", stringify!($prop));
962 }
963 }};
964 }
965
966 macro_rules! update_fixed_prop {
967 ($prop:ident, $basis:expr $(,)?) => {
968 if let Some(value) = self.$prop.as_ref().and_then(crate::Number::as_fixed) {
969 update_prop!(value, $prop, $basis);
970 }
971 };
972 }
973
974 if let Some(value) = &self.opacity {
975 update_prop!(value, opacity, 1.0);
976 }
977 update_fixed_prop!(border_top_left_radius, 0.0);
978 update_fixed_prop!(border_top_right_radius, 0.0);
979 update_fixed_prop!(border_bottom_left_radius, 0.0);
980 update_fixed_prop!(border_bottom_right_radius, 0.0);
981
982 false
983 }
984 }
985
986 impl<F: FontMetrics> Calculator<F> {
987 #[cfg_attr(feature = "profiling", profiling::function)]
988 pub fn calc_widths(&self, bfs: &BfsPaths, container: &mut Container) {
989 let each_parent = |container: &mut Container,
990 view_width,
991 view_height,
992 context: &Container,
993 defaults| {
994 container.calculate_font_size(view_width, view_height, context, defaults);
995 };
996 let each_child = |container: &mut Container,
997 view_width,
998 view_height,
999 context: &Container,
1000 defaults| {
1001 container.calculate_font_size(view_width, view_height, context, defaults);
1002
1003 container.calc_fixed_properties(view_width, view_height);
1004 };
1005
1006 calc_size_on_axis!(
1007 "calc_widths",
1008 self,
1009 bfs,
1010 container,
1011 width,
1012 Row,
1013 Column,
1014 left,
1015 right,
1016 x,
1017 each_parent,
1018 each_child,
1019 );
1020 }
1021 }
1022}
1023
1024mod pass_margin_and_padding {
1025 use paste::paste;
1026
1027 use crate::{
1028 BfsPaths, Container,
1029 layout::{calc::Calculator, font::FontMetrics, set_float},
1030 };
1031
1032 impl<F: FontMetrics> Calculator<F> {
1033 #[cfg_attr(feature = "profiling", profiling::function)]
1037 #[allow(clippy::too_many_lines)]
1038 pub fn calc_margin_and_padding(&self, bfs: &BfsPaths, container: &mut Container) {
1039 log::trace!("calc_margin_and_padding:\n{container}");
1040
1041 let view_width = container.calculated_width.expect("Missing view_width");
1042 let view_height = container.calculated_height.expect("Missing view_height");
1043
1044 #[allow(clippy::cognitive_complexity)]
1045 bfs.traverse_mut(container, |parent| {
1046 let container_width = parent.calculated_width.expect("Missing container_width");
1047
1048 if let Some(gap) = parent
1049 .column_gap
1050 .as_ref()
1051 .and_then(crate::Number::as_dynamic)
1052 {
1053 parent.calculated_column_gap =
1054 Some(gap.calc(container_width, view_width, view_height));
1055 }
1056
1057 for child in &mut parent.children {
1058 macro_rules! update_dynamic_prop {
1059 ($prop:ident $(,)?) => {
1060 if let Some(value) =
1061 child.$prop.as_ref().and_then(crate::Number::as_dynamic)
1062 {
1063 let size = value.calc(container_width, view_width, view_height);
1064 if set_float(&mut paste!(child.[<calculated_ $prop>]), size).is_some() {
1065 log::trace!("calc_margin_and_padding: updated from={value} to calculated_{}={size}", stringify!($prop));
1066 }
1067 }
1068 };
1069 }
1070
1071 update_dynamic_prop!(border_top_left_radius);
1072 update_dynamic_prop!(border_top_right_radius);
1073 update_dynamic_prop!(border_bottom_left_radius);
1074 update_dynamic_prop!(border_bottom_right_radius);
1075
1076 update_dynamic_prop!(margin_left);
1077 update_dynamic_prop!(margin_right);
1078 update_dynamic_prop!(margin_top);
1079 update_dynamic_prop!(margin_bottom);
1080
1081 update_dynamic_prop!(padding_left);
1082 update_dynamic_prop!(padding_right);
1083 update_dynamic_prop!(padding_top);
1084 update_dynamic_prop!(padding_bottom);
1085 }
1086 });
1087 }
1088 }
1089}
1090
1091mod pass_flex_width {
1092 use hyperchad_transformer_models::{LayoutDirection, LayoutPosition, Position};
1093
1094 use crate::{
1095 BfsPaths, Container,
1096 layout::{calc::Calculator, font::FontMetrics, set_float},
1097 };
1098
1099 impl<F: FontMetrics> Calculator<F> {
1100 #[cfg_attr(feature = "profiling", profiling::function)]
1101 pub fn flex_width(&self, bfs: &BfsPaths, container: &mut Container) {
1102 flex_on_axis!(
1103 "flex_width",
1104 bfs,
1105 container,
1106 width,
1107 Row,
1108 Column,
1109 col,
1110 left,
1111 right,
1112 x,
1113 );
1114 }
1115 }
1116}
1117
1118mod pass_wrap_horizontal {
1119 use crate::{
1120 BfsPaths, Container, Element, float_lte,
1121 layout::{calc::Calculator, font::FontMetrics, set_value},
1122 };
1123
1124 impl<F: FontMetrics> Calculator<F> {
1125 #[cfg_attr(feature = "profiling", profiling::function)]
1129 pub fn wrap_horizontal(&self, bfs: &BfsPaths, container: &mut Container) {
1130 let each_child =
1131 |container: &mut Container, container_width, _view_width, _view_height| {
1132 let Element::Raw { value } = &container.element else {
1133 return;
1134 };
1135 if float_lte!(
1136 container
1137 .calculated_width
1138 .expect("Missing calculated_width"),
1139 container_width
1140 ) {
1141 return;
1142 }
1143
1144 let font_size = container.calculated_font_size.expect("Missing font_size");
1145
1146 log::trace!(
1147 "wrap_horizontal: measuring text={value} container_width={container_width}"
1148 );
1149 let bounds = self
1150 .font_metrics
1151 .measure_text(value, font_size, container_width);
1152 log::trace!("wrap_horizontal: measured bounds={bounds:?}");
1153 let new_width = bounds.width();
1154 let new_height = bounds.height();
1155 log::trace!("wrap_horizontal: measured width={new_width} height={new_height}");
1156
1157 container.calculated_preferred_width = Some(new_width);
1158 container.calculated_width = Some(new_width);
1159 container.calculated_preferred_height = Some(new_height);
1160 container.calculated_height = Some(new_height);
1161 };
1162
1163 wrap_on_axis!(
1164 "wrap", Row, bfs, container, width, overflow_x, column_gap, each_child,
1165 );
1166 }
1167 }
1168}
1169
1170mod pass_heights {
1171 use crate::{
1172 BfsPaths, Container, Number,
1173 layout::{calc::Calculator, font::FontMetrics},
1174 };
1175
1176 impl<F: FontMetrics> Calculator<F> {
1177 #[cfg_attr(feature = "profiling", profiling::function)]
1178 pub fn calc_heights(&self, bfs: &BfsPaths, container: &mut Container) {
1179 calc_size_on_axis!(
1180 "calc_heights",
1181 self,
1182 bfs,
1183 container,
1184 height,
1185 Column,
1186 Row,
1187 top,
1188 bottom,
1189 y,
1190 (|_, _, _, _, _| {}),
1191 (|_, _, _, _, _| {}),
1192 );
1193 }
1194 }
1195}
1196
1197mod pass_flex_height {
1198 use hyperchad_transformer_models::{LayoutDirection, LayoutPosition, Position};
1199
1200 use crate::{
1201 BfsPaths, Container,
1202 layout::{calc::Calculator, font::FontMetrics, set_float},
1203 };
1204
1205 impl<F: FontMetrics> Calculator<F> {
1206 #[cfg_attr(feature = "profiling", profiling::function)]
1207 pub fn flex_height(&self, bfs: &BfsPaths, container: &mut Container) {
1208 flex_on_axis!(
1209 "flex_height",
1210 bfs,
1211 container,
1212 height,
1213 Column,
1214 Row,
1215 row,
1216 top,
1217 bottom,
1218 y,
1219 );
1220 }
1221 }
1222}
1223
1224mod pass_positioning {
1225 use bumpalo::Bump;
1226 use hyperchad_transformer_models::{
1227 AlignItems, JustifyContent, LayoutDirection, LayoutOverflow, LayoutPosition, Position,
1228 TextAlign, Visibility,
1229 };
1230
1231 use crate::{
1232 BfsPaths, Container, Element, float_lte,
1233 layout::{calc::Calculator, font::FontMetrics, set_float},
1234 };
1235
1236 impl<F: FontMetrics> Calculator<F> {
1237 #[allow(clippy::too_many_lines)]
1241 #[cfg_attr(feature = "profiling", profiling::function)]
1242 pub fn position_elements(
1243 &self,
1244 arena: &Bump,
1245 bfs: &BfsPaths,
1246 container: &mut Container,
1247 context: &mut Container,
1248 ) -> bool {
1249 log::trace!("position_elements:\n{container}");
1250
1251 let root_id = container.id;
1252 let root_text_align = container.text_align;
1253 let view_width = container.calculated_width.expect("Missing view_width");
1254 let view_height = container.calculated_height.expect("Missing view_height");
1255
1256 let mut changed = false;
1257
1258 #[allow(clippy::cognitive_complexity)]
1259 bfs.traverse_with_parents_ref_mut(
1260 true,
1261 context,
1262 container,
1263 |parent, relative_container| {
1264 if parent.id == root_id {
1265 relative_container.calculated_x = Some(0.0);
1266 relative_container.calculated_y = Some(0.0);
1267 relative_container.calculated_width = Some(view_width);
1268 relative_container.calculated_height = Some(view_height);
1269 relative_container.text_align = root_text_align;
1270 } else if parent.position == Some(Position::Relative) {
1271 relative_container.calculated_x =
1272 Some(parent.calculated_x.expect("Missing calculated_x"));
1273 relative_container.calculated_y =
1274 Some(parent.calculated_y.expect("Missing calculated_y"));
1275 relative_container.calculated_width =
1276 Some(parent.calculated_width.expect("Missing calculated_width"));
1277 relative_container.calculated_height =
1278 Some(parent.calculated_height.expect("Missing calculated_height"));
1279 }
1280
1281 if let Some(align) = parent.text_align {
1282 relative_container.text_align = Some(align);
1283 }
1284 },
1285 |parent, relative_container| {
1286 let is_top_level = parent.id == root_id;
1287 let direction = parent.direction;
1288 let justify_content = parent.justify_content.unwrap_or_default();
1289 let align_items = parent.align_items.unwrap_or_default();
1290 let container_width = parent
1291 .calculated_width
1292 .expect("Missing parent calculated_width");
1293 let container_height = parent
1294 .calculated_height
1295 .expect("Missing parent calculated_height");
1296
1297 if let LayoutOverflow::Wrap { grid } = parent.overflow_x {
1298 let mut last_row = 0;
1299 let mut col_count = 0;
1300 let mut max_col_count = 0;
1301 let mut row_width = 0.0;
1302 let gaps = &mut bumpalo::collections::Vec::new_in(arena);
1303 let grid_cell_size = parent
1304 .grid_cell_size
1305 .as_ref()
1306 .map(|x| x.calc(container_width, view_width, view_height));
1307 let row_gap = parent.calculated_row_gap.unwrap_or_default();
1308 let column_gap = parent.calculated_column_gap.unwrap_or_default();
1309
1310 #[allow(clippy::cast_precision_loss)]
1311 let mut add_gap = |row_width, col_count| {
1312 let mut col_count = col_count;
1313 let remainder = container_width - grid_cell_size.map_or(
1314 row_width,
1315 |cell_size| {
1316 col_count = 1;
1317 let mut size = cell_size + column_gap;
1318
1319 while float_lte!(size + cell_size, container_width) {
1320 col_count += 1;
1321 size += cell_size + column_gap;
1322 }
1323
1324 column_gap.mul_add(-(col_count as f32), size)
1325 }
1326 );
1327
1328 let gap = match justify_content {
1329 JustifyContent::Start
1330 | JustifyContent::Center
1331 | JustifyContent::End => column_gap,
1332 JustifyContent::SpaceBetween => {
1333 remainder / ((col_count - 1) as f32)
1334 }
1335 JustifyContent::SpaceEvenly => {
1336 remainder / ((col_count + 1) as f32)
1337 }
1338 };
1339
1340 gaps.push(gap);
1341
1342 gap
1343 };
1344
1345 for child in parent.relative_positioned_elements_mut().filter(|x| x.visibility != Some(Visibility::Hidden)) {
1346 let Some(LayoutPosition::Wrap { row, col }) = child.calculated_position
1347 else {
1348 continue;
1349 };
1350 log::trace!("position_elements: wrap calculating gaps (r{row}, c{col})");
1351
1352 if row != last_row {
1353 moosicbox_assert::assert!(row > last_row);
1354
1355 let gap = add_gap(row_width, col_count);
1356 log::trace!("position_elements: (r{row}, c{col}) gap={gap}");
1357
1358 if grid && col_count > max_col_count {
1359 max_col_count = col_count;
1360 }
1361
1362 row_width = 0.0;
1363 col_count = 0;
1364 last_row = row;
1365 }
1366
1367 row_width += grid_cell_size.unwrap_or_else(|| {
1368 child
1369 .calculated_width
1370 .expect("Child missing calculated_width")
1371 });
1372 col_count += 1;
1373 }
1374
1375 add_gap(row_width, col_count);
1376
1377 #[allow(unused_assignments)]
1378 if col_count > max_col_count {
1379 max_col_count = col_count;
1380 }
1381
1382 let mut gap = gaps.first().copied().unwrap_or_default();
1383
1384 let first_gap = |gap| match justify_content {
1385 JustifyContent::Start
1386 | JustifyContent::Center
1387 | JustifyContent::End
1388 | JustifyContent::SpaceBetween => 0.0,
1389 JustifyContent::SpaceEvenly => gap,
1390 };
1391
1392 let mut x = first_gap(gap);
1393 let mut y = 0.0;
1394
1395 let mut max_height = 0.0;
1396 last_row = 0;
1397
1398 for child in parent.relative_positioned_elements_mut().filter(|x| x.visibility != Some(Visibility::Hidden)) {
1399 let Some(LayoutPosition::Wrap { row, col }) = child.calculated_position
1400 else {
1401 continue;
1402 };
1403 log::trace!("position_elements: (r{row}, c{col}) gap={gap} row_gap={row_gap} last_row={last_row} ({x}, {y})");
1404
1405 let child_width = child.bounding_calculated_width().unwrap();
1406 let child_height = child.bounding_calculated_height().unwrap();
1407
1408 if row != last_row {
1409 moosicbox_assert::assert!(row > last_row);
1410
1411 if !grid {
1412 gap = gaps.get(row as usize).copied().unwrap_or_default();
1413 }
1414
1415 x = first_gap(gap);
1416 y += max_height + row_gap;
1417 max_height = 0.0;
1418 last_row = row;
1419 #[cfg(feature = "layout-offset")]
1420 {
1421 child.calculated_offset_x = Some(x);
1422 }
1423 }
1424
1425 #[cfg(feature = "layout-offset")]
1426 {
1427 child.calculated_offset_x = Some(if col > 0 { gap } else { x });
1428 child.calculated_offset_y = Some(if row > 0 { row_gap } else { 0.0 });
1429 }
1430
1431 if child_height > max_height {
1432 max_height = child_height;
1433 }
1434
1435 log::trace!(
1436 "position_elements: setting wrapped position ({x}, {y}):\n{child}"
1437 );
1438 if set_float(&mut child.calculated_x, x).is_some() && is_top_level {
1439 update_changed!(changed, "wrapped calculated_x changed to {x}");
1440 }
1441 if set_float(&mut child.calculated_y, y).is_some() && is_top_level {
1442 update_changed!(changed, "wrapped calculated_y changed to {y}");
1443 }
1444
1445 x += child_width + gap;
1446 }
1447 } else {
1448 let mut x = 0.0;
1449 let mut y = 0.0;
1450 let mut col_gap = parent.calculated_column_gap.unwrap_or_default();
1451 let row_gap = parent.calculated_row_gap.unwrap_or_default();
1452 let axis_gap = match direction {
1453 LayoutDirection::Row => col_gap,
1454 LayoutDirection::Column => row_gap,
1455 };
1456
1457 macro_rules! visible_elements {
1458 () => {{
1459 parent
1460 .relative_positioned_elements()
1461 .filter(|x| x.visibility != Some(Visibility::Hidden))
1462 }};
1463 }
1464
1465 macro_rules! visible_elements_mut {
1466 () => {{
1467 parent
1468 .relative_positioned_elements_mut()
1469 .filter(|x| x.visibility != Some(Visibility::Hidden))
1470 }};
1471 }
1472
1473 macro_rules! sizes_on_axis {
1474 ($direction:expr) => {{
1475 visible_elements!().filter_map(|x| match $direction {
1476 LayoutDirection::Row => x.bounding_calculated_width(),
1477 LayoutDirection::Column => x.bounding_calculated_height(),
1478 })
1479 }};
1480 }
1481
1482 match justify_content {
1483 JustifyContent::Start => {}
1484 JustifyContent::Center => {
1485 let count = visible_elements!().count();
1486 let size: f32 = sizes_on_axis!(direction).sum();
1487 #[allow(clippy::cast_precision_loss)]
1488 let gap_offset = (count - 1) as f32 * axis_gap;
1489
1490 match direction {
1491 LayoutDirection::Row => x += (container_width - size - gap_offset) / 2.0,
1492 LayoutDirection::Column => y += (container_height - size - gap_offset) / 2.0,
1493 }
1494 }
1495 JustifyContent::End => {
1496 let count = visible_elements!().count();
1497 let size: f32 = sizes_on_axis!(direction).sum();
1498 #[allow(clippy::cast_precision_loss)]
1499 let gap_offset = (count - 1) as f32 * axis_gap;
1500
1501 match direction {
1502 LayoutDirection::Row => x += container_width - size - gap_offset,
1503 LayoutDirection::Column => y += container_height - size - gap_offset,
1504 }
1505 }
1506 JustifyContent::SpaceBetween => {
1507 let count = visible_elements!().count();
1508 let size: f32 = sizes_on_axis!(direction).sum();
1509
1510 #[allow(clippy::cast_precision_loss)]
1511 match direction {
1512 LayoutDirection::Row => {
1513 col_gap = (container_width - size) / ((count - 1) as f32);
1514 }
1515 LayoutDirection::Column => {
1516 col_gap = (container_height - size) / ((count - 1) as f32);
1517 }
1518 }
1519 }
1520 JustifyContent::SpaceEvenly => {
1521 let count = visible_elements!().count();
1522 let size: f32 = sizes_on_axis!(direction).sum();
1523
1524 #[allow(clippy::cast_precision_loss)]
1525 match direction {
1526 LayoutDirection::Row => {
1527 col_gap = (container_width - size) / ((count + 1) as f32);
1528 }
1529 LayoutDirection::Column => {
1530 col_gap = (container_height - size) / ((count + 1) as f32);
1531 }
1532 }
1533
1534 x += col_gap;
1535 }
1536 }
1537
1538 if let Some(text_align) = relative_container.text_align {
1539 if visible_elements!().all(|x| matches!(x.element, Element::Raw { .. }))
1540 {
1541 match text_align {
1542 TextAlign::Start => {}
1543 TextAlign::Center => {
1544 let size: f32 = sizes_on_axis!(LayoutDirection::Row).sum();
1545
1546 log::trace!("position_elements: TextAlign::{text_align:?} container_width={container_width} container_height={container_height} size={size}");
1547
1548 x += (container_width - size) / 2.0;
1549 }
1550 TextAlign::End => {
1551 let size: f32 = sizes_on_axis!(LayoutDirection::Row).sum();
1552
1553 log::trace!("position_elements: TextAlign::{text_align:?} container_width={container_width} container_height={container_height} size={size}");
1554
1555 x += container_width - size;
1556 }
1557 TextAlign::Justify => {
1558 todo!();
1562 }
1563 }
1564 }
1565 }
1566
1567 for (i, child) in visible_elements_mut!().enumerate()
1568 {
1569 let start_x = x;
1570 let start_y = y;
1571
1572 match align_items {
1573 AlignItems::Start => {}
1574 AlignItems::Center | AlignItems::End => {
1575 let size = match direction {
1576 LayoutDirection::Row => child.bounding_calculated_height(),
1577 LayoutDirection::Column => child.bounding_calculated_width(),
1578 }.unwrap_or_default();
1579
1580 log::trace!("position_elements: AlignItems::{align_items:?} container_width={container_width} container_height={container_height} size={size}:\n{child}");
1581
1582 match align_items {
1583 AlignItems::Start => unreachable!(),
1584 AlignItems::Center => match direction {
1585 LayoutDirection::Row => y += (container_height - size) / 2.0,
1586 LayoutDirection::Column => x += (container_width - size) / 2.0,
1587 },
1588 AlignItems::End => match direction {
1589 LayoutDirection::Row => y += container_height - size,
1590 LayoutDirection::Column => x += container_width - size,
1591 },
1592 }
1593 }
1594 }
1595
1596 log::trace!("position_elements: setting position ({x}, {y}) i={i}:\n{child}");
1597 if set_float(&mut child.calculated_x, x).is_some() && is_top_level {
1598 update_changed!(changed, "calculated_x changed to {x}");
1599 }
1600 if set_float(&mut child.calculated_y, y).is_some() && is_top_level {
1601 update_changed!(changed, "calculated_y changed to {y}");
1602 }
1603
1604 match direction {
1605 LayoutDirection::Row => {
1606 #[cfg(feature = "layout-offset")]
1607 {
1608 child.calculated_offset_x = Some(if i == 0 { start_x } else { col_gap });
1609 child.calculated_offset_y = Some(y);
1610 }
1611 x += child.bounding_calculated_width().unwrap() + col_gap;
1612 y = start_y;
1613 }
1614 LayoutDirection::Column => {
1615 #[cfg(feature = "layout-offset")]
1616 {
1617 child.calculated_offset_x = Some(x);
1618 child.calculated_offset_y = Some(if i == 0 { start_y } else { row_gap });
1619 }
1620 x = start_x;
1621 y += child.bounding_calculated_height().unwrap() + row_gap;
1622 }
1623 }
1624 }
1625 }
1626
1627 let Container {
1630 calculated_width: Some(width),
1631 calculated_height: Some(height),
1632 ..
1633 } = relative_container
1634 else {
1635 panic!("Missing relative_container size");
1636 };
1637 let width = *width;
1638 let height = *height;
1639
1640 macro_rules! position_absolute {
1641 ($iter:expr) => {
1642 for child in ($iter) {
1643 let mut x = 0.0;
1644 let mut y = 0.0;
1645
1646 if let Some(left) = &child.left {
1647 let left = left.calc(width, view_width, view_height);
1648 x = left;
1649 }
1650 if let Some(right) = &child.right {
1651 let right = right.calc(width, view_width, view_height);
1652 let bounding_width = child.bounding_calculated_width().unwrap();
1653 let right = width - right - bounding_width;
1654 x = right;
1655 }
1656 if let Some(top) = &child.top {
1657 let top = top.calc(height, view_width, view_height);
1658 y = top;
1659 }
1660 if let Some(bottom) = &child.bottom {
1661 let bottom = bottom.calc(height, view_width, view_height);
1662 let bounding_height = child.bounding_calculated_height().unwrap();
1663 let bottom = height - bottom - bounding_height;
1664 y = bottom;
1665 }
1666
1667 child.calculated_x = Some(x);
1668 child.calculated_y = Some(y);
1669 }
1670 };
1671 }
1672
1673 position_absolute!(parent.absolute_positioned_elements_mut());
1674 position_absolute!(parent.fixed_positioned_elements_mut());
1675 },
1676 );
1677
1678 changed
1679 }
1680 }
1681}
1682
1683impl Container {
1684 fn is_expandable(&self, parent: &Self) -> bool {
1685 !self.is_span() && (!parent.is_flex_container() || self.flex.is_some())
1686 }
1687}
1688
1689macro_rules! axis_sum_func {
1690 ($prop:ident, $unit:ident, $x:ident, $y:ident $(,)?) => {
1691 paste! {
1692 impl Container {
1693 #[must_use]
1694 pub fn [<$prop _ $unit>](&self) -> Option<f32> {
1695 let mut value = None;
1696 if let Some(x) = self.[<calculated_ $prop _ $x>] {
1697 value = Some(x);
1698 }
1699 if let Some(y) = self.[<calculated_ $prop _ $y>] {
1700 value.replace(value.map_or(y, |x| x + y));
1701 }
1702 value
1703 }
1704 }
1705 }
1706 };
1707}
1708
1709axis_sum_func!(margin, x, left, right);
1710axis_sum_func!(margin, y, top, bottom);
1711axis_sum_func!(padding, x, left, right);
1712axis_sum_func!(padding, y, top, bottom);
1713
1714impl Container {
1715 #[must_use]
1716 pub fn border_x(&self) -> Option<f32> {
1717 let mut borders = None;
1718 if let Some((_, border_left)) = self.calculated_border_left {
1719 borders = Some(border_left);
1720 }
1721 if let Some((_, border_right)) = self.calculated_border_right {
1722 borders.replace(borders.map_or(border_right, |x| x + border_right));
1723 }
1724 borders
1725 }
1726
1727 #[must_use]
1728 pub fn border_y(&self) -> Option<f32> {
1729 let mut borders = None;
1730 if let Some((_, border_top)) = self.calculated_border_top {
1731 borders = Some(border_top);
1732 }
1733 if let Some((_, border_bottom)) = self.calculated_border_bottom {
1734 borders.replace(borders.map_or(border_bottom, |x| x + border_bottom));
1735 }
1736 borders
1737 }
1738
1739 #[must_use]
1740 pub fn bounding_calculated_width(&self) -> Option<f32> {
1741 self.calculated_width.map(|width| {
1742 width
1743 + self.padding_x().unwrap_or(0.0)
1744 + self.scrollbar_right.unwrap_or(0.0)
1745 + self.margin_x().unwrap_or(0.0)
1746 })
1747 }
1748
1749 #[must_use]
1750 pub fn bounding_calculated_height(&self) -> Option<f32> {
1751 self.calculated_height.map(|height| {
1752 height
1753 + self.padding_y().unwrap_or(0.0)
1754 + self.scrollbar_bottom.unwrap_or(0.0)
1755 + self.margin_y().unwrap_or(0.0)
1756 })
1757 }
1758}
1759
1760#[cfg(test)]
1761mod test {
1762 use hyperchad_transformer_models::AlignItems;
1763 use maud::html;
1764 use paste::paste;
1765 use pretty_assertions::assert_eq;
1766
1767 use crate::{
1768 Calculation, Container, Element, HeaderSize, Number, Position,
1769 layout::{
1770 Calc as _,
1771 font::{FontMetrics, FontMetricsBounds, FontMetricsRow},
1772 get_scrollbar_size,
1773 },
1774 models::{JustifyContent, LayoutDirection, LayoutOverflow, LayoutPosition},
1775 };
1776
1777 use super::{Calculator, CalculatorDefaults};
1778
1779 fn compare_containers(a: &Container, b: &Container) {
1780 assert_eq!(
1781 a.display_to_string(
1782 true,
1783 true,
1784 #[cfg(feature = "format")]
1785 true,
1786 #[cfg(feature = "syntax-highlighting")]
1787 false
1788 )
1789 .unwrap(),
1790 b.display_to_string(
1791 true,
1792 true,
1793 #[cfg(feature = "format")]
1794 true,
1795 #[cfg(feature = "syntax-highlighting")]
1796 false
1797 )
1798 .unwrap()
1799 );
1800 }
1801
1802 struct DefaultFontMetrics;
1803
1804 #[cfg_attr(feature = "profiling", profiling::all_functions)]
1805 impl FontMetrics for DefaultFontMetrics {
1806 fn measure_text(&self, text: &str, size: f32, wrap_width: f32) -> FontMetricsBounds {
1807 let mut rows = vec![];
1808 #[allow(clippy::cast_precision_loss)]
1809 let mut width = text.len() as f32 * size;
1810
1811 #[allow(clippy::while_float)]
1812 while width > wrap_width {
1813 rows.push(FontMetricsRow {
1814 width: wrap_width,
1815 height: size,
1816 });
1817 width -= wrap_width;
1818 }
1819
1820 if width > 0.0 {
1821 rows.push(FontMetricsRow {
1822 width,
1823 height: size,
1824 });
1825 }
1826
1827 FontMetricsBounds { rows }
1828 }
1829 }
1830
1831 #[allow(clippy::derivable_impls)]
1832 impl Default for CalculatorDefaults {
1833 fn default() -> Self {
1834 Self {
1835 font_size: Default::default(),
1836 font_margin_top: Default::default(),
1837 font_margin_bottom: Default::default(),
1838 h1_font_size: Default::default(),
1839 h1_font_margin_top: Default::default(),
1840 h1_font_margin_bottom: Default::default(),
1841 h2_font_size: Default::default(),
1842 h2_font_margin_top: Default::default(),
1843 h2_font_margin_bottom: Default::default(),
1844 h3_font_size: Default::default(),
1845 h3_font_margin_top: Default::default(),
1846 h3_font_margin_bottom: Default::default(),
1847 h4_font_size: Default::default(),
1848 h4_font_margin_top: Default::default(),
1849 h4_font_margin_bottom: Default::default(),
1850 h5_font_size: Default::default(),
1851 h5_font_margin_top: Default::default(),
1852 h5_font_margin_bottom: Default::default(),
1853 h6_font_size: Default::default(),
1854 h6_font_margin_top: Default::default(),
1855 h6_font_margin_bottom: Default::default(),
1856 }
1857 }
1858 }
1859
1860 static CALCULATOR: Calculator<DefaultFontMetrics> = Calculator::new(
1861 DefaultFontMetrics,
1862 CalculatorDefaults {
1863 font_size: 14.0,
1864 font_margin_top: 0.0,
1865 font_margin_bottom: 0.0,
1866 h1_font_size: 32.0,
1867 h1_font_margin_top: 0.0,
1868 h1_font_margin_bottom: 0.0,
1869 h2_font_size: 24.0,
1870 h2_font_margin_top: 0.0,
1871 h2_font_margin_bottom: 0.0,
1872 h3_font_size: 18.72,
1873 h3_font_margin_top: 0.0,
1874 h3_font_margin_bottom: 0.0,
1875 h4_font_size: 16.0,
1876 h4_font_margin_top: 0.0,
1877 h4_font_margin_bottom: 0.0,
1878 h5_font_size: 13.28,
1879 h5_font_margin_top: 0.0,
1880 h5_font_margin_bottom: 0.0,
1881 h6_font_size: 10.72,
1882 h6_font_margin_top: 0.0,
1883 h6_font_margin_bottom: 0.0,
1884 },
1885 );
1886
1887 mod scrollbar {
1888 use super::*;
1889
1890 #[test_log::test]
1891 #[ignore]
1892 fn calc_calculates_resized_wrapped_content_with_scrollbar_and_padding_correctly() {
1893 let mut container: Container = html! {
1894 div sx-width="100%" sx-height="100%" sx-position="relative" {
1895 section sx-dir="row" sx-height=("calc(100% - 140px)") {
1896 aside sx-width="calc(max(240, min(280, 15%)))" {}
1897 main sx-overflow-y="auto" {
1898 div
1899 sx-dir="row"
1900 sx-overflow-x="wrap"
1901 sx-justify-content="space-evenly"
1902 sx-gap=(15)
1903 sx-padding-left=(30)
1904 sx-padding-right=(30)
1905 sx-padding-top=(15)
1906 sx-padding-bottom=(15)
1907 {
1908 @for _ in 0..19 {
1909 div sx-width=(200) sx-height=(200 + 30) {}
1910 }
1911 }
1912 }
1913 }
1914 div
1915 sx-width="calc(min(500, 30%))"
1916 sx-height="calc(100% - 200)"
1917 sx-padding=(20)
1918 sx-position="absolute"
1919 sx-bottom=(170)
1920 sx-right=(0)
1921 {}
1922 }
1923 }
1924 .try_into()
1925 .unwrap();
1926
1927 container.calculated_width = Some(1600.0);
1928 container.calculated_height = Some(1000.0);
1929
1930 CALCULATOR.calc(&mut container);
1931 log::trace!("container:\n{container}");
1932
1933 let container = container.children[0].children[0].children[1].children[0].clone();
1934
1935 compare_containers(
1936 &container.clone(),
1937 &Container {
1938 calculated_width: Some(1360.0 - 30.0 - 30.0 - f32::from(get_scrollbar_size())),
1939 calculated_height: Some(920.0),
1940 calculated_x: Some(0.0),
1941 calculated_y: Some(0.0),
1942 calculated_padding_left: Some(30.0),
1943 calculated_padding_right: Some(30.0),
1944 calculated_padding_top: Some(15.0),
1945 calculated_padding_bottom: Some(15.0),
1946 ..container
1947 },
1948 );
1949 }
1950
1951 #[test_log::test]
1952 #[ignore]
1953 fn calc_auto_y_wraps_nested_elements_properly_by_taking_into_account_scrollbar_size() {
1954 let mut container = Container {
1955 children: vec![Container {
1956 children: vec![
1957 Container {
1958 width: Some(Number::Integer(25)),
1959 ..Default::default()
1960 },
1961 Container {
1962 width: Some(Number::Integer(25)),
1963 ..Default::default()
1964 },
1965 Container {
1966 width: Some(Number::Integer(25)),
1967 ..Default::default()
1968 },
1969 Container {
1970 width: Some(Number::Integer(25)),
1971 ..Default::default()
1972 },
1973 Container {
1974 width: Some(Number::Integer(25)),
1975 ..Default::default()
1976 },
1977 ],
1978 calculated_width: Some(75.0),
1979 calculated_height: Some(40.0),
1980 direction: LayoutDirection::Row,
1981 overflow_x: LayoutOverflow::Wrap { grid: true },
1982 overflow_y: LayoutOverflow::Expand,
1983 ..Default::default()
1984 }],
1985
1986 calculated_width: Some(75.0),
1987 calculated_height: Some(40.0),
1988 overflow_y: LayoutOverflow::Auto,
1989 ..Default::default()
1990 };
1991 CALCULATOR.calc(&mut container);
1992 log::trace!("container:\n{container}");
1993
1994 compare_containers(
1995 &container.clone(),
1996 &Container {
1997 children: vec![Container {
1998 children: vec![
1999 Container {
2000 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 0 }),
2001 calculated_width: Some(25.0),
2002 calculated_height: Some(40.0),
2003 calculated_x: Some(0.0),
2004 calculated_y: Some(0.0),
2005 ..container.children[0].children[0].clone()
2006 },
2007 Container {
2008 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 1 }),
2009 calculated_width: Some(25.0),
2010 calculated_height: Some(40.0),
2011 calculated_x: Some(25.0),
2012 calculated_y: Some(0.0),
2013 ..container.children[0].children[1].clone()
2014 },
2015 Container {
2016 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 0 }),
2017 calculated_width: Some(25.0),
2018 calculated_height: Some(40.0),
2019 calculated_x: Some(0.0),
2020 calculated_y: Some(40.0),
2021 ..container.children[0].children[2].clone()
2022 },
2023 Container {
2024 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 1 }),
2025 calculated_width: Some(25.0),
2026 calculated_height: Some(40.0),
2027 calculated_x: Some(25.0),
2028 calculated_y: Some(40.0),
2029 ..container.children[0].children[3].clone()
2030 },
2031 Container {
2032 calculated_position: Some(LayoutPosition::Wrap { row: 2, col: 0 }),
2033 calculated_width: Some(25.0),
2034 calculated_height: Some(40.0),
2035 calculated_x: Some(0.0),
2036 calculated_y: Some(80.0),
2037 ..container.children[0].children[4].clone()
2038 },
2039 ],
2040 ..container.children[0].clone()
2041 }],
2042
2043 calculated_width: Some(75.0 - f32::from(get_scrollbar_size())),
2044 calculated_height: Some(40.0),
2045 ..container
2046 },
2047 );
2048 }
2049 }
2050
2051 mod table {
2052 use super::*;
2053
2054 #[test_log::test]
2055 #[ignore]
2056 fn calc_can_calc_table_column_and_row_sizes() {
2057 let mut container = Container {
2058 children: vec![Container {
2059 element: Element::Table,
2060 children: vec![
2061 Container {
2062 element: Element::TR,
2063 direction: LayoutDirection::Row,
2064 children: vec![
2065 Container {
2066 element: Element::TD,
2067 children: vec![Container {
2068 element: Element::Div,
2069 width: Some(Number::Integer(40)),
2070 height: Some(Number::Integer(10)),
2071 ..Default::default()
2072 }],
2073 ..Container::default()
2074 },
2075 Container {
2076 element: Element::TD,
2077 children: vec![Container {
2078 element: Element::Div,
2079 width: Some(Number::Integer(30)),
2080 height: Some(Number::Integer(20)),
2081 ..Default::default()
2082 }],
2083 ..Container::default()
2084 },
2085 ],
2086 ..Default::default()
2087 },
2088 Container {
2089 element: Element::TR,
2090 direction: LayoutDirection::Row,
2091 children: vec![
2092 Container {
2093 element: Element::TD,
2094 children: vec![Container {
2095 element: Element::Div,
2096 width: Some(Number::Integer(10)),
2097 height: Some(Number::Integer(40)),
2098 ..Default::default()
2099 }],
2100 ..Container::default()
2101 },
2102 Container {
2103 element: Element::TD,
2104 children: vec![Container {
2105 element: Element::Div,
2106 width: Some(Number::Integer(20)),
2107 height: Some(Number::Integer(30)),
2108 ..Default::default()
2109 }],
2110 ..Container::default()
2111 },
2112 ],
2113 ..Default::default()
2114 },
2115 ],
2116 ..Default::default()
2117 }],
2118 calculated_width: Some(70.0),
2119 calculated_height: Some(80.0),
2120 ..Default::default()
2121 };
2122 CALCULATOR.calc(&mut container);
2123 log::trace!("container:\n{container}");
2124
2125 compare_containers(
2126 &container.clone(),
2127 &Container {
2128 children: vec![Container {
2129 children: vec![
2130 Container {
2131 children: vec![
2132 Container {
2133 children: vec![Container {
2134 calculated_width: Some(40.0),
2135 calculated_height: Some(10.0),
2136 ..container.children[0].children[0].children[0].children
2137 [0]
2138 .clone()
2139 }],
2140 calculated_width: Some(40.0),
2141 calculated_height: Some(20.0),
2142 ..container.children[0].children[0].children[0].clone()
2143 },
2144 Container {
2145 children: vec![Container {
2146 calculated_width: Some(30.0),
2147 calculated_height: Some(20.0),
2148 ..container.children[0].children[0].children[1].children
2149 [0]
2150 .clone()
2151 }],
2152 calculated_width: Some(30.0),
2153 calculated_height: Some(20.0),
2154 ..container.children[0].children[0].children[1].clone()
2155 },
2156 ],
2157 calculated_width: Some(70.0),
2158 calculated_height: Some(20.0),
2159 ..container.children[0].children[0].clone()
2160 },
2161 Container {
2162 children: vec![
2163 Container {
2164 children: vec![Container {
2165 calculated_width: Some(10.0),
2166 calculated_height: Some(40.0),
2167 ..container.children[0].children[1].children[0].children
2168 [0]
2169 .clone()
2170 }],
2171 calculated_width: Some(40.0),
2172 calculated_height: Some(40.0),
2173 ..container.children[0].children[1].children[0].clone()
2174 },
2175 Container {
2176 children: vec![Container {
2177 calculated_width: Some(20.0),
2178 calculated_height: Some(30.0),
2179 ..container.children[0].children[1].children[1].children
2180 [0]
2181 .clone()
2182 }],
2183 calculated_width: Some(30.0),
2184 calculated_height: Some(40.0),
2185 ..container.children[0].children[1].children[1].clone()
2186 },
2187 ],
2188 calculated_width: Some(70.0),
2189 calculated_height: Some(40.0),
2190 ..container.children[0].children[1].clone()
2191 },
2192 ],
2193 calculated_width: Some(70.0),
2194 calculated_height: Some(20.0 + 40.0),
2195 ..container.children[0].clone()
2196 }],
2197 ..container
2198 },
2199 );
2200 }
2201
2202 #[test_log::test]
2203 #[ignore]
2204 fn calc_can_calc_table_column_and_row_sizes_and_expand_to_fill_width() {
2205 let mut container = Container {
2206 children: vec![Container {
2207 element: Element::Table,
2208 children: vec![
2209 Container {
2210 element: Element::TR,
2211 direction: LayoutDirection::Row,
2212 children: vec![
2213 Container {
2214 element: Element::TD,
2215 children: vec![Container {
2216 width: Some(Number::Integer(40)),
2217 height: Some(Number::Integer(10)),
2218 ..Default::default()
2219 }],
2220 ..Container::default()
2221 },
2222 Container {
2223 element: Element::TD,
2224 children: vec![Container {
2225 width: Some(Number::Integer(30)),
2226 height: Some(Number::Integer(20)),
2227 ..Default::default()
2228 }],
2229 ..Container::default()
2230 },
2231 ],
2232 ..Default::default()
2233 },
2234 Container {
2235 element: Element::TR,
2236 direction: LayoutDirection::Row,
2237 children: vec![
2238 Container {
2239 element: Element::TD,
2240 children: vec![Container {
2241 width: Some(Number::Integer(10)),
2242 height: Some(Number::Integer(40)),
2243 ..Default::default()
2244 }],
2245 ..Container::default()
2246 },
2247 Container {
2248 element: Element::TD,
2249 children: vec![Container {
2250 width: Some(Number::Integer(20)),
2251 height: Some(Number::Integer(30)),
2252 ..Default::default()
2253 }],
2254 ..Container::default()
2255 },
2256 ],
2257 ..Default::default()
2258 },
2259 ],
2260 ..Default::default()
2261 }],
2262 calculated_width: Some(100.0),
2263 calculated_height: Some(80.0),
2264 ..Default::default()
2265 };
2266 CALCULATOR.calc(&mut container);
2267 log::trace!("container:\n{container}");
2268
2269 compare_containers(
2270 &container.clone(),
2271 &Container {
2272 children: vec![Container {
2273 children: vec![
2274 Container {
2275 children: vec![
2276 Container {
2277 children: vec![Container {
2278 calculated_width: Some(40.0),
2279 calculated_height: Some(10.0),
2280 ..container.children[0].children[0].children[0].children
2281 [0]
2282 .clone()
2283 }],
2284 calculated_width: Some(50.0),
2285 calculated_height: Some(20.0),
2286 ..container.children[0].children[0].children[0].clone()
2287 },
2288 Container {
2289 children: vec![Container {
2290 calculated_width: Some(30.0),
2291 calculated_height: Some(20.0),
2292 ..container.children[0].children[0].children[1].children
2293 [0]
2294 .clone()
2295 }],
2296 calculated_width: Some(50.0),
2297 calculated_height: Some(20.0),
2298 ..container.children[0].children[0].children[1].clone()
2299 },
2300 ],
2301 calculated_width: Some(100.0),
2302 calculated_height: Some(20.0),
2303 ..container.children[0].children[0].clone()
2304 },
2305 Container {
2306 children: vec![
2307 Container {
2308 children: vec![Container {
2309 calculated_width: Some(10.0),
2310 calculated_height: Some(40.0),
2311 ..container.children[0].children[1].children[0].children
2312 [0]
2313 .clone()
2314 }],
2315 calculated_width: Some(50.0),
2316 calculated_height: Some(40.0),
2317 ..container.children[0].children[1].children[0].clone()
2318 },
2319 Container {
2320 children: vec![Container {
2321 calculated_width: Some(20.0),
2322 calculated_height: Some(30.0),
2323 ..container.children[0].children[1].children[1].children
2324 [0]
2325 .clone()
2326 }],
2327 calculated_width: Some(50.0),
2328 calculated_height: Some(40.0),
2329 ..container.children[0].children[1].children[1].clone()
2330 },
2331 ],
2332 calculated_width: Some(100.0),
2333 calculated_height: Some(40.0),
2334 ..container.children[0].children[1].clone()
2335 },
2336 ],
2337 calculated_width: Some(100.0),
2338 calculated_height: Some(20.0 + 40.0),
2339 ..container.children[0].clone()
2340 }],
2341 ..container
2342 },
2343 );
2344 }
2345
2346 #[test_log::test]
2347 #[ignore]
2348 fn calc_can_calc_table_column_and_row_sizes_and_auto_size_unsized_cells() {
2349 let mut container = Container {
2350 children: vec![Container {
2351 element: Element::Table,
2352 children: vec![
2353 Container {
2354 element: Element::TR,
2355 direction: LayoutDirection::Row,
2356 children: vec![
2357 Container {
2358 element: Element::TD,
2359 children: vec![Container {
2360 width: Some(Number::Integer(40)),
2361 height: Some(Number::Integer(10)),
2362 ..Default::default()
2363 }],
2364 ..Container::default()
2365 },
2366 Container {
2367 element: Element::TD,
2368 children: vec![Container::default()],
2369 ..Container::default()
2370 },
2371 ],
2372 ..Default::default()
2373 },
2374 Container {
2375 element: Element::TR,
2376 direction: LayoutDirection::Row,
2377 children: vec![
2378 Container {
2379 element: Element::TD,
2380 children: vec![Container::default()],
2381 ..Container::default()
2382 },
2383 Container {
2384 element: Element::TD,
2385 children: vec![Container {
2386 width: Some(Number::Integer(20)),
2387 height: Some(Number::Integer(30)),
2388 ..Default::default()
2389 }],
2390 ..Container::default()
2391 },
2392 ],
2393 ..Default::default()
2394 },
2395 ],
2396 ..Default::default()
2397 }],
2398 calculated_width: Some(100.0),
2399 calculated_height: Some(80.0),
2400 ..Default::default()
2401 };
2402 CALCULATOR.calc(&mut container);
2403 log::trace!("container:\n{container}");
2404
2405 compare_containers(
2406 &container.clone(),
2407 &Container {
2408 children: vec![Container {
2409 children: vec![
2410 Container {
2411 children: vec![
2412 Container {
2413 children: vec![Container {
2414 calculated_width: Some(40.0),
2415 calculated_height: Some(10.0),
2416 ..container.children[0].children[0].children[0].children
2417 [0]
2418 .clone()
2419 }],
2420 calculated_width: Some(50.0),
2421 calculated_height: Some(10.0),
2422 ..container.children[0].children[0].children[0].clone()
2423 },
2424 Container {
2425 calculated_width: Some(50.0),
2426 calculated_height: Some(10.0),
2427 ..container.children[0].children[0].children[1].clone()
2428 },
2429 ],
2430 calculated_width: Some(100.0),
2431 calculated_height: Some(10.0),
2432 ..container.children[0].children[0].clone()
2433 },
2434 Container {
2435 children: vec![
2436 Container {
2437 calculated_width: Some(50.0),
2438 calculated_height: Some(30.0),
2439 ..container.children[0].children[1].children[0].clone()
2440 },
2441 Container {
2442 children: vec![Container {
2443 calculated_width: Some(20.0),
2444 calculated_height: Some(30.0),
2445 ..container.children[0].children[1].children[1].children
2446 [0]
2447 .clone()
2448 }],
2449 calculated_width: Some(50.0),
2450 calculated_height: Some(30.0),
2451 ..container.children[0].children[1].children[1].clone()
2452 },
2453 ],
2454 calculated_width: Some(100.0),
2455 calculated_height: Some(30.0),
2456 ..container.children[0].children[1].clone()
2457 },
2458 ],
2459 calculated_width: Some(100.0),
2460 calculated_height: Some(10.0 + 30.0),
2461 ..container.children[0].clone()
2462 }],
2463 ..container
2464 },
2465 );
2466 }
2467
2468 #[test_log::test]
2469 #[ignore]
2470 fn calc_can_calc_table_column_and_row_sizes_and_auto_size_unsized_cells_when_all_are_unsized()
2471 {
2472 let mut container = Container {
2473 children: vec![Container {
2474 element: Element::Table,
2475 children: vec![
2476 Container {
2477 element: Element::TR,
2478 direction: LayoutDirection::Row,
2479 children: vec![
2480 Container {
2481 element: Element::TD,
2482 children: vec![Container::default()],
2483 ..Container::default()
2484 },
2485 Container {
2486 element: Element::TD,
2487 children: vec![Container::default()],
2488 ..Container::default()
2489 },
2490 ],
2491 ..Default::default()
2492 },
2493 Container {
2494 element: Element::TR,
2495 direction: LayoutDirection::Row,
2496 children: vec![
2497 Container {
2498 element: Element::TD,
2499 children: vec![Container::default()],
2500 ..Container::default()
2501 },
2502 Container {
2503 element: Element::TD,
2504 children: vec![Container::default()],
2505 ..Container::default()
2506 },
2507 ],
2508 ..Default::default()
2509 },
2510 ],
2511 ..Default::default()
2512 }],
2513 calculated_width: Some(100.0),
2514 calculated_height: Some(80.0),
2515 ..Default::default()
2516 };
2517 CALCULATOR.calc(&mut container);
2518 log::trace!("container:\n{container}");
2519
2520 compare_containers(
2521 &container.clone(),
2522 &Container {
2523 children: vec![Container {
2524 children: vec![
2525 Container {
2526 children: vec![
2527 Container {
2528 children: vec![Container {
2529 calculated_width: Some(50.0),
2530 calculated_height: Some(25.0),
2531 ..container.children[0].children[0].children[0].children
2532 [0]
2533 .clone()
2534 }],
2535 calculated_width: Some(50.0),
2536 calculated_height: Some(25.0),
2537 ..container.children[0].children[0].children[0].clone()
2538 },
2539 Container {
2540 children: vec![Container {
2541 calculated_width: Some(50.0),
2542 calculated_height: Some(25.0),
2543 ..container.children[0].children[0].children[1].children
2544 [0]
2545 .clone()
2546 }],
2547 calculated_width: Some(50.0),
2548 calculated_height: Some(25.0),
2549 ..container.children[0].children[0].children[1].clone()
2550 },
2551 ],
2552 calculated_width: Some(100.0),
2553 calculated_height: Some(25.0),
2554 ..container.children[0].children[0].clone()
2555 },
2556 Container {
2557 children: vec![
2558 Container {
2559 children: vec![Container {
2560 calculated_width: Some(50.0),
2561 calculated_height: Some(25.0),
2562 ..container.children[0].children[1].children[0].children
2563 [0]
2564 .clone()
2565 }],
2566 calculated_width: Some(50.0),
2567 calculated_height: Some(25.0),
2568 ..container.children[0].children[1].children[0].clone()
2569 },
2570 Container {
2571 children: vec![Container {
2572 calculated_width: Some(50.0),
2573 calculated_height: Some(25.0),
2574 ..container.children[0].children[1].children[1].children
2575 [0]
2576 .clone()
2577 }],
2578 calculated_width: Some(50.0),
2579 calculated_height: Some(25.0),
2580 ..container.children[0].children[1].children[1].clone()
2581 },
2582 ],
2583 calculated_width: Some(100.0),
2584 calculated_height: Some(25.0),
2585 ..container.children[0].children[1].clone()
2586 },
2587 ],
2588 calculated_width: Some(100.0),
2589 calculated_height: Some(25.0 + 25.0),
2590 ..container.children[0].clone()
2591 }],
2592 ..container
2593 },
2594 );
2595 }
2596
2597 #[test_log::test]
2598 #[ignore]
2599 fn calc_can_calc_table_column_and_row_sizes_and_auto_size_raw_data() {
2600 let mut container: Container = html! {
2601 table {
2602 tr {
2603 td { "test" }
2604 td { "test" }
2605 }
2606 tr {
2607 td { "test" }
2608 td { "test" }
2609 }
2610 }
2611 }
2612 .try_into()
2613 .unwrap();
2614
2615 container.calculated_width = Some(100.0);
2616 container.calculated_height = Some(80.0);
2617
2618 CALCULATOR.calc(&mut container);
2619 log::trace!("container:\n{container}");
2620
2621 compare_containers(
2622 &container.clone(),
2623 &Container {
2624 children: vec![Container {
2625 children: vec![
2626 Container {
2627 children: vec![
2628 Container {
2629 children: container.children[0].children[0].children[0]
2630 .children
2631 .clone(),
2632 calculated_width: Some(50.0),
2633 calculated_height: Some(25.0),
2634 ..container.children[0].children[0].children[0].clone()
2635 },
2636 Container {
2637 children: container.children[0].children[0].children[1]
2638 .children
2639 .clone(),
2640 calculated_width: Some(50.0),
2641 calculated_height: Some(25.0),
2642 ..container.children[0].children[0].children[1].clone()
2643 },
2644 ],
2645 calculated_width: Some(100.0),
2646 calculated_height: Some(25.0),
2647 ..container.children[0].children[0].clone()
2648 },
2649 Container {
2650 children: vec![
2651 Container {
2652 children: container.children[0].children[1].children[0]
2653 .children
2654 .clone(),
2655 calculated_width: Some(50.0),
2656 calculated_height: Some(25.0),
2657 ..container.children[0].children[1].children[0].clone()
2658 },
2659 Container {
2660 children: container.children[0].children[1].children[1]
2661 .children
2662 .clone(),
2663 calculated_width: Some(50.0),
2664 calculated_height: Some(25.0),
2665 ..container.children[0].children[1].children[1].clone()
2666 },
2667 ],
2668 calculated_width: Some(100.0),
2669 calculated_height: Some(25.0),
2670 ..container.children[0].children[1].clone()
2671 },
2672 ],
2673 calculated_width: Some(100.0),
2674 calculated_height: Some(25.0 + 25.0),
2675 ..container.children[0].clone()
2676 }],
2677 ..container
2678 },
2679 );
2680 }
2681
2682 #[test_log::test]
2683 #[ignore]
2684 fn calc_can_calc_table_column_and_row_sizes_with_tbody() {
2685 let mut container = Container {
2686 children: vec![Container {
2687 element: Element::Table,
2688 children: vec![Container {
2689 element: Element::TBody,
2690 children: vec![
2691 Container {
2692 element: Element::TR,
2693 direction: LayoutDirection::Row,
2694 children: vec![
2695 Container {
2696 element: Element::TD,
2697 children: vec![Container {
2698 element: Element::Raw {
2699 value: "test".to_string(),
2700 },
2701 ..Container::default()
2702 }],
2703 ..Container::default()
2704 },
2705 Container {
2706 element: Element::TD,
2707 children: vec![Container {
2708 element: Element::Raw {
2709 value: "test".to_string(),
2710 },
2711 ..Container::default()
2712 }],
2713 ..Container::default()
2714 },
2715 ],
2716 ..Default::default()
2717 },
2718 Container {
2719 element: Element::TR,
2720 direction: LayoutDirection::Row,
2721 children: vec![
2722 Container {
2723 element: Element::TD,
2724 children: vec![Container {
2725 element: Element::Raw {
2726 value: "test".to_string(),
2727 },
2728 ..Container::default()
2729 }],
2730 ..Container::default()
2731 },
2732 Container {
2733 element: Element::TD,
2734 children: vec![Container {
2735 element: Element::Raw {
2736 value: "test".to_string(),
2737 },
2738 ..Container::default()
2739 }],
2740 ..Container::default()
2741 },
2742 ],
2743 ..Default::default()
2744 },
2745 ],
2746 ..Default::default()
2747 }],
2748 ..Default::default()
2749 }],
2750 calculated_width: Some(100.0),
2751 calculated_height: Some(80.0),
2752 ..Default::default()
2753 };
2754 CALCULATOR.calc(&mut container);
2755 log::trace!("container:\n{container}");
2756
2757 compare_containers(
2758 &container.clone(),
2759 &Container {
2760 children: vec![Container {
2761 children: vec![Container {
2762 children: vec![
2763 Container {
2764 children: vec![
2765 Container {
2766 children: container.children[0].children[0].children[0]
2767 .children[0]
2768 .children
2769 .clone(),
2770 calculated_width: Some(50.0),
2771 calculated_height: Some(25.0),
2772 ..container.children[0].children[0].children[0].children
2773 [0]
2774 .clone()
2775 },
2776 Container {
2777 children: container.children[0].children[0].children[0]
2778 .children[1]
2779 .children
2780 .clone(),
2781 calculated_width: Some(50.0),
2782 calculated_height: Some(25.0),
2783 ..container.children[0].children[0].children[0].children
2784 [1]
2785 .clone()
2786 },
2787 ],
2788 calculated_width: Some(100.0),
2789 calculated_height: Some(25.0),
2790 ..container.children[0].children[0].children[0].clone()
2791 },
2792 Container {
2793 children: vec![
2794 Container {
2795 children: container.children[0].children[0].children[1]
2796 .children[0]
2797 .children
2798 .clone(),
2799 calculated_width: Some(50.0),
2800 calculated_height: Some(25.0),
2801 ..container.children[0].children[0].children[1].children
2802 [0]
2803 .clone()
2804 },
2805 Container {
2806 children: container.children[0].children[0].children[1]
2807 .children[1]
2808 .children
2809 .clone(),
2810 calculated_width: Some(50.0),
2811 calculated_height: Some(25.0),
2812 ..container.children[0].children[0].children[1].children
2813 [1]
2814 .clone()
2815 },
2816 ],
2817 calculated_width: Some(100.0),
2818 calculated_height: Some(25.0),
2819 ..container.children[0].children[0].children[1].clone()
2820 },
2821 ],
2822 calculated_width: Some(100.0),
2823 calculated_height: Some(25.0 + 25.0),
2824 ..container.children[0].children[0].clone()
2825 }],
2826 ..container.children[0].clone()
2827 }],
2828 ..container
2829 },
2830 );
2831 }
2832
2833 #[test_log::test]
2834 #[ignore]
2835 fn calc_calculates_table_td_height_correctly() {
2836 let mut container: Container = html! {
2837 table {
2838 tr {
2839 td sx-height=(30) {}
2840 }
2841 }
2842 }
2843 .try_into()
2844 .unwrap();
2845
2846 container.calculated_width = Some(50.0);
2847 container.calculated_height = Some(100.0);
2848
2849 CALCULATOR.calc(&mut container);
2850 log::trace!("container:\n{container}");
2851
2852 let td = container.children[0].children[0].children[0].clone();
2853
2854 compare_containers(
2855 &td.clone(),
2856 &Container {
2857 calculated_height: Some(30.0),
2858 ..td
2859 },
2860 );
2861 }
2862
2863 #[test_log::test]
2864 #[ignore]
2865 fn calc_calculates_table_tr_height_correctly() {
2866 let mut container: Container = html! {
2867 table {
2868 tr {
2869 td sx-height=(30) {}
2870 }
2871 }
2872 }
2873 .try_into()
2874 .unwrap();
2875
2876 container.calculated_width = Some(50.0);
2877 container.calculated_height = Some(100.0);
2878
2879 CALCULATOR.calc(&mut container);
2880 log::trace!("container:\n{container}");
2881
2882 let tr = container.children[0].children[0].clone();
2883
2884 compare_containers(
2885 &tr.clone(),
2886 &Container {
2887 calculated_height: Some(30.0),
2888 ..tr
2889 },
2890 );
2891 }
2892
2893 #[test_log::test]
2894 #[ignore]
2895 fn calc_calculates_table_height_correctly() {
2896 let mut container: Container = html! {
2897 table {
2898 tr sx-height=(30) {
2899 td sx-height=(30) {}
2900 td sx-height=(30) {}
2901 td sx-height=(30) {}
2902 }
2903 tr sx-height=(30) {
2904 td sx-height=(30) {}
2905 td sx-height=(30) {}
2906 td sx-height=(30) {}
2907 }
2908 tr sx-height=(30) {
2909 td sx-height=(30) {}
2910 td sx-height=(30) {}
2911 td sx-height=(30) {}
2912 }
2913 }
2914 }
2915 .try_into()
2916 .unwrap();
2917
2918 container.calculated_width = Some(50.0);
2919 container.calculated_height = Some(100.0);
2920
2921 CALCULATOR.calc(&mut container);
2922 log::trace!("container:\n{container}");
2923
2924 compare_containers(
2925 &container,
2926 &Container {
2927 children: vec![Container {
2928 calculated_height: Some(90.0),
2929 ..container.children[0].clone()
2930 }],
2931 calculated_height: Some(100.0),
2932 ..container.clone()
2933 },
2934 );
2935 }
2936
2937 #[test_log::test]
2938 #[ignore]
2939 fn calc_overflow_y_squash_calculates_table_sibling_element_height_correctly() {
2940 let mut container: Container = html! {
2941 div {}
2942 table {
2943 tr sx-height=(30) {
2944 td sx-height=(30) {}
2945 td sx-height=(30) {}
2946 td sx-height=(30) {}
2947 }
2948 tr sx-height=(30) {
2949 td sx-height=(30) {}
2950 td sx-height=(30) {}
2951 td sx-height=(30) {}
2952 }
2953 tr sx-height=(30) {
2954 td sx-height=(30) {}
2955 td sx-height=(30) {}
2956 td sx-height=(30) {}
2957 }
2958 }
2959 }
2960 .try_into()
2961 .unwrap();
2962
2963 container.overflow_y = LayoutOverflow::Squash;
2964 container.calculated_width = Some(50.0);
2965 container.calculated_height = Some(100.0);
2966
2967 CALCULATOR.calc(&mut container);
2968 log::trace!("container:\n{container}");
2969
2970 compare_containers(
2971 &container,
2972 &Container {
2973 children: vec![
2974 Container {
2975 calculated_height: Some(10.0),
2976 ..container.children[0].clone()
2977 },
2978 Container {
2979 calculated_height: Some(90.0),
2980 ..container.children[1].clone()
2981 },
2982 ],
2983 calculated_height: Some(100.0),
2984 ..container.clone()
2985 },
2986 );
2987 }
2988
2989 #[test_log::test]
2990 #[ignore]
2991 fn calc_overflow_y_expand_calculates_table_sibling_element_height_correctly() {
2992 let mut container: Container = html! {
2993 div {}
2994 table {
2995 tr sx-height=(30) {
2996 td sx-height=(30) {}
2997 td sx-height=(30) {}
2998 td sx-height=(30) {}
2999 }
3000 tr sx-height=(30) {
3001 td sx-height=(30) {}
3002 td sx-height=(30) {}
3003 td sx-height=(30) {}
3004 }
3005 tr sx-height=(30) {
3006 td sx-height=(30) {}
3007 td sx-height=(30) {}
3008 td sx-height=(30) {}
3009 }
3010 }
3011 }
3012 .try_into()
3013 .unwrap();
3014
3015 container.calculated_width = Some(50.0);
3016 container.calculated_height = Some(100.0);
3017
3018 CALCULATOR.calc(&mut container);
3019 log::trace!("container:\n{container}");
3020
3021 compare_containers(
3022 &container,
3023 &Container {
3024 children: vec![
3025 Container {
3026 calculated_height: Some(10.0),
3027 ..container.children[0].clone()
3028 },
3029 Container {
3030 calculated_height: Some(90.0),
3031 ..container.children[1].clone()
3032 },
3033 ],
3034 calculated_height: Some(100.0),
3035 ..container.clone()
3036 },
3037 );
3038 }
3039
3040 #[test_log::test]
3041 #[ignore]
3042 fn calc_calculates_table_column_widths_the_same_across_headers_and_body() {
3043 let mut container: Container = html! {
3044 table {
3045 thead {
3046 tr {
3047 th { "#" }
3048 th { "Time" }
3049 }
3050 }
3051 tbody id="album-page-tracks" {
3052 tr sx-border-radius=(5) {
3053 td sx-padding-x=(10) sx-padding-y=(15) {
3054 span class="track-number" { "1" }
3055 button class="play-button" sx-visibility="hidden" {
3056 img sx-width=(12) sx-height=(12);
3057 }
3058 }
3059 td sx-padding-x=(10) sx-padding-y=(15) {
3060 "Even Still I Want To"
3061 }
3062 }
3063 }
3064 }
3065 }
3066 .try_into()
3067 .unwrap();
3068
3069 container.calculated_width = Some(1232.0);
3070 container.calculated_height = Some(500.0);
3071
3072 CALCULATOR.calc(&mut container);
3073 log::trace!("container:\n{container}");
3074
3075 compare_containers(
3076 &container.clone(),
3077 &Container {
3078 children: vec![Container {
3079 children: vec![
3080 Container {
3081 children: vec![Container {
3082 children: vec![
3083 Container {
3084 calculated_width: Some(616.0),
3085 ..container.children[0].children[0].children[0].children
3086 [0]
3087 .clone()
3088 },
3089 Container {
3090 calculated_width: Some(616.0),
3091 ..container.children[0].children[0].children[0].children
3092 [1]
3093 .clone()
3094 },
3095 ],
3096 ..container.children[0].children[0].children[0].clone()
3097 }],
3098 ..container.children[0].children[0].clone()
3099 },
3100 Container {
3101 children: vec![Container {
3102 children: vec![
3103 Container {
3104 calculated_width: Some(596.0),
3105 ..container.children[0].children[1].children[0].children
3106 [0]
3107 .clone()
3108 },
3109 Container {
3110 calculated_width: Some(596.0),
3111 ..container.children[0].children[1].children[0].children
3112 [1]
3113 .clone()
3114 },
3115 ],
3116 ..container.children[0].children[1].children[0].clone()
3117 }],
3118 ..container.children[0].children[1].clone()
3119 },
3120 ],
3121 ..container.children[0].clone()
3122 }],
3123 ..container
3124 },
3125 );
3126 }
3127
3128 #[test_log::test]
3129 #[ignore]
3130 fn calc_calculates_table_th_sizes_with_padding_taken_into_account() {
3131 let mut container: Container = html! {
3132 table {
3133 thead {
3134 tr {
3135 th sx-padding-x=(10) sx-padding-y=(15) {}
3136 }
3137 }
3138 }
3139 }
3140 .try_into()
3141 .unwrap();
3142
3143 container.calculated_width = Some(1232.0);
3144 container.calculated_height = Some(500.0);
3145
3146 CALCULATOR.calc(&mut container);
3147 log::trace!("container:\n{container}");
3148
3149 compare_containers(
3150 &container,
3151 &Container {
3152 children: vec![Container {
3153 children: vec![Container {
3154 children: vec![Container {
3155 children: vec![Container {
3156 calculated_width: Some(1212.0),
3157 calculated_height: Some(25.0),
3158 ..container.children[0].children[0].children[0].children[0]
3159 .clone()
3160 }],
3161 ..container.children[0].children[0].children[0].clone()
3162 }],
3163 ..container.children[0].children[0].clone()
3164 }],
3165 ..container.children[0].clone()
3166 }],
3167 ..container.clone()
3168 },
3169 );
3170 }
3171
3172 #[test_log::test]
3173 #[ignore]
3174 fn calc_calculates_table_td_sizes_with_padding_taken_into_account() {
3175 let mut container: Container = html! {
3176 table {
3177 tr {
3178 td sx-padding-x=(10) sx-padding-y=(15) {}
3179 }
3180 }
3181 }
3182 .try_into()
3183 .unwrap();
3184
3185 container.calculated_width = Some(1232.0);
3186 container.calculated_height = Some(500.0);
3187
3188 CALCULATOR.calc(&mut container);
3189 log::trace!("container:\n{container}");
3190
3191 compare_containers(
3192 &container,
3193 &Container {
3194 children: vec![Container {
3195 children: vec![Container {
3196 children: vec![Container {
3197 calculated_width: Some(1212.0),
3198 calculated_height: Some(25.0),
3199 ..container.children[0].children[0].children[0].clone()
3200 }],
3201 ..container.children[0].children[0].clone()
3202 }],
3203 ..container.children[0].clone()
3204 }],
3205 ..container.clone()
3206 },
3207 );
3208 }
3209 }
3210
3211 #[test_log::test]
3212 fn calc_can_calc_single_element_size() {
3213 let mut container = Container {
3214 children: vec![Container::default()],
3215 calculated_width: Some(100.0),
3216 calculated_height: Some(50.0),
3217 justify_content: Some(JustifyContent::Start),
3218 ..Default::default()
3219 };
3220 CALCULATOR.calc(&mut container);
3221 log::trace!("container:\n{container}");
3222
3223 compare_containers(
3224 &container,
3225 &Container {
3226 children: vec![Container {
3227 calculated_width: Some(100.0),
3228 calculated_height: Some(0.0),
3229 calculated_x: Some(0.0),
3230 calculated_y: Some(0.0),
3231 calculated_position: Some(LayoutPosition::Default),
3232 ..container.children[0].clone()
3233 }],
3234 ..container.clone()
3235 },
3236 );
3237 }
3238
3239 #[test_log::test]
3240 fn calc_can_calc_two_elements_with_size_split_evenly_row() {
3241 let mut container: Container = html! {
3242 div sx-dir=(LayoutDirection::Row) {
3243 div {} div {}
3244 }
3245 }
3246 .try_into()
3247 .unwrap();
3248
3249 container.calculated_width = Some(100.0);
3250 container.calculated_height = Some(40.0);
3251 container.justify_content = Some(JustifyContent::Start);
3252
3253 CALCULATOR.calc(&mut container);
3254 log::trace!("container:\n{container}");
3255
3256 compare_containers(
3257 &container,
3258 &Container {
3259 children: vec![Container {
3260 children: vec![
3261 Container {
3262 calculated_width: Some(0.0),
3263 calculated_height: Some(0.0),
3264 calculated_x: Some(0.0),
3265 calculated_y: Some(0.0),
3266 calculated_position: Some(LayoutPosition::Default),
3267 ..container.children[0].children[0].clone()
3268 },
3269 Container {
3270 calculated_width: Some(0.0),
3271 calculated_height: Some(0.0),
3272 calculated_x: Some(0.0),
3273 calculated_y: Some(0.0),
3274 calculated_position: Some(LayoutPosition::Default),
3275 ..container.children[0].children[1].clone()
3276 },
3277 ],
3278 calculated_width: Some(100.0),
3279 calculated_height: Some(0.0),
3280 calculated_x: Some(0.0),
3281 calculated_y: Some(0.0),
3282 calculated_position: Some(LayoutPosition::Default),
3283 direction: LayoutDirection::Row,
3284 ..container.children[0].clone()
3285 }],
3286 ..container.clone()
3287 },
3288 );
3289 }
3290
3291 #[test_log::test]
3292 fn calc_can_calc_horizontal_split_above_a_vertial_split() {
3293 let mut container: Container = html! {
3294 div sx-dir=(LayoutDirection::Row) sx-justify-content=(JustifyContent::Start) {
3295 div {} div {}
3296 }
3297 div {}
3298 }
3299 .try_into()
3300 .unwrap();
3301
3302 container.calculated_width = Some(100.0);
3303 container.calculated_height = Some(40.0);
3304 container.justify_content = Some(JustifyContent::Start);
3305
3306 CALCULATOR.calc(&mut container);
3307 log::trace!("container:\n{container}");
3308
3309 compare_containers(
3310 &container,
3311 &Container {
3312 children: vec![
3313 Container {
3314 children: vec![
3315 Container {
3316 calculated_height: Some(0.0),
3317 calculated_y: Some(0.0),
3318 calculated_position: Some(LayoutPosition::Default),
3319 ..container.children[0].children[0].clone()
3320 },
3321 Container {
3322 calculated_height: Some(0.0),
3323 calculated_y: Some(0.0),
3324 calculated_position: Some(LayoutPosition::Default),
3325 ..container.children[0].children[1].clone()
3326 },
3327 ],
3328 calculated_width: Some(100.0),
3329 calculated_height: Some(0.0),
3330 calculated_x: Some(0.0),
3331 calculated_y: Some(0.0),
3332 calculated_position: Some(LayoutPosition::Default),
3333 direction: LayoutDirection::Row,
3334 ..container.children[0].clone()
3335 },
3336 Container {
3337 calculated_width: Some(100.0),
3338 calculated_height: Some(0.0),
3339 calculated_x: Some(0.0),
3340 calculated_y: Some(0.0),
3341 calculated_position: Some(LayoutPosition::Default),
3342 ..container.children[1].clone()
3343 },
3344 ],
3345 ..container.clone()
3346 },
3347 );
3348 }
3349
3350 #[test_log::test]
3351 fn calc_calcs_contained_height_correctly() {
3352 let mut container: Container = html! {
3353 div {}
3354 div sx-dir=(LayoutDirection::Row) {
3355 div {}
3356 div {}
3357 }
3358 }
3359 .try_into()
3360 .unwrap();
3361
3362 container.calculated_width = Some(100.0);
3363 container.calculated_height = Some(40.0);
3364 container.direction = LayoutDirection::Row;
3365 container.overflow_x = LayoutOverflow::Squash;
3366 container.overflow_y = LayoutOverflow::Squash;
3367
3368 CALCULATOR.calc(&mut container);
3369 log::trace!("container:\n{container}");
3370
3371 compare_containers(
3372 &container,
3373 &Container {
3374 children: vec![
3375 Container {
3376 calculated_height: Some(40.0),
3377 ..container.children[0].clone()
3378 },
3379 Container {
3380 children: vec![
3381 Container {
3382 calculated_height: Some(40.0),
3383 ..container.children[1].children[0].clone()
3384 },
3385 Container {
3386 calculated_height: Some(40.0),
3387 ..container.children[1].children[1].clone()
3388 },
3389 ],
3390 calculated_height: Some(40.0),
3391 ..container.children[1].clone()
3392 },
3393 ],
3394 ..container.clone()
3395 },
3396 );
3397 }
3398
3399 #[test_log::test]
3400 fn handles_justify_content_space_between_and_wraps_elements_properly() {
3401 let mut container = Container {
3402 children: vec![
3403 Container {
3404 width: Some(Number::Integer(20)),
3405 calculated_width: Some(20.0),
3406 calculated_height: Some(20.0),
3407 ..Default::default()
3408 },
3409 Container {
3410 width: Some(Number::Integer(20)),
3411 calculated_width: Some(20.0),
3412 calculated_height: Some(20.0),
3413 ..Default::default()
3414 },
3415 Container {
3416 width: Some(Number::Integer(20)),
3417 calculated_width: Some(20.0),
3418 calculated_height: Some(20.0),
3419 ..Default::default()
3420 },
3421 Container {
3422 width: Some(Number::Integer(20)),
3423 calculated_width: Some(20.0),
3424 calculated_height: Some(20.0),
3425 ..Default::default()
3426 },
3427 Container {
3428 width: Some(Number::Integer(20)),
3429 calculated_width: Some(20.0),
3430 calculated_height: Some(20.0),
3431 ..Default::default()
3432 },
3433 ],
3434 calculated_width: Some(75.0),
3435 calculated_height: Some(40.0),
3436 direction: LayoutDirection::Row,
3437 overflow_x: LayoutOverflow::Wrap { grid: true },
3438 justify_content: Some(JustifyContent::SpaceBetween),
3439 ..Default::default()
3440 };
3441
3442 CALCULATOR.calc(&mut container);
3443 log::trace!("container:\n{container}");
3444
3445 compare_containers(
3446 &container.clone(),
3447 &Container {
3448 children: vec![
3449 Container {
3450 calculated_width: Some(20.0),
3451 calculated_height: Some(20.0),
3452 calculated_x: Some(0.0),
3453 calculated_y: Some(0.0),
3454 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 0 }),
3455 ..container.children[0].clone()
3456 },
3457 Container {
3458 calculated_width: Some(20.0),
3459 calculated_height: Some(20.0),
3460 calculated_x: Some(20.0 + 7.5),
3461 calculated_y: Some(0.0),
3462 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 1 }),
3463 ..container.children[1].clone()
3464 },
3465 Container {
3466 calculated_width: Some(20.0),
3467 calculated_height: Some(20.0),
3468 calculated_x: Some(40.0 + 7.5 + 7.5),
3469 calculated_y: Some(0.0),
3470 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 2 }),
3471 ..container.children[2].clone()
3472 },
3473 Container {
3474 calculated_width: Some(20.0),
3475 calculated_height: Some(20.0),
3476 calculated_x: Some(0.0),
3477 calculated_y: Some(20.0),
3478 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 0 }),
3479 ..container.children[3].clone()
3480 },
3481 Container {
3482 calculated_width: Some(20.0),
3483 calculated_height: Some(20.0),
3484 calculated_x: Some(20.0 + 7.5),
3485 calculated_y: Some(20.0),
3486 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 1 }),
3487 ..container.children[4].clone()
3488 },
3489 ],
3490 calculated_width: Some(75.0),
3491 calculated_height: Some(40.0),
3492 ..container
3493 },
3494 );
3495 }
3496
3497 #[test_log::test]
3498 fn handles_justify_content_space_between_and_wraps_elements_properly_with_hidden_div() {
3499 let mut container = Container {
3500 children: vec![
3501 Container {
3502 width: Some(Number::Integer(20)),
3503 calculated_width: Some(20.0),
3504 calculated_height: Some(20.0),
3505 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 0 }),
3506 ..Default::default()
3507 },
3508 Container {
3509 width: Some(Number::Integer(20)),
3510 calculated_width: Some(20.0),
3511 calculated_height: Some(20.0),
3512 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 1 }),
3513 ..Default::default()
3514 },
3515 Container {
3516 width: Some(Number::Integer(20)),
3517 calculated_width: Some(20.0),
3518 calculated_height: Some(20.0),
3519 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 1 }),
3520 ..Default::default()
3521 },
3522 Container {
3523 width: Some(Number::Integer(20)),
3524 calculated_width: Some(20.0),
3525 calculated_height: Some(20.0),
3526 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 0 }),
3527 ..Default::default()
3528 },
3529 Container {
3530 width: Some(Number::Integer(20)),
3531 calculated_width: Some(20.0),
3532 calculated_height: Some(20.0),
3533 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 1 }),
3534 ..Default::default()
3535 },
3536 Container {
3537 hidden: Some(true),
3538 ..Default::default()
3539 },
3540 ],
3541 calculated_width: Some(75.0),
3542 calculated_height: Some(40.0),
3543 direction: LayoutDirection::Row,
3544 overflow_x: LayoutOverflow::Wrap { grid: true },
3545 justify_content: Some(JustifyContent::SpaceBetween),
3546 ..Default::default()
3547 };
3548
3549 CALCULATOR.calc(&mut container);
3550 log::trace!("container:\n{container}");
3551
3552 compare_containers(
3553 &container.clone(),
3554 &Container {
3555 children: vec![
3556 Container {
3557 calculated_width: Some(20.0),
3558 calculated_height: Some(20.0),
3559 calculated_x: Some(0.0),
3560 calculated_y: Some(0.0),
3561 ..container.children[0].clone()
3562 },
3563 Container {
3564 calculated_width: Some(20.0),
3565 calculated_height: Some(20.0),
3566 calculated_x: Some(20.0 + 7.5),
3567 calculated_y: Some(0.0),
3568 ..container.children[1].clone()
3569 },
3570 Container {
3571 calculated_width: Some(20.0),
3572 calculated_height: Some(20.0),
3573 calculated_x: Some(40.0 + 7.5 + 7.5),
3574 calculated_y: Some(0.0),
3575 ..container.children[2].clone()
3576 },
3577 Container {
3578 calculated_width: Some(20.0),
3579 calculated_height: Some(20.0),
3580 calculated_x: Some(0.0),
3581 calculated_y: Some(20.0),
3582 ..container.children[3].clone()
3583 },
3584 Container {
3585 calculated_width: Some(20.0),
3586 calculated_height: Some(20.0),
3587 calculated_x: Some(20.0 + 7.5),
3588 calculated_y: Some(20.0),
3589 ..container.children[4].clone()
3590 },
3591 Container {
3592 hidden: Some(true),
3593 ..container.children[5].clone()
3594 },
3595 ],
3596 calculated_width: Some(75.0),
3597 calculated_height: Some(40.0),
3598 ..container
3599 },
3600 );
3601 }
3602
3603 #[test_log::test]
3604 fn handle_overflow_y_squash_handles_justify_content_space_between_and_wraps_elements_properly_and_can_recalc_with_new_rows()
3605 {
3606 const ROW_HEIGHT: f32 = 40.0 / 4.0;
3607
3608 let div = Container {
3609 width: Some(Number::Integer(20)),
3610 calculated_width: Some(20.0),
3611 calculated_height: Some(20.0),
3612 ..Default::default()
3613 };
3614
3615 let mut container = Container {
3616 children: vec![
3617 div.clone(),
3618 div.clone(),
3619 div.clone(),
3620 div.clone(),
3621 div.clone(),
3622 ],
3623 calculated_width: Some(75.0),
3624 calculated_height: Some(40.0),
3625 direction: LayoutDirection::Row,
3626 overflow_x: LayoutOverflow::Wrap { grid: true },
3627 overflow_y: LayoutOverflow::Squash,
3628 justify_content: Some(JustifyContent::SpaceBetween),
3629 ..Default::default()
3630 };
3631
3632 log::debug!("First calc");
3633 CALCULATOR.calc(&mut container);
3634 log::trace!("first container:\n{container}");
3635
3636 container.children.extend(vec![
3637 div.clone(),
3638 div.clone(),
3639 div.clone(),
3640 div.clone(),
3641 div,
3642 ]);
3643
3644 log::debug!("Second calc");
3645 CALCULATOR.calc(&mut container);
3646 log::trace!("second container:\n{container}");
3647
3648 compare_containers(
3649 &container.clone(),
3650 &Container {
3651 children: vec![
3652 Container {
3653 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 0 }),
3654 calculated_width: Some(20.0),
3655 calculated_height: Some(10.0),
3656 calculated_x: Some(0.0),
3657 calculated_y: Some(ROW_HEIGHT * 0.0),
3658 ..container.children[0].clone()
3659 },
3660 Container {
3661 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 1 }),
3662 calculated_width: Some(20.0),
3663 calculated_height: Some(10.0),
3664 calculated_x: Some(20.0 + 7.5),
3665 calculated_y: Some(ROW_HEIGHT * 0.0),
3666 ..container.children[1].clone()
3667 },
3668 Container {
3669 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 2 }),
3670 calculated_width: Some(20.0),
3671 calculated_height: Some(10.0),
3672 calculated_x: Some(40.0 + 7.5 + 7.5),
3673 calculated_y: Some(ROW_HEIGHT * 0.0),
3674 ..container.children[2].clone()
3675 },
3676 Container {
3677 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 0 }),
3678 calculated_width: Some(20.0),
3679 calculated_height: Some(10.0),
3680 calculated_x: Some(0.0),
3681 calculated_y: Some(ROW_HEIGHT * 1.0),
3682 ..container.children[3].clone()
3683 },
3684 Container {
3685 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 1 }),
3686 calculated_width: Some(20.0),
3687 calculated_height: Some(10.0),
3688 calculated_x: Some(20.0 + 7.5),
3689 calculated_y: Some(ROW_HEIGHT * 1.0),
3690 ..container.children[4].clone()
3691 },
3692 Container {
3693 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 2 }),
3694 calculated_width: Some(20.0),
3695 calculated_height: Some(10.0),
3696 calculated_x: Some(40.0 + 7.5 + 7.5),
3697 calculated_y: Some(ROW_HEIGHT * 1.0),
3698 ..container.children[5].clone()
3699 },
3700 Container {
3701 calculated_position: Some(LayoutPosition::Wrap { row: 2, col: 0 }),
3702 calculated_width: Some(20.0),
3703 calculated_height: Some(10.0),
3704 calculated_x: Some(0.0),
3705 calculated_y: Some(ROW_HEIGHT * 2.0),
3706 ..container.children[6].clone()
3707 },
3708 Container {
3709 calculated_position: Some(LayoutPosition::Wrap { row: 2, col: 1 }),
3710 calculated_width: Some(20.0),
3711 calculated_height: Some(10.0),
3712 calculated_x: Some(20.0 + 7.5),
3713 calculated_y: Some(ROW_HEIGHT * 2.0),
3714 ..container.children[7].clone()
3715 },
3716 Container {
3717 calculated_position: Some(LayoutPosition::Wrap { row: 2, col: 2 }),
3718 calculated_width: Some(20.0),
3719 calculated_height: Some(10.0),
3720 calculated_x: Some(40.0 + 7.5 + 7.5),
3721 calculated_y: Some(ROW_HEIGHT * 2.0),
3722 ..container.children[8].clone()
3723 },
3724 Container {
3725 calculated_position: Some(LayoutPosition::Wrap { row: 3, col: 0 }),
3726 calculated_width: Some(20.0),
3727 calculated_height: Some(10.0),
3728 calculated_x: Some(0.0),
3729 calculated_y: Some(ROW_HEIGHT * 3.0),
3730 ..container.children[9].clone()
3731 },
3732 ],
3733 calculated_width: Some(75.0),
3734 calculated_height: Some(40.0),
3735 ..container
3736 },
3737 );
3738 }
3739
3740 #[test_log::test]
3741 fn handle_overflow_y_expand_handles_justify_content_space_between_and_wraps_elements_properly_and_can_recalc_with_new_rows()
3742 {
3743 const ROW_HEIGHT: f32 = 10.0;
3744
3745 let div = Container {
3746 width: Some(Number::Integer(20)),
3747 ..Default::default()
3748 };
3749
3750 let mut container = Container {
3751 children: vec![
3752 div.clone(),
3753 div.clone(),
3754 div.clone(),
3755 div.clone(),
3756 div.clone(),
3757 ],
3758 calculated_width: Some(75.0),
3759 calculated_height: Some(40.0),
3760 direction: LayoutDirection::Row,
3761 overflow_x: LayoutOverflow::Wrap { grid: true },
3762 overflow_y: LayoutOverflow::Expand,
3763 justify_content: Some(JustifyContent::SpaceBetween),
3764 ..Default::default()
3765 };
3766
3767 log::debug!("First calc");
3768 CALCULATOR.calc(&mut container);
3769 log::trace!("first container:\n{container}");
3770
3771 container.children.extend(vec![
3772 div.clone(),
3773 div.clone(),
3774 div.clone(),
3775 div.clone(),
3776 div,
3777 ]);
3778
3779 log::debug!("Second calc");
3780 CALCULATOR.calc(&mut container);
3781 log::trace!("second container:\n{container}");
3782
3783 compare_containers(
3784 &container.clone(),
3785 &Container {
3786 children: vec![
3787 Container {
3788 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 0 }),
3789 calculated_width: Some(20.0),
3790 calculated_height: Some(ROW_HEIGHT),
3791 calculated_x: Some(0.0),
3792 calculated_y: Some(ROW_HEIGHT * 0.0),
3793 ..container.children[0].clone()
3794 },
3795 Container {
3796 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 1 }),
3797 calculated_width: Some(20.0),
3798 calculated_height: Some(ROW_HEIGHT),
3799 calculated_x: Some(20.0 + 7.5),
3800 calculated_y: Some(ROW_HEIGHT * 0.0),
3801 ..container.children[1].clone()
3802 },
3803 Container {
3804 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 2 }),
3805 calculated_width: Some(20.0),
3806 calculated_height: Some(ROW_HEIGHT),
3807 calculated_x: Some(40.0 + 7.5 + 7.5),
3808 calculated_y: Some(ROW_HEIGHT * 0.0),
3809 ..container.children[2].clone()
3810 },
3811 Container {
3812 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 0 }),
3813 calculated_width: Some(20.0),
3814 calculated_height: Some(ROW_HEIGHT),
3815 calculated_x: Some(0.0),
3816 calculated_y: Some(ROW_HEIGHT * 1.0),
3817 ..container.children[3].clone()
3818 },
3819 Container {
3820 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 1 }),
3821 calculated_width: Some(20.0),
3822 calculated_height: Some(ROW_HEIGHT),
3823 calculated_x: Some(20.0 + 7.5),
3824 calculated_y: Some(ROW_HEIGHT * 1.0),
3825 ..container.children[4].clone()
3826 },
3827 Container {
3828 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 2 }),
3829 calculated_width: Some(20.0),
3830 calculated_height: Some(ROW_HEIGHT),
3831 calculated_x: Some(40.0 + 7.5 + 7.5),
3832 calculated_y: Some(ROW_HEIGHT * 1.0),
3833 ..container.children[5].clone()
3834 },
3835 Container {
3836 calculated_position: Some(LayoutPosition::Wrap { row: 2, col: 0 }),
3837 calculated_width: Some(20.0),
3838 calculated_height: Some(ROW_HEIGHT),
3839 calculated_x: Some(0.0),
3840 calculated_y: Some(ROW_HEIGHT * 2.0),
3841 ..container.children[6].clone()
3842 },
3843 Container {
3844 calculated_position: Some(LayoutPosition::Wrap { row: 2, col: 1 }),
3845 calculated_width: Some(20.0),
3846 calculated_height: Some(ROW_HEIGHT),
3847 calculated_x: Some(20.0 + 7.5),
3848 calculated_y: Some(ROW_HEIGHT * 2.0),
3849 ..container.children[7].clone()
3850 },
3851 Container {
3852 calculated_position: Some(LayoutPosition::Wrap { row: 2, col: 2 }),
3853 calculated_width: Some(20.0),
3854 calculated_height: Some(ROW_HEIGHT),
3855 calculated_x: Some(40.0 + 7.5 + 7.5),
3856 calculated_y: Some(ROW_HEIGHT * 2.0),
3857 ..container.children[8].clone()
3858 },
3859 Container {
3860 calculated_position: Some(LayoutPosition::Wrap { row: 3, col: 0 }),
3861 calculated_width: Some(20.0),
3862 calculated_height: Some(ROW_HEIGHT),
3863 calculated_x: Some(0.0),
3864 calculated_y: Some(ROW_HEIGHT * 3.0),
3865 ..container.children[9].clone()
3866 },
3867 ],
3868 calculated_width: Some(75.0),
3869 calculated_height: Some(40.0),
3870 ..container
3871 },
3872 );
3873 }
3874
3875 #[test_log::test]
3876 fn handles_justify_content_space_between_with_gap_and_wraps_elements_properly() {
3877 const ROW_HEIGHT: f32 = 40.0 / 3.0;
3878
3879 let mut container = Container {
3880 children: vec![
3881 Container {
3882 width: Some(Number::Integer(20)),
3883 ..Default::default()
3884 },
3885 Container {
3886 width: Some(Number::Integer(20)),
3887 ..Default::default()
3888 },
3889 Container {
3890 width: Some(Number::Integer(20)),
3891 ..Default::default()
3892 },
3893 Container {
3894 width: Some(Number::Integer(20)),
3895 ..Default::default()
3896 },
3897 Container {
3898 width: Some(Number::Integer(20)),
3899 ..Default::default()
3900 },
3901 ],
3902 calculated_width: Some(75.0),
3903 calculated_height: Some(40.0),
3904 direction: LayoutDirection::Row,
3905 overflow_x: LayoutOverflow::Wrap { grid: true },
3906 overflow_y: LayoutOverflow::Expand,
3907 justify_content: Some(JustifyContent::SpaceBetween),
3908 column_gap: Some(Number::Integer(10)),
3909 row_gap: Some(Number::Integer(10)),
3910 ..Default::default()
3911 };
3912
3913 CALCULATOR.calc(&mut container);
3914 log::trace!("container:\n{container}");
3915
3916 compare_containers(
3917 &container,
3918 &Container {
3919 children: vec![
3920 Container {
3921 calculated_width: Some(20.0),
3922 calculated_height: Some(ROW_HEIGHT),
3923 calculated_x: Some(0.0),
3924 calculated_y: Some(0.0),
3925 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 0 }),
3926 ..container.children[0].clone()
3927 },
3928 Container {
3929 calculated_width: Some(20.0),
3930 calculated_height: Some(ROW_HEIGHT),
3931 calculated_x: Some(75.0 - 20.0),
3932 calculated_y: Some(0.0),
3933 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 1 }),
3934 ..container.children[1].clone()
3935 },
3936 Container {
3937 calculated_width: Some(20.0),
3938 calculated_height: Some(ROW_HEIGHT),
3939 calculated_x: Some(0.0),
3940 calculated_y: Some(ROW_HEIGHT.mul_add(1.0, 10.0)),
3941 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 0 }),
3942 ..container.children[2].clone()
3943 },
3944 Container {
3945 calculated_width: Some(20.0),
3946 calculated_height: Some(ROW_HEIGHT),
3947 calculated_x: Some(75.0 - 20.0),
3948 calculated_y: Some(ROW_HEIGHT.mul_add(1.0, 10.0)),
3949 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 1 }),
3950 ..container.children[3].clone()
3951 },
3952 Container {
3953 calculated_width: Some(20.0),
3954 calculated_height: Some(ROW_HEIGHT),
3955 calculated_x: Some(0.0),
3956 calculated_y: Some(ROW_HEIGHT.mul_add(2.0, 10.0 + 10.0)),
3957 calculated_position: Some(LayoutPosition::Wrap { row: 2, col: 0 }),
3958 ..container.children[4].clone()
3959 },
3960 ],
3961 calculated_width: Some(75.0),
3962 calculated_height: Some(40.0),
3963 ..container.clone()
3964 },
3965 );
3966 }
3967
3968 #[test_log::test]
3969 fn handles_justify_content_space_between_with_gap_and_wraps_elements_properly_and_can_recalc() {
3970 const ROW_HEIGHT: f32 = 40.0 / 3.0;
3971
3972 let mut container = Container {
3973 children: vec![
3974 Container {
3975 width: Some(Number::Integer(20)),
3976 ..Default::default()
3977 },
3978 Container {
3979 width: Some(Number::Integer(20)),
3980 ..Default::default()
3981 },
3982 Container {
3983 width: Some(Number::Integer(20)),
3984 ..Default::default()
3985 },
3986 Container {
3987 width: Some(Number::Integer(20)),
3988 ..Default::default()
3989 },
3990 Container {
3991 width: Some(Number::Integer(20)),
3992 ..Default::default()
3993 },
3994 ],
3995 calculated_width: Some(75.0),
3996 calculated_height: Some(40.0),
3997 direction: LayoutDirection::Row,
3998 overflow_x: LayoutOverflow::Wrap { grid: true },
3999 overflow_y: LayoutOverflow::Expand,
4000 justify_content: Some(JustifyContent::SpaceBetween),
4001 column_gap: Some(Number::Integer(10)),
4002 row_gap: Some(Number::Integer(10)),
4003 ..Default::default()
4004 };
4005
4006 CALCULATOR.calc(&mut container);
4007 log::trace!("first container:\n{container}");
4008
4009 let mut actual = container.clone();
4010 let expected = Container {
4011 children: vec![
4012 Container {
4013 calculated_width: Some(20.0),
4014 calculated_height: Some(ROW_HEIGHT),
4015 calculated_x: Some(0.0),
4016 calculated_y: Some(0.0),
4017 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 0 }),
4018 ..container.children[0].clone()
4019 },
4020 Container {
4021 calculated_width: Some(20.0),
4022 calculated_height: Some(ROW_HEIGHT),
4023 calculated_x: Some(75.0 - 20.0),
4024 calculated_y: Some(0.0),
4025 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 1 }),
4026 ..container.children[1].clone()
4027 },
4028 Container {
4029 calculated_width: Some(20.0),
4030 calculated_height: Some(ROW_HEIGHT),
4031 calculated_x: Some(0.0),
4032 calculated_y: Some(ROW_HEIGHT.mul_add(1.0, 10.0)),
4033 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 0 }),
4034 ..container.children[2].clone()
4035 },
4036 Container {
4037 calculated_width: Some(20.0),
4038 calculated_height: Some(ROW_HEIGHT),
4039 calculated_x: Some(75.0 - 20.0),
4040 calculated_y: Some(ROW_HEIGHT.mul_add(1.0, 10.0)),
4041 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 1 }),
4042 ..container.children[3].clone()
4043 },
4044 Container {
4045 calculated_width: Some(20.0),
4046 calculated_height: Some(ROW_HEIGHT),
4047 calculated_x: Some(0.0),
4048 calculated_y: Some(ROW_HEIGHT.mul_add(2.0, 10.0 + 10.0)),
4049 calculated_position: Some(LayoutPosition::Wrap { row: 2, col: 0 }),
4050 ..container.children[4].clone()
4051 },
4052 ],
4053 calculated_width: Some(75.0),
4054 calculated_height: Some(40.0),
4055 ..container
4056 };
4057
4058 compare_containers(&actual, &expected);
4059
4060 CALCULATOR.calc(&mut actual);
4061 log::trace!("second container:\n{actual}");
4062
4063 compare_containers(&actual, &expected);
4064 }
4065
4066 #[test_log::test]
4067 fn handles_justify_content_space_evenly_and_wraps_elements_properly() {
4068 const ROW_HEIGHT: f32 = 40.0 / 2.0;
4069
4070 let mut container = Container {
4071 children: vec![
4072 Container {
4073 width: Some(Number::Integer(20)),
4074 ..Default::default()
4075 },
4076 Container {
4077 width: Some(Number::Integer(20)),
4078 ..Default::default()
4079 },
4080 Container {
4081 width: Some(Number::Integer(20)),
4082 ..Default::default()
4083 },
4084 Container {
4085 width: Some(Number::Integer(20)),
4086 ..Default::default()
4087 },
4088 Container {
4089 width: Some(Number::Integer(20)),
4090 ..Default::default()
4091 },
4092 ],
4093 calculated_width: Some(75.0),
4094 calculated_height: Some(40.0),
4095 direction: LayoutDirection::Row,
4096 overflow_x: LayoutOverflow::Wrap { grid: true },
4097 justify_content: Some(JustifyContent::SpaceEvenly),
4098 ..Default::default()
4099 };
4100
4101 CALCULATOR.calc(&mut container);
4102 log::trace!("container:\n{container}");
4103
4104 compare_containers(
4105 &container,
4106 &Container {
4107 children: vec![
4108 Container {
4109 calculated_width: Some(20.0),
4110 calculated_height: Some(ROW_HEIGHT),
4111 calculated_x: Some(3.75),
4112 calculated_y: Some(ROW_HEIGHT * 0.0),
4113 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 0 }),
4114 ..container.children[0].clone()
4115 },
4116 Container {
4117 calculated_width: Some(20.0),
4118 calculated_height: Some(ROW_HEIGHT),
4119 calculated_x: Some(20.0 + 3.75 + 3.75),
4120 calculated_y: Some(ROW_HEIGHT * 0.0),
4121 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 1 }),
4122 ..container.children[1].clone()
4123 },
4124 Container {
4125 calculated_width: Some(20.0),
4126 calculated_height: Some(ROW_HEIGHT),
4127 calculated_x: Some(40.0 + 3.75 + 3.75 + 3.75),
4128 calculated_y: Some(ROW_HEIGHT * 0.0),
4129 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 2 }),
4130 ..container.children[2].clone()
4131 },
4132 Container {
4133 calculated_width: Some(20.0),
4134 calculated_height: Some(ROW_HEIGHT),
4135 calculated_x: Some(3.75),
4136 calculated_y: Some(ROW_HEIGHT * 1.0),
4137 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 0 }),
4138 ..container.children[3].clone()
4139 },
4140 Container {
4141 calculated_width: Some(20.0),
4142 calculated_height: Some(ROW_HEIGHT),
4143 calculated_x: Some(20.0 + 3.75 + 3.75),
4144 calculated_y: Some(ROW_HEIGHT * 1.0),
4145 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 1 }),
4146 ..container.children[4].clone()
4147 },
4148 ],
4149 calculated_width: Some(75.0),
4150 calculated_height: Some(40.0),
4151 ..container.clone()
4152 },
4153 );
4154 }
4155
4156 #[test_log::test]
4157 fn handle_overflow_y_squash_handles_justify_content_space_evenly_with_padding_and_wraps_elements_properly()
4158 {
4159 let mut container = Container {
4160 children: vec![
4161 Container {
4162 width: Some(Number::Integer(20)),
4163 height: Some(Number::Integer(20)),
4164 ..Default::default()
4165 },
4166 Container {
4167 width: Some(Number::Integer(20)),
4168 height: Some(Number::Integer(20)),
4169 ..Default::default()
4170 },
4171 Container {
4172 width: Some(Number::Integer(20)),
4173 height: Some(Number::Integer(20)),
4174 ..Default::default()
4175 },
4176 Container {
4177 width: Some(Number::Integer(20)),
4178 height: Some(Number::Integer(20)),
4179 ..Default::default()
4180 },
4181 Container {
4182 width: Some(Number::Integer(20)),
4183 height: Some(Number::Integer(20)),
4184 ..Default::default()
4185 },
4186 ],
4187 calculated_width: Some(75.0),
4188 calculated_height: Some(40.0),
4189 calculated_padding_left: Some(20.0),
4190 calculated_padding_right: Some(20.0),
4191 direction: LayoutDirection::Row,
4192 overflow_x: LayoutOverflow::Wrap { grid: true },
4193 overflow_y: LayoutOverflow::Squash,
4194 justify_content: Some(JustifyContent::SpaceEvenly),
4195 ..Default::default()
4196 };
4197 CALCULATOR.calc(&mut container);
4198 log::trace!("container:\n{container}");
4199
4200 compare_containers(
4201 &container.clone(),
4202 &Container {
4203 children: vec![
4204 Container {
4205 calculated_width: Some(20.0),
4206 calculated_height: Some(20.0),
4207 calculated_x: Some(3.75),
4208 calculated_y: Some(0.0),
4209 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 0 }),
4210 ..container.children[0].clone()
4211 },
4212 Container {
4213 calculated_width: Some(20.0),
4214 calculated_height: Some(20.0),
4215 calculated_x: Some(20.0 + 3.75 + 3.75),
4216 calculated_y: Some(0.0),
4217 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 1 }),
4218 ..container.children[1].clone()
4219 },
4220 Container {
4221 calculated_width: Some(20.0),
4222 calculated_height: Some(20.0),
4223 calculated_x: Some(40.0 + 3.75 + 3.75 + 3.75),
4224 calculated_y: Some(0.0),
4225 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 2 }),
4226 ..container.children[2].clone()
4227 },
4228 Container {
4229 calculated_width: Some(20.0),
4230 calculated_height: Some(20.0),
4231 calculated_x: Some(3.75),
4232 calculated_y: Some(20.0),
4233 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 0 }),
4234 ..container.children[3].clone()
4235 },
4236 Container {
4237 calculated_width: Some(20.0),
4238 calculated_height: Some(20.0),
4239 calculated_x: Some(20.0 + 3.75 + 3.75),
4240 calculated_y: Some(20.0),
4241 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 1 }),
4242 ..container.children[4].clone()
4243 },
4244 ],
4245 ..container
4246 },
4247 );
4248 }
4249
4250 #[test_log::test]
4251 fn handle_overflow_y_expand_handles_justify_content_space_evenly_with_padding_and_wraps_elements_properly()
4252 {
4253 let mut container: Container = html! {
4254 div sx-width=(20) {}
4255 div sx-width=(20) {}
4256 div sx-width=(20) {}
4257 div sx-width=(20) {}
4258 div sx-width=(20) {}
4259 }
4260 .try_into()
4261 .unwrap();
4262
4263 container.calculated_width = Some(75.0);
4264 container.calculated_height = Some(40.0);
4265 container.calculated_padding_left = Some(20.0);
4266 container.calculated_padding_right = Some(20.0);
4267 container.direction = LayoutDirection::Row;
4268 container.overflow_x = LayoutOverflow::Wrap { grid: true };
4269 container.overflow_y = LayoutOverflow::Expand;
4270 container.justify_content = Some(JustifyContent::SpaceEvenly);
4271
4272 CALCULATOR.calc(&mut container);
4273 log::trace!("container:\n{container}");
4274
4275 compare_containers(
4276 &container.clone(),
4277 &Container {
4278 children: vec![
4279 Container {
4280 calculated_width: Some(20.0),
4281 calculated_height: Some(20.0),
4282 calculated_x: Some(3.75),
4283 calculated_y: Some(0.0),
4284 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 0 }),
4285 ..container.children[0].clone()
4286 },
4287 Container {
4288 calculated_width: Some(20.0),
4289 calculated_height: Some(20.0),
4290 calculated_x: Some(20.0 + 3.75 + 3.75),
4291 calculated_y: Some(0.0),
4292 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 1 }),
4293 ..container.children[1].clone()
4294 },
4295 Container {
4296 calculated_width: Some(20.0),
4297 calculated_height: Some(20.0),
4298 calculated_x: Some(40.0 + 3.75 + 3.75 + 3.75),
4299 calculated_y: Some(0.0),
4300 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 2 }),
4301 ..container.children[2].clone()
4302 },
4303 Container {
4304 calculated_width: Some(20.0),
4305 calculated_height: Some(20.0),
4306 calculated_x: Some(3.75),
4307 calculated_y: Some(20.0),
4308 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 0 }),
4309 ..container.children[3].clone()
4310 },
4311 Container {
4312 calculated_width: Some(20.0),
4313 calculated_height: Some(20.0),
4314 calculated_x: Some(20.0 + 3.75 + 3.75),
4315 calculated_y: Some(20.0),
4316 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 1 }),
4317 ..container.children[4].clone()
4318 },
4319 ],
4320 ..container
4321 },
4322 );
4323 }
4324
4325 #[test_log::test]
4326 fn handles_justify_content_space_evenly_and_wraps_elements_properly_with_hidden_div() {
4327 let mut container: Container = html! {
4328 div sx-width=(20) {}
4329 div sx-width=(20) {}
4330 div sx-width=(20) {}
4331 div sx-width=(20) {}
4332 div sx-width=(20) {}
4333 div sx-hidden=(true) {}
4334 }
4335 .try_into()
4336 .unwrap();
4337
4338 container.calculated_width = Some(75.0);
4339 container.calculated_height = Some(40.0);
4340 container.direction = LayoutDirection::Row;
4341 container.overflow_x = LayoutOverflow::Wrap { grid: true };
4342 container.justify_content = Some(JustifyContent::SpaceEvenly);
4343
4344 CALCULATOR.calc(&mut container);
4345 log::trace!("container:\n{container}");
4346
4347 compare_containers(
4348 &container.clone(),
4349 &Container {
4350 children: vec![
4351 Container {
4352 calculated_width: Some(20.0),
4353 calculated_height: Some(20.0),
4354 calculated_x: Some(3.75),
4355 calculated_y: Some(0.0),
4356 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 0 }),
4357 ..container.children[0].clone()
4358 },
4359 Container {
4360 calculated_width: Some(20.0),
4361 calculated_height: Some(20.0),
4362 calculated_x: Some(20.0 + 3.75 + 3.75),
4363 calculated_y: Some(0.0),
4364 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 1 }),
4365 ..container.children[1].clone()
4366 },
4367 Container {
4368 calculated_width: Some(20.0),
4369 calculated_height: Some(20.0),
4370 calculated_x: Some(40.0 + 3.75 + 3.75 + 3.75),
4371 calculated_y: Some(0.0),
4372 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 2 }),
4373 ..container.children[2].clone()
4374 },
4375 Container {
4376 calculated_width: Some(20.0),
4377 calculated_height: Some(20.0),
4378 calculated_x: Some(3.75),
4379 calculated_y: Some(20.0),
4380 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 0 }),
4381 ..container.children[3].clone()
4382 },
4383 Container {
4384 calculated_width: Some(20.0),
4385 calculated_height: Some(20.0),
4386 calculated_x: Some(20.0 + 3.75 + 3.75),
4387 calculated_y: Some(20.0),
4388 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 1 }),
4389 ..container.children[4].clone()
4390 },
4391 Container {
4392 hidden: Some(true),
4393 ..container.children[5].clone()
4394 },
4395 ],
4396 ..container
4397 },
4398 );
4399 }
4400
4401 #[test_log::test]
4402 fn handle_overflow_y_squash_handles_justify_content_space_evenly_and_wraps_elements_properly_and_can_recalc_with_new_rows()
4403 {
4404 const ROW_HEIGHT: f32 = 40.0 / 4.0;
4405
4406 let div = Container {
4407 width: Some(Number::Integer(20)),
4408 ..Default::default()
4409 };
4410
4411 let mut container = Container {
4412 children: vec![
4413 div.clone(),
4414 div.clone(),
4415 div.clone(),
4416 div.clone(),
4417 div.clone(),
4418 ],
4419 calculated_width: Some(75.0),
4420 calculated_height: Some(40.0),
4421 direction: LayoutDirection::Row,
4422 overflow_x: LayoutOverflow::Wrap { grid: true },
4423 overflow_y: LayoutOverflow::Squash,
4424 justify_content: Some(JustifyContent::SpaceEvenly),
4425 ..Default::default()
4426 };
4427
4428 log::debug!("First calc");
4429 CALCULATOR.calc(&mut container);
4430 log::trace!("first container:\n{container}");
4431
4432 container.children.extend(vec![
4433 div.clone(),
4434 div.clone(),
4435 div.clone(),
4436 div.clone(),
4437 div,
4438 ]);
4439
4440 log::debug!("Second calc");
4441 CALCULATOR.calc(&mut container);
4442 log::trace!("second container:\n{container}");
4443
4444 compare_containers(
4445 &container.clone(),
4446 &Container {
4447 children: vec![
4448 Container {
4449 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 0 }),
4450 calculated_width: Some(20.0),
4451 calculated_height: Some(10.0),
4452 calculated_x: Some(3.75),
4453 calculated_y: Some(ROW_HEIGHT * 0.0),
4454 ..container.children[0].clone()
4455 },
4456 Container {
4457 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 1 }),
4458 calculated_width: Some(20.0),
4459 calculated_height: Some(10.0),
4460 calculated_x: Some(20.0 + 3.75 + 3.75),
4461 calculated_y: Some(ROW_HEIGHT * 0.0),
4462 ..container.children[1].clone()
4463 },
4464 Container {
4465 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 2 }),
4466 calculated_width: Some(20.0),
4467 calculated_height: Some(10.0),
4468 calculated_x: Some(40.0 + 3.75 + 3.75 + 3.75),
4469 calculated_y: Some(ROW_HEIGHT * 0.0),
4470 ..container.children[2].clone()
4471 },
4472 Container {
4473 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 0 }),
4474 calculated_width: Some(20.0),
4475 calculated_height: Some(10.0),
4476 calculated_x: Some(3.75),
4477 calculated_y: Some(ROW_HEIGHT * 1.0),
4478 ..container.children[3].clone()
4479 },
4480 Container {
4481 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 1 }),
4482 calculated_width: Some(20.0),
4483 calculated_height: Some(10.0),
4484 calculated_x: Some(20.0 + 3.75 + 3.75),
4485 calculated_y: Some(ROW_HEIGHT * 1.0),
4486 ..container.children[4].clone()
4487 },
4488 Container {
4489 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 2 }),
4490 calculated_width: Some(20.0),
4491 calculated_height: Some(10.0),
4492 calculated_x: Some(40.0 + 3.75 + 3.75 + 3.75),
4493 calculated_y: Some(ROW_HEIGHT * 1.0),
4494 ..container.children[5].clone()
4495 },
4496 Container {
4497 calculated_position: Some(LayoutPosition::Wrap { row: 2, col: 0 }),
4498 calculated_width: Some(20.0),
4499 calculated_height: Some(10.0),
4500 calculated_x: Some(3.75),
4501 calculated_y: Some(ROW_HEIGHT * 2.0),
4502 ..container.children[6].clone()
4503 },
4504 Container {
4505 calculated_position: Some(LayoutPosition::Wrap { row: 2, col: 1 }),
4506 calculated_width: Some(20.0),
4507 calculated_height: Some(10.0),
4508 calculated_x: Some(20.0 + 3.75 + 3.75),
4509 calculated_y: Some(ROW_HEIGHT * 2.0),
4510 ..container.children[7].clone()
4511 },
4512 Container {
4513 calculated_position: Some(LayoutPosition::Wrap { row: 2, col: 2 }),
4514 calculated_width: Some(20.0),
4515 calculated_height: Some(10.0),
4516 calculated_x: Some(40.0 + 3.75 + 3.75 + 3.75),
4517 calculated_y: Some(ROW_HEIGHT * 2.0),
4518 ..container.children[8].clone()
4519 },
4520 Container {
4521 calculated_position: Some(LayoutPosition::Wrap { row: 3, col: 0 }),
4522 calculated_width: Some(20.0),
4523 calculated_height: Some(10.0),
4524 calculated_x: Some(3.75),
4525 calculated_y: Some(ROW_HEIGHT * 3.0),
4526 ..container.children[9].clone()
4527 },
4528 ],
4529 calculated_width: Some(75.0),
4530 calculated_height: Some(40.0),
4531 ..container
4532 },
4533 );
4534 }
4535
4536 #[test_log::test]
4537 fn handle_overflow_y_expand_handles_justify_content_space_evenly_and_wraps_elements_properly_and_can_recalc_with_new_rows()
4538 {
4539 const ROW_HEIGHT: f32 = 40.0 / 4.0;
4540
4541 let div = Container {
4542 width: Some(Number::Integer(20)),
4543 ..Default::default()
4544 };
4545
4546 let mut container = Container {
4547 children: vec![
4548 div.clone(),
4549 div.clone(),
4550 div.clone(),
4551 div.clone(),
4552 div.clone(),
4553 ],
4554 calculated_width: Some(75.0),
4555 calculated_height: Some(40.0),
4556 direction: LayoutDirection::Row,
4557 overflow_x: LayoutOverflow::Wrap { grid: true },
4558 overflow_y: LayoutOverflow::Expand,
4559 justify_content: Some(JustifyContent::SpaceEvenly),
4560 ..Default::default()
4561 };
4562
4563 log::debug!("First calc");
4564 CALCULATOR.calc(&mut container);
4565 log::trace!("first container:\n{container}");
4566
4567 container.children.extend(vec![
4568 div.clone(),
4569 div.clone(),
4570 div.clone(),
4571 div.clone(),
4572 div,
4573 ]);
4574
4575 log::debug!("Second calc");
4576 CALCULATOR.calc(&mut container);
4577 log::trace!("second container:\n{container}");
4578
4579 compare_containers(
4580 &container,
4581 &Container {
4582 children: vec![
4583 Container {
4584 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 0 }),
4585 calculated_width: Some(20.0),
4586 calculated_height: Some(ROW_HEIGHT),
4587 calculated_x: Some(3.75),
4588 calculated_y: Some(ROW_HEIGHT * 0.0),
4589 ..container.children[0].clone()
4590 },
4591 Container {
4592 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 1 }),
4593 calculated_width: Some(20.0),
4594 calculated_height: Some(ROW_HEIGHT),
4595 calculated_x: Some(20.0 + 3.75 + 3.75),
4596 calculated_y: Some(ROW_HEIGHT * 0.0),
4597 ..container.children[1].clone()
4598 },
4599 Container {
4600 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 2 }),
4601 calculated_width: Some(20.0),
4602 calculated_height: Some(ROW_HEIGHT),
4603 calculated_x: Some(40.0 + 3.75 + 3.75 + 3.75),
4604 calculated_y: Some(ROW_HEIGHT * 0.0),
4605 ..container.children[2].clone()
4606 },
4607 Container {
4608 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 0 }),
4609 calculated_width: Some(20.0),
4610 calculated_height: Some(ROW_HEIGHT),
4611 calculated_x: Some(3.75),
4612 calculated_y: Some(ROW_HEIGHT * 1.0),
4613 ..container.children[3].clone()
4614 },
4615 Container {
4616 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 1 }),
4617 calculated_width: Some(20.0),
4618 calculated_height: Some(ROW_HEIGHT),
4619 calculated_x: Some(20.0 + 3.75 + 3.75),
4620 calculated_y: Some(ROW_HEIGHT * 1.0),
4621 ..container.children[4].clone()
4622 },
4623 Container {
4624 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 2 }),
4625 calculated_width: Some(20.0),
4626 calculated_height: Some(ROW_HEIGHT),
4627 calculated_x: Some(40.0 + 3.75 + 3.75 + 3.75),
4628 calculated_y: Some(ROW_HEIGHT * 1.0),
4629 ..container.children[5].clone()
4630 },
4631 Container {
4632 calculated_position: Some(LayoutPosition::Wrap { row: 2, col: 0 }),
4633 calculated_width: Some(20.0),
4634 calculated_height: Some(ROW_HEIGHT),
4635 calculated_x: Some(3.75),
4636 calculated_y: Some(ROW_HEIGHT * 2.0),
4637 ..container.children[6].clone()
4638 },
4639 Container {
4640 calculated_position: Some(LayoutPosition::Wrap { row: 2, col: 1 }),
4641 calculated_width: Some(20.0),
4642 calculated_height: Some(ROW_HEIGHT),
4643 calculated_x: Some(20.0 + 3.75 + 3.75),
4644 calculated_y: Some(ROW_HEIGHT * 2.0),
4645 ..container.children[7].clone()
4646 },
4647 Container {
4648 calculated_position: Some(LayoutPosition::Wrap { row: 2, col: 2 }),
4649 calculated_width: Some(20.0),
4650 calculated_height: Some(ROW_HEIGHT),
4651 calculated_x: Some(40.0 + 3.75 + 3.75 + 3.75),
4652 calculated_y: Some(ROW_HEIGHT * 2.0),
4653 ..container.children[8].clone()
4654 },
4655 Container {
4656 calculated_position: Some(LayoutPosition::Wrap { row: 3, col: 0 }),
4657 calculated_width: Some(20.0),
4658 calculated_height: Some(ROW_HEIGHT),
4659 calculated_x: Some(3.75),
4660 calculated_y: Some(ROW_HEIGHT * 3.0),
4661 ..container.children[9].clone()
4662 },
4663 ],
4664 calculated_width: Some(75.0),
4665 calculated_height: Some(40.0),
4666 ..container.clone()
4667 },
4668 );
4669 }
4670
4671 #[test_log::test]
4672 fn handles_justify_content_space_evenly_with_gap_and_wraps_elements_properly() {
4673 const ROW_HEIGHT: f32 = 40.0 / 3.0;
4674
4675 let mut container = Container {
4676 children: vec![
4677 Container {
4678 width: Some(Number::Integer(20)),
4679 calculated_width: Some(20.0),
4680 calculated_height: Some(20.0),
4681 ..Default::default()
4682 },
4683 Container {
4684 width: Some(Number::Integer(20)),
4685 calculated_width: Some(20.0),
4686 calculated_height: Some(20.0),
4687 ..Default::default()
4688 },
4689 Container {
4690 width: Some(Number::Integer(20)),
4691 calculated_width: Some(20.0),
4692 calculated_height: Some(20.0),
4693 ..Default::default()
4694 },
4695 Container {
4696 width: Some(Number::Integer(20)),
4697 calculated_width: Some(20.0),
4698 calculated_height: Some(20.0),
4699 ..Default::default()
4700 },
4701 Container {
4702 width: Some(Number::Integer(20)),
4703 calculated_width: Some(20.0),
4704 calculated_height: Some(20.0),
4705 ..Default::default()
4706 },
4707 ],
4708 calculated_width: Some(75.0),
4709 calculated_height: Some(40.0),
4710 direction: LayoutDirection::Row,
4711 overflow_x: LayoutOverflow::Wrap { grid: true },
4712 overflow_y: LayoutOverflow::Expand,
4713 justify_content: Some(JustifyContent::SpaceEvenly),
4714 column_gap: Some(Number::Integer(10)),
4715 row_gap: Some(Number::Integer(10)),
4716 ..Default::default()
4717 };
4718
4719 CALCULATOR.calc(&mut container);
4720 log::trace!("container:\n{container}");
4721
4722 compare_containers(
4723 &container,
4724 &Container {
4725 children: vec![
4726 Container {
4727 calculated_width: Some(20.0),
4728 calculated_height: Some(ROW_HEIGHT),
4729 calculated_x: Some(11.666_667),
4730 calculated_y: Some(0.0),
4731 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 0 }),
4732 ..container.children[0].clone()
4733 },
4734 Container {
4735 calculated_width: Some(20.0),
4736 calculated_height: Some(ROW_HEIGHT),
4737 calculated_x: Some(43.333_336),
4738 calculated_y: Some(0.0),
4739 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 1 }),
4740 ..container.children[1].clone()
4741 },
4742 Container {
4743 calculated_width: Some(20.0),
4744 calculated_height: Some(ROW_HEIGHT),
4745 calculated_x: Some(11.666_667),
4746 calculated_y: Some(ROW_HEIGHT + 10.0),
4747 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 0 }),
4748 ..container.children[2].clone()
4749 },
4750 Container {
4751 calculated_width: Some(20.0),
4752 calculated_height: Some(ROW_HEIGHT),
4753 calculated_x: Some(43.333_336),
4754 calculated_y: Some(ROW_HEIGHT + 10.0),
4755 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 1 }),
4756 ..container.children[3].clone()
4757 },
4758 Container {
4759 calculated_width: Some(20.0),
4760 calculated_height: Some(ROW_HEIGHT),
4761 calculated_x: Some(11.666_667),
4762 calculated_y: Some(ROW_HEIGHT.mul_add(2.0, 10.0 + 10.0)),
4763 calculated_position: Some(LayoutPosition::Wrap { row: 2, col: 0 }),
4764 ..container.children[4].clone()
4765 },
4766 ],
4767 calculated_width: Some(75.0),
4768 calculated_height: Some(40.0),
4769 ..container.clone()
4770 },
4771 );
4772 }
4773
4774 #[test_log::test]
4775 fn handles_justify_content_space_evenly_with_gap_and_wraps_elements_properly_and_can_recalc() {
4776 const ROW_HEIGHT: f32 = 40.0 / 3.0;
4777
4778 let mut container = Container {
4779 children: vec![
4780 Container {
4781 width: Some(Number::Integer(20)),
4782 calculated_width: Some(20.0),
4783 calculated_height: Some(20.0),
4784 ..Default::default()
4785 },
4786 Container {
4787 width: Some(Number::Integer(20)),
4788 calculated_width: Some(20.0),
4789 calculated_height: Some(20.0),
4790 ..Default::default()
4791 },
4792 Container {
4793 width: Some(Number::Integer(20)),
4794 calculated_width: Some(20.0),
4795 calculated_height: Some(20.0),
4796 ..Default::default()
4797 },
4798 Container {
4799 width: Some(Number::Integer(20)),
4800 calculated_width: Some(20.0),
4801 calculated_height: Some(20.0),
4802 ..Default::default()
4803 },
4804 Container {
4805 width: Some(Number::Integer(20)),
4806 calculated_width: Some(20.0),
4807 calculated_height: Some(20.0),
4808 ..Default::default()
4809 },
4810 ],
4811 calculated_width: Some(75.0),
4812 calculated_height: Some(40.0),
4813 direction: LayoutDirection::Row,
4814 overflow_x: LayoutOverflow::Wrap { grid: true },
4815 overflow_y: LayoutOverflow::Expand,
4816 justify_content: Some(JustifyContent::SpaceEvenly),
4817 column_gap: Some(Number::Integer(10)),
4818 row_gap: Some(Number::Integer(10)),
4819 ..Default::default()
4820 };
4821
4822 CALCULATOR.calc(&mut container);
4823 log::trace!("first container:\n{container}");
4824
4825 let mut actual = container.clone();
4826 let expected = Container {
4827 children: vec![
4828 Container {
4829 calculated_width: Some(20.0),
4830 calculated_height: Some(ROW_HEIGHT),
4831 calculated_x: Some(11.666_667),
4832 calculated_y: Some(0.0),
4833 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 0 }),
4834 ..container.children[0].clone()
4835 },
4836 Container {
4837 calculated_width: Some(20.0),
4838 calculated_height: Some(ROW_HEIGHT),
4839 calculated_x: Some(43.333_336),
4840 calculated_y: Some(0.0),
4841 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 1 }),
4842 ..container.children[1].clone()
4843 },
4844 Container {
4845 calculated_width: Some(20.0),
4846 calculated_height: Some(ROW_HEIGHT),
4847 calculated_x: Some(11.666_667),
4848 calculated_y: Some(ROW_HEIGHT + 10.0),
4849 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 0 }),
4850 ..container.children[2].clone()
4851 },
4852 Container {
4853 calculated_width: Some(20.0),
4854 calculated_height: Some(ROW_HEIGHT),
4855 calculated_x: Some(43.333_336),
4856 calculated_y: Some(ROW_HEIGHT + 10.0),
4857 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 1 }),
4858 ..container.children[3].clone()
4859 },
4860 Container {
4861 calculated_width: Some(20.0),
4862 calculated_height: Some(ROW_HEIGHT),
4863 calculated_x: Some(11.666_667),
4864 calculated_y: Some(ROW_HEIGHT.mul_add(2.0, 10.0 + 10.0)),
4865 calculated_position: Some(LayoutPosition::Wrap { row: 2, col: 0 }),
4866 ..container.children[4].clone()
4867 },
4868 ],
4869 calculated_width: Some(75.0),
4870 calculated_height: Some(40.0),
4871 ..container
4872 };
4873
4874 compare_containers(&actual, &expected);
4875
4876 CALCULATOR.calc(&mut actual);
4877 log::trace!("second container:\n{actual}");
4878
4879 compare_containers(&actual, &expected);
4880 }
4881
4882 #[test_log::test]
4883 fn calc_child_minimum_height_is_propagated_upward() {
4884 let mut container = Container {
4885 children: vec![Container {
4886 children: vec![
4887 Container {
4888 width: Some(Number::Integer(25)),
4889 height: Some(Number::Integer(40)),
4890 ..Default::default()
4891 },
4892 Container {
4893 width: Some(Number::Integer(25)),
4894 height: Some(Number::Integer(40)),
4895 ..Default::default()
4896 },
4897 Container {
4898 width: Some(Number::Integer(25)),
4899 height: Some(Number::Integer(40)),
4900 ..Default::default()
4901 },
4902 ],
4903 ..Default::default()
4904 }],
4905 calculated_width: Some(50.0),
4906 calculated_height: Some(40.0),
4907 direction: LayoutDirection::Row,
4908 overflow_x: LayoutOverflow::Wrap { grid: true },
4909 overflow_y: LayoutOverflow::Expand,
4910 ..Default::default()
4911 };
4912
4913 CALCULATOR.calc(&mut container);
4914 log::trace!("container:\n{container}");
4915
4916 compare_containers(
4917 &container,
4918 &Container {
4919 children: vec![Container {
4920 calculated_child_min_width: Some(25.0),
4921 calculated_width: Some(25.0),
4922 calculated_height: Some(120.0),
4923 ..container.children[0].clone()
4924 }],
4925 calculated_width: Some(50.0),
4926 calculated_height: Some(40.0),
4927 direction: LayoutDirection::Row,
4928 ..container.clone()
4929 },
4930 );
4931 }
4932
4933 #[test_log::test]
4934 fn calc_child_minimum_height_is_propagated_upward_and_recalc() {
4935 let mut container = Container {
4936 children: vec![Container {
4937 children: vec![
4938 Container {
4939 width: Some(Number::Integer(25)),
4940 height: Some(Number::Integer(40)),
4941 ..Default::default()
4942 },
4943 Container {
4944 width: Some(Number::Integer(25)),
4945 height: Some(Number::Integer(40)),
4946 ..Default::default()
4947 },
4948 Container {
4949 width: Some(Number::Integer(25)),
4950 height: Some(Number::Integer(40)),
4951 ..Default::default()
4952 },
4953 ],
4954 ..Default::default()
4955 }],
4956 calculated_width: Some(50.0),
4957 calculated_height: Some(40.0),
4958 direction: LayoutDirection::Row,
4959 overflow_x: LayoutOverflow::Wrap { grid: true },
4960 overflow_y: LayoutOverflow::Expand,
4961 ..Default::default()
4962 };
4963
4964 CALCULATOR.calc(&mut container);
4965 log::trace!("first container:\n{container}");
4966
4967 CALCULATOR.calc(&mut container);
4968 log::trace!("second container:\n{container}");
4969
4970 compare_containers(
4971 &container,
4972 &Container {
4973 children: vec![Container {
4974 calculated_child_min_width: Some(25.0),
4975 calculated_width: Some(25.0),
4976 calculated_height: Some(120.0),
4977 ..container.children[0].clone()
4978 }],
4979 calculated_width: Some(50.0),
4980 calculated_height: Some(40.0),
4981 direction: LayoutDirection::Row,
4982 ..container.clone()
4983 },
4984 );
4985 }
4986
4987 #[test_log::test]
4988 fn calc_resizes_when_a_new_row_was_shifted_into_view() {
4989 let mut container = Container {
4990 children: vec![
4991 Container {
4992 width: Some(Number::Integer(25)),
4993 height: Some(Number::Integer(40)),
4994 ..Default::default()
4995 },
4996 Container {
4997 width: Some(Number::Integer(25)),
4998 height: Some(Number::Integer(40)),
4999 ..Default::default()
5000 },
5001 Container {
5002 width: Some(Number::Integer(25)),
5003 height: Some(Number::Integer(40)),
5004 ..Default::default()
5005 },
5006 ],
5007 calculated_width: Some(50.0),
5008 calculated_height: Some(40.0),
5009 direction: LayoutDirection::Row,
5010 overflow_x: LayoutOverflow::Wrap { grid: true },
5011 overflow_y: LayoutOverflow::Squash,
5012 ..Default::default()
5013 };
5014
5015 CALCULATOR.calc(&mut container);
5016 log::trace!("container:\n{container}");
5017
5018 compare_containers(
5019 &container,
5020 &Container {
5021 children: vec![
5022 Container {
5023 calculated_height: Some(40.0),
5024 ..container.children[0].clone()
5025 },
5026 Container {
5027 calculated_height: Some(40.0),
5028 ..container.children[1].clone()
5029 },
5030 Container {
5031 calculated_height: Some(40.0),
5032 ..container.children[2].clone()
5033 },
5034 ],
5035 ..container.clone()
5036 },
5037 );
5038 }
5039
5040 #[test_log::test]
5041 fn calc_allows_expanding_height_for_overflow_y_scroll() {
5042 let mut container = Container {
5043 children: vec![
5044 Container {
5045 width: Some(Number::Integer(25)),
5046 height: Some(Number::Integer(40)),
5047 ..Default::default()
5048 },
5049 Container {
5050 width: Some(Number::Integer(25)),
5051 height: Some(Number::Integer(40)),
5052 ..Default::default()
5053 },
5054 Container {
5055 width: Some(Number::Integer(25)),
5056 height: Some(Number::Integer(40)),
5057 ..Default::default()
5058 },
5059 ],
5060 calculated_width: Some(50.0 + f32::from(get_scrollbar_size())),
5061 calculated_height: Some(40.0),
5062 direction: LayoutDirection::Row,
5063 overflow_x: LayoutOverflow::Wrap { grid: true },
5064 overflow_y: LayoutOverflow::Scroll,
5065 ..Default::default()
5066 };
5067
5068 CALCULATOR.calc(&mut container);
5069 log::trace!("container:\n{container}");
5070
5071 compare_containers(
5072 &container,
5073 &Container {
5074 children: vec![
5075 Container {
5076 calculated_height: Some(40.0),
5077 ..container.children[0].clone()
5078 },
5079 Container {
5080 calculated_height: Some(40.0),
5081 ..container.children[1].clone()
5082 },
5083 Container {
5084 calculated_height: Some(40.0),
5085 ..container.children[2].clone()
5086 },
5087 ],
5088 ..container.clone()
5089 },
5090 );
5091 }
5092
5093 #[test_log::test]
5094 fn handle_overflow_wraps_single_row_overflow_content_correctly() {
5095 let mut container = Container {
5096 children: vec![
5097 Container {
5098 width: Some(Number::Integer(25)),
5099 height: Some(Number::Integer(40)),
5100 ..Default::default()
5101 },
5102 Container {
5103 width: Some(Number::Integer(25)),
5104 height: Some(Number::Integer(40)),
5105 ..Default::default()
5106 },
5107 Container {
5108 width: Some(Number::Integer(25)),
5109 height: Some(Number::Integer(40)),
5110 ..Default::default()
5111 },
5112 ],
5113 calculated_width: Some(50.0),
5114 calculated_height: Some(40.0),
5115 direction: LayoutDirection::Row,
5116 overflow_x: LayoutOverflow::Wrap { grid: true },
5117 overflow_y: LayoutOverflow::Squash,
5118 ..Default::default()
5119 };
5120
5121 CALCULATOR.calc(&mut container);
5122 log::trace!("container:\n{container}");
5123
5124 compare_containers(
5125 &container,
5126 &Container {
5127 children: vec![
5128 Container {
5129 calculated_width: Some(25.0),
5130 calculated_height: Some(40.0),
5131 calculated_x: Some(0.0),
5132 calculated_y: Some(0.0),
5133 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 0 }),
5134 ..container.children[0].clone()
5135 },
5136 Container {
5137 calculated_width: Some(25.0),
5138 calculated_height: Some(40.0),
5139 calculated_x: Some(25.0),
5140 calculated_y: Some(0.0),
5141 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 1 }),
5142 ..container.children[1].clone()
5143 },
5144 Container {
5145 calculated_width: Some(25.0),
5146 calculated_height: Some(40.0),
5147 calculated_x: Some(0.0),
5148 calculated_y: Some(40.0),
5149 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 0 }),
5150 ..container.children[2].clone()
5151 },
5152 ],
5153 ..container.clone()
5154 },
5155 );
5156 }
5157
5158 #[test_log::test]
5159 fn handle_overflow_wraps_multi_row_overflow_content_correctly() {
5160 const ROW_HEIGHT: f32 = 40.0;
5161
5162 let mut container = Container {
5163 children: vec![
5164 Container {
5165 width: Some(Number::Integer(25)),
5166 height: Some(Number::Integer(40)),
5167 ..Default::default()
5168 },
5169 Container {
5170 width: Some(Number::Integer(25)),
5171 height: Some(Number::Integer(40)),
5172 ..Default::default()
5173 },
5174 Container {
5175 width: Some(Number::Integer(25)),
5176 height: Some(Number::Integer(40)),
5177 ..Default::default()
5178 },
5179 Container {
5180 width: Some(Number::Integer(25)),
5181 height: Some(Number::Integer(40)),
5182 ..Default::default()
5183 },
5184 Container {
5185 width: Some(Number::Integer(25)),
5186 height: Some(Number::Integer(40)),
5187 ..Default::default()
5188 },
5189 ],
5190 calculated_width: Some(50.0),
5191 calculated_height: Some(40.0),
5192 direction: LayoutDirection::Row,
5193 overflow_x: LayoutOverflow::Wrap { grid: true },
5194 overflow_y: LayoutOverflow::Squash,
5195 ..Default::default()
5196 };
5197
5198 CALCULATOR.calc(&mut container);
5199 log::trace!("container:\n{container}");
5200
5201 compare_containers(
5202 &container,
5203 &Container {
5204 children: vec![
5205 Container {
5206 calculated_width: Some(25.0),
5207 calculated_height: Some(ROW_HEIGHT),
5208 calculated_x: Some(0.0),
5209 calculated_y: Some(0.0),
5210 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 0 }),
5211 ..container.children[0].clone()
5212 },
5213 Container {
5214 calculated_width: Some(25.0),
5215 calculated_height: Some(ROW_HEIGHT),
5216 calculated_x: Some(25.0),
5217 calculated_y: Some(0.0),
5218 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 1 }),
5219 ..container.children[1].clone()
5220 },
5221 Container {
5222 calculated_width: Some(25.0),
5223 calculated_height: Some(ROW_HEIGHT),
5224 calculated_x: Some(0.0),
5225 calculated_y: Some(ROW_HEIGHT),
5226 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 0 }),
5227 ..container.children[2].clone()
5228 },
5229 Container {
5230 calculated_width: Some(25.0),
5231 calculated_height: Some(ROW_HEIGHT),
5232 calculated_x: Some(25.0),
5233 calculated_y: Some(ROW_HEIGHT),
5234 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 1 }),
5235 ..container.children[3].clone()
5236 },
5237 Container {
5238 calculated_width: Some(25.0),
5239 calculated_height: Some(ROW_HEIGHT),
5240 calculated_x: Some(0.0),
5241 calculated_y: Some(ROW_HEIGHT * 2.0),
5242 calculated_position: Some(LayoutPosition::Wrap { row: 2, col: 0 }),
5243 ..container.children[4].clone()
5244 },
5245 ],
5246 ..container.clone()
5247 },
5248 );
5249 }
5250
5251 #[test_log::test]
5252 fn handle_overflow_wraps_row_content_correctly_in_overflow_y_scroll() {
5253 let mut container = Container {
5254 children: vec![
5255 Container {
5256 width: Some(Number::Integer(25)),
5257 height: Some(Number::Integer(40)),
5258 ..Default::default()
5259 },
5260 Container {
5261 width: Some(Number::Integer(25)),
5262 height: Some(Number::Integer(40)),
5263 ..Default::default()
5264 },
5265 Container {
5266 width: Some(Number::Integer(25)),
5267 height: Some(Number::Integer(40)),
5268 ..Default::default()
5269 },
5270 ],
5271 calculated_width: Some(50.0 + f32::from(get_scrollbar_size())),
5272 calculated_height: Some(80.0),
5273 direction: LayoutDirection::Row,
5274 overflow_x: LayoutOverflow::Wrap { grid: true },
5275 overflow_y: LayoutOverflow::Scroll,
5276 ..Default::default()
5277 };
5278
5279 CALCULATOR.calc(&mut container);
5280 log::trace!("container:\n{container}");
5281
5282 compare_containers(
5283 &container.clone(),
5284 &Container {
5285 children: vec![
5286 Container {
5287 calculated_width: Some(25.0),
5288 calculated_height: Some(40.0),
5289 calculated_x: Some(0.0),
5290 calculated_y: Some(0.0),
5291 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 0 }),
5292 ..container.children[0].clone()
5293 },
5294 Container {
5295 calculated_width: Some(25.0),
5296 calculated_height: Some(40.0),
5297 calculated_x: Some(25.0),
5298 calculated_y: Some(0.0),
5299 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 1 }),
5300 ..container.children[1].clone()
5301 },
5302 Container {
5303 calculated_width: Some(25.0),
5304 calculated_height: Some(40.0),
5305 calculated_x: Some(0.0),
5306 calculated_y: Some(40.0),
5307 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 0 }),
5308 ..container.children[2].clone()
5309 },
5310 ],
5311 ..container
5312 },
5313 );
5314 }
5315
5316 #[test_log::test]
5317 fn calc_inner_wraps_row_content_correctly() {
5318 let mut container = Container {
5319 children: vec![
5320 Container {
5321 width: Some(Number::Integer(25)),
5322 ..Default::default()
5323 },
5324 Container {
5325 width: Some(Number::Integer(25)),
5326 ..Default::default()
5327 },
5328 Container {
5329 width: Some(Number::Integer(25)),
5330 ..Default::default()
5331 },
5332 ],
5333 calculated_width: Some(50.0),
5334 calculated_height: Some(40.0),
5335 direction: LayoutDirection::Row,
5336 overflow_x: LayoutOverflow::Wrap { grid: true },
5337 overflow_y: LayoutOverflow::Squash,
5338 ..Default::default()
5339 };
5340 CALCULATOR.calc(&mut container);
5341 log::trace!("container:\n{container}");
5342
5343 compare_containers(
5344 &container,
5345 &Container {
5346 children: vec![
5347 Container {
5348 width: Some(Number::Integer(25)),
5349 calculated_width: Some(25.0),
5350 calculated_height: Some(20.0),
5351 calculated_x: Some(0.0),
5352 calculated_y: Some(0.0),
5353 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 0 }),
5354 ..container.children[0].clone()
5355 },
5356 Container {
5357 width: Some(Number::Integer(25)),
5358 calculated_width: Some(25.0),
5359 calculated_height: Some(20.0),
5360 calculated_x: Some(25.0),
5361 calculated_y: Some(0.0),
5362 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 1 }),
5363 ..container.children[1].clone()
5364 },
5365 Container {
5366 width: Some(Number::Integer(25)),
5367 calculated_width: Some(25.0),
5368 calculated_height: Some(20.0),
5369 calculated_x: Some(0.0),
5370 calculated_y: Some(20.0),
5371 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 0 }),
5372 ..container.children[2].clone()
5373 },
5374 ],
5375 ..container.clone()
5376 },
5377 );
5378 }
5379
5380 #[test_log::test]
5381 fn calc_inner_children_overflow_squash_wraps_row_content_with_nested_width_correctly() {
5382 let mut container = Container {
5383 children: vec![
5384 Container {
5385 children: vec![Container {
5386 width: Some(Number::Integer(25)),
5387 ..Default::default()
5388 }],
5389 overflow_x: LayoutOverflow::Squash,
5390 overflow_y: LayoutOverflow::Squash,
5391 justify_content: Some(JustifyContent::Start),
5392 ..Default::default()
5393 },
5394 Container {
5395 children: vec![Container {
5396 width: Some(Number::Integer(25)),
5397 ..Default::default()
5398 }],
5399 overflow_x: LayoutOverflow::Squash,
5400 overflow_y: LayoutOverflow::Squash,
5401 justify_content: Some(JustifyContent::Start),
5402 ..Default::default()
5403 },
5404 Container {
5405 children: vec![Container {
5406 width: Some(Number::Integer(25)),
5407 ..Default::default()
5408 }],
5409 overflow_x: LayoutOverflow::Squash,
5410 overflow_y: LayoutOverflow::Squash,
5411 justify_content: Some(JustifyContent::Start),
5412 ..Default::default()
5413 },
5414 ],
5415 calculated_width: Some(50.0),
5416 calculated_height: Some(40.0),
5417 direction: LayoutDirection::Row,
5418 overflow_x: LayoutOverflow::Wrap { grid: true },
5419 overflow_y: LayoutOverflow::Squash,
5420 justify_content: Some(JustifyContent::Start),
5421 ..Default::default()
5422 };
5423 CALCULATOR.calc(&mut container);
5424 log::trace!("container:\n{container}");
5425
5426 compare_containers(
5427 &container.clone(),
5428 &Container {
5429 children: vec![
5430 Container {
5431 children: vec![Container {
5432 calculated_width: Some(25.0),
5433 calculated_height: Some(0.0),
5434 calculated_x: Some(0.0),
5435 calculated_y: Some(0.0),
5436 calculated_position: Some(LayoutPosition::default()),
5437 ..container.children[0].children[0].clone()
5438 }],
5439 calculated_width: Some(25.0),
5440 calculated_height: Some(20.0),
5441 calculated_x: Some(0.0),
5442 calculated_y: Some(0.0),
5443 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 0 }),
5444 ..container.children[0].clone()
5445 },
5446 Container {
5447 children: vec![Container {
5448 width: Some(Number::Integer(25)),
5449 calculated_width: Some(25.0),
5450 calculated_height: Some(0.0),
5451 calculated_x: Some(0.0),
5452 calculated_y: Some(0.0),
5453 calculated_position: Some(LayoutPosition::default()),
5454 ..container.children[1].children[0].clone()
5455 }],
5456 calculated_width: Some(25.0),
5457 calculated_height: Some(20.0),
5458 calculated_x: Some(25.0),
5459 calculated_y: Some(0.0),
5460 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 1 }),
5461 ..container.children[1].clone()
5462 },
5463 Container {
5464 children: vec![Container {
5465 width: Some(Number::Integer(25)),
5466 calculated_width: Some(25.0),
5467 calculated_height: Some(0.0),
5468 calculated_x: Some(0.0),
5469 calculated_y: Some(0.0),
5470 calculated_position: Some(LayoutPosition::default()),
5471 ..container.children[2].children[0].clone()
5472 }],
5473 calculated_width: Some(25.0),
5474 calculated_height: Some(20.0),
5475 calculated_x: Some(0.0),
5476 calculated_y: Some(20.0),
5477 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 0 }),
5478 ..container.children[2].clone()
5479 },
5480 ],
5481 ..container
5482 },
5483 );
5484 }
5485
5486 #[test_log::test]
5487 fn calc_inner_children_overflow_expand_wraps_row_content_with_nested_width_correctly() {
5488 let mut container = Container {
5489 children: vec![
5490 Container {
5491 children: vec![Container {
5492 width: Some(Number::Integer(25)),
5493 ..Default::default()
5494 }],
5495 overflow_x: LayoutOverflow::Expand,
5496 overflow_y: LayoutOverflow::Expand,
5497 justify_content: Some(JustifyContent::Start),
5498 ..Default::default()
5499 },
5500 Container {
5501 children: vec![Container {
5502 width: Some(Number::Integer(25)),
5503 ..Default::default()
5504 }],
5505 overflow_x: LayoutOverflow::Expand,
5506 overflow_y: LayoutOverflow::Expand,
5507 justify_content: Some(JustifyContent::Start),
5508 ..Default::default()
5509 },
5510 Container {
5511 children: vec![Container {
5512 width: Some(Number::Integer(25)),
5513 ..Default::default()
5514 }],
5515 overflow_x: LayoutOverflow::Expand,
5516 overflow_y: LayoutOverflow::Expand,
5517 justify_content: Some(JustifyContent::Start),
5518 ..Default::default()
5519 },
5520 ],
5521 calculated_width: Some(50.0),
5522 calculated_height: Some(40.0),
5523 direction: LayoutDirection::Row,
5524 overflow_x: LayoutOverflow::Wrap { grid: true },
5525 overflow_y: LayoutOverflow::Squash,
5526 justify_content: Some(JustifyContent::Start),
5527 ..Default::default()
5528 };
5529
5530 CALCULATOR.calc(&mut container);
5531 log::trace!("container:\n{container}");
5532
5533 compare_containers(
5534 &container.clone(),
5535 &Container {
5536 children: vec![
5537 Container {
5538 children: vec![Container {
5539 width: Some(Number::Integer(25)),
5540 calculated_width: Some(25.0),
5541 calculated_height: Some(0.0),
5542 calculated_x: Some(0.0),
5543 calculated_y: Some(0.0),
5544 calculated_position: Some(LayoutPosition::default()),
5545 ..container.children[0].children[0].clone()
5546 }],
5547 calculated_width: Some(25.0),
5548 calculated_height: Some(20.0),
5549 calculated_x: Some(0.0),
5550 calculated_y: Some(0.0),
5551 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 0 }),
5552 ..container.children[0].clone()
5553 },
5554 Container {
5555 children: vec![Container {
5556 width: Some(Number::Integer(25)),
5557 calculated_width: Some(25.0),
5558 calculated_height: Some(0.0),
5559 calculated_x: Some(0.0),
5560 calculated_y: Some(0.0),
5561 calculated_position: Some(LayoutPosition::default()),
5562 ..container.children[1].children[0].clone()
5563 }],
5564 calculated_width: Some(25.0),
5565 calculated_height: Some(20.0),
5566 calculated_x: Some(25.0),
5567 calculated_y: Some(0.0),
5568 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 1 }),
5569 ..container.children[1].clone()
5570 },
5571 Container {
5572 children: vec![Container {
5573 width: Some(Number::Integer(25)),
5574 calculated_width: Some(25.0),
5575 calculated_height: Some(0.0),
5576 calculated_x: Some(0.0),
5577 calculated_y: Some(0.0),
5578 calculated_position: Some(LayoutPosition::default()),
5579 ..container.children[2].children[0].clone()
5580 }],
5581 calculated_width: Some(25.0),
5582 calculated_height: Some(20.0),
5583 calculated_x: Some(0.0),
5584 calculated_y: Some(20.0),
5585 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 0 }),
5586 ..container.children[2].clone()
5587 },
5588 ],
5589 ..container
5590 },
5591 );
5592 }
5593
5594 #[test_log::test]
5595 fn calc_inner_children_overflow_squash_wraps_row_content_with_nested_explicit_width_correctly()
5596 {
5597 let mut container = Container {
5598 children: vec![
5599 Container {
5600 width: Some(Number::Integer(25)),
5601 children: vec![Container {
5602 width: Some(Number::Integer(25)),
5603 ..Default::default()
5604 }],
5605 overflow_x: LayoutOverflow::Squash,
5606 overflow_y: LayoutOverflow::Squash,
5607 justify_content: Some(JustifyContent::Start),
5608 ..Default::default()
5609 },
5610 Container {
5611 width: Some(Number::Integer(25)),
5612 children: vec![Container {
5613 width: Some(Number::Integer(25)),
5614 ..Default::default()
5615 }],
5616 overflow_x: LayoutOverflow::Squash,
5617 overflow_y: LayoutOverflow::Squash,
5618 justify_content: Some(JustifyContent::Start),
5619 ..Default::default()
5620 },
5621 Container {
5622 width: Some(Number::Integer(25)),
5623 children: vec![Container {
5624 width: Some(Number::Integer(25)),
5625 ..Default::default()
5626 }],
5627 overflow_x: LayoutOverflow::Squash,
5628 overflow_y: LayoutOverflow::Squash,
5629 justify_content: Some(JustifyContent::Start),
5630 ..Default::default()
5631 },
5632 ],
5633 calculated_width: Some(50.0),
5634 calculated_height: Some(40.0),
5635 direction: LayoutDirection::Row,
5636 overflow_x: LayoutOverflow::Wrap { grid: true },
5637 overflow_y: LayoutOverflow::Squash,
5638 justify_content: Some(JustifyContent::Start),
5639 ..Default::default()
5640 };
5641 CALCULATOR.calc(&mut container);
5642 log::trace!("container:\n{container}");
5643
5644 compare_containers(
5645 &container.clone(),
5646 &Container {
5647 children: vec![
5648 Container {
5649 width: Some(Number::Integer(25)),
5650 children: vec![Container {
5651 width: Some(Number::Integer(25)),
5652 calculated_width: Some(25.0),
5653 calculated_height: Some(0.0),
5654 calculated_x: Some(0.0),
5655 calculated_y: Some(0.0),
5656 calculated_position: Some(LayoutPosition::default()),
5657 ..container.children[0].children[0].clone()
5658 }],
5659 calculated_width: Some(25.0),
5660 calculated_height: Some(20.0),
5661 calculated_x: Some(0.0),
5662 calculated_y: Some(0.0),
5663 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 0 }),
5664 ..container.children[0].clone()
5665 },
5666 Container {
5667 width: Some(Number::Integer(25)),
5668 children: vec![Container {
5669 width: Some(Number::Integer(25)),
5670 calculated_width: Some(25.0),
5671 calculated_height: Some(0.0),
5672 calculated_x: Some(0.0),
5673 calculated_y: Some(0.0),
5674 calculated_position: Some(LayoutPosition::default()),
5675 ..container.children[1].children[0].clone()
5676 }],
5677 calculated_width: Some(25.0),
5678 calculated_height: Some(20.0),
5679 calculated_x: Some(25.0),
5680 calculated_y: Some(0.0),
5681 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 1 }),
5682 ..container.children[1].clone()
5683 },
5684 Container {
5685 width: Some(Number::Integer(25)),
5686 children: vec![Container {
5687 width: Some(Number::Integer(25)),
5688 calculated_width: Some(25.0),
5689 calculated_height: Some(0.0),
5690 calculated_x: Some(0.0),
5691 calculated_y: Some(0.0),
5692 calculated_position: Some(LayoutPosition::default()),
5693 ..container.children[2].children[0].clone()
5694 }],
5695 calculated_width: Some(25.0),
5696 calculated_height: Some(20.0),
5697 calculated_x: Some(0.0),
5698 calculated_y: Some(20.0),
5699 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 0 }),
5700 ..container.children[2].clone()
5701 },
5702 ],
5703 ..container
5704 },
5705 );
5706 }
5707
5708 #[test_log::test]
5709 fn calc_inner_children_overflow_expand_wraps_row_content_with_nested_explicit_width_correctly()
5710 {
5711 let mut container = Container {
5712 children: vec![
5713 Container {
5714 width: Some(Number::Integer(25)),
5715 children: vec![Container {
5716 width: Some(Number::Integer(25)),
5717 ..Default::default()
5718 }],
5719 overflow_x: LayoutOverflow::Expand,
5720 overflow_y: LayoutOverflow::Expand,
5721 justify_content: Some(JustifyContent::Start),
5722 ..Default::default()
5723 },
5724 Container {
5725 width: Some(Number::Integer(25)),
5726 children: vec![Container {
5727 width: Some(Number::Integer(25)),
5728 ..Default::default()
5729 }],
5730 overflow_x: LayoutOverflow::Expand,
5731 overflow_y: LayoutOverflow::Expand,
5732 justify_content: Some(JustifyContent::Start),
5733 ..Default::default()
5734 },
5735 Container {
5736 width: Some(Number::Integer(25)),
5737 children: vec![Container {
5738 width: Some(Number::Integer(25)),
5739 ..Default::default()
5740 }],
5741 overflow_x: LayoutOverflow::Expand,
5742 overflow_y: LayoutOverflow::Expand,
5743 justify_content: Some(JustifyContent::Start),
5744 ..Default::default()
5745 },
5746 ],
5747 calculated_width: Some(50.0),
5748 calculated_height: Some(40.0),
5749 direction: LayoutDirection::Row,
5750 overflow_x: LayoutOverflow::Wrap { grid: true },
5751 overflow_y: LayoutOverflow::Squash,
5752 justify_content: Some(JustifyContent::Start),
5753 ..Default::default()
5754 };
5755 CALCULATOR.calc(&mut container);
5756 log::trace!("container:\n{container}");
5757
5758 compare_containers(
5759 &container.clone(),
5760 &Container {
5761 children: vec![
5762 Container {
5763 width: Some(Number::Integer(25)),
5764 children: vec![Container {
5765 width: Some(Number::Integer(25)),
5766 calculated_width: Some(25.0),
5767 calculated_height: Some(0.0),
5768 calculated_x: Some(0.0),
5769 calculated_y: Some(0.0),
5770 calculated_position: Some(LayoutPosition::default()),
5771 ..container.children[0].children[0].clone()
5772 }],
5773 calculated_width: Some(25.0),
5774 calculated_height: Some(20.0),
5775 calculated_x: Some(0.0),
5776 calculated_y: Some(0.0),
5777 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 0 }),
5778 ..container.children[0].clone()
5779 },
5780 Container {
5781 width: Some(Number::Integer(25)),
5782 children: vec![Container {
5783 width: Some(Number::Integer(25)),
5784 calculated_width: Some(25.0),
5785 calculated_height: Some(0.0),
5786 calculated_x: Some(0.0),
5787 calculated_y: Some(0.0),
5788 calculated_position: Some(LayoutPosition::default()),
5789 ..container.children[1].children[0].clone()
5790 }],
5791 calculated_width: Some(25.0),
5792 calculated_height: Some(20.0),
5793 calculated_x: Some(25.0),
5794 calculated_y: Some(0.0),
5795 calculated_position: Some(LayoutPosition::Wrap { row: 0, col: 1 }),
5796 ..container.children[1].clone()
5797 },
5798 Container {
5799 width: Some(Number::Integer(25)),
5800 children: vec![Container {
5801 width: Some(Number::Integer(25)),
5802 calculated_width: Some(25.0),
5803 calculated_height: Some(0.0),
5804 calculated_x: Some(0.0),
5805 calculated_y: Some(0.0),
5806 calculated_position: Some(LayoutPosition::default()),
5807 ..container.children[2].children[0].clone()
5808 }],
5809 calculated_width: Some(25.0),
5810 calculated_height: Some(20.0),
5811 calculated_x: Some(0.0),
5812 calculated_y: Some(20.0),
5813 calculated_position: Some(LayoutPosition::Wrap { row: 1, col: 0 }),
5814 ..container.children[2].clone()
5815 },
5816 ],
5817 ..container
5818 },
5819 );
5820 }
5821
5822 #[test_log::test]
5823 fn calc_can_calc_horizontal_split_with_row_content_in_right_pane_above_a_vertial_split() {
5824 let mut container = Container {
5825 children: vec![
5826 Container {
5827 children: vec![
5828 Container::default(),
5829 Container {
5830 children: vec![Container::default(), Container::default()],
5831 direction: LayoutDirection::Row,
5832 justify_content: Some(JustifyContent::Start),
5833 ..Default::default()
5834 },
5835 ],
5836 direction: LayoutDirection::Row,
5837 justify_content: Some(JustifyContent::Start),
5838 ..Default::default()
5839 },
5840 Container::default(),
5841 ],
5842 calculated_width: Some(100.0),
5843 calculated_height: Some(40.0),
5844 justify_content: Some(JustifyContent::Start),
5845 ..Default::default()
5846 };
5847 CALCULATOR.calc(&mut container);
5848 log::trace!("container:\n{container}");
5849
5850 compare_containers(
5851 &container,
5852 &Container {
5853 children: vec![
5854 Container {
5855 children: vec![
5856 Container {
5857 calculated_width: Some(0.0),
5858 calculated_height: Some(0.0),
5859 calculated_x: Some(0.0),
5860 calculated_y: Some(0.0),
5861 calculated_position: Some(LayoutPosition::Default),
5862 ..container.children[0].children[0].clone()
5863 },
5864 Container {
5865 calculated_width: Some(0.0),
5866 calculated_height: Some(0.0),
5867 calculated_x: Some(0.0),
5868 calculated_y: Some(0.0),
5869 calculated_position: Some(LayoutPosition::Default),
5870 direction: LayoutDirection::Row,
5871 children: vec![
5872 Container {
5873 calculated_width: Some(0.0),
5874 calculated_height: Some(0.0),
5875 calculated_x: Some(0.0),
5876 calculated_y: Some(0.0),
5877 calculated_position: Some(LayoutPosition::Default),
5878 ..container.children[0].children[1].children[0].clone()
5879 },
5880 Container {
5881 calculated_width: Some(0.0),
5882 calculated_height: Some(0.0),
5883 calculated_x: Some(0.0),
5884 calculated_y: Some(0.0),
5885 calculated_position: Some(LayoutPosition::Default),
5886 ..container.children[0].children[1].children[1].clone()
5887 },
5888 ],
5889 ..container.children[0].children[1].clone()
5890 },
5891 ],
5892 calculated_width: Some(100.0),
5893 calculated_height: Some(0.0),
5894 calculated_x: Some(0.0),
5895 calculated_y: Some(0.0),
5896 calculated_position: Some(LayoutPosition::Default),
5897 direction: LayoutDirection::Row,
5898 ..container.children[0].clone()
5899 },
5900 Container {
5901 calculated_width: Some(100.0),
5902 calculated_height: Some(0.0),
5903 calculated_x: Some(0.0),
5904 calculated_y: Some(0.0),
5905 calculated_position: Some(LayoutPosition::Default),
5906 ..container.children[1].clone()
5907 },
5908 ],
5909 ..container.clone()
5910 },
5911 );
5912 }
5913
5914 #[test_log::test]
5915 fn calc_can_calc_horizontal_split_with_row_content_in_right_pane_above_a_vertial_split_with_a_specified_height()
5916 {
5917 let mut container = Container {
5918 children: vec![
5919 Container {
5920 children: vec![
5921 Container::default(),
5922 Container {
5923 children: vec![Container::default(), Container::default()],
5924 direction: LayoutDirection::Row,
5925 justify_content: Some(JustifyContent::Start),
5926 ..Default::default()
5927 },
5928 ],
5929 direction: LayoutDirection::Row,
5930 justify_content: Some(JustifyContent::Start),
5931 ..Default::default()
5932 },
5933 Container {
5934 height: Some(Number::Integer(10)),
5935 ..Default::default()
5936 },
5937 ],
5938 calculated_width: Some(100.0),
5939 calculated_height: Some(80.0),
5940 justify_content: Some(JustifyContent::Start),
5941 ..Default::default()
5942 };
5943 CALCULATOR.calc(&mut container);
5944 log::trace!("container:\n{container}");
5945
5946 compare_containers(
5947 &container.clone(),
5948 &Container {
5949 children: vec![
5950 Container {
5951 children: vec![
5952 Container {
5953 calculated_width: Some(0.0),
5954 calculated_height: Some(0.0),
5955 calculated_x: Some(0.0),
5956 calculated_y: Some(0.0),
5957 calculated_position: Some(LayoutPosition::Default),
5958 ..container.children[0].children[0].clone()
5959 },
5960 Container {
5961 calculated_width: Some(0.0),
5962 calculated_height: Some(0.0),
5963 calculated_x: Some(0.0),
5964 calculated_y: Some(0.0),
5965 calculated_position: Some(LayoutPosition::Default),
5966 direction: LayoutDirection::Row,
5967 children: vec![
5968 Container {
5969 calculated_width: Some(0.0),
5970 calculated_height: Some(0.0),
5971 calculated_x: Some(0.0),
5972 calculated_y: Some(0.0),
5973 calculated_position: Some(LayoutPosition::Default),
5974 ..container.children[0].children[1].children[0].clone()
5975 },
5976 Container {
5977 calculated_width: Some(0.0),
5978 calculated_height: Some(0.0),
5979 calculated_x: Some(0.0),
5980 calculated_y: Some(0.0),
5981 calculated_position: Some(LayoutPosition::Default),
5982 ..container.children[0].children[1].children[1].clone()
5983 },
5984 ],
5985 ..container.children[0].children[1].clone()
5986 },
5987 ],
5988 calculated_width: Some(100.0),
5989 calculated_height: Some(0.0),
5990 calculated_x: Some(0.0),
5991 calculated_y: Some(0.0),
5992 calculated_position: Some(LayoutPosition::Default),
5993 direction: LayoutDirection::Row,
5994 ..container.children[0].clone()
5995 },
5996 Container {
5997 height: Some(Number::Integer(10)),
5998 calculated_width: Some(100.0),
5999 calculated_height: Some(10.0),
6000 calculated_x: Some(0.0),
6001 calculated_y: Some(0.0),
6002 calculated_position: Some(LayoutPosition::Default),
6003 ..container.children[1].clone()
6004 },
6005 ],
6006 ..container
6007 },
6008 );
6009 }
6010
6011 #[test_log::test]
6012 fn calc_can_calc_absolute_positioned_element_on_top_of_a_relative_element() {
6013 let mut container = Container {
6014 children: vec![
6015 Container::default(),
6016 Container {
6017 position: Some(Position::Absolute),
6018 ..Default::default()
6019 },
6020 ],
6021 calculated_width: Some(100.0),
6022 calculated_height: Some(50.0),
6023 position: Some(Position::Relative),
6024 justify_content: Some(JustifyContent::Start),
6025 ..Default::default()
6026 };
6027 CALCULATOR.calc(&mut container);
6028 log::trace!("container:\n{container}");
6029
6030 compare_containers(
6031 &container,
6032 &Container {
6033 children: vec![
6034 Container {
6035 calculated_width: Some(100.0),
6036 calculated_x: Some(0.0),
6037 calculated_position: Some(LayoutPosition::Default),
6038 ..container.children[0].clone()
6039 },
6040 Container {
6041 calculated_width: Some(100.0),
6042 calculated_height: Some(50.0),
6043 calculated_x: Some(0.0),
6044 calculated_y: Some(0.0),
6045 position: Some(Position::Absolute),
6046 ..container.children[1].clone()
6047 },
6048 ],
6049 ..container.clone()
6050 },
6051 );
6052 }
6053
6054 #[test_log::test]
6055 fn calc_can_calc_absolute_positioned_element_nested_on_top_of_a_relative_element_with_left_offset()
6056 {
6057 let mut container = Container {
6058 children: vec![Container {
6059 children: vec![
6060 Container::default(),
6061 Container {
6062 left: Some(Number::Integer(30)),
6063 position: Some(Position::Absolute),
6064 ..Default::default()
6065 },
6066 ],
6067 justify_content: Some(JustifyContent::Start),
6068 ..Default::default()
6069 }],
6070 calculated_width: Some(100.0),
6071 calculated_height: Some(50.0),
6072 position: Some(Position::Relative),
6073 justify_content: Some(JustifyContent::Start),
6074 ..Default::default()
6075 };
6076 CALCULATOR.calc(&mut container);
6077 log::trace!("container:\n{container}");
6078
6079 compare_containers(
6080 &container.clone(),
6081 &Container {
6082 children: vec![Container {
6083 children: vec![
6084 Container {
6085 calculated_width: Some(100.0),
6086 calculated_height: Some(0.0),
6087 calculated_x: Some(0.0),
6088 calculated_y: Some(0.0),
6089 calculated_position: Some(LayoutPosition::Default),
6090 ..container.children[0].children[0].clone()
6091 },
6092 Container {
6093 calculated_width: Some(100.0),
6094 calculated_height: Some(50.0),
6095 calculated_x: Some(30.0),
6096 calculated_y: Some(0.0),
6097 position: Some(Position::Absolute),
6098 ..container.children[0].children[1].clone()
6099 },
6100 ],
6101 ..container.children[0].clone()
6102 }],
6103 ..container
6104 },
6105 );
6106 }
6107
6108 #[test_log::test]
6109 fn calc_can_calc_absolute_positioned_element_on_top_of_a_relative_element_with_left_offset() {
6110 let mut container = Container {
6111 children: vec![
6112 Container::default(),
6113 Container {
6114 left: Some(Number::Integer(30)),
6115 position: Some(Position::Absolute),
6116 ..Default::default()
6117 },
6118 ],
6119 calculated_width: Some(100.0),
6120 calculated_height: Some(50.0),
6121 position: Some(Position::Relative),
6122 justify_content: Some(JustifyContent::Start),
6123 ..Default::default()
6124 };
6125 CALCULATOR.calc(&mut container);
6126 log::trace!("container:\n{container}");
6127
6128 compare_containers(
6129 &container.clone(),
6130 &Container {
6131 children: vec![
6132 Container {
6133 calculated_width: Some(100.0),
6134 calculated_x: Some(0.0),
6135 calculated_position: Some(LayoutPosition::Default),
6136 ..container.children[0].clone()
6137 },
6138 Container {
6139 calculated_width: Some(100.0),
6140 calculated_height: Some(50.0),
6141 calculated_x: Some(30.0),
6142 calculated_y: Some(0.0),
6143 position: Some(Position::Absolute),
6144 ..container.children[1].clone()
6145 },
6146 ],
6147 ..container
6148 },
6149 );
6150 }
6151
6152 #[test_log::test]
6153 fn calc_can_calc_absolute_positioned_element_with_explicit_sizes() {
6154 let mut container = Container {
6155 children: vec![
6156 Container::default(),
6157 Container {
6158 width: Some(Number::Integer(30)),
6159 height: Some(Number::Integer(20)),
6160 left: Some(Number::Integer(30)),
6161 position: Some(Position::Absolute),
6162 ..Default::default()
6163 },
6164 ],
6165 calculated_width: Some(100.0),
6166 calculated_height: Some(50.0),
6167 position: Some(Position::Relative),
6168 justify_content: Some(JustifyContent::Start),
6169 ..Default::default()
6170 };
6171 CALCULATOR.calc(&mut container);
6172 log::trace!("container:\n{container}");
6173
6174 compare_containers(
6175 &container.clone(),
6176 &Container {
6177 children: vec![
6178 Container {
6179 calculated_width: Some(100.0),
6180 calculated_x: Some(0.0),
6181 calculated_position: Some(LayoutPosition::Default),
6182 ..container.children[0].clone()
6183 },
6184 Container {
6185 calculated_width: Some(30.0),
6186 calculated_height: Some(20.0),
6187 calculated_x: Some(30.0),
6188 calculated_y: Some(0.0),
6189 position: Some(Position::Absolute),
6190 ..container.children[1].clone()
6191 },
6192 ],
6193 ..container
6194 },
6195 );
6196 }
6197
6198 #[test_log::test]
6199 fn calc_can_calc_justify_content_center_horizontally() {
6200 let mut container = Container {
6201 children: vec![Container {
6202 width: Some(Number::Integer(30)),
6203 ..Default::default()
6204 }],
6205
6206 calculated_width: Some(100.0),
6207 calculated_height: Some(50.0),
6208 direction: LayoutDirection::Row,
6209 justify_content: Some(JustifyContent::Center),
6210 ..Default::default()
6211 };
6212 CALCULATOR.calc(&mut container);
6213 log::trace!("container:\n{container}");
6214
6215 compare_containers(
6216 &container,
6217 &Container {
6218 children: vec![Container {
6219 calculated_x: Some((100.0 - 30.0) / 2.0),
6220 ..container.children[0].clone()
6221 }],
6222 ..container.clone()
6223 },
6224 );
6225 }
6226
6227 #[test_log::test]
6228 fn calc_can_calc_justify_content_start() {
6229 let mut container = Container {
6230 children: vec![
6231 Container {
6232 width: Some(Number::Integer(30)),
6233 ..Default::default()
6234 },
6235 Container {
6236 width: Some(Number::Integer(30)),
6237 ..Default::default()
6238 },
6239 ],
6240 calculated_width: Some(100.0),
6241 calculated_height: Some(50.0),
6242 direction: LayoutDirection::Row,
6243 justify_content: Some(JustifyContent::Start),
6244 ..Default::default()
6245 };
6246 CALCULATOR.calc(&mut container);
6247 log::trace!("container:\n{container}");
6248
6249 compare_containers(
6250 &container.clone(),
6251 &Container {
6252 children: vec![
6253 Container {
6254 calculated_x: Some(0.0),
6255 ..container.children[0].clone()
6256 },
6257 Container {
6258 calculated_x: Some(30.0),
6259 ..container.children[1].clone()
6260 },
6261 ],
6262 ..container
6263 },
6264 );
6265 }
6266
6267 #[test_log::test]
6268 fn calc_includes_horizontal_margins_in_content_width() {
6269 let mut container = Container {
6270 children: vec![
6271 Container {
6272 width: Some(Number::Integer(30)),
6273 margin_left: Some(Number::Integer(35)),
6274 ..Default::default()
6275 },
6276 Container {
6277 width: Some(Number::Integer(20)),
6278 ..Default::default()
6279 },
6280 ],
6281 calculated_width: Some(100.0),
6282 calculated_height: Some(50.0),
6283 direction: LayoutDirection::Row,
6284 ..Default::default()
6285 };
6286 CALCULATOR.calc(&mut container);
6287 log::trace!("container:\n{container}");
6288
6289 compare_containers(
6290 &container.clone(),
6291 &Container {
6292 children: vec![
6293 Container {
6294 calculated_width: Some(30.0),
6295 calculated_margin_left: Some(35.0),
6296 calculated_x: Some(0.0),
6297 ..container.children[0].clone()
6298 },
6299 Container {
6300 calculated_width: Some(20.0),
6301 calculated_x: Some(65.0),
6302 ..container.children[1].clone()
6303 },
6304 ],
6305 ..container
6306 },
6307 );
6308 }
6309
6310 #[test_log::test]
6311 fn calc_includes_horizontal_padding_in_content_width() {
6312 let mut container = Container {
6313 children: vec![
6314 Container {
6315 width: Some(Number::Integer(30)),
6316 padding_right: Some(Number::Integer(35)),
6317 ..Default::default()
6318 },
6319 Container {
6320 width: Some(Number::Integer(20)),
6321 ..Default::default()
6322 },
6323 ],
6324 calculated_width: Some(100.0),
6325 calculated_height: Some(50.0),
6326 direction: LayoutDirection::Row,
6327 ..Default::default()
6328 };
6329 CALCULATOR.calc(&mut container);
6330 log::trace!("container:\n{container}");
6331
6332 compare_containers(
6333 &container.clone(),
6334 &Container {
6335 children: vec![
6336 Container {
6337 calculated_width: Some(30.0),
6338 calculated_padding_right: Some(35.0),
6339 calculated_x: Some(0.0),
6340 ..container.children[0].clone()
6341 },
6342 Container {
6343 calculated_width: Some(20.0),
6344 calculated_x: Some(65.0),
6345 ..container.children[1].clone()
6346 },
6347 ],
6348 ..container
6349 },
6350 );
6351 }
6352
6353 #[test_log::test]
6354 fn calc_includes_horizontal_padding_in_auto_calculated_content_width() {
6355 let mut container = Container {
6356 children: vec![
6357 Container::default(),
6358 Container {
6359 padding_right: Some(Number::Integer(30)),
6360 ..Default::default()
6361 },
6362 ],
6363 calculated_width: Some(100.0),
6364 calculated_height: Some(50.0),
6365 direction: LayoutDirection::Row,
6366 overflow_x: LayoutOverflow::Wrap { grid: true },
6367 ..Default::default()
6368 };
6369 CALCULATOR.calc(&mut container);
6370 log::trace!("container:\n{container}");
6371
6372 compare_containers(
6373 &container.clone(),
6374 &Container {
6375 children: vec![
6376 Container {
6377 calculated_width: Some(0.0),
6378 calculated_x: Some(0.0),
6379 ..container.children[0].clone()
6380 },
6381 Container {
6382 calculated_width: Some(0.0),
6383 calculated_padding_right: Some(30.0),
6384 calculated_x: Some(0.0),
6385 ..container.children[1].clone()
6386 },
6387 ],
6388 ..container
6389 },
6390 );
6391 }
6392
6393 #[test_log::test]
6394 fn calc_includes_horizontal_margin_in_auto_calculated_content_width() {
6395 let mut container = Container {
6396 children: vec![
6397 Container::default(),
6398 Container {
6399 margin_right: Some(Number::Integer(30)),
6400 ..Default::default()
6401 },
6402 ],
6403 calculated_width: Some(100.0),
6404 calculated_height: Some(50.0),
6405 direction: LayoutDirection::Row,
6406 overflow_x: LayoutOverflow::Wrap { grid: true },
6407 ..Default::default()
6408 };
6409 CALCULATOR.calc(&mut container);
6410 log::trace!("container:\n{container}");
6411
6412 compare_containers(
6413 &container.clone(),
6414 &Container {
6415 children: vec![
6416 Container {
6417 calculated_width: Some(0.0),
6418 calculated_x: Some(0.0),
6419 ..container.children[0].clone()
6420 },
6421 Container {
6422 calculated_width: Some(0.0),
6423 calculated_margin_right: Some(30.0),
6424 calculated_x: Some(0.0),
6425 ..container.children[1].clone()
6426 },
6427 ],
6428 ..container
6429 },
6430 );
6431 }
6432
6433 #[test_log::test]
6434 fn calc_calculates_sized_widths_based_on_the_container_width_minus_all_its_childrens_padding() {
6435 let mut container = Container {
6436 children: vec![
6437 Container {
6438 width: Some(Number::IntegerPercent(50)),
6439 padding_right: Some(Number::Integer(20)),
6440 ..Default::default()
6441 },
6442 Container {
6443 width: Some(Number::IntegerPercent(50)),
6444 ..Default::default()
6445 },
6446 ],
6447 calculated_width: Some(100.0),
6448 calculated_height: Some(50.0),
6449 direction: LayoutDirection::Row,
6450 overflow_x: LayoutOverflow::Wrap { grid: true },
6451 ..Default::default()
6452 };
6453 CALCULATOR.calc(&mut container);
6454 log::trace!("container:\n{container}");
6455
6456 compare_containers(
6457 &container.clone(),
6458 &Container {
6459 children: vec![
6460 Container {
6461 calculated_width: Some(40.0),
6462 calculated_padding_right: Some(20.0),
6463 calculated_x: Some(0.0),
6464 ..container.children[0].clone()
6465 },
6466 Container {
6467 calculated_width: Some(40.0),
6468 calculated_x: Some(60.0),
6469 ..container.children[1].clone()
6470 },
6471 ],
6472 ..container
6473 },
6474 );
6475 }
6476
6477 #[test_log::test]
6478 fn calc_calculates_unsized_widths_based_on_the_container_width_minus_all_its_childrens_padding()
6479 {
6480 let mut container = Container {
6481 children: vec![
6482 Container {
6483 width: Some(Number::IntegerPercent(50)),
6484 padding_right: Some(Number::Integer(20)),
6485 ..Default::default()
6486 },
6487 Container::default(),
6488 ],
6489 calculated_width: Some(100.0),
6490 calculated_height: Some(50.0),
6491 direction: LayoutDirection::Row,
6492 overflow_x: LayoutOverflow::Wrap { grid: true },
6493 ..Default::default()
6494 };
6495 CALCULATOR.calc(&mut container);
6496 log::trace!("container:\n{container}");
6497
6498 compare_containers(
6499 &container.clone(),
6500 &Container {
6501 children: vec![
6502 Container {
6503 calculated_width: Some(40.0),
6504 calculated_padding_right: Some(20.0),
6505 calculated_x: Some(0.0),
6506 ..container.children[0].clone()
6507 },
6508 Container {
6509 calculated_width: Some(0.0),
6510 calculated_x: Some(60.0),
6511 ..container.children[1].clone()
6512 },
6513 ],
6514 ..container
6515 },
6516 );
6517 }
6518
6519 #[test_log::test]
6520 fn calc_calculates_unsized_widths_based_on_the_container_width_minus_second_childs_padding() {
6521 let mut container = Container {
6522 children: vec![
6523 Container {
6524 width: Some(Number::IntegerPercent(50)),
6525 ..Default::default()
6526 },
6527 Container {
6528 padding_right: Some(Number::Integer(20)),
6529 ..Default::default()
6530 },
6531 ],
6532 calculated_width: Some(100.0),
6533 calculated_height: Some(50.0),
6534 direction: LayoutDirection::Row,
6535 overflow_x: LayoutOverflow::Wrap { grid: true },
6536 ..Default::default()
6537 };
6538 CALCULATOR.calc(&mut container);
6539 log::trace!("container:\n{container}");
6540
6541 compare_containers(
6542 &container.clone(),
6543 &Container {
6544 children: vec![
6545 Container {
6546 calculated_width: Some(40.0),
6547 calculated_x: Some(0.0),
6548 ..container.children[0].clone()
6549 },
6550 Container {
6551 calculated_width: Some(0.0),
6552 calculated_padding_right: Some(20.0),
6553 calculated_x: Some(40.0),
6554 ..container.children[1].clone()
6555 },
6556 ],
6557 ..container
6558 },
6559 );
6560 }
6561
6562 #[test_log::test]
6563 fn calc_horizontal_padding_on_vertical_sibling_doesnt_affect_size_of_other_sibling() {
6564 let mut container = Container {
6565 children: vec![
6566 Container::default(),
6567 Container {
6568 padding_right: Some(Number::Integer(20)),
6569 ..Default::default()
6570 },
6571 ],
6572 calculated_width: Some(100.0),
6573 calculated_height: Some(50.0),
6574 ..Default::default()
6575 };
6576 CALCULATOR.calc(&mut container);
6577 log::trace!("container:\n{container}");
6578
6579 compare_containers(
6580 &container.clone(),
6581 &Container {
6582 children: vec![
6583 Container {
6584 calculated_width: Some(100.0),
6585 calculated_x: Some(0.0),
6586 ..container.children[0].clone()
6587 },
6588 Container {
6589 calculated_width: Some(80.0),
6590 calculated_padding_right: Some(20.0),
6591 calculated_x: Some(0.0),
6592 ..container.children[1].clone()
6593 },
6594 ],
6595 ..container
6596 },
6597 );
6598 }
6599
6600 #[test_log::test]
6601 fn calc_child_padding_does_not_add_to_parent_container() {
6602 let mut container = Container {
6603 children: vec![
6604 Container {
6605 padding_right: Some(Number::Integer(20)),
6606 ..Default::default()
6607 },
6608 Container::default(),
6609 Container::default(),
6610 ],
6611 calculated_width: Some(110.0),
6612 calculated_height: Some(50.0),
6613 direction: LayoutDirection::Row,
6614 overflow_x: LayoutOverflow::Wrap { grid: true },
6615 ..Default::default()
6616 };
6617 CALCULATOR.calc(&mut container);
6618 log::trace!("container:\n{container}");
6619
6620 compare_containers(
6621 &container.clone(),
6622 &Container {
6623 children: vec![
6624 Container {
6625 calculated_width: Some(0.0),
6626 calculated_padding_right: Some(20.0),
6627 calculated_x: Some(0.0),
6628 ..container.children[0].clone()
6629 },
6630 Container {
6631 calculated_width: Some(0.0),
6632 calculated_x: Some(20.0),
6633 ..container.children[1].clone()
6634 },
6635 Container {
6636 calculated_width: Some(0.0),
6637 calculated_x: Some(20.0),
6638 ..container.children[2].clone()
6639 },
6640 ],
6641 ..container
6642 },
6643 );
6644 }
6645
6646 #[test_log::test]
6647 fn calc_nested_child_padding_does_not_offset_unsized_container_siblings() {
6648 let mut container = Container {
6649 children: vec![
6650 Container {
6651 children: vec![Container {
6652 padding_right: Some(Number::Integer(20)),
6653 ..Default::default()
6654 }],
6655 ..Default::default()
6656 },
6657 Container::default(),
6658 Container::default(),
6659 ],
6660 calculated_width: Some(90.0),
6661 calculated_height: Some(50.0),
6662 direction: LayoutDirection::Row,
6663 ..Default::default()
6664 };
6665 CALCULATOR.calc(&mut container);
6666 log::trace!("container:\n{container}");
6667
6668 compare_containers(
6669 &container.clone(),
6670 &Container {
6671 children: vec![
6672 Container {
6673 children: vec![Container {
6674 calculated_width: Some(20.0),
6675 calculated_padding_right: Some(20.0),
6676 calculated_x: Some(0.0),
6677 ..container.children[0].children[0].clone()
6678 }],
6679 calculated_width: Some(20.0),
6680 calculated_x: Some(0.0),
6681 ..container.children[0].clone()
6682 },
6683 Container {
6684 calculated_width: Some(0.0),
6685 calculated_x: Some(20.0),
6686 ..container.children[1].clone()
6687 },
6688 Container {
6689 calculated_width: Some(0.0),
6690 calculated_x: Some(20.0),
6691 ..container.children[2].clone()
6692 },
6693 ],
6694 ..container
6695 },
6696 );
6697 }
6698
6699 #[test_log::test]
6700 fn calc_horizontal_sibling_left_raw_still_divides_the_unsized_width() {
6701 let metrics = DefaultFontMetrics;
6702 let text_width = metrics.measure_text("test", 14.0, f32::INFINITY).width();
6703
6704 let mut container = Container {
6705 children: vec![
6706 Container {
6707 element: Element::Raw {
6708 value: "test".to_string(),
6709 },
6710 ..Container::default()
6711 },
6712 Container::default(),
6713 ],
6714 calculated_width: Some(100.0),
6715 calculated_height: Some(50.0),
6716 direction: LayoutDirection::Row,
6717 ..Default::default()
6718 };
6719 CALCULATOR.calc(&mut container);
6720 log::trace!("container:\n{container}");
6721
6722 compare_containers(
6723 &container,
6724 &Container {
6725 children: vec![
6726 container.children[0].clone(),
6727 Container {
6728 calculated_width: Some(0.0),
6729 calculated_x: Some(text_width),
6730 ..container.children[1].clone()
6731 },
6732 ],
6733 calculated_width: Some(100.0),
6734 ..container.clone()
6735 },
6736 );
6737 }
6738
6739 #[test_log::test]
6740 fn calc_calculates_width_minus_the_horizontal_padding() {
6741 let mut container = Container {
6742 children: vec![Container {
6743 padding_left: Some(Number::Integer(10)),
6744 padding_right: Some(Number::Integer(20)),
6745 ..Default::default()
6746 }],
6747 calculated_width: Some(100.0),
6748 calculated_height: Some(50.0),
6749 ..Default::default()
6750 };
6751 CALCULATOR.calc(&mut container);
6752 log::trace!("container:\n{container}");
6753
6754 compare_containers(
6755 &container.clone(),
6756 &Container {
6757 children: vec![Container {
6758 calculated_width: Some(70.0),
6759 calculated_x: Some(0.0),
6760 ..container.children[0].clone()
6761 }],
6762 ..container
6763 },
6764 );
6765 }
6766
6767 #[test_log::test]
6768 fn calc_calculates_height_minus_the_vertical_padding() {
6769 let mut container = Container {
6770 children: vec![Container {
6771 padding_top: Some(Number::Integer(10)),
6772 padding_bottom: Some(Number::Integer(20)),
6773 ..Default::default()
6774 }],
6775 calculated_width: Some(100.0),
6776 calculated_height: Some(50.0),
6777 justify_content: Some(JustifyContent::Start),
6778 ..Default::default()
6779 };
6780
6781 CALCULATOR.calc(&mut container);
6782 log::trace!("container:\n{container}");
6783
6784 compare_containers(
6785 &container.clone(),
6786 &Container {
6787 children: vec![Container {
6788 calculated_height: Some(0.0),
6789 calculated_y: Some(0.0),
6790 ..container.children[0].clone()
6791 }],
6792 ..container
6793 },
6794 );
6795 }
6796
6797 #[test_log::test]
6798 fn calc_calculates_width_minus_the_horizontal_padding_with_percentage_width() {
6799 let mut container = Container {
6800 children: vec![Container {
6801 width: Some(Number::IntegerPercent(50)),
6802 padding_left: Some(Number::Integer(10)),
6803 padding_right: Some(Number::Integer(20)),
6804 padding_top: Some(Number::Integer(15)),
6805 ..Default::default()
6806 }],
6807 calculated_width: Some(100.0),
6808 calculated_height: Some(50.0),
6809 height: Some(Number::Integer(50)),
6810 justify_content: Some(JustifyContent::Start),
6811 ..Default::default()
6812 };
6813 CALCULATOR.calc(&mut container);
6814 log::trace!("container:\n{container}");
6815
6816 compare_containers(
6817 &container.clone(),
6818 &Container {
6819 children: vec![Container {
6820 calculated_width: Some(35.0),
6821 calculated_x: Some(0.0),
6822 ..container.children[0].clone()
6823 }],
6824 ..container
6825 },
6826 );
6827 }
6828
6829 #[test_log::test]
6830 fn calc_calculates_width_minus_the_horizontal_padding_with_percentage_width_nested() {
6831 let mut container = Container {
6832 children: vec![Container {
6833 children: vec![Container {
6834 width: Some(Number::IntegerPercent(50)),
6835 padding_left: Some(Number::Integer(2)),
6836 padding_right: Some(Number::Integer(3)),
6837 padding_top: Some(Number::Integer(1)),
6838 ..Default::default()
6839 }],
6840 width: Some(Number::IntegerPercent(100)),
6841 padding_left: Some(Number::Integer(10)),
6842 padding_right: Some(Number::Integer(20)),
6843 padding_top: Some(Number::Integer(15)),
6844 justify_content: Some(JustifyContent::Start),
6845 ..Default::default()
6846 }],
6847 calculated_width: Some(100.0),
6848 calculated_height: Some(50.0),
6849 height: Some(Number::Integer(50)),
6850 justify_content: Some(JustifyContent::Start),
6851 ..Default::default()
6852 };
6853 CALCULATOR.calc(&mut container);
6854 log::trace!("container:\n{container}");
6855
6856 compare_containers(
6857 &container.clone(),
6858 &Container {
6859 children: vec![Container {
6860 children: vec![Container {
6861 calculated_width: Some(32.5),
6862 calculated_x: Some(0.0),
6863 calculated_padding_left: Some(2.0),
6864 calculated_padding_right: Some(3.0),
6865 calculated_padding_top: Some(1.0),
6866 ..container.children[0].children[0].clone()
6867 }],
6868 calculated_width: Some(70.0),
6869 calculated_x: Some(0.0),
6870 calculated_padding_left: Some(10.0),
6871 calculated_padding_right: Some(20.0),
6872 calculated_padding_top: Some(15.0),
6873 ..container.children[0].clone()
6874 }],
6875 ..container
6876 },
6877 );
6878 }
6879
6880 #[test_log::test]
6881 fn calc_calculates_width_minus_the_horizontal_padding_with_calc_width_nested() {
6882 let mut container = Container {
6883 children: vec![Container {
6884 children: vec![Container {
6885 width: Some(Number::IntegerPercent(50)),
6886 padding_left: Some(Number::Integer(2)),
6887 padding_right: Some(Number::Integer(3)),
6888 padding_top: Some(Number::Integer(1)),
6889 ..Default::default()
6890 }],
6891 width: Some(Number::Calc(Calculation::Number(Box::new(
6892 Number::IntegerPercent(100),
6893 )))),
6894 padding_left: Some(Number::Integer(10)),
6895 padding_right: Some(Number::Integer(20)),
6896 padding_top: Some(Number::Integer(15)),
6897 justify_content: Some(JustifyContent::Start),
6898 ..Default::default()
6899 }],
6900 calculated_width: Some(100.0),
6901 calculated_height: Some(50.0),
6902 height: Some(Number::Integer(50)),
6903 justify_content: Some(JustifyContent::Start),
6904 ..Default::default()
6905 };
6906 CALCULATOR.calc(&mut container);
6907 log::trace!("container:\n{container}");
6908
6909 compare_containers(
6910 &container.clone(),
6911 &Container {
6912 children: vec![Container {
6913 children: vec![Container {
6914 calculated_width: Some(32.5),
6915 calculated_x: Some(0.0),
6916 calculated_padding_left: Some(2.0),
6917 calculated_padding_right: Some(3.0),
6918 calculated_padding_top: Some(1.0),
6919 ..container.children[0].children[0].clone()
6920 }],
6921 calculated_width: Some(70.0),
6922 calculated_x: Some(0.0),
6923 calculated_padding_left: Some(10.0),
6924 calculated_padding_right: Some(20.0),
6925 calculated_padding_top: Some(15.0),
6926 ..container.children[0].clone()
6927 }],
6928 ..container
6929 },
6930 );
6931 }
6932
6933 #[test_log::test]
6934 fn calc_calculates_width_minus_the_horizontal_padding_for_absolute_position_children() {
6935 let mut container = Container {
6936 children: vec![Container {
6937 width: Some(Number::Calc(Calculation::Number(Box::new(
6938 Number::IntegerPercent(100),
6939 )))),
6940 padding_left: Some(Number::Integer(10)),
6941 padding_right: Some(Number::Integer(20)),
6942 padding_top: Some(Number::Integer(15)),
6943 position: Some(Position::Absolute),
6944 ..Default::default()
6945 }],
6946 calculated_width: Some(100.0),
6947 calculated_height: Some(50.0),
6948 position: Some(Position::Relative),
6949 justify_content: Some(JustifyContent::Start),
6950 ..Default::default()
6951 };
6952 CALCULATOR.calc(&mut container);
6953 log::trace!("container:\n{container}");
6954
6955 compare_containers(
6956 &container.clone(),
6957 &Container {
6958 children: vec![Container {
6959 calculated_width: Some(70.0),
6960 calculated_height: Some(35.0),
6961 calculated_x: Some(0.0),
6962 calculated_y: Some(0.0),
6963 calculated_padding_left: Some(10.0),
6964 calculated_padding_right: Some(20.0),
6965 calculated_padding_top: Some(15.0),
6966 ..container.children[0].clone()
6967 }],
6968 ..container
6969 },
6970 );
6971 }
6972
6973 #[test_log::test]
6974 fn calc_uses_bounding_width_for_absolute_position_children_with_right_offset() {
6975 let mut container = Container {
6976 children: vec![Container {
6977 width: Some(Number::Calc(Calculation::Number(Box::new(
6978 Number::IntegerPercent(50),
6979 )))),
6980 padding_left: Some(Number::Integer(10)),
6981 padding_right: Some(Number::Integer(20)),
6982 right: Some(Number::Integer(5)),
6983 position: Some(Position::Absolute),
6984 ..Default::default()
6985 }],
6986
6987 calculated_width: Some(100.0),
6988 calculated_height: Some(50.0),
6989 position: Some(Position::Relative),
6990 ..Default::default()
6991 };
6992 CALCULATOR.calc(&mut container);
6993 log::trace!("container:\n{container}");
6994
6995 compare_containers(
6996 &container.clone(),
6997 &Container {
6998 children: vec![Container {
6999 calculated_width: Some(35.0),
7000 calculated_height: Some(50.0),
7001 calculated_x: Some(100.0 - 35.0 - 10.0 - 20.0 - 5.0),
7002 calculated_y: Some(0.0),
7003 calculated_padding_left: Some(10.0),
7004 calculated_padding_right: Some(20.0),
7005 ..container.children[0].clone()
7006 }],
7007 ..container
7008 },
7009 );
7010 }
7011
7012 #[test_log::test]
7013 fn calc_calculates_flex_height_for_single_unsized_child_with_sized_child() {
7014 let mut container: Container = html! {
7015 div {
7016 div sx-dir="row" {
7017 div sx-width=(50) sx-height=(36) { "Albums" }
7018 }
7019 }
7020 }
7021 .try_into()
7022 .unwrap();
7023
7024 container.calculated_width = Some(160.0);
7025 container.calculated_height = Some(100.0);
7026
7027 CALCULATOR.calc(&mut container);
7028 log::trace!("container:\n{container}");
7029
7030 compare_containers(
7031 &container,
7032 &Container {
7033 children: vec![Container {
7034 children: vec![Container {
7035 children: vec![Container {
7036 calculated_width: Some(50.0),
7037 calculated_height: Some(36.0),
7038 ..container.children[0].children[0].children[0].clone()
7039 }],
7040 ..container.children[0].children[0].clone()
7041 }],
7042 ..container.children[0].clone()
7043 }],
7044 ..container.clone()
7045 },
7046 );
7047 }
7048
7049 #[test_log::test]
7050 fn calc_calculates_flex_height_for_two_unsized_children_with_sized_child() {
7051 let mut container: Container = html! {
7052 div {
7053 div sx-dir="row" {
7054 div sx-width=(50) sx-height=(36) { "Albums" }
7055 }
7056 div sx-dir="row" {
7057 div sx-width=(50) sx-height=(36) { "Albums2" }
7058 }
7059 }
7060 }
7061 .try_into()
7062 .unwrap();
7063
7064 container.calculated_width = Some(160.0);
7065 container.calculated_height = Some(100.0);
7066
7067 CALCULATOR.calc(&mut container);
7068 log::trace!("container:\n{container}");
7069
7070 compare_containers(
7071 &container,
7072 &Container {
7073 children: vec![Container {
7074 children: vec![
7075 Container {
7076 children: vec![Container {
7077 calculated_width: Some(50.0),
7078 calculated_height: Some(36.0),
7079 ..container.children[0].children[0].children[0].clone()
7080 }],
7081 ..container.children[0].children[0].clone()
7082 },
7083 Container {
7084 children: vec![Container {
7085 calculated_width: Some(50.0),
7086 calculated_height: Some(36.0),
7087 ..container.children[0].children[1].children[0].clone()
7088 }],
7089 ..container.children[0].children[1].clone()
7090 },
7091 ],
7092 ..container.children[0].clone()
7093 }],
7094 ..container.clone()
7095 },
7096 );
7097 }
7098
7099 #[test_log::test]
7100 fn calc_calculates_width_minus_the_horizontal_padding_for_nested_children_with_calc_parent_sizes()
7101 {
7102 let mut container: Container = html! {
7103 div sx-width="100%" sx-height="100%" sx-position="relative" {
7104 section sx-dir="row" sx-height=("calc(100% - 140px)") {
7105 aside sx-width="calc(max(240, min(280, 15%)))" {}
7106 main sx-overflow-y="auto" sx-flex=(1) {
7107 div sx-height=(76) sx-justify-content=(JustifyContent::Start) {
7108 div
7109 sx-padding-left=(30)
7110 sx-padding-right=(30)
7111 sx-padding-top=(15)
7112 {
7113 div sx-dir="row" {
7114 h1 sx-width=(50) sx-height=(36) { "Albums" }
7115 }
7116 }
7117 }
7118 }
7119 }
7120 }
7121 }
7122 .try_into()
7123 .unwrap();
7124
7125 container.calculated_width = Some(1600.0);
7126 container.calculated_height = Some(1000.0);
7127 container.justify_content = Some(JustifyContent::Start);
7128
7129 CALCULATOR.calc(&mut container);
7130 log::trace!("container:\n{container}");
7131
7132 let container = container.children[0].children[0].children[1].clone();
7133
7134 compare_containers(
7135 &container.clone(),
7136 &Container {
7137 children: vec![Container {
7138 children: vec![Container {
7139 children: vec![Container {
7140 children: vec![Container {
7141 element: Element::Heading {
7142 size: HeaderSize::H1,
7143 },
7144 calculated_width: Some(50.0),
7145 calculated_height: Some(36.0),
7146 ..container.children[0].children[0].children[0].children[0].clone()
7147 }],
7148 ..container.children[0].children[0].children[0].clone()
7149 }],
7150 calculated_width: Some(1300.0),
7151 calculated_height: Some(36.0),
7152 calculated_padding_left: Some(30.0),
7153 calculated_padding_right: Some(30.0),
7154 calculated_padding_top: Some(15.0),
7155 calculated_x: Some(0.0),
7156 calculated_y: Some(0.0),
7157 ..container.children[0].children[0].clone()
7158 }],
7159 calculated_width: Some(1360.0),
7160 calculated_height: Some(76.0),
7161 calculated_x: Some(0.0),
7162 calculated_y: Some(0.0),
7163 ..container.children[0].clone()
7164 }],
7165 ..container
7166 },
7167 );
7168 }
7169
7170 #[test_log::test]
7171 fn calc_calculates_horizontal_position_from_right_for_absolute_position_with_padding() {
7172 let mut container: Container = html! {
7173 div
7174 sx-width="calc(min(500, 30%))"
7175 sx-height="calc(100% - 200)"
7176 sx-padding-left=(20)
7177 sx-padding-right=(20)
7178 sx-position="absolute"
7179 sx-right=(0)
7180 {}
7181 }
7182 .try_into()
7183 .unwrap();
7184
7185 container.calculated_width = Some(1600.0);
7186 container.calculated_height = Some(1000.0);
7187 container.position = Some(Position::Relative);
7188
7189 CALCULATOR.calc(&mut container);
7190 log::trace!("container:\n{container}");
7191
7192 compare_containers(
7193 &container.clone(),
7194 &Container {
7195 children: vec![Container {
7196 calculated_width: Some((1600.0 - 40.0) * 0.3),
7197 calculated_height: Some(800.0),
7198 calculated_x: Some(1092.0),
7199 calculated_y: Some(0.0),
7200 calculated_padding_left: Some(20.0),
7201 calculated_padding_right: Some(20.0),
7202 ..container.children[0].clone()
7203 }],
7204 ..container
7205 },
7206 );
7207 }
7208
7209 #[test_log::test]
7210 fn calc_calculates_vertical_position_from_right_for_absolute_position_with_padding() {
7211 let mut container: Container = html! {
7212 div
7213 sx-width="calc(min(500, 30%))"
7214 sx-height="calc(100% - 200)"
7215 sx-padding-top=(20)
7216 sx-padding-bottom=(20)
7217 sx-position="absolute"
7218 sx-bottom=(170)
7219 {}
7220 }
7221 .try_into()
7222 .unwrap();
7223
7224 container.calculated_width = Some(1600.0);
7225 container.calculated_height = Some(1000.0);
7226 container.position = Some(Position::Relative);
7227
7228 CALCULATOR.calc(&mut container);
7229 log::trace!("container:\n{container}");
7230
7231 compare_containers(
7232 &container.clone(),
7233 &Container {
7234 children: vec![Container {
7235 calculated_width: Some(1600.0 * 0.3),
7236 calculated_height: Some(1000.0 - 200.0 - 40.0),
7237 calculated_x: Some(0.0),
7238 calculated_y: Some(30.0),
7239 calculated_padding_top: Some(20.0),
7240 calculated_padding_bottom: Some(20.0),
7241 ..container.children[0].clone()
7242 }],
7243 ..container
7244 },
7245 );
7246 }
7247
7248 #[test_log::test]
7249 fn calc_calculates_horizontal_and_vertical_position_from_right_for_absolute_position_with_padding()
7250 {
7251 let mut container: Container = html! {
7252 div
7253 sx-width="calc(min(500, 30%))"
7254 sx-height="calc(100% - 200)"
7255 sx-padding=(20)
7256 sx-position="absolute"
7257 sx-bottom=(170)
7258 sx-right=(0)
7259 {}
7260 }
7261 .try_into()
7262 .unwrap();
7263
7264 container.calculated_width = Some(1600.0);
7265 container.calculated_height = Some(1000.0);
7266 container.position = Some(Position::Relative);
7267
7268 CALCULATOR.calc(&mut container);
7269 log::trace!("container:\n{container}");
7270
7271 compare_containers(
7272 &container.clone(),
7273 &Container {
7274 children: vec![Container {
7275 calculated_width: Some((1600.0 - 40.0) * 0.3),
7276 calculated_height: Some(1000.0 - 200.0 - 40.0),
7277 calculated_x: Some(1092.0),
7278 calculated_y: Some(30.0),
7279 calculated_padding_left: Some(20.0),
7280 calculated_padding_right: Some(20.0),
7281 calculated_padding_top: Some(20.0),
7282 calculated_padding_bottom: Some(20.0),
7283 ..container.children[0].clone()
7284 }],
7285 ..container
7286 },
7287 );
7288 }
7289
7290 #[test_log::test]
7291 fn calc_calculates_horizontal_and_vertical_position_from_right_for_nested_absolute_position_with_padding()
7292 {
7293 let mut container: Container = html! {
7294 div sx-width="100%" sx-height="100%" sx-position="relative" {
7295 section sx-dir="row" sx-height=("calc(100% - 140px)") {
7296 aside sx-width="calc(max(240, min(280, 15%)))" {}
7297 main sx-overflow-y="auto" {}
7298 }
7299 div
7300 sx-width="calc(min(500, 30%))"
7301 sx-height="calc(100% - 200)"
7302 sx-padding=(20)
7303 sx-position="absolute"
7304 sx-bottom=(170)
7305 sx-right=(0)
7306 {}
7307 }
7308 }
7309 .try_into()
7310 .unwrap();
7311
7312 container.calculated_width = Some(1600.0);
7313 container.calculated_height = Some(1000.0);
7314
7315 CALCULATOR.calc(&mut container);
7316 log::trace!("container:\n{container}");
7317
7318 let container = container.children[0].children[1].clone();
7319
7320 compare_containers(
7321 &container.clone(),
7322 &Container {
7323 calculated_width: Some((1600.0 - 40.0) * 0.3),
7324 calculated_height: Some(1000.0 - 200.0 - 40.0),
7325 calculated_x: Some(1092.0),
7326 calculated_y: Some(30.0),
7327 calculated_padding_left: Some(20.0),
7328 calculated_padding_right: Some(20.0),
7329 calculated_padding_top: Some(20.0),
7330 calculated_padding_bottom: Some(20.0),
7331 ..container
7332 },
7333 );
7334 }
7335
7336 #[test_log::test]
7337 fn calc_calculates_horizontal_padding_on_sized_element_correctly() {
7338 let mut container: Container = html! {
7339 div sx-width="100%" sx-height="100%" sx-position="relative" {
7340 section sx-dir="row" sx-height=("calc(100% - 140)") {
7341 aside sx-width="calc(max(240, min(280, 15%)))" sx-padding=(20) {}
7342 main sx-overflow-y="auto" sx-flex=(1) {}
7343 }
7344 }
7345 }
7346 .try_into()
7347 .unwrap();
7348
7349 container.calculated_width = Some(1600.0);
7350 container.calculated_height = Some(1000.0);
7351
7352 CALCULATOR.calc(&mut container);
7353 log::trace!("container:\n{container}");
7354
7355 let main = container.children[0].children[0].children[1].clone();
7356
7357 compare_containers(
7358 &main.clone(),
7359 &Container {
7360 calculated_width: Some(1320.0),
7361 calculated_height: Some(860.0),
7362 calculated_x: Some(280.0),
7363 calculated_y: Some(0.0),
7364 ..main
7365 },
7366 );
7367
7368 let aside = container.children[0].children[0].children[0].clone();
7369
7370 compare_containers(
7371 &aside.clone(),
7372 &Container {
7373 calculated_width: Some(240.0),
7374 calculated_x: Some(0.0),
7375 calculated_y: Some(0.0),
7376 calculated_padding_left: Some(20.0),
7377 calculated_padding_right: Some(20.0),
7378 ..aside
7379 },
7380 );
7381 }
7382
7383 #[test_log::test]
7384 fn calc_calculates_vertical_padding_on_sized_element_correctly() {
7385 let mut container: Container = html! {
7386 div sx-width="100%" sx-height="100%" sx-position="relative" {
7387 section sx-dir="row" sx-height=("calc(100% - 140)") {
7388 aside
7389 sx-justify-content=(JustifyContent::Start)
7390 sx-width="calc(max(240, min(280, 15%)))"
7391 sx-padding=(20)
7392 {
7393 div sx-justify-content=(JustifyContent::Start) {
7394 div {}
7395 ul sx-justify-content=(JustifyContent::Start) { li {} li {} }
7396 }
7397 }
7398 main sx-overflow-y="auto" sx-flex=(1) {}
7399 }
7400 footer sx-height=(140) {}
7401 }
7402 }
7403 .try_into()
7404 .unwrap();
7405
7406 container.calculated_width = Some(1600.0);
7407 container.calculated_height = Some(1000.0);
7408 container.justify_content = Some(JustifyContent::Start);
7409
7410 CALCULATOR.calc(&mut container);
7411 log::trace!("container:\n{container}");
7412
7413 let main = container.children[0].children[0].children[1].clone();
7414
7415 compare_containers(
7416 &main.clone(),
7417 &Container {
7418 calculated_width: Some(1320.0),
7419 calculated_height: Some(860.0),
7420 calculated_x: Some(280.0),
7421 calculated_y: Some(0.0),
7422 ..main
7423 },
7424 );
7425
7426 let aside = container.children[0].children[0].children[0].clone();
7427
7428 compare_containers(
7429 &aside.clone(),
7430 &Container {
7431 calculated_height: Some(820.0),
7432 calculated_x: Some(0.0),
7433 calculated_y: Some(0.0),
7434 calculated_padding_top: Some(20.0),
7435 calculated_padding_bottom: Some(20.0),
7436 ..aside
7437 },
7438 );
7439 }
7440
7441 #[test_log::test]
7442 fn calc_overflow_y_squash_expands_height_of_largest_child_as_much_as_possible() {
7443 let mut container: Container = html! {
7444 div {
7445 div sx-height=(40) {}
7446 }
7447 div {
7448 div sx-height=(600) {}
7449 }
7450 }
7451 .try_into()
7452 .unwrap();
7453
7454 container.calculated_width = Some(100.0);
7455 container.calculated_height = Some(500.0);
7456
7457 CALCULATOR.calc(&mut container);
7458 log::trace!("container:\n{container}");
7459
7460 compare_containers(
7461 &container,
7462 &Container {
7463 children: vec![
7464 Container {
7465 calculated_height: Some(40.0),
7466 ..container.children[0].clone()
7467 },
7468 Container {
7469 calculated_height: Some(600.0),
7470 ..container.children[1].clone()
7471 },
7472 ],
7473 calculated_height: Some(500.0),
7474 ..container.clone()
7475 },
7476 );
7477 }
7478
7479 #[test_log::test]
7480 fn calc_overflow_y_expand_expands_height_when_contained_height_is_greater_than_single_unsized_div()
7481 {
7482 let mut container: Container = html! {
7483 div {
7484 div {
7485 div sx-height=(600) {}
7486 }
7487 }
7488 }
7489 .try_into()
7490 .unwrap();
7491
7492 container.calculated_width = Some(100.0);
7493 container.calculated_height = Some(500.0);
7494
7495 CALCULATOR.calc(&mut container);
7496 log::trace!("container:\n{container}");
7497
7498 compare_containers(
7499 &container,
7500 &Container {
7501 children: vec![Container {
7502 children: vec![Container {
7503 children: vec![Container {
7504 calculated_height: Some(600.0),
7505 ..container.children[0].children[0].children[0].clone()
7506 }],
7507 calculated_height: Some(600.0),
7508 ..container.children[0].children[0].clone()
7509 }],
7510 calculated_height: Some(600.0),
7511 ..container.children[0].clone()
7512 }],
7513 calculated_height: Some(500.0),
7514 ..container.clone()
7515 },
7516 );
7517 }
7518
7519 #[test_log::test]
7520 fn calc_overflow_y_expand_expands_height_when_contained_height_is_greater_than_two_unsized_divs()
7521 {
7522 let mut container: Container = html! {
7523 div {
7524 div {
7525 div sx-height=(40) {}
7526 }
7527 div {
7528 div sx-height=(600) {}
7529 }
7530 }
7531 }
7532 .try_into()
7533 .unwrap();
7534
7535 container.calculated_width = Some(100.0);
7536 container.calculated_height = Some(500.0);
7537
7538 CALCULATOR.calc(&mut container);
7539 log::trace!("container:\n{container}");
7540
7541 compare_containers(
7542 &container,
7543 &Container {
7544 children: vec![Container {
7545 children: vec![
7546 Container {
7547 calculated_height: Some(40.0),
7548 ..container.children[0].children[0].clone()
7549 },
7550 Container {
7551 calculated_height: Some(600.0),
7552 ..container.children[0].children[1].clone()
7553 },
7554 ],
7555 calculated_height: Some(640.0),
7556 ..container.children[0].clone()
7557 }],
7558 calculated_height: Some(500.0),
7559 ..container.clone()
7560 },
7561 );
7562 }
7563
7564 #[test_log::test]
7565 fn calc_overflow_y_auto_justify_content_start_only_takes_up_sized_height() {
7566 let mut container: Container = html! {
7567 div sx-overflow-y="auto" sx-justify-content=(JustifyContent::Start) {
7568 div {
7569 div sx-height=(40) {}
7570 }
7571 div {
7572 div sx-height=(600) {}
7573 }
7574 }
7575 }
7576 .try_into()
7577 .unwrap();
7578
7579 container.calculated_width = Some(100.0);
7580 container.calculated_height = Some(500.0);
7581 container.justify_content = Some(JustifyContent::Start);
7582
7583 CALCULATOR.calc(&mut container);
7584 log::trace!("container:\n{container}");
7585
7586 compare_containers(
7587 &container,
7588 &Container {
7589 children: vec![Container {
7590 children: vec![
7591 Container {
7592 calculated_height: Some(40.0),
7593 ..container.children[0].children[0].clone()
7594 },
7595 Container {
7596 calculated_height: Some(600.0),
7597 ..container.children[0].children[1].clone()
7598 },
7599 ],
7600 calculated_height: Some(500.0),
7601 ..container.children[0].clone()
7602 }],
7603 calculated_height: Some(500.0),
7604 ..container.clone()
7605 },
7606 );
7607 }
7608
7609 #[test_log::test]
7610 fn calc_does_calculate_fixed_top_left_border_radius() {
7611 let mut container: Container = html! {
7612 div sx-border-top-left-radius=(5) {}
7613 }
7614 .try_into()
7615 .unwrap();
7616
7617 container.calculated_width = Some(100.0);
7618 container.calculated_height = Some(500.0);
7619
7620 CALCULATOR.calc(&mut container);
7621 log::trace!("container:\n{container}");
7622
7623 compare_containers(
7624 &container,
7625 &Container {
7626 children: vec![Container {
7627 calculated_border_top_left_radius: Some(5.0),
7628 ..container.children[0].clone()
7629 }],
7630 ..container.clone()
7631 },
7632 );
7633 }
7634
7635 #[test_log::test]
7636 fn calc_does_calculate_fixed_top_right_border_radius() {
7637 let mut container: Container = html! {
7638 div sx-border-top-right-radius=(5) {}
7639 }
7640 .try_into()
7641 .unwrap();
7642
7643 container.calculated_width = Some(100.0);
7644 container.calculated_height = Some(500.0);
7645
7646 CALCULATOR.calc(&mut container);
7647 log::trace!("container:\n{container}");
7648
7649 compare_containers(
7650 &container,
7651 &Container {
7652 children: vec![Container {
7653 calculated_border_top_right_radius: Some(5.0),
7654 ..container.children[0].clone()
7655 }],
7656 ..container.clone()
7657 },
7658 );
7659 }
7660
7661 #[test_log::test]
7662 fn calc_does_calculate_fixed_bottom_left_border_radius() {
7663 let mut container: Container = html! {
7664 div sx-border-bottom-left-radius=(5) {}
7665 }
7666 .try_into()
7667 .unwrap();
7668
7669 container.calculated_width = Some(100.0);
7670 container.calculated_height = Some(500.0);
7671
7672 CALCULATOR.calc(&mut container);
7673 log::trace!("container:\n{container}");
7674
7675 compare_containers(
7676 &container,
7677 &Container {
7678 children: vec![Container {
7679 calculated_border_bottom_left_radius: Some(5.0),
7680 ..container.children[0].clone()
7681 }],
7682 ..container.clone()
7683 },
7684 );
7685 }
7686
7687 #[test_log::test]
7688 fn calc_does_calculate_fixed_bottom_right_border_radius() {
7689 let mut container: Container = html! {
7690 div sx-border-bottom-right-radius=(5) {}
7691 }
7692 .try_into()
7693 .unwrap();
7694
7695 container.calculated_width = Some(100.0);
7696 container.calculated_height = Some(500.0);
7697
7698 CALCULATOR.calc(&mut container);
7699 log::trace!("container:\n{container}");
7700
7701 compare_containers(
7702 &container,
7703 &Container {
7704 children: vec![Container {
7705 calculated_border_bottom_right_radius: Some(5.0),
7706 ..container.children[0].clone()
7707 }],
7708 ..container.clone()
7709 },
7710 );
7711 }
7712
7713 #[test_log::test]
7714 fn calc_does_calculate_percentage_top_left_border_radius() {
7715 let mut container: Container = html! {
7716 div sx-border-top-left-radius="100%" {}
7717 }
7718 .try_into()
7719 .unwrap();
7720
7721 container.calculated_width = Some(100.0);
7722 container.calculated_height = Some(500.0);
7723
7724 CALCULATOR.calc(&mut container);
7725 log::trace!("container:\n{container}");
7726
7727 compare_containers(
7728 &container,
7729 &Container {
7730 children: vec![Container {
7731 calculated_border_top_left_radius: Some(100.0),
7732 ..container.children[0].clone()
7733 }],
7734 ..container.clone()
7735 },
7736 );
7737 }
7738
7739 #[test_log::test]
7740 fn calc_does_calculate_percentage_top_right_border_radius() {
7741 let mut container: Container = html! {
7742 div sx-border-top-right-radius="100%" {}
7743 }
7744 .try_into()
7745 .unwrap();
7746
7747 container.calculated_width = Some(100.0);
7748 container.calculated_height = Some(500.0);
7749
7750 CALCULATOR.calc(&mut container);
7751 log::trace!("container:\n{container}");
7752
7753 compare_containers(
7754 &container,
7755 &Container {
7756 children: vec![Container {
7757 calculated_border_top_right_radius: Some(100.0),
7758 ..container.children[0].clone()
7759 }],
7760 ..container.clone()
7761 },
7762 );
7763 }
7764
7765 #[test_log::test]
7766 fn calc_does_calculate_percentage_bottom_left_border_radius() {
7767 let mut container: Container = html! {
7768 div sx-border-bottom-left-radius="100%" {}
7769 }
7770 .try_into()
7771 .unwrap();
7772
7773 container.calculated_width = Some(100.0);
7774 container.calculated_height = Some(500.0);
7775
7776 CALCULATOR.calc(&mut container);
7777 log::trace!("container:\n{container}");
7778
7779 compare_containers(
7780 &container,
7781 &Container {
7782 children: vec![Container {
7783 calculated_border_bottom_left_radius: Some(100.0),
7784 ..container.children[0].clone()
7785 }],
7786 ..container.clone()
7787 },
7788 );
7789 }
7790
7791 #[test_log::test]
7792 fn calc_does_calculate_percentage_bottom_right_border_radius() {
7793 let mut container: Container = html! {
7794 div sx-border-bottom-right-radius="100%" {}
7795 }
7796 .try_into()
7797 .unwrap();
7798
7799 container.calculated_width = Some(100.0);
7800 container.calculated_height = Some(500.0);
7801
7802 CALCULATOR.calc(&mut container);
7803 log::trace!("container:\n{container}");
7804
7805 compare_containers(
7806 &container,
7807 &Container {
7808 children: vec![Container {
7809 calculated_border_bottom_right_radius: Some(100.0),
7810 ..container.children[0].clone()
7811 }],
7812 ..container.clone()
7813 },
7814 );
7815 }
7816
7817 #[test_log::test]
7818 fn calc_does_calculate_fixed_opacity() {
7819 let mut container: Container = html! {
7820 div sx-opacity=(0.5) {}
7821 }
7822 .try_into()
7823 .unwrap();
7824
7825 container.calculated_width = Some(100.0);
7826 container.calculated_height = Some(500.0);
7827
7828 CALCULATOR.calc(&mut container);
7829 log::trace!("container:\n{container}");
7830
7831 compare_containers(
7832 &container,
7833 &Container {
7834 children: vec![Container {
7835 calculated_opacity: Some(0.5),
7836 ..container.children[0].clone()
7837 }],
7838 ..container.clone()
7839 },
7840 );
7841 }
7842
7843 #[test_log::test]
7844 fn calc_does_calculate_percentage_opacity() {
7845 let mut container: Container = html! {
7846 div sx-opacity="100%" {}
7847 }
7848 .try_into()
7849 .unwrap();
7850
7851 container.calculated_width = Some(100.0);
7852 container.calculated_height = Some(500.0);
7853
7854 CALCULATOR.calc(&mut container);
7855 log::trace!("container:\n{container}");
7856
7857 compare_containers(
7858 &container,
7859 &Container {
7860 children: vec![Container {
7861 calculated_opacity: Some(1.0),
7862 ..container.children[0].clone()
7863 }],
7864 ..container.clone()
7865 },
7866 );
7867 }
7868
7869 #[test_log::test]
7870 fn calc_includes_fixed_left_margin_in_min_size_with_no_explicit_fixed_size() {
7871 let mut container: Container = html! {
7872 div sx-margin-left=(50.0) {}
7873 }
7874 .try_into()
7875 .unwrap();
7876
7877 container.calculated_width = Some(100.0);
7878 container.calculated_height = Some(500.0);
7879
7880 CALCULATOR.calc(&mut container);
7881 log::trace!("container:\n{container}");
7882
7883 compare_containers(
7884 &container,
7885 &Container {
7886 children: vec![Container {
7887 calculated_width: Some(50.0),
7888 calculated_child_min_width: Some(50.0),
7889 ..container.children[0].clone()
7890 }],
7891 ..container.clone()
7892 },
7893 );
7894 }
7895
7896 #[test_log::test]
7897 fn calc_includes_fixed_right_margin_in_min_size_with_no_explicit_fixed_size() {
7898 let mut container: Container = html! {
7899 div sx-margin-right=(50.0) {}
7900 }
7901 .try_into()
7902 .unwrap();
7903
7904 container.calculated_width = Some(100.0);
7905 container.calculated_height = Some(500.0);
7906
7907 CALCULATOR.calc(&mut container);
7908 log::trace!("container:\n{container}");
7909
7910 compare_containers(
7911 &container,
7912 &Container {
7913 children: vec![Container {
7914 calculated_width: Some(50.0),
7915 calculated_child_min_width: Some(50.0),
7916 ..container.children[0].clone()
7917 }],
7918 ..container.clone()
7919 },
7920 );
7921 }
7922
7923 #[test_log::test]
7924 fn calc_includes_fixed_top_margin_in_min_size_with_no_explicit_fixed_size() {
7925 let mut container: Container = html! {
7926 div sx-margin-top=(50.0) {}
7927 }
7928 .try_into()
7929 .unwrap();
7930
7931 container.calculated_width = Some(100.0);
7932 container.calculated_height = Some(500.0);
7933 container.justify_content = Some(JustifyContent::Start);
7934
7935 CALCULATOR.calc(&mut container);
7936 log::trace!("container:\n{container}");
7937
7938 compare_containers(
7939 &container,
7940 &Container {
7941 children: vec![Container {
7942 calculated_height: Some(0.0),
7943 calculated_child_min_height: Some(50.0),
7944 ..container.children[0].clone()
7945 }],
7946 ..container.clone()
7947 },
7948 );
7949 }
7950
7951 #[test_log::test]
7952 fn calc_includes_fixed_bottom_margin_in_min_size_with_no_explicit_fixed_size() {
7953 let mut container: Container = html! {
7954 div sx-margin-bottom=(50.0) {}
7955 }
7956 .try_into()
7957 .unwrap();
7958
7959 container.calculated_width = Some(100.0);
7960 container.calculated_height = Some(500.0);
7961 container.justify_content = Some(JustifyContent::Start);
7962
7963 CALCULATOR.calc(&mut container);
7964 log::trace!("container:\n{container}");
7965
7966 compare_containers(
7967 &container,
7968 &Container {
7969 children: vec![Container {
7970 calculated_height: Some(0.0),
7971 calculated_child_min_height: Some(50.0),
7972 ..container.children[0].clone()
7973 }],
7974 ..container.clone()
7975 },
7976 );
7977 }
7978
7979 #[test_log::test]
7980 fn calc_includes_fixed_left_margin_in_min_size_with_explicit_fixed_size() {
7981 let mut container: Container = html! {
7982 div sx-margin-left=(50.0) sx-width=(25.0) {}
7983 }
7984 .try_into()
7985 .unwrap();
7986
7987 container.calculated_width = Some(100.0);
7988 container.calculated_height = Some(500.0);
7989 container.justify_content = Some(JustifyContent::Start);
7990
7991 CALCULATOR.calc(&mut container);
7992 log::trace!("container:\n{container}");
7993
7994 compare_containers(
7995 &container,
7996 &Container {
7997 children: vec![Container {
7998 calculated_width: Some(25.0),
7999 calculated_child_min_width: Some(75.0),
8000 ..container.children[0].clone()
8001 }],
8002 ..container.clone()
8003 },
8004 );
8005 }
8006
8007 #[test_log::test]
8008 fn calc_includes_fixed_right_margin_in_min_size_with_explicit_fixed_size() {
8009 let mut container: Container = html! {
8010 div sx-margin-right=(50.0) sx-width=(25.0) {}
8011 }
8012 .try_into()
8013 .unwrap();
8014
8015 container.calculated_width = Some(100.0);
8016 container.calculated_height = Some(500.0);
8017 container.justify_content = Some(JustifyContent::Start);
8018
8019 CALCULATOR.calc(&mut container);
8020 log::trace!("container:\n{container}");
8021
8022 compare_containers(
8023 &container,
8024 &Container {
8025 children: vec![Container {
8026 calculated_width: Some(25.0),
8027 calculated_child_min_width: Some(75.0),
8028 ..container.children[0].clone()
8029 }],
8030 ..container.clone()
8031 },
8032 );
8033 }
8034
8035 #[test_log::test]
8036 fn calc_includes_fixed_top_margin_in_min_size_with_explicit_fixed_size() {
8037 let mut container: Container = html! {
8038 div sx-margin-top=(50.0) sx-height=(25.0) {}
8039 }
8040 .try_into()
8041 .unwrap();
8042
8043 container.calculated_width = Some(100.0);
8044 container.calculated_height = Some(500.0);
8045 container.justify_content = Some(JustifyContent::Start);
8046
8047 CALCULATOR.calc(&mut container);
8048 log::trace!("container:\n{container}");
8049
8050 compare_containers(
8051 &container,
8052 &Container {
8053 children: vec![Container {
8054 calculated_height: Some(25.0),
8055 calculated_child_min_height: Some(75.0),
8056 ..container.children[0].clone()
8057 }],
8058 ..container.clone()
8059 },
8060 );
8061 }
8062
8063 #[test_log::test]
8064 fn calc_includes_fixed_bottom_margin_in_min_size_with_explicit_fixed_size() {
8065 let mut container: Container = html! {
8066 div sx-margin-bottom=(50.0) sx-height=(25.0) {}
8067 }
8068 .try_into()
8069 .unwrap();
8070
8071 container.calculated_width = Some(100.0);
8072 container.calculated_height = Some(500.0);
8073 container.justify_content = Some(JustifyContent::Start);
8074
8075 CALCULATOR.calc(&mut container);
8076 log::trace!("container:\n{container}");
8077
8078 compare_containers(
8079 &container,
8080 &Container {
8081 children: vec![Container {
8082 calculated_height: Some(25.0),
8083 calculated_child_min_height: Some(75.0),
8084 ..container.children[0].clone()
8085 }],
8086 ..container.clone()
8087 },
8088 );
8089 }
8090
8091 #[test_log::test]
8092 fn calc_includes_fixed_left_padding_in_min_size_with_no_explicit_fixed_size() {
8093 let mut container: Container = html! {
8094 div sx-padding-left=(50.0) {}
8095 }
8096 .try_into()
8097 .unwrap();
8098
8099 container.calculated_width = Some(100.0);
8100 container.calculated_height = Some(500.0);
8101 container.justify_content = Some(JustifyContent::Start);
8102
8103 CALCULATOR.calc(&mut container);
8104 log::trace!("container:\n{container}");
8105
8106 compare_containers(
8107 &container,
8108 &Container {
8109 children: vec![Container {
8110 calculated_width: Some(50.0),
8111 calculated_child_min_width: Some(50.0),
8112 ..container.children[0].clone()
8113 }],
8114 ..container.clone()
8115 },
8116 );
8117 }
8118
8119 #[test_log::test]
8120 fn calc_includes_fixed_right_padding_in_min_size_with_no_explicit_fixed_size() {
8121 let mut container: Container = html! {
8122 div sx-padding-right=(50.0) {}
8123 }
8124 .try_into()
8125 .unwrap();
8126
8127 container.calculated_width = Some(100.0);
8128 container.calculated_height = Some(500.0);
8129 container.justify_content = Some(JustifyContent::Start);
8130
8131 CALCULATOR.calc(&mut container);
8132 log::trace!("container:\n{container}");
8133
8134 compare_containers(
8135 &container,
8136 &Container {
8137 children: vec![Container {
8138 calculated_width: Some(50.0),
8139 calculated_child_min_width: Some(50.0),
8140 ..container.children[0].clone()
8141 }],
8142 ..container.clone()
8143 },
8144 );
8145 }
8146
8147 #[test_log::test]
8148 fn calc_includes_fixed_top_padding_in_min_size_with_no_explicit_fixed_size() {
8149 let mut container: Container = html! {
8150 div sx-padding-top=(50.0) {}
8151 }
8152 .try_into()
8153 .unwrap();
8154
8155 container.calculated_width = Some(100.0);
8156 container.calculated_height = Some(500.0);
8157 container.justify_content = Some(JustifyContent::Start);
8158
8159 CALCULATOR.calc(&mut container);
8160 log::trace!("container:\n{container}");
8161
8162 compare_containers(
8163 &container,
8164 &Container {
8165 children: vec![Container {
8166 calculated_height: Some(0.0),
8167 calculated_child_min_height: Some(50.0),
8168 ..container.children[0].clone()
8169 }],
8170 ..container.clone()
8171 },
8172 );
8173 }
8174
8175 #[test_log::test]
8176 fn calc_includes_fixed_bottom_padding_in_min_size_with_no_explicit_fixed_size() {
8177 let mut container: Container = html! {
8178 div sx-padding-bottom=(50.0) {}
8179 }
8180 .try_into()
8181 .unwrap();
8182
8183 container.calculated_width = Some(100.0);
8184 container.calculated_height = Some(500.0);
8185 container.justify_content = Some(JustifyContent::Start);
8186
8187 CALCULATOR.calc(&mut container);
8188 log::trace!("container:\n{container}");
8189
8190 compare_containers(
8191 &container,
8192 &Container {
8193 children: vec![Container {
8194 calculated_height: Some(0.0),
8195 calculated_child_min_height: Some(50.0),
8196 ..container.children[0].clone()
8197 }],
8198 ..container.clone()
8199 },
8200 );
8201 }
8202
8203 #[test_log::test]
8204 fn calc_includes_fixed_left_padding_in_min_size_with_explicit_fixed_size() {
8205 let mut container: Container = html! {
8206 div sx-padding-left=(50.0) sx-width=(25.0) {}
8207 }
8208 .try_into()
8209 .unwrap();
8210
8211 container.calculated_width = Some(100.0);
8212 container.calculated_height = Some(500.0);
8213 container.justify_content = Some(JustifyContent::Start);
8214
8215 CALCULATOR.calc(&mut container);
8216 log::trace!("container:\n{container}");
8217
8218 compare_containers(
8219 &container,
8220 &Container {
8221 children: vec![Container {
8222 calculated_width: Some(25.0),
8223 calculated_child_min_width: Some(75.0),
8224 ..container.children[0].clone()
8225 }],
8226 ..container.clone()
8227 },
8228 );
8229 }
8230
8231 #[test_log::test]
8232 fn calc_includes_fixed_right_padding_in_min_size_with_explicit_fixed_size() {
8233 let mut container: Container = html! {
8234 div sx-padding-right=(50.0) sx-width=(25.0) {}
8235 }
8236 .try_into()
8237 .unwrap();
8238
8239 container.calculated_width = Some(100.0);
8240 container.calculated_height = Some(500.0);
8241 container.justify_content = Some(JustifyContent::Start);
8242
8243 CALCULATOR.calc(&mut container);
8244 log::trace!("container:\n{container}");
8245
8246 compare_containers(
8247 &container,
8248 &Container {
8249 children: vec![Container {
8250 calculated_width: Some(25.0),
8251 calculated_child_min_width: Some(75.0),
8252 ..container.children[0].clone()
8253 }],
8254 ..container.clone()
8255 },
8256 );
8257 }
8258
8259 #[test_log::test]
8260 fn calc_includes_fixed_top_padding_in_min_size_with_explicit_fixed_size() {
8261 let mut container: Container = html! {
8262 div sx-padding-top=(50.0) sx-height=(25.0) {}
8263 }
8264 .try_into()
8265 .unwrap();
8266
8267 container.calculated_width = Some(100.0);
8268 container.calculated_height = Some(500.0);
8269 container.justify_content = Some(JustifyContent::Start);
8270
8271 CALCULATOR.calc(&mut container);
8272 log::trace!("container:\n{container}");
8273
8274 compare_containers(
8275 &container,
8276 &Container {
8277 children: vec![Container {
8278 calculated_height: Some(25.0),
8279 calculated_child_min_height: Some(75.0),
8280 ..container.children[0].clone()
8281 }],
8282 ..container.clone()
8283 },
8284 );
8285 }
8286
8287 #[test_log::test]
8288 fn calc_includes_fixed_bottom_padding_in_min_size_with_explicit_fixed_size() {
8289 let mut container: Container = html! {
8290 div sx-padding-bottom=(50.0) sx-height=(25.0) {}
8291 }
8292 .try_into()
8293 .unwrap();
8294
8295 container.calculated_width = Some(100.0);
8296 container.calculated_height = Some(500.0);
8297 container.justify_content = Some(JustifyContent::Start);
8298
8299 CALCULATOR.calc(&mut container);
8300 log::trace!("container:\n{container}");
8301
8302 compare_containers(
8303 &container,
8304 &Container {
8305 children: vec![Container {
8306 calculated_height: Some(25.0),
8307 calculated_child_min_height: Some(75.0),
8308 ..container.children[0].clone()
8309 }],
8310 ..container.clone()
8311 },
8312 );
8313 }
8314
8315 #[test_log::test]
8316 fn calc_evenly_distributes_row_width_even_when_one_child_has_a_min_width() {
8317 let mut container: Container = html! {
8318 div sx-dir="row" {
8319 div {}
8320 div {
8321 div sx-width=(50) {}
8322 }
8323 }
8324 }
8325 .try_into()
8326 .unwrap();
8327
8328 container.calculated_width = Some(400.0);
8329 container.calculated_height = Some(100.0);
8330 container.justify_content = Some(JustifyContent::Start);
8331 CALCULATOR.calc(&mut container);
8332 log::trace!("container:\n{container}");
8333
8334 compare_containers(
8335 &container,
8336 &Container {
8337 children: vec![Container {
8338 children: vec![
8339 Container {
8340 calculated_width: Some(0.0),
8341 calculated_height: Some(0.0),
8342 ..container.children[0].children[0].clone()
8343 },
8344 Container {
8345 calculated_width: Some(50.0),
8346 calculated_height: Some(0.0),
8347 ..container.children[0].children[1].clone()
8348 },
8349 ],
8350 calculated_width: Some(400.0),
8351 calculated_height: Some(0.0),
8352 ..container.children[0].clone()
8353 }],
8354 calculated_width: Some(400.0),
8355 calculated_height: Some(100.0),
8356 ..container.clone()
8357 },
8358 );
8359 }
8360
8361 #[test_log::test]
8362 fn calc_only_takes_height_necessary_for_non_flex_container_contents() {
8363 let mut container: Container = html! {
8364 div {
8365 div sx-height=(10) {}
8366 }
8367 div {
8368 div sx-height=(15) {}
8369 }
8370 }
8371 .try_into()
8372 .unwrap();
8373
8374 container.calculated_width = Some(400.0);
8375 container.calculated_height = Some(100.0);
8376
8377 CALCULATOR.calc(&mut container);
8378 log::trace!("container:\n{container}");
8379
8380 compare_containers(
8381 &container,
8382 &Container {
8383 children: vec![
8384 Container {
8385 calculated_width: Some(400.0),
8386 calculated_height: Some(10.0),
8387 ..container.children[0].clone()
8388 },
8389 Container {
8390 calculated_width: Some(400.0),
8391 calculated_height: Some(15.0),
8392 ..container.children[1].clone()
8393 },
8394 ],
8395 calculated_width: Some(400.0),
8396 calculated_height: Some(100.0),
8397 ..container.clone()
8398 },
8399 );
8400 }
8401
8402 #[test_log::test]
8403 fn calc_only_takes_height_necessary_for_flex_cross_axis_column_container_contents_when_align_items_is_set()
8404 {
8405 let mut container: Container = html! {
8406 div sx-dir=(LayoutDirection::Row) sx-align-items=(AlignItems::Center) sx-height=(50) {
8407 div { div { "one" } div { "two" } }
8408 div { "three" }
8409 }
8410 }
8411 .try_into()
8412 .unwrap();
8413
8414 container.calculated_width = Some(400.0);
8415 container.calculated_height = Some(100.0);
8416
8417 CALCULATOR.calc(&mut container);
8418 log::trace!("full container:\n{container}");
8419 container = container.children[0].clone();
8420 log::trace!("container:\n{container}");
8421
8422 compare_containers(
8423 &container,
8424 &Container {
8425 children: vec![
8426 Container {
8427 calculated_height: Some(14.0 * 2.0),
8428 ..container.children[0].clone()
8429 },
8430 Container {
8431 calculated_height: Some(14.0),
8432 ..container.children[1].clone()
8433 },
8434 ],
8435 calculated_height: Some(50.0),
8436 ..container.clone()
8437 },
8438 );
8439 }
8440
8441 #[test_log::test]
8442 fn calc_only_takes_height_necessary_for_flex_cross_axis_row_container_contents_when_align_items_is_set()
8443 {
8444 let mut container: Container = html! {
8445 div sx-align-items=(AlignItems::Center) sx-width=(150) {
8446 div sx-dir=(LayoutDirection::Row) { div { "one" } div { "two" } }
8447 div sx-dir=(LayoutDirection::Row) { "three" }
8448 }
8449 }
8450 .try_into()
8451 .unwrap();
8452
8453 container.calculated_width = Some(400.0);
8454 container.calculated_height = Some(100.0);
8455
8456 CALCULATOR.calc(&mut container);
8457 log::trace!("full container:\n{container}");
8458 container = container.children[0].clone();
8459 log::trace!("container:\n{container}");
8460
8461 compare_containers(
8462 &container,
8463 &Container {
8464 children: vec![
8465 Container {
8466 calculated_width: Some(14.0 * 6.0),
8467 ..container.children[0].clone()
8468 },
8469 Container {
8470 calculated_width: Some(14.0 * 5.0),
8471 ..container.children[1].clone()
8472 },
8473 ],
8474 calculated_width: Some(150.0),
8475 ..container.clone()
8476 },
8477 );
8478 }
8479
8480 #[test_log::test]
8481 fn calc_direction_row_doesnt_take_full_width() {
8482 let mut container: Container = html! {
8483 div sx-width=(200) sx-dir=(LayoutDirection::Row) {
8484 h1 { "test" }
8485 div sx-width=(10) {}
8486 }
8487 }
8488 .try_into()
8489 .unwrap();
8490
8491 container.calculated_width = Some(400.0);
8492 container.calculated_height = Some(100.0);
8493
8494 CALCULATOR.calc(&mut container);
8495 log::trace!("full container:\n{container}");
8496 container = container.children[0].clone();
8497 log::trace!("container:\n{container}");
8498
8499 compare_containers(
8500 &container,
8501 &Container {
8502 children: vec![
8503 Container {
8504 calculated_width: Some(32.0 * 4.0),
8505 ..container.children[0].clone()
8506 },
8507 Container {
8508 calculated_width: Some(10.0),
8509 ..container.children[1].clone()
8510 },
8511 ],
8512 calculated_width: Some(200.0),
8513 ..container.clone()
8514 },
8515 );
8516 }
8517
8518 mod text {
8519 use super::*;
8520
8521 #[test_log::test]
8522 fn does_calculate_text_height_properly() {
8523 let mut container: Container = html! {
8524 div { "test" }
8525 }
8526 .try_into()
8527 .unwrap();
8528
8529 container.calculated_width = Some(400.0);
8530 container.calculated_height = Some(100.0);
8531
8532 CALCULATOR.calc(&mut container);
8533 log::trace!("full container:\n{container}");
8534 container = container.children[0].clone();
8535 log::trace!("container:\n{container}");
8536
8537 compare_containers(
8538 &container,
8539 &Container {
8540 children: vec![Container {
8541 calculated_height: Some(14.0),
8542 ..container.children[0].clone()
8543 }],
8544 ..container.clone()
8545 },
8546 );
8547 }
8548
8549 #[test_log::test]
8550 fn does_propagate_text_height_properly() {
8551 let mut container: Container = html! {
8552 div { "test" }
8553 }
8554 .try_into()
8555 .unwrap();
8556
8557 container.calculated_width = Some(400.0);
8558 container.calculated_height = Some(100.0);
8559
8560 CALCULATOR.calc(&mut container);
8561 log::trace!("full container:\n{container}");
8562 container = container.children[0].clone();
8563 log::trace!("container:\n{container}");
8564
8565 compare_containers(
8566 &container,
8567 &Container {
8568 children: vec![Container {
8569 calculated_height: Some(14.0),
8570 ..container.children[0].clone()
8571 }],
8572 calculated_height: Some(14.0),
8573 ..container.clone()
8574 },
8575 );
8576 }
8577
8578 #[test_log::test]
8579 fn does_use_preferred_width_for_nested_text() {
8580 let mut container: Container = html! {
8581 div sx-dir=(LayoutDirection::Row) sx-align-items=(AlignItems::Start) {
8582 "test" span { "two" }
8583 }
8584 }
8585 .try_into()
8586 .unwrap();
8587
8588 container.calculated_width = Some(400.0);
8589 container.calculated_height = Some(100.0);
8590
8591 CALCULATOR.calc(&mut container);
8592 log::trace!("full container:\n{container}");
8593 container = container.children[0].clone();
8594 log::trace!("container:\n{container}");
8595
8596 compare_containers(
8597 &container,
8598 &Container {
8599 children: vec![
8600 Container {
8601 calculated_width: Some(14.0 * 4.0),
8602 ..container.children[0].clone()
8603 },
8604 Container {
8605 calculated_width: Some(14.0 * 3.0),
8606 ..container.children[1].clone()
8607 },
8608 ],
8609 ..container.clone()
8610 },
8611 );
8612 }
8613
8614 #[test_log::test]
8615 fn does_use_preferred_width_for_nested_text_in_dynamically_sized_child() {
8616 let mut container: Container = html! {
8617 div sx-dir=(LayoutDirection::Row) sx-align-items=(AlignItems::Center) {
8618 div sx-justify-content=(JustifyContent::Center) {
8619 div sx-dir=(LayoutDirection::Row) {
8620 "test" span { "two" }
8621 }
8622 }
8623 }
8624 }
8625 .try_into()
8626 .unwrap();
8627
8628 container.calculated_width = Some(400.0);
8629 container.calculated_height = Some(100.0);
8630
8631 CALCULATOR.calc(&mut container);
8632 log::trace!("full container:\n{container}");
8633 container = container.children[0].clone();
8634 log::trace!("container:\n{container}");
8635
8636 compare_containers(
8637 &container,
8638 &Container {
8639 children: vec![Container {
8640 children: vec![Container {
8641 children: vec![
8642 Container {
8643 calculated_width: Some(14.0 * 4.0),
8644 ..container.children[0].children[0].children[0].clone()
8645 },
8646 Container {
8647 calculated_width: Some(14.0 * 3.0),
8648 ..container.children[0].children[0].children[1].clone()
8649 },
8650 ],
8651 calculated_width: Some(14.0 * (4.0 + 3.0)),
8652 ..container.children[0].children[0].clone()
8653 }],
8654 ..container.children[0].clone()
8655 }],
8656 ..container.clone()
8657 },
8658 );
8659 }
8660
8661 #[test_log::test]
8662 fn does_not_expand_past_preferred_width() {
8663 let mut container: Container = html! {
8664 div sx-width=(100) { "test" }
8665 }
8666 .try_into()
8667 .unwrap();
8668
8669 container.calculated_width = Some(400.0);
8670 container.calculated_height = Some(100.0);
8671
8672 CALCULATOR.calc(&mut container);
8673 log::trace!("full container:\n{container}");
8674 container = container.children[0].clone();
8675 log::trace!("container:\n{container}");
8676
8677 compare_containers(
8678 &container,
8679 &Container {
8680 children: vec![Container {
8681 calculated_width: Some(14.0 * 4.0),
8682 ..container.children[0].clone()
8683 }],
8684 calculated_width: Some(100.0),
8685 ..container.clone()
8686 },
8687 );
8688 }
8689
8690 #[test_log::test]
8691 fn does_wrap_long_line_of_text_to_2_lines() {
8692 let mut container: Container = html! {
8693 div sx-width=(100) { "test test" }
8694 }
8695 .try_into()
8696 .unwrap();
8697
8698 container.calculated_width = Some(400.0);
8699 container.calculated_height = Some(100.0);
8700
8701 CALCULATOR.calc(&mut container);
8702 log::trace!("full container:\n{container}");
8703 container = container.children[0].clone();
8704 log::trace!("container:\n{container}");
8705
8706 compare_containers(
8707 &container,
8708 &Container {
8709 children: vec![Container {
8710 calculated_width: Some(100.0),
8711 calculated_height: Some(14.0 * 2.0),
8712 ..container.children[0].clone()
8713 }],
8714 calculated_width: Some(100.0),
8715 ..container.clone()
8716 },
8717 );
8718 }
8719
8720 #[test_log::test]
8721 fn does_wrap_nested_text_longer_than_container_can_fit() {
8722 let mut container: Container = html! {
8723 div sx-width=(200) {
8724 span { "aoeu aoeu aoeu aoeu aoeu" }
8725 }
8726 }
8727 .try_into()
8728 .unwrap();
8729
8730 container.calculated_width = Some(400.0);
8731 container.calculated_height = Some(100.0);
8732
8733 CALCULATOR.calc(&mut container);
8734 log::trace!("full container:\n{container}");
8735 container = container.children[0].clone();
8736 log::trace!("container:\n{container}");
8737
8738 compare_containers(
8739 &container,
8740 &Container {
8741 children: vec![Container {
8742 calculated_width: Some(200.0),
8743 calculated_height: Some(14.0 * 2.0),
8744 ..container.children[0].clone()
8745 }],
8746 calculated_width: Some(200.0),
8747 ..container.clone()
8748 },
8749 );
8750 }
8751
8752 #[test_log::test]
8753 fn does_wrap_nested_text_longer_than_container_can_fit_with_align_items_center() {
8754 let mut container: Container = html! {
8755 div sx-width=(200) sx-align-items=(AlignItems::Center) {
8756 span { "aoeu aoeu aoeu aoeu aoeu" }
8757 }
8758 }
8759 .try_into()
8760 .unwrap();
8761
8762 container.calculated_width = Some(400.0);
8763 container.calculated_height = Some(100.0);
8764
8765 CALCULATOR.calc(&mut container);
8766 log::trace!("full container:\n{container}");
8767 container = container.children[0].clone();
8768 log::trace!("container:\n{container}");
8769
8770 compare_containers(
8771 &container,
8772 &Container {
8773 children: vec![Container {
8774 calculated_width: Some(200.0),
8775 calculated_height: Some(14.0 * 2.0),
8776 ..container.children[0].clone()
8777 }],
8778 calculated_width: Some(200.0),
8779 ..container.clone()
8780 },
8781 );
8782 }
8783
8784 #[test_log::test]
8785 fn does_wrap_text_longer_than_nested_div_container_can_fit_with_align_items_center() {
8786 let mut container: Container = html! {
8787 div sx-width=(200) sx-align-items=(AlignItems::Center) {
8788 div { "aoeu aoeu aoeu aoeu aoeu" }
8789 }
8790 }
8791 .try_into()
8792 .unwrap();
8793
8794 container.calculated_width = Some(400.0);
8795 container.calculated_height = Some(100.0);
8796
8797 CALCULATOR.calc(&mut container);
8798 log::trace!("full container:\n{container}");
8799 container = container.children[0].clone();
8800 log::trace!("container:\n{container}");
8801
8802 compare_containers(
8803 &container,
8804 &Container {
8805 children: vec![Container {
8806 calculated_width: Some(200.0),
8807 calculated_height: Some(14.0 * 2.0),
8808 ..container.children[0].clone()
8809 }],
8810 calculated_width: Some(200.0),
8811 ..container.clone()
8812 },
8813 );
8814 }
8815
8816 #[test_log::test]
8817 fn does_use_default_font_size() {
8818 let mut container: Container = html! {
8819 "aoeu"
8820 }
8821 .try_into()
8822 .unwrap();
8823
8824 container.calculated_font_size = Some(20.0);
8825 container.calculated_width = Some(400.0);
8826 container.calculated_height = Some(100.0);
8827
8828 let calculator = Calculator::new(
8829 DefaultFontMetrics,
8830 CalculatorDefaults {
8831 font_size: 20.0,
8832 ..Default::default()
8833 },
8834 );
8835 calculator.calc(&mut container);
8836 log::trace!("container:\n{container}");
8837
8838 compare_containers(
8839 &container,
8840 &Container {
8841 children: vec![Container {
8842 calculated_width: Some(20.0 * 4.0),
8843 calculated_height: Some(20.0),
8844 ..container.children[0].clone()
8845 }],
8846 ..container.clone()
8847 },
8848 );
8849 }
8850
8851 #[test_log::test]
8852 fn does_use_direct_parent_fixed_font_size() {
8853 let mut container: Container = html! {
8854 div sx-font-size=(10) {
8855 "aoeu"
8856 }
8857 }
8858 .try_into()
8859 .unwrap();
8860
8861 container.calculated_width = Some(400.0);
8862 container.calculated_height = Some(100.0);
8863
8864 let calculator = Calculator::new(
8865 DefaultFontMetrics,
8866 CalculatorDefaults {
8867 font_size: 20.0,
8868 ..Default::default()
8869 },
8870 );
8871 calculator.calc(&mut container);
8872 log::trace!("container:\n{container}");
8873
8874 compare_containers(
8875 &container,
8876 &Container {
8877 children: vec![Container {
8878 children: vec![Container {
8879 calculated_width: Some(10.0 * 4.0),
8880 calculated_height: Some(10.0),
8881 ..container.children[0].children[0].clone()
8882 }],
8883 ..container.children[0].clone()
8884 }],
8885 ..container.clone()
8886 },
8887 );
8888 }
8889
8890 #[test_log::test]
8891 fn does_use_direct_parent_dynamic_font_size() {
8892 let mut container: Container = html! {
8893 div sx-font-size="80%" {
8894 "aoeu"
8895 }
8896 }
8897 .try_into()
8898 .unwrap();
8899
8900 container.calculated_width = Some(400.0);
8901 container.calculated_height = Some(100.0);
8902
8903 let calculator = Calculator::new(
8904 DefaultFontMetrics,
8905 CalculatorDefaults {
8906 font_size: 20.0,
8907 ..Default::default()
8908 },
8909 );
8910 calculator.calc(&mut container);
8911 log::trace!("container:\n{container}");
8912
8913 compare_containers(
8914 &container,
8915 &Container {
8916 children: vec![Container {
8917 children: vec![Container {
8918 calculated_width: Some(16.0 * 4.0),
8919 calculated_height: Some(16.0),
8920 ..container.children[0].children[0].clone()
8921 }],
8922 ..container.children[0].clone()
8923 }],
8924 ..container.clone()
8925 },
8926 );
8927 }
8928
8929 #[test_log::test]
8930 fn does_use_ascestor_fixed_font_size() {
8931 let mut container: Container = html! {
8932 div sx-font-size=(10) {
8933 div { "aoeu" }
8934 }
8935 }
8936 .try_into()
8937 .unwrap();
8938
8939 container.calculated_width = Some(400.0);
8940 container.calculated_height = Some(100.0);
8941
8942 let calculator = Calculator::new(
8943 DefaultFontMetrics,
8944 CalculatorDefaults {
8945 font_size: 20.0,
8946 ..Default::default()
8947 },
8948 );
8949 calculator.calc(&mut container);
8950 log::trace!("container:\n{container}");
8951
8952 compare_containers(
8953 &container,
8954 &Container {
8955 children: vec![Container {
8956 children: vec![Container {
8957 children: vec![Container {
8958 calculated_width: Some(10.0 * 4.0),
8959 calculated_height: Some(10.0),
8960 ..container.children[0].children[0].children[0].clone()
8961 }],
8962 ..container.children[0].children[0].clone()
8963 }],
8964 ..container.children[0].clone()
8965 }],
8966 ..container.clone()
8967 },
8968 );
8969 }
8970
8971 #[test_log::test]
8972 fn does_use_ascestor_dynamic_font_size() {
8973 let mut container: Container = html! {
8974 div sx-font-size="80%" {
8975 div { "aoeu" }
8976 }
8977 }
8978 .try_into()
8979 .unwrap();
8980
8981 container.calculated_width = Some(400.0);
8982 container.calculated_height = Some(100.0);
8983
8984 let calculator = Calculator::new(
8985 DefaultFontMetrics,
8986 CalculatorDefaults {
8987 font_size: 20.0,
8988 ..Default::default()
8989 },
8990 );
8991 calculator.calc(&mut container);
8992 log::trace!("container:\n{container}");
8993
8994 compare_containers(
8995 &container,
8996 &Container {
8997 children: vec![Container {
8998 children: vec![Container {
8999 children: vec![Container {
9000 calculated_width: Some(16.0 * 4.0),
9001 calculated_height: Some(16.0),
9002 ..container.children[0].children[0].children[0].clone()
9003 }],
9004 ..container.children[0].children[0].clone()
9005 }],
9006 ..container.children[0].clone()
9007 }],
9008 ..container.clone()
9009 },
9010 );
9011 }
9012
9013 #[test_log::test]
9014 fn doesnt_use_sibling_fixed_font_size() {
9015 let mut container: Container = html! {
9016 div sx-font-size=(10) {}
9017 div { "aoeu" }
9018 }
9019 .try_into()
9020 .unwrap();
9021
9022 container.calculated_width = Some(400.0);
9023 container.calculated_height = Some(100.0);
9024
9025 let calculator = Calculator::new(
9026 DefaultFontMetrics,
9027 CalculatorDefaults {
9028 font_size: 20.0,
9029 ..Default::default()
9030 },
9031 );
9032 calculator.calc(&mut container);
9033 log::trace!("container:\n{container}");
9034
9035 compare_containers(
9036 &container,
9037 &Container {
9038 children: vec![
9039 container.children[0].clone(),
9040 Container {
9041 children: vec![Container {
9042 calculated_width: Some(20.0 * 4.0),
9043 calculated_height: Some(20.0),
9044 ..container.children[1].children[0].clone()
9045 }],
9046 ..container.children[1].clone()
9047 },
9048 ],
9049 ..container.clone()
9050 },
9051 );
9052 }
9053
9054 #[test_log::test]
9055 fn doesnt_use_sibling_dynamic_font_size() {
9056 let mut container: Container = html! {
9057 div sx-font-size="80%" {}
9058 div { "aoeu" }
9059 }
9060 .try_into()
9061 .unwrap();
9062
9063 container.calculated_width = Some(400.0);
9064 container.calculated_height = Some(100.0);
9065
9066 let calculator = Calculator::new(
9067 DefaultFontMetrics,
9068 CalculatorDefaults {
9069 font_size: 20.0,
9070 ..Default::default()
9071 },
9072 );
9073 calculator.calc(&mut container);
9074 log::trace!("container:\n{container}");
9075
9076 compare_containers(
9077 &container,
9078 &Container {
9079 children: vec![
9080 container.children[0].clone(),
9081 Container {
9082 children: vec![Container {
9083 calculated_width: Some(20.0 * 4.0),
9084 calculated_height: Some(20.0),
9085 ..container.children[1].children[0].clone()
9086 }],
9087 ..container.children[1].clone()
9088 },
9089 ],
9090 ..container.clone()
9091 },
9092 );
9093 }
9094
9095 macro_rules! test_heading {
9096 ($heading:tt, $font_size:ident, $margin_top:ident, $margin_bottom:ident $(,)?) => {
9097 paste! {
9098 #[test_log::test]
9099 fn [<does_use_ $heading _font_size>]() {
9100 let mut container: Container = html! {
9101 $heading {
9102 "aoeu"
9103 }
9104 }
9105 .try_into()
9106 .unwrap();
9107
9108 container.calculated_font_size = Some(20.0);
9109 container.calculated_width = Some(400.0);
9110 container.calculated_height = Some(100.0);
9111
9112 let calculator = Calculator::new(
9113 DefaultFontMetrics,
9114 CalculatorDefaults {
9115 font_size: 20.0,
9116 $font_size: 30.0,
9117 ..Default::default()
9118 },
9119 );
9120 calculator.calc(&mut container);
9121 log::trace!("container:\n{}", container);
9122
9123 compare_containers(
9124 &container,
9125 &Container {
9126 children: vec![Container {
9127 calculated_font_size: Some(30.0),
9128 ..container.children[0].clone()
9129 }],
9130 calculated_font_size: Some(20.0),
9131 ..container.clone()
9132 },
9133 );
9134 }
9135
9136 #[test_log::test]
9137 fn [<does_use_ $heading _font_size_for_raw_child>]() {
9138 let mut container: Container = html! {
9139 $heading {
9140 "aoeu"
9141 }
9142 }
9143 .try_into()
9144 .unwrap();
9145
9146 container.calculated_font_size = Some(20.0);
9147 container.calculated_width = Some(400.0);
9148 container.calculated_height = Some(100.0);
9149
9150 let calculator = Calculator::new(
9151 DefaultFontMetrics,
9152 CalculatorDefaults {
9153 font_size: 20.0,
9154 $font_size: 30.0,
9155 ..Default::default()
9156 },
9157 );
9158 calculator.calc(&mut container);
9159 log::trace!("container:\n{}", container);
9160
9161 compare_containers(
9162 &container,
9163 &Container {
9164 children: vec![Container {
9165 children: vec![Container {
9166 calculated_font_size: Some(30.0),
9167 ..container.children[0].children[0].clone()
9168 }],
9169 calculated_font_size: Some(30.0),
9170 ..container.children[0].clone()
9171 }],
9172 calculated_font_size: Some(20.0),
9173 ..container.clone()
9174 },
9175 );
9176 }
9177
9178 #[test_log::test]
9179 fn [<does_use_ $heading _font_size_for_nested_raw_child>]() {
9180 let mut container: Container = html! {
9181 $heading {
9182 div {
9183 "aoeu"
9184 }
9185 }
9186 }
9187 .try_into()
9188 .unwrap();
9189
9190 container.calculated_font_size = Some(20.0);
9191 container.calculated_width = Some(400.0);
9192 container.calculated_height = Some(100.0);
9193
9194 let calculator = Calculator::new(
9195 DefaultFontMetrics,
9196 CalculatorDefaults {
9197 font_size: 20.0,
9198 $font_size: 30.0,
9199 ..Default::default()
9200 },
9201 );
9202 calculator.calc(&mut container);
9203 log::trace!("container:\n{}", container);
9204
9205 compare_containers(
9206 &container,
9207 &Container {
9208 children: vec![Container {
9209 children: vec![Container {
9210 children: vec![Container {
9211 calculated_font_size: Some(30.0),
9212 ..container.children[0].children[0].children[0].clone()
9213 }],
9214 calculated_font_size: Some(30.0),
9215 ..container.children[0].children[0].clone()
9216 }],
9217 calculated_font_size: Some(30.0),
9218 ..container.children[0].clone()
9219 }],
9220 calculated_font_size: Some(20.0),
9221 ..container.clone()
9222 },
9223 );
9224 }
9225
9226 #[test_log::test]
9227 fn [<does_use_ $margin_top>]() {
9228 let mut container: Container = html! {
9229 $heading {
9230 "aoeu"
9231 }
9232 }
9233 .try_into()
9234 .unwrap();
9235
9236 container.calculated_font_size = Some(20.0);
9237 container.calculated_width = Some(400.0);
9238 container.calculated_height = Some(100.0);
9239
9240 let calculator = Calculator::new(
9241 DefaultFontMetrics,
9242 CalculatorDefaults {
9243 font_size: 20.0,
9244 $font_size: 30.0,
9245 $margin_top: 6.0,
9246 ..Default::default()
9247 },
9248 );
9249 calculator.calc(&mut container);
9250 log::trace!("container:\n{}", container);
9251
9252 compare_containers(
9253 &container,
9254 &Container {
9255 children: vec![Container {
9256 calculated_margin_top: Some(6.0),
9257 ..container.children[0].clone()
9258 }],
9259 ..container.clone()
9260 },
9261 );
9262 }
9263 #[test_log::test]
9264 fn [<does_use_ $margin_bottom>]() {
9265 let mut container: Container = html! {
9266 $heading {
9267 "aoeu"
9268 }
9269 }
9270 .try_into()
9271 .unwrap();
9272
9273 container.calculated_font_size = Some(20.0);
9274 container.calculated_width = Some(400.0);
9275 container.calculated_height = Some(100.0);
9276
9277 let calculator = Calculator::new(
9278 DefaultFontMetrics,
9279 CalculatorDefaults {
9280 font_size: 20.0,
9281 $font_size: 30.0,
9282 $margin_bottom: 6.0,
9283 ..Default::default()
9284 },
9285 );
9286 calculator.calc(&mut container);
9287 log::trace!("container:\n{}", container);
9288
9289 compare_containers(
9290 &container,
9291 &Container {
9292 children: vec![Container {
9293 calculated_margin_bottom: Some(6.0),
9294 ..container.children[0].clone()
9295 }],
9296 ..container.clone()
9297 },
9298 );
9299 }
9300
9301 #[test_log::test]
9302 fn [<doesnt_propagate_ $margin_top _to_children>]() {
9303 let mut container: Container = html! {
9304 $heading {
9305 "aoeu"
9306 }
9307 }
9308 .try_into()
9309 .unwrap();
9310
9311 container.calculated_font_size = Some(20.0);
9312 container.calculated_width = Some(400.0);
9313 container.calculated_height = Some(100.0);
9314
9315 let calculator = Calculator::new(
9316 DefaultFontMetrics,
9317 CalculatorDefaults {
9318 font_size: 20.0,
9319 $font_size: 30.0,
9320 $margin_top: 6.0,
9321 ..Default::default()
9322 },
9323 );
9324 calculator.calc(&mut container);
9325 log::trace!("container:\n{}", container);
9326
9327 compare_containers(
9328 &container,
9329 &Container {
9330 children: vec![Container {
9331 children: vec![Container {
9332 calculated_margin_bottom: None,
9333 ..container.children[0].children[0].clone()
9334 }],
9335 calculated_margin_top: Some(6.0),
9336 ..container.children[0].clone()
9337 }],
9338 ..container.clone()
9339 },
9340 );
9341 }
9342
9343 #[test_log::test]
9344 fn [<doesnt_propagate_ $margin_bottom _to_children>]() {
9345 let mut container: Container = html! {
9346 $heading {
9347 "aoeu"
9348 }
9349 }
9350 .try_into()
9351 .unwrap();
9352
9353 container.calculated_font_size = Some(20.0);
9354 container.calculated_width = Some(400.0);
9355 container.calculated_height = Some(100.0);
9356
9357 let calculator = Calculator::new(
9358 DefaultFontMetrics,
9359 CalculatorDefaults {
9360 font_size: 20.0,
9361 $font_size: 30.0,
9362 $margin_bottom: 6.0,
9363 ..Default::default()
9364 },
9365 );
9366 calculator.calc(&mut container);
9367 log::trace!("container:\n{}", container);
9368
9369 compare_containers(
9370 &container,
9371 &Container {
9372 children: vec![Container {
9373 children: vec![Container {
9374 calculated_margin_bottom: None,
9375 ..container.children[0].children[0].clone()
9376 }],
9377 calculated_margin_bottom: Some(6.0),
9378 ..container.children[0].clone()
9379 }],
9380 ..container.clone()
9381 },
9382 );
9383 }
9384 }
9385 };
9386 }
9387
9388 test_heading!(h1, h1_font_size, h1_font_margin_top, h1_font_margin_bottom);
9389 test_heading!(h2, h2_font_size, h2_font_margin_top, h2_font_margin_bottom);
9390 test_heading!(h3, h3_font_size, h3_font_margin_top, h3_font_margin_bottom);
9391 test_heading!(h4, h4_font_size, h4_font_margin_top, h4_font_margin_bottom);
9392 test_heading!(h5, h5_font_size, h5_font_margin_top, h5_font_margin_bottom);
9393 test_heading!(h6, h6_font_size, h6_font_margin_top, h6_font_margin_bottom);
9394 }
9395
9396 mod sizing {
9397 use super::*;
9398
9399 #[test_log::test]
9400 fn does_take_into_account_explicit_fixed_min_width() {
9401 let mut container: Container = html! {
9402 div sx-dir=(LayoutDirection::Row) {
9403 div sx-min-width=(100) {}
9404 }
9405 }
9406 .try_into()
9407 .unwrap();
9408
9409 container.calculated_width = Some(400.0);
9410 container.calculated_height = Some(100.0);
9411
9412 CALCULATOR.calc(&mut container);
9413 log::trace!("full container:\n{container}");
9414 container = container.children[0].clone();
9415 log::trace!("container:\n{container}");
9416
9417 compare_containers(
9418 &container,
9419 &Container {
9420 children: vec![Container {
9421 calculated_width: Some(100.0),
9422 ..container.children[0].clone()
9423 }],
9424 calculated_width: Some(400.0),
9425 ..container.clone()
9426 },
9427 );
9428 }
9429
9430 #[test_log::test]
9431 fn does_take_into_account_explicit_fixed_min_width_with_fixed_child_content() {
9432 let mut container: Container = html! {
9433 div sx-dir=(LayoutDirection::Row) {
9434 div sx-min-width=(100) {
9435 div sx-width=(10) {}
9436 }
9437 }
9438 }
9439 .try_into()
9440 .unwrap();
9441
9442 container.calculated_width = Some(400.0);
9443 container.calculated_height = Some(100.0);
9444
9445 CALCULATOR.calc(&mut container);
9446 log::trace!("full container:\n{container}");
9447 container = container.children[0].clone();
9448 log::trace!("container:\n{container}");
9449
9450 compare_containers(
9451 &container,
9452 &Container {
9453 children: vec![Container {
9454 calculated_width: Some(100.0),
9455 ..container.children[0].clone()
9456 }],
9457 calculated_width: Some(400.0),
9458 ..container.clone()
9459 },
9460 );
9461 }
9462
9463 #[test_log::test]
9464 fn does_take_into_account_explicit_fixed_min_height() {
9465 let mut container: Container = html! {
9466 div sx-dir=(LayoutDirection::Column) sx-height="100%" {
9467 div sx-min-height=(100) {}
9468 }
9469 }
9470 .try_into()
9471 .unwrap();
9472
9473 container.calculated_width = Some(100.0);
9474 container.calculated_height = Some(400.0);
9475
9476 CALCULATOR.calc(&mut container);
9477 log::trace!("full container:\n{container}");
9478 container = container.children[0].clone();
9479 log::trace!("container:\n{container}");
9480
9481 compare_containers(
9482 &container,
9483 &Container {
9484 children: vec![Container {
9485 calculated_height: Some(100.0),
9486 ..container.children[0].clone()
9487 }],
9488 calculated_height: Some(400.0),
9489 ..container.clone()
9490 },
9491 );
9492 }
9493
9494 #[test_log::test]
9495 fn does_take_into_account_explicit_fixed_min_height_with_fixed_child_content() {
9496 let mut container: Container = html! {
9497 div sx-dir=(LayoutDirection::Column) sx-height="100%" {
9498 div sx-min-height=(100) {
9499 div sx-height=(10) {}
9500 }
9501 }
9502 }
9503 .try_into()
9504 .unwrap();
9505
9506 container.calculated_width = Some(100.0);
9507 container.calculated_height = Some(400.0);
9508
9509 CALCULATOR.calc(&mut container);
9510 log::trace!("full container:\n{container}");
9511 container = container.children[0].clone();
9512 log::trace!("container:\n{container}");
9513
9514 compare_containers(
9515 &container,
9516 &Container {
9517 children: vec![Container {
9518 calculated_height: Some(100.0),
9519 ..container.children[0].clone()
9520 }],
9521 calculated_height: Some(400.0),
9522 ..container.clone()
9523 },
9524 );
9525 }
9526
9527 #[test_log::test]
9528 fn does_take_into_account_explicit_dynamic_min_width() {
9529 let mut container: Container = html! {
9530 div sx-dir=(LayoutDirection::Row) {
9531 div sx-min-width="50%" {}
9532 }
9533 }
9534 .try_into()
9535 .unwrap();
9536
9537 container.calculated_width = Some(400.0);
9538 container.calculated_height = Some(100.0);
9539
9540 CALCULATOR.calc(&mut container);
9541 log::trace!("full container:\n{container}");
9542 container = container.children[0].clone();
9543 log::trace!("container:\n{container}");
9544
9545 compare_containers(
9546 &container,
9547 &Container {
9548 children: vec![Container {
9549 calculated_width: Some(200.0),
9550 ..container.children[0].clone()
9551 }],
9552 calculated_width: Some(400.0),
9553 ..container.clone()
9554 },
9555 );
9556 }
9557
9558 #[test_log::test]
9559 fn does_take_into_account_explicit_dynamic_min_width_with_fixed_child_content() {
9560 let mut container: Container = html! {
9561 div sx-dir=(LayoutDirection::Row) {
9562 div sx-min-width="50%" {
9563 div sx-width=(10) {}
9564 }
9565 }
9566 }
9567 .try_into()
9568 .unwrap();
9569
9570 container.calculated_width = Some(400.0);
9571 container.calculated_height = Some(100.0);
9572
9573 CALCULATOR.calc(&mut container);
9574 log::trace!("full container:\n{container}");
9575 container = container.children[0].clone();
9576 log::trace!("container:\n{container}");
9577
9578 compare_containers(
9579 &container,
9580 &Container {
9581 children: vec![Container {
9582 calculated_width: Some(200.0),
9583 ..container.children[0].clone()
9584 }],
9585 calculated_width: Some(400.0),
9586 ..container.clone()
9587 },
9588 );
9589 }
9590
9591 #[test_log::test]
9592 fn does_take_into_account_explicit_dynamic_min_height() {
9593 let mut container: Container = html! {
9594 div sx-dir=(LayoutDirection::Column) sx-height="100%" {
9595 div sx-min-height="50%" {}
9596 }
9597 }
9598 .try_into()
9599 .unwrap();
9600
9601 container.calculated_width = Some(100.0);
9602 container.calculated_height = Some(400.0);
9603
9604 CALCULATOR.calc(&mut container);
9605 log::trace!("full container:\n{container}");
9606 container = container.children[0].clone();
9607 log::trace!("container:\n{container}");
9608
9609 compare_containers(
9610 &container,
9611 &Container {
9612 children: vec![Container {
9613 calculated_height: Some(200.0),
9614 ..container.children[0].clone()
9615 }],
9616 calculated_height: Some(400.0),
9617 ..container.clone()
9618 },
9619 );
9620 }
9621
9622 #[test_log::test]
9623 fn does_take_into_account_explicit_dynamic_min_height_with_fixed_child_content() {
9624 let mut container: Container = html! {
9625 div sx-dir=(LayoutDirection::Column) sx-height="100%" {
9626 div sx-min-height="50%" {
9627 div sx-height=(10) {}
9628 }
9629 }
9630 }
9631 .try_into()
9632 .unwrap();
9633
9634 container.calculated_width = Some(100.0);
9635 container.calculated_height = Some(400.0);
9636
9637 CALCULATOR.calc(&mut container);
9638 log::trace!("full container:\n{container}");
9639 container = container.children[0].clone();
9640 log::trace!("container:\n{container}");
9641
9642 compare_containers(
9643 &container,
9644 &Container {
9645 children: vec![Container {
9646 calculated_height: Some(200.0),
9647 ..container.children[0].clone()
9648 }],
9649 calculated_height: Some(400.0),
9650 ..container.clone()
9651 },
9652 );
9653 }
9654
9655 #[test_log::test]
9656 fn does_take_into_account_explicit_fixed_max_width() {
9657 let mut container: Container = html! {
9658 div sx-dir=(LayoutDirection::Column) {
9659 div sx-max-width=(100) {}
9660 }
9661 }
9662 .try_into()
9663 .unwrap();
9664
9665 container.calculated_width = Some(400.0);
9666 container.calculated_height = Some(100.0);
9667
9668 CALCULATOR.calc(&mut container);
9669 log::trace!("full container:\n{container}");
9670 container = container.children[0].clone();
9671 log::trace!("container:\n{container}");
9672
9673 compare_containers(
9674 &container,
9675 &Container {
9676 children: vec![Container {
9677 calculated_width: Some(100.0),
9678 ..container.children[0].clone()
9679 }],
9680 calculated_width: Some(400.0),
9681 ..container.clone()
9682 },
9683 );
9684 }
9685
9686 #[test_log::test]
9687 fn does_take_into_account_explicit_fixed_max_width_with_fixed_child_content() {
9688 let mut container: Container = html! {
9689 div sx-dir=(LayoutDirection::Column) {
9690 div sx-max-width=(100) {
9691 div sx-width=(200) {}
9692 }
9693 }
9694 }
9695 .try_into()
9696 .unwrap();
9697
9698 container.calculated_width = Some(400.0);
9699 container.calculated_height = Some(100.0);
9700
9701 CALCULATOR.calc(&mut container);
9702 log::trace!("full container:\n{container}");
9703 container = container.children[0].clone();
9704 log::trace!("container:\n{container}");
9705
9706 compare_containers(
9707 &container,
9708 &Container {
9709 children: vec![Container {
9710 calculated_width: Some(100.0),
9711 ..container.children[0].clone()
9712 }],
9713 calculated_width: Some(400.0),
9714 ..container.clone()
9715 },
9716 );
9717 }
9718
9719 #[test_log::test]
9720 fn does_take_into_account_explicit_fixed_max_height() {
9721 let mut container: Container = html! {
9722 div sx-dir=(LayoutDirection::Row) sx-height="100%" {
9723 div sx-max-height=(100) {}
9724 }
9725 }
9726 .try_into()
9727 .unwrap();
9728
9729 container.calculated_width = Some(100.0);
9730 container.calculated_height = Some(400.0);
9731
9732 CALCULATOR.calc(&mut container);
9733 log::trace!("full container:\n{container}");
9734 container = container.children[0].clone();
9735 log::trace!("container:\n{container}");
9736
9737 compare_containers(
9738 &container,
9739 &Container {
9740 children: vec![Container {
9741 calculated_height: Some(100.0),
9742 ..container.children[0].clone()
9743 }],
9744 calculated_height: Some(400.0),
9745 ..container.clone()
9746 },
9747 );
9748 }
9749
9750 #[test_log::test]
9751 fn does_take_into_account_explicit_fixed_max_height_with_fixed_child_content() {
9752 let mut container: Container = html! {
9753 div sx-dir=(LayoutDirection::Row) sx-height="100%" {
9754 div sx-max-height=(100) {
9755 div sx-height=(200) {}
9756 }
9757 }
9758 }
9759 .try_into()
9760 .unwrap();
9761
9762 container.calculated_width = Some(100.0);
9763 container.calculated_height = Some(400.0);
9764
9765 CALCULATOR.calc(&mut container);
9766 log::trace!("full container:\n{container}");
9767 container = container.children[0].clone();
9768 log::trace!("container:\n{container}");
9769
9770 compare_containers(
9771 &container,
9772 &Container {
9773 children: vec![Container {
9774 calculated_height: Some(100.0),
9775 ..container.children[0].clone()
9776 }],
9777 calculated_height: Some(400.0),
9778 ..container.clone()
9779 },
9780 );
9781 }
9782
9783 #[test_log::test]
9784 fn does_take_into_account_explicit_dynamic_max_width() {
9785 let mut container: Container = html! {
9786 div sx-dir=(LayoutDirection::Column) {
9787 div sx-max-width="50%" {}
9788 }
9789 }
9790 .try_into()
9791 .unwrap();
9792
9793 container.calculated_width = Some(400.0);
9794 container.calculated_height = Some(100.0);
9795
9796 CALCULATOR.calc(&mut container);
9797 log::trace!("full container:\n{container}");
9798 container = container.children[0].clone();
9799 log::trace!("container:\n{container}");
9800
9801 compare_containers(
9802 &container,
9803 &Container {
9804 children: vec![Container {
9805 calculated_width: Some(200.0),
9806 ..container.children[0].clone()
9807 }],
9808 calculated_width: Some(400.0),
9809 ..container.clone()
9810 },
9811 );
9812 }
9813
9814 #[test_log::test]
9815 fn does_take_into_account_explicit_dynamic_max_width_with_fixed_child_content() {
9816 let mut container: Container = html! {
9817 div sx-dir=(LayoutDirection::Column) {
9818 div sx-max-width="50%" {
9819 div sx-width=(300) {}
9820 }
9821 }
9822 }
9823 .try_into()
9824 .unwrap();
9825
9826 container.calculated_width = Some(400.0);
9827 container.calculated_height = Some(100.0);
9828
9829 CALCULATOR.calc(&mut container);
9830 log::trace!("full container:\n{container}");
9831 container = container.children[0].clone();
9832 log::trace!("container:\n{container}");
9833
9834 compare_containers(
9835 &container,
9836 &Container {
9837 children: vec![Container {
9838 calculated_width: Some(200.0),
9839 ..container.children[0].clone()
9840 }],
9841 calculated_width: Some(400.0),
9842 ..container.clone()
9843 },
9844 );
9845 }
9846
9847 #[test_log::test]
9848 fn does_take_into_account_explicit_dynamic_max_height() {
9849 let mut container: Container = html! {
9850 div sx-dir=(LayoutDirection::Row) sx-height="100%" {
9851 div sx-max-height="50%" {}
9852 }
9853 }
9854 .try_into()
9855 .unwrap();
9856
9857 container.calculated_width = Some(100.0);
9858 container.calculated_height = Some(400.0);
9859
9860 CALCULATOR.calc(&mut container);
9861 log::trace!("full container:\n{container}");
9862 container = container.children[0].clone();
9863 log::trace!("container:\n{container}");
9864
9865 compare_containers(
9866 &container,
9867 &Container {
9868 children: vec![Container {
9869 calculated_height: Some(200.0),
9870 ..container.children[0].clone()
9871 }],
9872 calculated_height: Some(400.0),
9873 ..container.clone()
9874 },
9875 );
9876 }
9877
9878 #[test_log::test]
9879 fn does_take_into_account_explicit_dynamic_max_height_with_fixed_child_content() {
9880 let mut container: Container = html! {
9881 div sx-dir=(LayoutDirection::Row) sx-height="100%" {
9882 div sx-max-height="50%" {
9883 div sx-height=(300) {}
9884 }
9885 }
9886 }
9887 .try_into()
9888 .unwrap();
9889
9890 container.calculated_width = Some(100.0);
9891 container.calculated_height = Some(400.0);
9892
9893 CALCULATOR.calc(&mut container);
9894 log::trace!("full container:\n{container}");
9895 container = container.children[0].clone();
9896 log::trace!("container:\n{container}");
9897
9898 compare_containers(
9899 &container,
9900 &Container {
9901 children: vec![Container {
9902 calculated_height: Some(200.0),
9903 ..container.children[0].clone()
9904 }],
9905 calculated_height: Some(400.0),
9906 ..container.clone()
9907 },
9908 );
9909 }
9910
9911 #[test_log::test]
9912 fn does_prioritize_explicit_fixed_min_width_and_max_fixed_width() {
9913 let mut container: Container = html! {
9914 div sx-dir=(LayoutDirection::Row) {
9915 div sx-min-width=(100) sx-max-width=(90) {}
9916 }
9917 }
9918 .try_into()
9919 .unwrap();
9920
9921 container.calculated_width = Some(400.0);
9922 container.calculated_height = Some(100.0);
9923
9924 CALCULATOR.calc(&mut container);
9925 log::trace!("full container:\n{container}");
9926 container = container.children[0].clone();
9927 log::trace!("container:\n{container}");
9928
9929 compare_containers(
9930 &container,
9931 &Container {
9932 children: vec![Container {
9933 calculated_width: Some(100.0),
9934 ..container.children[0].clone()
9935 }],
9936 calculated_width: Some(400.0),
9937 ..container.clone()
9938 },
9939 );
9940 }
9941
9942 #[test_log::test]
9943 fn does_prioritize_explicit_fixed_min_width_and_max_fixed_width_with_fixed_child_content() {
9944 let mut container: Container = html! {
9945 div sx-dir=(LayoutDirection::Row) {
9946 div sx-min-width=(100) sx-max-width=(90) {
9947 div sx-width=(10) {}
9948 }
9949 }
9950 }
9951 .try_into()
9952 .unwrap();
9953
9954 container.calculated_width = Some(400.0);
9955 container.calculated_height = Some(100.0);
9956
9957 CALCULATOR.calc(&mut container);
9958 log::trace!("full container:\n{container}");
9959 container = container.children[0].clone();
9960 log::trace!("container:\n{container}");
9961
9962 compare_containers(
9963 &container,
9964 &Container {
9965 children: vec![Container {
9966 calculated_width: Some(100.0),
9967 ..container.children[0].clone()
9968 }],
9969 calculated_width: Some(400.0),
9970 ..container.clone()
9971 },
9972 );
9973 }
9974
9975 #[test_log::test]
9976 fn does_prioritize_explicit_fixed_min_height_and_max_fixed_height() {
9977 let mut container: Container = html! {
9978 div sx-dir=(LayoutDirection::Column) sx-height="100%" {
9979 div sx-min-height=(100) sx-max-height=(90) {}
9980 }
9981 }
9982 .try_into()
9983 .unwrap();
9984
9985 container.calculated_width = Some(100.0);
9986 container.calculated_height = Some(400.0);
9987
9988 CALCULATOR.calc(&mut container);
9989 log::trace!("full container:\n{container}");
9990 container = container.children[0].clone();
9991 log::trace!("container:\n{container}");
9992
9993 compare_containers(
9994 &container,
9995 &Container {
9996 children: vec![Container {
9997 calculated_height: Some(100.0),
9998 ..container.children[0].clone()
9999 }],
10000 calculated_height: Some(400.0),
10001 ..container.clone()
10002 },
10003 );
10004 }
10005
10006 #[test_log::test]
10007 fn does_prioritize_explicit_fixed_min_height_and_max_fixed_height_with_fixed_child_content()
10008 {
10009 let mut container: Container = html! {
10010 div sx-dir=(LayoutDirection::Column) sx-height="100%" {
10011 div sx-min-height=(100) sx-max-height=(90) {
10012 div sx-height=(10) {}
10013 }
10014 }
10015 }
10016 .try_into()
10017 .unwrap();
10018
10019 container.calculated_width = Some(100.0);
10020 container.calculated_height = Some(400.0);
10021
10022 CALCULATOR.calc(&mut container);
10023 log::trace!("full container:\n{container}");
10024 container = container.children[0].clone();
10025 log::trace!("container:\n{container}");
10026
10027 compare_containers(
10028 &container,
10029 &Container {
10030 children: vec![Container {
10031 calculated_height: Some(100.0),
10032 ..container.children[0].clone()
10033 }],
10034 calculated_height: Some(400.0),
10035 ..container.clone()
10036 },
10037 );
10038 }
10039
10040 #[test_log::test]
10041 fn does_prioritize_explicit_dynamic_min_width_and_max_fixed_width() {
10042 let mut container: Container = html! {
10043 div sx-dir=(LayoutDirection::Row) {
10044 div sx-min-width="50%" sx-max-width=(90) {}
10045 }
10046 }
10047 .try_into()
10048 .unwrap();
10049
10050 container.calculated_width = Some(400.0);
10051 container.calculated_height = Some(100.0);
10052
10053 CALCULATOR.calc(&mut container);
10054 log::trace!("full container:\n{container}");
10055 container = container.children[0].clone();
10056 log::trace!("container:\n{container}");
10057
10058 compare_containers(
10059 &container,
10060 &Container {
10061 children: vec![Container {
10062 calculated_width: Some(200.0),
10063 ..container.children[0].clone()
10064 }],
10065 calculated_width: Some(400.0),
10066 ..container.clone()
10067 },
10068 );
10069 }
10070
10071 #[test_log::test]
10072 fn does_prioritize_explicit_dynamic_min_width_and_max_fixed_width_with_fixed_child_content()
10073 {
10074 let mut container: Container = html! {
10075 div sx-dir=(LayoutDirection::Row) {
10076 div sx-min-width="50%" sx-max-width=(90) {
10077 div sx-width=(10) {}
10078 }
10079 }
10080 }
10081 .try_into()
10082 .unwrap();
10083
10084 container.calculated_width = Some(400.0);
10085 container.calculated_height = Some(100.0);
10086
10087 CALCULATOR.calc(&mut container);
10088 log::trace!("full container:\n{container}");
10089 container = container.children[0].clone();
10090 log::trace!("container:\n{container}");
10091
10092 compare_containers(
10093 &container,
10094 &Container {
10095 children: vec![Container {
10096 calculated_width: Some(200.0),
10097 ..container.children[0].clone()
10098 }],
10099 calculated_width: Some(400.0),
10100 ..container.clone()
10101 },
10102 );
10103 }
10104
10105 #[test_log::test]
10106 fn does_prioritize_explicit_dynamic_min_height_and_max_fixed_height() {
10107 let mut container: Container = html! {
10108 div sx-dir=(LayoutDirection::Column) sx-height="100%" {
10109 div sx-min-height="50%" sx-max-height=(90) {}
10110 }
10111 }
10112 .try_into()
10113 .unwrap();
10114
10115 container.calculated_width = Some(100.0);
10116 container.calculated_height = Some(400.0);
10117
10118 CALCULATOR.calc(&mut container);
10119 log::trace!("full container:\n{container}");
10120 container = container.children[0].clone();
10121 log::trace!("container:\n{container}");
10122
10123 compare_containers(
10124 &container,
10125 &Container {
10126 children: vec![Container {
10127 calculated_height: Some(200.0),
10128 ..container.children[0].clone()
10129 }],
10130 calculated_height: Some(400.0),
10131 ..container.clone()
10132 },
10133 );
10134 }
10135
10136 #[test_log::test]
10137 fn does_prioritize_explicit_dynamic_min_height_and_max_fixed_height_with_fixed_child_content()
10138 {
10139 let mut container: Container = html! {
10140 div sx-dir=(LayoutDirection::Column) sx-height="100%" {
10141 div sx-min-height="50%" sx-max-height=(90) {
10142 div sx-height=(10) {}
10143 }
10144 }
10145 }
10146 .try_into()
10147 .unwrap();
10148
10149 container.calculated_width = Some(100.0);
10150 container.calculated_height = Some(400.0);
10151
10152 CALCULATOR.calc(&mut container);
10153 log::trace!("full container:\n{container}");
10154 container = container.children[0].clone();
10155 log::trace!("container:\n{container}");
10156
10157 compare_containers(
10158 &container,
10159 &Container {
10160 children: vec![Container {
10161 calculated_height: Some(200.0),
10162 ..container.children[0].clone()
10163 }],
10164 calculated_height: Some(400.0),
10165 ..container.clone()
10166 },
10167 );
10168 }
10169
10170 #[test_log::test]
10171 fn does_prioritize_explicit_fixed_min_width_and_max_dynamic_width() {
10172 let mut container: Container = html! {
10173 div sx-dir=(LayoutDirection::Row) {
10174 div sx-min-width=(100) sx-max-width="0%" {}
10175 }
10176 }
10177 .try_into()
10178 .unwrap();
10179
10180 container.calculated_width = Some(400.0);
10181 container.calculated_height = Some(100.0);
10182
10183 CALCULATOR.calc(&mut container);
10184 log::trace!("full container:\n{container}");
10185 container = container.children[0].clone();
10186 log::trace!("container:\n{container}");
10187
10188 compare_containers(
10189 &container,
10190 &Container {
10191 children: vec![Container {
10192 calculated_width: Some(100.0),
10193 ..container.children[0].clone()
10194 }],
10195 calculated_width: Some(400.0),
10196 ..container.clone()
10197 },
10198 );
10199 }
10200
10201 #[test_log::test]
10202 fn does_prioritize_explicit_fixed_min_width_and_max_dynamic_width_with_fixed_child_content()
10203 {
10204 let mut container: Container = html! {
10205 div sx-dir=(LayoutDirection::Row) {
10206 div sx-min-width=(100) sx-max-width="0%" {
10207 div sx-width=(10) {}
10208 }
10209 }
10210 }
10211 .try_into()
10212 .unwrap();
10213
10214 container.calculated_width = Some(400.0);
10215 container.calculated_height = Some(100.0);
10216
10217 CALCULATOR.calc(&mut container);
10218 log::trace!("full container:\n{container}");
10219 container = container.children[0].clone();
10220 log::trace!("container:\n{container}");
10221
10222 compare_containers(
10223 &container,
10224 &Container {
10225 children: vec![Container {
10226 calculated_width: Some(100.0),
10227 ..container.children[0].clone()
10228 }],
10229 calculated_width: Some(400.0),
10230 ..container.clone()
10231 },
10232 );
10233 }
10234
10235 #[test_log::test]
10236 fn does_prioritize_explicit_fixed_min_height_and_max_dynamic_height() {
10237 let mut container: Container = html! {
10238 div sx-dir=(LayoutDirection::Column) sx-height="100%" {
10239 div sx-min-height=(100) sx-max-height="0%" {}
10240 }
10241 }
10242 .try_into()
10243 .unwrap();
10244
10245 container.calculated_width = Some(100.0);
10246 container.calculated_height = Some(400.0);
10247
10248 CALCULATOR.calc(&mut container);
10249 log::trace!("full container:\n{container}");
10250 container = container.children[0].clone();
10251 log::trace!("container:\n{container}");
10252
10253 compare_containers(
10254 &container,
10255 &Container {
10256 children: vec![Container {
10257 calculated_height: Some(100.0),
10258 ..container.children[0].clone()
10259 }],
10260 calculated_height: Some(400.0),
10261 ..container.clone()
10262 },
10263 );
10264 }
10265
10266 #[test_log::test]
10267 fn does_prioritize_explicit_fixed_min_height_and_max_dynamic_height_with_fixed_child_content()
10268 {
10269 let mut container: Container = html! {
10270 div sx-dir=(LayoutDirection::Column) sx-height="100%" {
10271 div sx-min-height=(100) sx-max-height="0%" {
10272 div sx-height=(10) {}
10273 }
10274 }
10275 }
10276 .try_into()
10277 .unwrap();
10278
10279 container.calculated_width = Some(100.0);
10280 container.calculated_height = Some(400.0);
10281
10282 CALCULATOR.calc(&mut container);
10283 log::trace!("full container:\n{container}");
10284 container = container.children[0].clone();
10285 log::trace!("container:\n{container}");
10286
10287 compare_containers(
10288 &container,
10289 &Container {
10290 children: vec![Container {
10291 calculated_height: Some(100.0),
10292 ..container.children[0].clone()
10293 }],
10294 calculated_height: Some(400.0),
10295 ..container.clone()
10296 },
10297 );
10298 }
10299
10300 #[test_log::test]
10301 fn does_prioritize_explicit_dynamic_min_width_and_max_dynamic_width() {
10302 let mut container: Container = html! {
10303 div sx-dir=(LayoutDirection::Row) {
10304 div sx-min-width="50%" sx-max-width="0%" {}
10305 }
10306 }
10307 .try_into()
10308 .unwrap();
10309
10310 container.calculated_width = Some(400.0);
10311 container.calculated_height = Some(100.0);
10312
10313 CALCULATOR.calc(&mut container);
10314 log::trace!("full container:\n{container}");
10315 container = container.children[0].clone();
10316 log::trace!("container:\n{container}");
10317
10318 compare_containers(
10319 &container,
10320 &Container {
10321 children: vec![Container {
10322 calculated_width: Some(200.0),
10323 ..container.children[0].clone()
10324 }],
10325 calculated_width: Some(400.0),
10326 ..container.clone()
10327 },
10328 );
10329 }
10330
10331 #[test_log::test]
10332 fn does_prioritize_explicit_dynamic_min_width_and_max_dynamic_width_with_fixed_child_content()
10333 {
10334 let mut container: Container = html! {
10335 div sx-dir=(LayoutDirection::Row) {
10336 div sx-min-width="50%" sx-max-width="0%" {
10337 div sx-width=(10) {}
10338 }
10339 }
10340 }
10341 .try_into()
10342 .unwrap();
10343
10344 container.calculated_width = Some(400.0);
10345 container.calculated_height = Some(100.0);
10346
10347 CALCULATOR.calc(&mut container);
10348 log::trace!("full container:\n{container}");
10349 container = container.children[0].clone();
10350 log::trace!("container:\n{container}");
10351
10352 compare_containers(
10353 &container,
10354 &Container {
10355 children: vec![Container {
10356 calculated_width: Some(200.0),
10357 ..container.children[0].clone()
10358 }],
10359 calculated_width: Some(400.0),
10360 ..container.clone()
10361 },
10362 );
10363 }
10364
10365 #[test_log::test]
10366 fn does_prioritize_explicit_dynamic_min_height_and_max_dynamic_height() {
10367 let mut container: Container = html! {
10368 div sx-dir=(LayoutDirection::Column) sx-height="100%" {
10369 div sx-min-height="50%" sx-max-height="0%" {}
10370 }
10371 }
10372 .try_into()
10373 .unwrap();
10374
10375 container.calculated_width = Some(100.0);
10376 container.calculated_height = Some(400.0);
10377
10378 CALCULATOR.calc(&mut container);
10379 log::trace!("full container:\n{container}");
10380 container = container.children[0].clone();
10381 log::trace!("container:\n{container}");
10382
10383 compare_containers(
10384 &container,
10385 &Container {
10386 children: vec![Container {
10387 calculated_height: Some(200.0),
10388 ..container.children[0].clone()
10389 }],
10390 calculated_height: Some(400.0),
10391 ..container.clone()
10392 },
10393 );
10394 }
10395
10396 #[test_log::test]
10397 fn does_prioritize_explicit_dynamic_min_height_and_max_dynamic_height_with_fixed_child_content()
10398 {
10399 let mut container: Container = html! {
10400 div sx-dir=(LayoutDirection::Column) sx-height="100%" {
10401 div sx-min-height="50%" sx-max-height="0%" {
10402 div sx-height=(10) {}
10403 }
10404 }
10405 }
10406 .try_into()
10407 .unwrap();
10408
10409 container.calculated_width = Some(100.0);
10410 container.calculated_height = Some(400.0);
10411
10412 CALCULATOR.calc(&mut container);
10413 log::trace!("full container:\n{container}");
10414 container = container.children[0].clone();
10415 log::trace!("container:\n{container}");
10416
10417 compare_containers(
10418 &container,
10419 &Container {
10420 children: vec![Container {
10421 calculated_height: Some(200.0),
10422 ..container.children[0].clone()
10423 }],
10424 calculated_height: Some(400.0),
10425 ..container.clone()
10426 },
10427 );
10428 }
10429
10430 #[test_log::test]
10431 fn does_include_margin_top_in_parent_height() {
10432 let mut container: Container = html! {
10433 div sx-dir=(LayoutDirection::Column) {
10434 div sx-margin-top=(5) sx-height=(10) {}
10435 }
10436 }
10437 .try_into()
10438 .unwrap();
10439
10440 container.direction = LayoutDirection::Column;
10441 container.calculated_width = Some(100.0);
10442 container.calculated_height = Some(400.0);
10443
10444 CALCULATOR.calc(&mut container);
10445 log::trace!("container:\n{container}");
10446
10447 compare_containers(
10448 &container,
10449 &Container {
10450 children: vec![Container {
10451 children: vec![Container {
10452 calculated_height: Some(10.0),
10453 ..container.children[0].children[0].clone()
10454 }],
10455 calculated_height: Some(15.0),
10456 ..container.children[0].clone()
10457 }],
10458 calculated_height: Some(400.0),
10459 ..container.clone()
10460 },
10461 );
10462 }
10463
10464 #[test_log::test]
10465 fn does_include_margin_bottom_in_parent_height() {
10466 let mut container: Container = html! {
10467 div sx-dir=(LayoutDirection::Column) {
10468 div sx-margin-bottom=(5) sx-height=(10) {}
10469 }
10470 }
10471 .try_into()
10472 .unwrap();
10473
10474 container.direction = LayoutDirection::Column;
10475 container.calculated_width = Some(100.0);
10476 container.calculated_height = Some(400.0);
10477
10478 CALCULATOR.calc(&mut container);
10479 log::trace!("container:\n{container}");
10480
10481 compare_containers(
10482 &container,
10483 &Container {
10484 children: vec![Container {
10485 children: vec![Container {
10486 calculated_height: Some(10.0),
10487 ..container.children[0].children[0].clone()
10488 }],
10489 calculated_height: Some(15.0),
10490 ..container.children[0].clone()
10491 }],
10492 calculated_height: Some(400.0),
10493 ..container.clone()
10494 },
10495 );
10496 }
10497
10498 #[test_log::test]
10499 fn does_include_margin_left_in_parent_width() {
10500 let mut container: Container = html! {
10501 div sx-dir=(LayoutDirection::Row) {
10502 div sx-margin-left=(5) sx-width=(10) {}
10503 }
10504 }
10505 .try_into()
10506 .unwrap();
10507
10508 container.direction = LayoutDirection::Row;
10509 container.calculated_width = Some(400.0);
10510 container.calculated_height = Some(100.0);
10511
10512 CALCULATOR.calc(&mut container);
10513 log::trace!("container:\n{container}");
10514
10515 compare_containers(
10516 &container,
10517 &Container {
10518 children: vec![Container {
10519 children: vec![Container {
10520 calculated_width: Some(10.0),
10521 ..container.children[0].children[0].clone()
10522 }],
10523 calculated_width: Some(15.0),
10524 ..container.children[0].clone()
10525 }],
10526 calculated_width: Some(400.0),
10527 ..container.clone()
10528 },
10529 );
10530 }
10531
10532 #[test_log::test]
10533 fn does_include_margin_right_in_parent_width() {
10534 let mut container: Container = html! {
10535 div sx-dir=(LayoutDirection::Row) {
10536 div sx-margin-right=(5) sx-width=(10) {}
10537 }
10538 }
10539 .try_into()
10540 .unwrap();
10541
10542 container.direction = LayoutDirection::Row;
10543 container.calculated_width = Some(400.0);
10544 container.calculated_height = Some(100.0);
10545
10546 CALCULATOR.calc(&mut container);
10547 log::trace!("container:\n{container}");
10548
10549 compare_containers(
10550 &container,
10551 &Container {
10552 children: vec![Container {
10553 children: vec![Container {
10554 calculated_width: Some(10.0),
10555 ..container.children[0].children[0].clone()
10556 }],
10557 calculated_width: Some(15.0),
10558 ..container.children[0].clone()
10559 }],
10560 calculated_width: Some(400.0),
10561 ..container.clone()
10562 },
10563 );
10564 }
10565
10566 #[test_log::test]
10567 #[ignore]
10568 fn flex_child_does_take_full_width_if_flex_is_specified() {
10569 let mut container: Container = html! {
10570 div sx-width="100%" sx-dir=(LayoutDirection::Row) {
10571 div flex=(1) {}
10572 }
10573 }
10574 .try_into()
10575 .unwrap();
10576
10577 container.calculated_width = Some(400.0);
10578 container.calculated_height = Some(100.0);
10579
10580 CALCULATOR.calc(&mut container);
10581 log::trace!("container:\n{container}");
10582
10583 compare_containers(
10584 &container,
10585 &Container {
10586 children: vec![Container {
10587 children: vec![Container {
10588 calculated_width: Some(400.0),
10589 ..container.children[0].children[0].clone()
10590 }],
10591 calculated_width: Some(400.0),
10592 ..container.children[0].clone()
10593 }],
10594 calculated_width: Some(400.0),
10595 ..container.clone()
10596 },
10597 );
10598 }
10599 }
10600
10601 mod position_sticky {
10602 use super::*;
10603
10604 #[test_log::test]
10605 fn does_include_size_in_parent_width() {
10606 let mut container: Container = html! {
10607 div {
10608 div sx-position=(Position::Sticky) sx-width=(100) {}
10609 }
10610 }
10611 .try_into()
10612 .unwrap();
10613
10614 container.direction = LayoutDirection::Row;
10615 container.calculated_width = Some(400.0);
10616 container.calculated_height = Some(100.0);
10617
10618 CALCULATOR.calc(&mut container);
10619 log::trace!("container:\n{container}");
10620
10621 compare_containers(
10622 &container,
10623 &Container {
10624 children: vec![Container {
10625 children: vec![Container {
10626 calculated_width: Some(100.0),
10627 ..container.children[0].children[0].clone()
10628 }],
10629 calculated_width: Some(100.0),
10630 ..container.children[0].clone()
10631 }],
10632 ..container.clone()
10633 },
10634 );
10635 }
10636
10637 #[test_log::test]
10638 fn does_include_size_in_parent_height() {
10639 let mut container: Container = html! {
10640 div {
10641 div sx-position=(Position::Sticky) sx-height=(100) {}
10642 }
10643 }
10644 .try_into()
10645 .unwrap();
10646
10647 container.direction = LayoutDirection::Column;
10648 container.calculated_width = Some(400.0);
10649 container.calculated_height = Some(200.0);
10650
10651 CALCULATOR.calc(&mut container);
10652 log::trace!("container:\n{container}");
10653
10654 compare_containers(
10655 &container,
10656 &Container {
10657 children: vec![Container {
10658 children: vec![Container {
10659 calculated_height: Some(100.0),
10660 ..container.children[0].children[0].clone()
10661 }],
10662 calculated_height: Some(100.0),
10663 ..container.children[0].clone()
10664 }],
10665 ..container.clone()
10666 },
10667 );
10668 }
10669 }
10670
10671 mod position_fixed {
10672 use super::*;
10673
10674 #[test_log::test]
10675 fn does_size_dynamic_width_correctly() {
10676 let mut container: Container = html! {
10677 div sx-position=(Position::Fixed) sx-width="100%" {}
10678 }
10679 .try_into()
10680 .unwrap();
10681
10682 container.calculated_width = Some(400.0);
10683 container.calculated_height = Some(100.0);
10684
10685 CALCULATOR.calc(&mut container);
10686 log::trace!("container:\n{container}");
10687
10688 compare_containers(
10689 &container,
10690 &Container {
10691 children: vec![Container {
10692 calculated_width: Some(400.0),
10693 ..container.children[0].clone()
10694 }],
10695 ..container.clone()
10696 },
10697 );
10698 }
10699
10700 #[test_log::test]
10701 fn does_size_dynamic_height_correctly() {
10702 let mut container: Container = html! {
10703 div sx-position=(Position::Fixed) sx-height="100%" {}
10704 }
10705 .try_into()
10706 .unwrap();
10707
10708 container.calculated_width = Some(400.0);
10709 container.calculated_height = Some(100.0);
10710
10711 CALCULATOR.calc(&mut container);
10712 log::trace!("container:\n{container}");
10713
10714 compare_containers(
10715 &container,
10716 &Container {
10717 children: vec![Container {
10718 calculated_height: Some(100.0),
10719 ..container.children[0].clone()
10720 }],
10721 ..container.clone()
10722 },
10723 );
10724 }
10725
10726 #[test_log::test]
10727 fn does_place_child_element_with_horizontal_margins_correctly() {
10728 let mut container: Container = html! {
10729 div
10730 sx-position=(Position::Fixed)
10731 sx-width="100%"
10732 sx-height="100%"
10733 sx-justify-content=(JustifyContent::Center)
10734 {
10735 div
10736 sx-flex=(1)
10737 sx-margin-x="calc(20vw)"
10738 sx-min-height="calc(min(90vh, 300px))"
10739 sx-max-height="90vh"
10740 sx-overflow-y=(LayoutOverflow::Auto)
10741 {}
10742 }
10743 }
10744 .try_into()
10745 .unwrap();
10746
10747 container.calculated_width = Some(1000.0);
10748 container.calculated_height = Some(500.0);
10749
10750 CALCULATOR.calc(&mut container);
10751 log::trace!("container:\n{container}");
10752
10753 compare_containers(
10754 &container,
10755 &Container {
10756 children: vec![Container {
10757 children: vec![Container {
10758 calculated_x: Some(0.0),
10759 calculated_y: Some(0.0),
10760 calculated_width: Some(600.0),
10761 calculated_height: Some(500.0),
10762 ..container.children[0].children[0].clone()
10763 }],
10764 ..container.children[0].clone()
10765 }],
10766 ..container.clone()
10767 },
10768 );
10769 }
10770
10771 #[test_log::test]
10772 fn does_size_horizontally_child_element_correctly_with_flex_1_and_direction_row_parent() {
10773 let mut container: Container = html! {
10774 div
10775 sx-dir=(LayoutDirection::Row)
10776 sx-position=(Position::Fixed)
10777 sx-width="100%"
10778 sx-align-items=(AlignItems::Center)
10779 sx-justify-content=(JustifyContent::Center)
10780 {
10781 div
10782 sx-flex=(1)
10783 sx-margin-x="calc(20vw)"
10784 sx-overflow-y=(LayoutOverflow::Auto)
10785 { "test" }
10786 }
10787 }
10788 .try_into()
10789 .unwrap();
10790
10791 container.calculated_width = Some(1000.0);
10792 container.calculated_height = Some(500.0);
10793
10794 CALCULATOR.calc(&mut container);
10795 log::trace!("container:\n{container}");
10796
10797 compare_containers(
10798 &container,
10799 &Container {
10800 children: vec![Container {
10801 children: vec![Container {
10802 calculated_width: Some(600.0),
10803 ..container.children[0].children[0].clone()
10804 }],
10805 calculated_width: Some(1000.0),
10806 ..container.children[0].clone()
10807 }],
10808 calculated_width: Some(1000.0),
10809 ..container.clone()
10810 },
10811 );
10812 }
10813
10814 #[test_log::test]
10815 fn calc_can_calc_fixed_positioned_element_nested_on_top_of_a_relative_element_with_left_offset()
10816 {
10817 let mut container = Container {
10818 children: vec![Container {
10819 children: vec![
10820 Container::default(),
10821 Container {
10822 left: Some(Number::Integer(30)),
10823 position: Some(Position::Fixed),
10824 ..Default::default()
10825 },
10826 ],
10827 justify_content: Some(JustifyContent::Start),
10828 ..Default::default()
10829 }],
10830 calculated_width: Some(100.0),
10831 calculated_height: Some(50.0),
10832 position: Some(Position::Relative),
10833 justify_content: Some(JustifyContent::Start),
10834 ..Default::default()
10835 };
10836 CALCULATOR.calc(&mut container);
10837 log::trace!("container:\n{container}");
10838
10839 compare_containers(
10840 &container.clone(),
10841 &Container {
10842 children: vec![Container {
10843 children: vec![
10844 Container {
10845 calculated_width: Some(100.0),
10846 calculated_x: Some(0.0),
10847 calculated_position: Some(LayoutPosition::Default),
10848 ..container.children[0].children[0].clone()
10849 },
10850 Container {
10851 calculated_width: Some(0.0),
10852 calculated_height: Some(0.0),
10853 calculated_x: Some(30.0),
10854 calculated_y: Some(0.0),
10855 position: Some(Position::Fixed),
10856 ..container.children[0].children[1].clone()
10857 },
10858 ],
10859 ..container.children[0].clone()
10860 }],
10861 ..container
10862 },
10863 );
10864 }
10865
10866 #[test_log::test]
10867 fn calc_can_calc_fixed_positioned_element_on_top_of_a_relative_element_with_left_offset() {
10868 let mut container = Container {
10869 children: vec![
10870 Container::default(),
10871 Container {
10872 left: Some(Number::Integer(30)),
10873 position: Some(Position::Fixed),
10874 ..Default::default()
10875 },
10876 ],
10877 calculated_width: Some(100.0),
10878 calculated_height: Some(50.0),
10879 position: Some(Position::Relative),
10880 justify_content: Some(JustifyContent::Start),
10881 ..Default::default()
10882 };
10883 CALCULATOR.calc(&mut container);
10884 log::trace!("container:\n{container}");
10885
10886 compare_containers(
10887 &container.clone(),
10888 &Container {
10889 children: vec![
10890 Container {
10891 calculated_width: Some(100.0),
10892 calculated_x: Some(0.0),
10893 calculated_position: Some(LayoutPosition::Default),
10894 ..container.children[0].clone()
10895 },
10896 Container {
10897 left: Some(Number::Integer(30)),
10898 calculated_width: Some(0.0),
10899 calculated_height: Some(0.0),
10900 calculated_x: Some(30.0),
10901 calculated_y: Some(0.0),
10902 position: Some(Position::Fixed),
10903 ..container.children[1].clone()
10904 },
10905 ],
10906 ..container
10907 },
10908 );
10909 }
10910
10911 #[test_log::test]
10912 fn calc_can_calc_fixed_positioned_element_with_explicit_sizes() {
10913 let mut container = Container {
10914 children: vec![
10915 Container::default(),
10916 Container {
10917 width: Some(Number::Integer(30)),
10918 height: Some(Number::Integer(20)),
10919 left: Some(Number::Integer(30)),
10920 position: Some(Position::Fixed),
10921 ..Default::default()
10922 },
10923 ],
10924 calculated_width: Some(100.0),
10925 calculated_height: Some(50.0),
10926 position: Some(Position::Relative),
10927 justify_content: Some(JustifyContent::Start),
10928 ..Default::default()
10929 };
10930 CALCULATOR.calc(&mut container);
10931 log::trace!("container:\n{container}");
10932
10933 compare_containers(
10934 &container.clone(),
10935 &Container {
10936 children: vec![
10937 Container {
10938 calculated_width: Some(100.0),
10939 calculated_x: Some(0.0),
10940 calculated_position: Some(LayoutPosition::Default),
10941 ..container.children[0].clone()
10942 },
10943 Container {
10944 calculated_width: Some(30.0),
10945 calculated_height: Some(20.0),
10946 calculated_x: Some(30.0),
10947 calculated_y: Some(0.0),
10948 position: Some(Position::Fixed),
10949 ..container.children[1].clone()
10950 },
10951 ],
10952 ..container
10953 },
10954 );
10955 }
10956
10957 #[test_log::test]
10958 fn calc_can_calc_fixed_positioned_element_on_top_of_a_relative_element_doesnt_affect_fixed_position_element_location()
10959 {
10960 let mut container = Container {
10961 children: vec![
10962 Container::default(),
10963 Container {
10964 children: vec![Container {
10965 position: Some(Position::Fixed),
10966 ..Default::default()
10967 }],
10968 left: Some(Number::Integer(30)),
10969 position: Some(Position::Relative),
10970 ..Default::default()
10971 },
10972 ],
10973 calculated_width: Some(100.0),
10974 calculated_height: Some(50.0),
10975 position: Some(Position::Relative),
10976 justify_content: Some(JustifyContent::Start),
10977 ..Default::default()
10978 };
10979
10980 CALCULATOR.calc(&mut container);
10981 log::trace!("container:\n{container}");
10982
10983 compare_containers(
10984 &container.clone(),
10985 &Container {
10986 children: vec![
10987 Container {
10988 calculated_width: Some(100.0),
10989 calculated_x: Some(0.0),
10990 calculated_position: Some(LayoutPosition::Default),
10991 ..container.children[0].clone()
10992 },
10993 Container {
10994 children: vec![Container {
10995 calculated_width: Some(0.0),
10996 calculated_x: Some(0.0),
10997 position: Some(Position::Fixed),
10998 ..container.children[1].children[0].clone()
10999 }],
11000 calculated_width: Some(100.0),
11001 calculated_x: Some(0.0),
11002 position: Some(Position::Relative),
11003 ..container.children[1].clone()
11004 },
11005 ],
11006 ..container
11007 },
11008 );
11009 }
11010
11011 #[test_log::test]
11012 fn calc_can_calc_fixed_positioned_element_on_top_of_a_relative_element_and_have_it_not_inherit_position_or_size()
11013 {
11014 let mut container = Container {
11015 children: vec![
11016 Container::default(),
11017 Container {
11018 position: Some(Position::Fixed),
11019 ..Default::default()
11020 },
11021 ],
11022 calculated_width: Some(100.0),
11023 calculated_height: Some(50.0),
11024 position: Some(Position::Relative),
11025 justify_content: Some(JustifyContent::Start),
11026 ..Default::default()
11027 };
11028 CALCULATOR.calc(&mut container);
11029 log::trace!("container:\n{container}");
11030
11031 compare_containers(
11032 &container.clone(),
11033 &Container {
11034 children: vec![
11035 Container {
11036 calculated_width: Some(100.0),
11037 calculated_x: Some(0.0),
11038 calculated_position: Some(LayoutPosition::Default),
11039 ..container.children[0].clone()
11040 },
11041 Container {
11042 calculated_width: Some(0.0),
11043 calculated_height: Some(0.0),
11044 calculated_x: Some(0.0),
11045 calculated_y: Some(0.0),
11046 position: Some(Position::Fixed),
11047 ..container.children[1].clone()
11048 },
11049 ],
11050 ..container
11051 },
11052 );
11053 }
11054 }
11055
11056 mod positioning {
11057 use hyperchad_transformer_models::{AlignItems, TextAlign, Visibility};
11058
11059 use super::*;
11060
11061 #[test_log::test]
11062 fn does_center_child_correctly() {
11063 let mut container: Container = html! {
11064 div
11065 sx-width=(100)
11066 sx-height=(50)
11067 sx-justify-content=(JustifyContent::Center)
11068 sx-align-items=(AlignItems::Center)
11069 {
11070 div sx-width=(20) sx-height=(10) {}
11071 }
11072 }
11073 .try_into()
11074 .unwrap();
11075
11076 container.calculated_width = Some(400.0);
11077 container.calculated_height = Some(100.0);
11078
11079 CALCULATOR.calc(&mut container);
11080 log::trace!("full container:\n{container}");
11081 container = container.children[0].clone();
11082 log::trace!("container:\n{container}");
11083
11084 compare_containers(
11085 &container,
11086 &Container {
11087 children: vec![Container {
11088 calculated_x: Some(40.0),
11089 calculated_y: Some(20.0),
11090 ..container.children[0].clone()
11091 }],
11092 ..container.clone()
11093 },
11094 );
11095 }
11096
11097 #[test_log::test]
11098 fn does_center_raw_content_vertically_correctly() {
11099 let mut container: Container = html! {
11100 div
11101 sx-width=(100)
11102 sx-height=(50)
11103 sx-justify-content=(JustifyContent::Center)
11104 {
11105 "test"
11106 }
11107 }
11108 .try_into()
11109 .unwrap();
11110
11111 container.calculated_width = Some(400.0);
11112 container.calculated_height = Some(100.0);
11113
11114 CALCULATOR.calc(&mut container);
11115 log::trace!("full container:\n{container}");
11116 container = container.children[0].clone();
11117 log::trace!("container:\n{container}");
11118
11119 compare_containers(
11120 &container,
11121 &Container {
11122 children: vec![Container {
11123 calculated_y: Some(18.0),
11124 ..container.children[0].clone()
11125 }],
11126 ..container.clone()
11127 },
11128 );
11129 }
11130
11131 #[test_log::test]
11132 fn does_not_include_invisible_children_in_position() {
11133 let mut container: Container = html! {
11134 div sx-width=(100) sx-height=(50) {
11135 div sx-visibility=(Visibility::Hidden) sx-height=(20) {}
11136 "test"
11137 }
11138 }
11139 .try_into()
11140 .unwrap();
11141
11142 container.calculated_width = Some(400.0);
11143 container.calculated_height = Some(100.0);
11144
11145 CALCULATOR.calc(&mut container);
11146 log::trace!("full container:\n{container}");
11147 container = container.children[0].clone();
11148 log::trace!("container:\n{container}");
11149
11150 compare_containers(
11151 &container,
11152 &Container {
11153 children: vec![
11154 Container {
11155 calculated_y: None,
11156 ..container.children[0].clone()
11157 },
11158 Container {
11159 calculated_y: Some(0.0),
11160 ..container.children[1].clone()
11161 },
11162 ],
11163 ..container.clone()
11164 },
11165 );
11166 }
11167
11168 #[test_log::test]
11169 fn does_center_child_correctly_with_dir_row_and_multiple_children() {
11170 let mut container: Container = html! {
11171 div
11172 sx-dir=(LayoutDirection::Row)
11173 sx-width=(100)
11174 sx-height=(50)
11175 sx-justify-content=(JustifyContent::Center)
11176 sx-align-items=(AlignItems::Center)
11177 {
11178 div sx-width=(20) sx-height=(10) {}
11179 div sx-width=(20) sx-height=(10) {}
11180 div sx-width=(20) sx-height=(10) {}
11181 }
11182 }
11183 .try_into()
11184 .unwrap();
11185
11186 container.calculated_width = Some(400.0);
11187 container.calculated_height = Some(100.0);
11188
11189 CALCULATOR.calc(&mut container);
11190 log::trace!("full container:\n{container}");
11191 container = container.children[0].clone();
11192 log::trace!("container:\n{container}");
11193
11194 compare_containers(
11195 &container,
11196 &Container {
11197 children: vec![
11198 Container {
11199 calculated_x: Some(20.0),
11200 calculated_y: Some(20.0),
11201 ..container.children[0].clone()
11202 },
11203 Container {
11204 calculated_x: Some(40.0),
11205 calculated_y: Some(20.0),
11206 ..container.children[1].clone()
11207 },
11208 Container {
11209 calculated_x: Some(60.0),
11210 calculated_y: Some(20.0),
11211 ..container.children[2].clone()
11212 },
11213 ],
11214 ..container.clone()
11215 },
11216 );
11217 }
11218
11219 #[test_log::test]
11220 fn does_center_row_text_when_text_align_is_center() {
11221 let mut container: Container = html! {
11222 div
11223 sx-width=(100)
11224 sx-height=(50)
11225 sx-text-align=(TextAlign::Center)
11226 {
11227 "test"
11228 }
11229 }
11230 .try_into()
11231 .unwrap();
11232
11233 container.calculated_width = Some(400.0);
11234 container.calculated_height = Some(100.0);
11235
11236 CALCULATOR.calc(&mut container);
11237 log::trace!("full container:\n{container}");
11238 container = container.children[0].clone();
11239 log::trace!("container:\n{container}");
11240
11241 compare_containers(
11242 &container,
11243 &Container {
11244 children: vec![Container {
11245 calculated_x: Some(22.0),
11246 ..container.children[0].clone()
11247 }],
11248 ..container.clone()
11249 },
11250 );
11251 }
11252
11253 #[test_log::test]
11254 fn does_center_row_text_when_text_align_is_center_and_container_direction_is_row() {
11255 let mut container: Container = html! {
11256 div
11257 sx-dir=(LayoutDirection::Row)
11258 sx-width=(100)
11259 sx-height=(50)
11260 sx-text-align=(TextAlign::Center)
11261 {
11262 "test"
11263 }
11264 }
11265 .try_into()
11266 .unwrap();
11267
11268 container.calculated_width = Some(400.0);
11269 container.calculated_height = Some(100.0);
11270
11271 CALCULATOR.calc(&mut container);
11272 log::trace!("full container:\n{container}");
11273 container = container.children[0].clone();
11274 log::trace!("container:\n{container}");
11275
11276 compare_containers(
11277 &container,
11278 &Container {
11279 children: vec![Container {
11280 calculated_x: Some(22.0),
11281 ..container.children[0].clone()
11282 }],
11283 ..container.clone()
11284 },
11285 );
11286 }
11287
11288 #[test_log::test]
11289 fn does_center_vertical_row_children() {
11290 let mut container: Container = html! {
11291 div sx-dir=(LayoutDirection::Row) sx-width=(100) sx-height=(100) sx-align-items=(AlignItems::Center) {
11292 div sx-height=(70) {}
11293 div sx-height=(48) {}
11294 }
11295 }
11296 .try_into()
11297 .unwrap();
11298
11299 container.calculated_width = Some(400.0);
11300 container.calculated_height = Some(100.0);
11301
11302 CALCULATOR.calc(&mut container);
11303 log::trace!("full container:\n{container}");
11304 container = container.children[0].clone();
11305 log::trace!("container:\n{container}");
11306
11307 compare_containers(
11308 &container,
11309 &Container {
11310 children: vec![
11311 Container {
11312 calculated_y: Some(15.0),
11313 ..container.children[0].clone()
11314 },
11315 Container {
11316 calculated_y: Some(26.0),
11317 ..container.children[1].clone()
11318 },
11319 ],
11320 ..container.clone()
11321 },
11322 );
11323 }
11324
11325 #[test_log::test]
11326 fn does_center_horizontal_column_children() {
11327 let mut container: Container = html! {
11328 div sx-width=(100) sx-height=(100) sx-align-items=(AlignItems::Center) {
11329 div sx-width=(70) {}
11330 div sx-width=(48) {}
11331 }
11332 }
11333 .try_into()
11334 .unwrap();
11335
11336 container.calculated_width = Some(400.0);
11337 container.calculated_height = Some(100.0);
11338
11339 CALCULATOR.calc(&mut container);
11340 log::trace!("full container:\n{container}");
11341 container = container.children[0].clone();
11342 log::trace!("container:\n{container}");
11343
11344 compare_containers(
11345 &container,
11346 &Container {
11347 children: vec![
11348 Container {
11349 calculated_x: Some(15.0),
11350 ..container.children[0].clone()
11351 },
11352 Container {
11353 calculated_x: Some(26.0),
11354 ..container.children[1].clone()
11355 },
11356 ],
11357 ..container.clone()
11358 },
11359 );
11360 }
11361
11362 #[test_log::test]
11363 fn does_take_into_account_column_gap_for_non_wrapping_div() {
11364 let mut container: Container = html! {
11365 div sx-width=(20) {}
11366 div sx-width=(30) {}
11367 }
11368 .try_into()
11369 .unwrap();
11370
11371 container.direction = LayoutDirection::Row;
11372 container.calculated_width = Some(400.0);
11373 container.calculated_height = Some(100.0);
11374 container.column_gap = Some(Number::Integer(5));
11375
11376 CALCULATOR.calc(&mut container);
11377 log::trace!("container:\n{container}");
11378
11379 compare_containers(
11380 &container,
11381 &Container {
11382 children: vec![
11383 Container {
11384 calculated_x: Some(0.0),
11385 ..container.children[0].clone()
11386 },
11387 Container {
11388 calculated_x: Some(20.0 + 5.0),
11389 ..container.children[1].clone()
11390 },
11391 ],
11392 ..container.clone()
11393 },
11394 );
11395 }
11396
11397 #[test_log::test]
11398 fn does_take_into_account_column_gap_for_non_wrapping_div_and_centers_properly() {
11399 let mut container: Container = html! {
11400 div sx-width=(20) {}
11401 div sx-width=(30) {}
11402 }
11403 .try_into()
11404 .unwrap();
11405
11406 container.direction = LayoutDirection::Row;
11407 container.calculated_width = Some(400.0);
11408 container.calculated_height = Some(100.0);
11409 container.column_gap = Some(Number::Integer(5));
11410 container.justify_content = Some(JustifyContent::Center);
11411
11412 CALCULATOR.calc(&mut container);
11413 log::trace!("container:\n{container}");
11414
11415 compare_containers(
11416 &container,
11417 &Container {
11418 children: vec![
11419 Container {
11420 calculated_x: Some(400.0 / 2.0 - (20.0 + 30.0 + 5.0) / 2.0),
11421 ..container.children[0].clone()
11422 },
11423 Container {
11424 calculated_x: Some(
11425 400.0 / 2.0 - (20.0 + 30.0 + 5.0) / 2.0 + 20.0 + 5.0,
11426 ),
11427 ..container.children[1].clone()
11428 },
11429 ],
11430 ..container.clone()
11431 },
11432 );
11433 }
11434
11435 #[test_log::test]
11436 fn does_take_into_account_row_gap_for_non_wrapping_div() {
11437 let mut container: Container = html! {
11438 div sx-height=(20) {}
11439 div sx-height=(30) {}
11440 }
11441 .try_into()
11442 .unwrap();
11443
11444 container.direction = LayoutDirection::Column;
11445 container.calculated_width = Some(100.0);
11446 container.calculated_height = Some(400.0);
11447 container.row_gap = Some(Number::Integer(5));
11448
11449 CALCULATOR.calc(&mut container);
11450 log::trace!("container:\n{container}");
11451
11452 compare_containers(
11453 &container,
11454 &Container {
11455 children: vec![
11456 Container {
11457 calculated_y: Some(0.0),
11458 ..container.children[0].clone()
11459 },
11460 Container {
11461 calculated_y: Some(20.0 + 5.0),
11462 ..container.children[1].clone()
11463 },
11464 ],
11465 ..container.clone()
11466 },
11467 );
11468 }
11469
11470 #[test_log::test]
11471 fn does_take_into_account_row_gap_for_non_wrapping_div_and_centers_properly() {
11472 let mut container: Container = html! {
11473 div sx-height=(20) {}
11474 div sx-height=(30) {}
11475 }
11476 .try_into()
11477 .unwrap();
11478
11479 container.direction = LayoutDirection::Column;
11480 container.calculated_width = Some(100.0);
11481 container.calculated_height = Some(400.0);
11482 container.row_gap = Some(Number::Integer(5));
11483 container.justify_content = Some(JustifyContent::Center);
11484
11485 CALCULATOR.calc(&mut container);
11486 log::trace!("container:\n{container}");
11487
11488 compare_containers(
11489 &container,
11490 &Container {
11491 children: vec![
11492 Container {
11493 calculated_y: Some(400.0 / 2.0 - (20.0 + 30.0 + 5.0) / 2.0),
11494 ..container.children[0].clone()
11495 },
11496 Container {
11497 calculated_y: Some(
11498 400.0 / 2.0 - (20.0 + 30.0 + 5.0) / 2.0 + 20.0 + 5.0,
11499 ),
11500 ..container.children[1].clone()
11501 },
11502 ],
11503 ..container.clone()
11504 },
11505 );
11506 }
11507
11508 #[cfg(feature = "layout-offset")]
11509 mod offset {
11510 use super::*;
11511
11512 #[test_log::test]
11513 fn does_set_offset_x_for_single_element() {
11514 let mut container: Container = html! {
11515 div {}
11516 }
11517 .try_into()
11518 .unwrap();
11519
11520 container.calculated_width = Some(400.0);
11521 container.calculated_height = Some(100.0);
11522
11523 CALCULATOR.calc(&mut container);
11524 log::trace!("full container:\n{container}");
11525 container = container.children[0].clone();
11526 log::trace!("container:\n{container}");
11527
11528 compare_containers(
11529 &container,
11530 &Container {
11531 calculated_offset_x: Some(0.0),
11532 ..container.clone()
11533 },
11534 );
11535 }
11536
11537 #[test_log::test]
11538 fn does_set_offset_y_for_single_element() {
11539 let mut container: Container = html! {
11540 div {}
11541 }
11542 .try_into()
11543 .unwrap();
11544
11545 container.calculated_width = Some(400.0);
11546 container.calculated_height = Some(100.0);
11547
11548 CALCULATOR.calc(&mut container);
11549 log::trace!("full container:\n{container}");
11550 container = container.children[0].clone();
11551 log::trace!("container:\n{container}");
11552
11553 compare_containers(
11554 &container,
11555 &Container {
11556 calculated_offset_y: Some(0.0),
11557 ..container.clone()
11558 },
11559 );
11560 }
11561
11562 #[test_log::test]
11563 fn does_set_offset_x_for_two_elements_col() {
11564 let mut container: Container = html! {
11565 div {
11566 div {}
11567 div {}
11568 }
11569 }
11570 .try_into()
11571 .unwrap();
11572
11573 container.calculated_width = Some(400.0);
11574 container.calculated_height = Some(100.0);
11575
11576 CALCULATOR.calc(&mut container);
11577 log::trace!("full container:\n{container}");
11578 container = container.children[0].clone();
11579 log::trace!("container:\n{container}");
11580
11581 compare_containers(
11582 &container,
11583 &Container {
11584 children: vec![
11585 Container {
11586 calculated_offset_x: Some(0.0),
11587 ..container.children[0].clone()
11588 },
11589 Container {
11590 calculated_offset_x: Some(0.0),
11591 ..container.children[1].clone()
11592 },
11593 ],
11594 ..container.clone()
11595 },
11596 );
11597 }
11598
11599 #[test_log::test]
11600 fn does_set_offset_x_for_justify_content_end_row() {
11601 let mut container: Container = html! {
11602 div sx-dir=(LayoutDirection::Row) sx-justify-content=(JustifyContent::End) {
11603 div sx-width=(50) {}
11604 }
11605 }
11606 .try_into()
11607 .unwrap();
11608
11609 container.calculated_width = Some(400.0);
11610 container.calculated_height = Some(100.0);
11611
11612 CALCULATOR.calc(&mut container);
11613 log::trace!("full container:\n{container}");
11614 container = container.children[0].clone();
11615 log::trace!("container:\n{container}");
11616
11617 compare_containers(
11618 &container,
11619 &Container {
11620 children: vec![Container {
11621 calculated_offset_x: Some(400.0 - 50.0),
11622 ..container.children[0].clone()
11623 }],
11624 ..container.clone()
11625 },
11626 );
11627 }
11628
11629 #[test_log::test]
11630 fn does_set_offset_y_for_justify_content_end_col() {
11631 let mut container: Container = html! {
11632 div sx-height=(100) sx-justify-content=(JustifyContent::End) {
11633 div sx-height=(20) {}
11634 }
11635 }
11636 .try_into()
11637 .unwrap();
11638
11639 container.calculated_width = Some(400.0);
11640 container.calculated_height = Some(100.0);
11641
11642 CALCULATOR.calc(&mut container);
11643 log::trace!("full container:\n{container}");
11644 container = container.children[0].clone();
11645 log::trace!("container:\n{container}");
11646
11647 compare_containers(
11648 &container,
11649 &Container {
11650 children: vec![Container {
11651 calculated_offset_y: Some(100.0 - 20.0),
11652 ..container.children[0].clone()
11653 }],
11654 ..container.clone()
11655 },
11656 );
11657 }
11658
11659 #[test_log::test]
11660 fn does_set_offset_y_for_align_items_end_row() {
11661 let mut container: Container = html! {
11662 div sx-height=(100) sx-dir=(LayoutDirection::Row) sx-align-items=(JustifyContent::End) {
11663 div sx-height=(20) {}
11664 }
11665 }
11666 .try_into()
11667 .unwrap();
11668
11669 container.calculated_width = Some(400.0);
11670 container.calculated_height = Some(100.0);
11671
11672 CALCULATOR.calc(&mut container);
11673 log::trace!("full container:\n{container}");
11674 container = container.children[0].clone();
11675 log::trace!("container:\n{container}");
11676
11677 compare_containers(
11678 &container,
11679 &Container {
11680 children: vec![Container {
11681 calculated_offset_y: Some(100.0 - 20.0),
11682 ..container.children[0].clone()
11683 }],
11684 ..container.clone()
11685 },
11686 );
11687 }
11688
11689 #[test_log::test]
11690 fn does_set_offset_x_for_align_items_end_col() {
11691 let mut container: Container = html! {
11692 div sx-align-items=(JustifyContent::End) {
11693 div sx-width=(50) {}
11694 }
11695 }
11696 .try_into()
11697 .unwrap();
11698
11699 container.calculated_width = Some(400.0);
11700 container.calculated_height = Some(100.0);
11701
11702 CALCULATOR.calc(&mut container);
11703 log::trace!("full container:\n{container}");
11704 container = container.children[0].clone();
11705 log::trace!("container:\n{container}");
11706
11707 compare_containers(
11708 &container,
11709 &Container {
11710 children: vec![Container {
11711 calculated_offset_x: Some(400.0 - 50.0),
11712 ..container.children[0].clone()
11713 }],
11714 ..container.clone()
11715 },
11716 );
11717 }
11718
11719 #[test_log::test]
11720 fn does_set_offset_x_for_two_elements_row() {
11721 let mut container: Container = html! {
11722 div sx-dir=(LayoutDirection::Row) {
11723 div {}
11724 div {}
11725 }
11726 }
11727 .try_into()
11728 .unwrap();
11729
11730 container.calculated_width = Some(400.0);
11731 container.calculated_height = Some(100.0);
11732
11733 CALCULATOR.calc(&mut container);
11734 log::trace!("full container:\n{container}");
11735 container = container.children[0].clone();
11736 log::trace!("container:\n{container}");
11737
11738 compare_containers(
11739 &container,
11740 &Container {
11741 children: vec![
11742 Container {
11743 calculated_offset_x: Some(0.0),
11744 ..container.children[0].clone()
11745 },
11746 Container {
11747 calculated_offset_x: Some(0.0),
11748 ..container.children[1].clone()
11749 },
11750 ],
11751 ..container.clone()
11752 },
11753 );
11754 }
11755
11756 #[test_log::test]
11757 fn does_set_offset_y_for_two_elements_col() {
11758 let mut container: Container = html! {
11759 div {
11760 div {}
11761 div {}
11762 }
11763 }
11764 .try_into()
11765 .unwrap();
11766
11767 container.calculated_width = Some(400.0);
11768 container.calculated_height = Some(100.0);
11769
11770 CALCULATOR.calc(&mut container);
11771 log::trace!("full container:\n{container}");
11772 container = container.children[0].clone();
11773 log::trace!("container:\n{container}");
11774
11775 compare_containers(
11776 &container,
11777 &Container {
11778 children: vec![
11779 Container {
11780 calculated_offset_y: Some(0.0),
11781 ..container.children[0].clone()
11782 },
11783 Container {
11784 calculated_offset_y: Some(0.0),
11785 ..container.children[1].clone()
11786 },
11787 ],
11788 ..container.clone()
11789 },
11790 );
11791 }
11792
11793 #[test_log::test]
11794 fn does_set_offset_y_for_two_elements_row() {
11795 let mut container: Container = html! {
11796 div sx-dir=(LayoutDirection::Row) {
11797 div {}
11798 div {}
11799 }
11800 }
11801 .try_into()
11802 .unwrap();
11803
11804 container.calculated_width = Some(400.0);
11805 container.calculated_height = Some(100.0);
11806
11807 CALCULATOR.calc(&mut container);
11808 log::trace!("full container:\n{container}");
11809 container = container.children[0].clone();
11810 log::trace!("container:\n{container}");
11811
11812 compare_containers(
11813 &container,
11814 &Container {
11815 children: vec![
11816 Container {
11817 calculated_offset_y: Some(0.0),
11818 ..container.children[0].clone()
11819 },
11820 Container {
11821 calculated_offset_y: Some(0.0),
11822 ..container.children[1].clone()
11823 },
11824 ],
11825 ..container.clone()
11826 },
11827 );
11828 }
11829
11830 #[test_log::test]
11831 fn does_include_gap_in_offset_x_overflow_x_wrap() {
11832 let mut container: Container = html! {
11833 div sx-dir=(LayoutDirection::Row) sx-overflow-x=(LayoutOverflow::Wrap { grid: false }) sx-gap=(10) {
11834 div sx-width=(50) {}
11835 div sx-width=(50) {}
11836 }
11837 }
11838 .try_into()
11839 .unwrap();
11840
11841 container.calculated_width = Some(400.0);
11842 container.calculated_height = Some(100.0);
11843
11844 CALCULATOR.calc(&mut container);
11845 log::trace!("full container:\n{container}");
11846 container = container.children[0].clone();
11847 log::trace!("container:\n{container}");
11848
11849 compare_containers(
11850 &container,
11851 &Container {
11852 children: vec![
11853 Container {
11854 calculated_offset_x: Some(0.0),
11855 ..container.children[0].clone()
11856 },
11857 Container {
11858 calculated_offset_x: Some(10.0),
11859 ..container.children[1].clone()
11860 },
11861 ],
11862 ..container.clone()
11863 },
11864 );
11865 }
11866
11867 #[test_log::test]
11868 #[ignore]
11869 fn does_include_gap_in_offset_y_overflow_y_wrap() {
11870 let mut container: Container = html! {
11871 div sx-overflow-y=(LayoutOverflow::Wrap { grid: false }) sx-gap=(10) {
11872 div sx-height=(50) {}
11873 div sx-height=(50) {}
11874 }
11875 }
11876 .try_into()
11877 .unwrap();
11878
11879 container.calculated_width = Some(400.0);
11880 container.calculated_height = Some(100.0);
11881
11882 CALCULATOR.calc(&mut container);
11883 log::trace!("full container:\n{container}");
11884 container = container.children[0].clone();
11885 log::trace!("container:\n{container}");
11886
11887 compare_containers(
11888 &container,
11889 &Container {
11890 children: vec![
11891 Container {
11892 calculated_offset_y: Some(0.0),
11893 ..container.children[0].clone()
11894 },
11895 Container {
11896 calculated_offset_y: Some(10.0),
11897 ..container.children[1].clone()
11898 },
11899 ],
11900 ..container.clone()
11901 },
11902 );
11903 }
11904
11905 #[test_log::test]
11906 fn does_include_gap_in_offset_y_overflow_x_wrap() {
11907 let mut container: Container = html! {
11908 div sx-width=(50) sx-dir=(LayoutDirection::Row) sx-overflow-x=(LayoutOverflow::Wrap { grid: false }) sx-gap=(10) {
11909 div sx-width=(50) {}
11910 div sx-width=(50) {}
11911 }
11912 }
11913 .try_into()
11914 .unwrap();
11915
11916 container.calculated_width = Some(400.0);
11917 container.calculated_height = Some(100.0);
11918
11919 CALCULATOR.calc(&mut container);
11920 log::trace!("full container:\n{container}");
11921 container = container.children[0].clone();
11922 log::trace!("container:\n{container}");
11923
11924 compare_containers(
11925 &container,
11926 &Container {
11927 children: vec![
11928 Container {
11929 calculated_offset_y: Some(0.0),
11930 ..container.children[0].clone()
11931 },
11932 Container {
11933 calculated_offset_y: Some(10.0),
11934 ..container.children[1].clone()
11935 },
11936 ],
11937 ..container.clone()
11938 },
11939 );
11940 }
11941
11942 #[test_log::test]
11943 #[ignore]
11944 fn does_include_gap_in_offset_x_overflow_y_wrap() {
11945 let mut container: Container = html! {
11946 div sx-height=(50) sx-overflow-y=(LayoutOverflow::Wrap { grid: false }) sx-gap=(10) {
11947 div sx-height=(50) {}
11948 div sx-height=(50) {}
11949 }
11950 }
11951 .try_into()
11952 .unwrap();
11953
11954 container.calculated_width = Some(400.0);
11955 container.calculated_height = Some(100.0);
11956
11957 CALCULATOR.calc(&mut container);
11958 log::trace!("full container:\n{container}");
11959 container = container.children[0].clone();
11960 log::trace!("container:\n{container}");
11961
11962 compare_containers(
11963 &container,
11964 &Container {
11965 children: vec![
11966 Container {
11967 calculated_offset_x: Some(0.0),
11968 ..container.children[0].clone()
11969 },
11970 Container {
11971 calculated_offset_x: Some(10.0),
11972 ..container.children[1].clone()
11973 },
11974 ],
11975 ..container.clone()
11976 },
11977 );
11978 }
11979 }
11980 }
11981}