1use super::types::{GridTrack, TrackCounts};
4use crate::geometry::AbsoluteAxis;
5use crate::style::{LengthPercentage, RepetitionCount, TrackSizingFunction};
6use crate::style_helpers::TaffyAuto;
7use crate::util::sys::{ceil, floor, Vec};
8use crate::util::MaybeMath;
9use crate::util::ResolveOrZero;
10use crate::{GenericGridTemplateComponent, GenericRepetition, GridContainerStyle};
11
12pub(crate) enum AutoRepeatStrategy {
14 MaxRepetitionsThatDoNotOverflow,
18 MinRepetitionsThatDoOverflow,
21}
22
23pub(crate) fn compute_explicit_grid_size_in_axis(
25 style: &impl GridContainerStyle,
26 auto_fit_container_size: Option<f32>,
27 auto_fit_strategy: AutoRepeatStrategy,
28 resolve_calc_value: impl Fn(*const (), f32) -> f32,
29 axis: AbsoluteAxis,
30) -> (u16, u16) {
31 let template = match axis {
32 AbsoluteAxis::Horizontal => style.grid_template_columns(),
33 AbsoluteAxis::Vertical => style.grid_template_rows(),
34 };
35 let Some(template) = template else {
36 return (0, 0);
37 };
38
39 let track_count = template.len();
41 if track_count == 0 {
42 return (0, 0);
43 }
44
45 let template_has_repetitions_with_zero_tracks = template.clone().any(|track_def| match track_def {
48 GenericGridTemplateComponent::Single(_) => false,
49 GenericGridTemplateComponent::Repeat(repeat) => repeat.track_count() == 0,
50 });
51 if template_has_repetitions_with_zero_tracks {
52 return (0, 0);
53 }
54
55 let non_auto_repeating_track_count = template
57 .clone()
58 .map(|track_def| match track_def {
59 GenericGridTemplateComponent::Single(_) => 1,
60 GenericGridTemplateComponent::Repeat(repeat) => match repeat.count() {
61 RepetitionCount::Count(count) => count * repeat.track_count(),
62 RepetitionCount::AutoFit | RepetitionCount::AutoFill => 0,
63 },
64 })
65 .sum::<u16>();
66
67 let auto_repetition_count: u16 = template.clone().filter(|track_def| track_def.is_auto_repetition()).count() as u16;
68 let all_track_defs_have_fixed_component = template.clone().all(|track_def| match track_def {
69 GenericGridTemplateComponent::Single(sizing_function) => sizing_function.has_fixed_component(),
70 GenericGridTemplateComponent::Repeat(repeat) => {
71 repeat.tracks().all(|sizing_function| sizing_function.has_fixed_component())
72 }
73 });
74
75 let template_is_valid =
76 auto_repetition_count == 0 || (auto_repetition_count == 1 && all_track_defs_have_fixed_component);
77
78 if !template_is_valid {
81 return (0, 0);
82 }
83
84 if auto_repetition_count == 0 {
87 return (0, non_auto_repeating_track_count);
88 }
89
90 let repetition_definition = template
91 .clone()
92 .find_map(|def| match def {
93 GenericGridTemplateComponent::Single(_) => None,
94 GenericGridTemplateComponent::Repeat(repeat) => match repeat.count() {
95 RepetitionCount::Count(_) => None,
96 RepetitionCount::AutoFit | RepetitionCount::AutoFill => Some(repeat),
97 },
98 })
99 .unwrap();
100 let repetition_definition_iter = repetition_definition.tracks();
101 let repetition_track_count = repetition_definition_iter.len() as u16;
102
103 let num_repetitions: u16 = match auto_fit_container_size {
105 None => 1,
106 Some(inner_container_size) => {
107 let parent_size = Some(inner_container_size);
108
109 fn track_definite_value(
112 sizing_function: TrackSizingFunction,
113 parent_size: Option<f32>,
114 calc_resolver: impl Fn(*const (), f32) -> f32,
115 ) -> f32 {
116 let max_size = sizing_function.max.definite_value(parent_size, &calc_resolver);
117 let min_size = sizing_function.min.definite_value(parent_size, &calc_resolver);
118 max_size.map(|max| max.maybe_max(min_size)).or(min_size).unwrap()
119 }
120
121 let non_repeating_track_used_space: f32 = template
122 .clone()
123 .map(|track_def| match track_def {
124 GenericGridTemplateComponent::Single(sizing_function) => {
125 track_definite_value(sizing_function, parent_size, &resolve_calc_value)
126 }
127 GenericGridTemplateComponent::Repeat(repeat) => match repeat.count() {
128 RepetitionCount::Count(count) => {
129 let sum = repeat
130 .tracks()
131 .map(|sizing_function| {
132 track_definite_value(sizing_function, parent_size, &resolve_calc_value)
133 })
134 .sum::<f32>();
135 sum * (count as f32)
136 }
137 RepetitionCount::AutoFit | RepetitionCount::AutoFill => 0.0,
138 },
139 })
140 .sum();
141 let gap_size = style.gap().get_abs(axis).resolve_or_zero(Some(inner_container_size), &resolve_calc_value);
142
143 let per_repetition_track_used_space: f32 = repetition_definition_iter
145 .map(|sizing_function| track_definite_value(sizing_function, parent_size, &resolve_calc_value))
146 .sum::<f32>();
147
148 let first_repetition_and_non_repeating_tracks_used_space = non_repeating_track_used_space
151 + per_repetition_track_used_space
152 + ((non_auto_repeating_track_count + repetition_track_count).saturating_sub(1) as f32 * gap_size);
153
154 if first_repetition_and_non_repeating_tracks_used_space > inner_container_size {
157 1u16
158 } else {
159 let per_repetition_gap_used_space = (repetition_track_count as f32) * gap_size;
160 let per_repetition_used_space = per_repetition_track_used_space + per_repetition_gap_used_space;
161 let num_repetition_that_fit = (inner_container_size
162 - first_repetition_and_non_repeating_tracks_used_space)
163 / per_repetition_used_space;
164
165 match auto_fit_strategy {
172 AutoRepeatStrategy::MaxRepetitionsThatDoNotOverflow => (floor(num_repetition_that_fit) as u16) + 1,
173 AutoRepeatStrategy::MinRepetitionsThatDoOverflow => (ceil(num_repetition_that_fit) as u16) + 1,
174 }
175 }
176 }
177 };
178
179 let grid_template_track_count = non_auto_repeating_track_count + (repetition_track_count * num_repetitions);
180 (num_repetitions, grid_template_track_count)
181}
182
183pub(super) fn initialize_grid_tracks(
186 tracks: &mut Vec<GridTrack>,
187 counts: TrackCounts,
188 style: &impl GridContainerStyle,
189 axis: AbsoluteAxis,
190 track_has_items: impl Fn(usize) -> bool,
191) {
192 let track_template;
194 let auto_tracks;
195 let gap;
196 match axis {
197 AbsoluteAxis::Horizontal => {
198 track_template = style.grid_template_columns();
199 auto_tracks = style.grid_auto_columns();
200 gap = style.gap().width;
201 }
202 AbsoluteAxis::Vertical => {
203 track_template = style.grid_template_rows();
204 auto_tracks = style.grid_auto_rows();
205 gap = style.gap().height;
206 }
207 };
208
209 tracks.clear();
212 tracks.reserve((counts.len() * 2) + 1);
213 tracks.push(GridTrack::gutter(gap));
214
215 let auto_track_count = auto_tracks.len();
216
217 if counts.negative_implicit > 0 {
219 if auto_track_count == 0 {
220 let iter = core::iter::repeat(TrackSizingFunction::AUTO);
221 create_implicit_tracks(tracks, counts.negative_implicit, iter, gap)
222 } else {
223 let offset = auto_track_count - (counts.negative_implicit as usize % auto_track_count);
224 let iter = auto_tracks.clone().cycle().skip(offset);
225 create_implicit_tracks(tracks, counts.negative_implicit, iter, gap)
226 }
227 }
228
229 let mut current_track_index = (counts.negative_implicit) as usize;
230
231 if counts.explicit > 0 {
235 if let Some(track_template) = track_template {
236 track_template.clone().for_each(|track_sizing_function| {
237 match track_sizing_function {
238 GenericGridTemplateComponent::Single(sizing_function) => {
239 tracks.push(GridTrack::new(
240 sizing_function.min_sizing_function(),
241 sizing_function.max_sizing_function(),
242 ));
243 tracks.push(GridTrack::gutter(gap));
244 current_track_index += 1;
245 }
246 GenericGridTemplateComponent::Repeat(repeat) => match repeat.count() {
247 RepetitionCount::Count(count) => {
248 let track_iter = repeat.tracks();
249 let track_iter = track_iter.cycle().take(repeat.track_count() as usize * count as usize);
250 track_iter.for_each(|sizing_function| {
251 tracks.push(GridTrack::new(
252 sizing_function.min_sizing_function(),
253 sizing_function.max_sizing_function(),
254 ));
255 tracks.push(GridTrack::gutter(gap));
256 current_track_index += 1;
257 });
258 }
259 RepetitionCount::AutoFit | RepetitionCount::AutoFill => {
260 let auto_repeated_track_count =
261 (counts.explicit - (track_template.len() as u16 - 1)) as usize;
262 let iter = repeat.tracks().cycle();
263 for track_def in iter.take(auto_repeated_track_count) {
264 let mut track =
265 GridTrack::new(track_def.min_sizing_function(), track_def.max_sizing_function());
266 let mut gutter = GridTrack::gutter(gap);
267
268 if repeat.count() == RepetitionCount::AutoFit && !track_has_items(current_track_index) {
270 track.collapse();
271 gutter.collapse();
272 }
273
274 tracks.push(track);
275 tracks.push(gutter);
276
277 current_track_index += 1;
278 }
279 }
280 },
281 }
282 });
283 }
284 }
285
286 let grid_area_tracks = (counts.negative_implicit + counts.explicit) - current_track_index as u16;
287
288 if auto_track_count == 0 {
290 let iter = core::iter::repeat(TrackSizingFunction::AUTO);
291 create_implicit_tracks(tracks, counts.positive_implicit + grid_area_tracks, iter, gap)
292 } else {
293 let iter = auto_tracks.clone().cycle();
294 create_implicit_tracks(tracks, counts.positive_implicit + grid_area_tracks, iter, gap)
295 }
296
297 tracks.first_mut().unwrap().collapse();
299 tracks.last_mut().unwrap().collapse();
300}
301
302fn create_implicit_tracks(
304 tracks: &mut Vec<GridTrack>,
305 count: u16,
306 mut auto_tracks_iter: impl Iterator<Item = TrackSizingFunction>,
307 gap: LengthPercentage,
308) {
309 for _ in 0..count {
310 let track_def = auto_tracks_iter.next().unwrap();
311 tracks.push(GridTrack::new(track_def.min_sizing_function(), track_def.max_sizing_function()));
312 tracks.push(GridTrack::gutter(gap));
313 }
314}
315
316#[cfg(test)]
317mod test {
318 use super::compute_explicit_grid_size_in_axis;
319 use super::initialize_grid_tracks;
320 use crate::compute::grid::explicit_grid::AutoRepeatStrategy;
321 use crate::compute::grid::types::GridTrackKind;
322 use crate::compute::grid::types::TrackCounts;
323 use crate::compute::grid::util::*;
324 use crate::geometry::AbsoluteAxis;
325 use crate::prelude::*;
326 use crate::sys::DefaultCheapStr;
327
328 #[test]
329 fn explicit_grid_sizing_no_repeats() {
330 let grid_style = (600.0, 600.0, 2, 4).into_grid();
331 let preferred_size = grid_style.size.map(|s| s.into_option());
332 let (auto_col_reps, col_count) = compute_explicit_grid_size_in_axis(
333 &grid_style,
334 preferred_size.get_abs(AbsoluteAxis::Horizontal),
335 AutoRepeatStrategy::MaxRepetitionsThatDoNotOverflow,
336 |_, _| 42.42,
337 AbsoluteAxis::Horizontal,
338 );
339 let (auto_row_reps, row_count) = compute_explicit_grid_size_in_axis(
340 &grid_style,
341 preferred_size.get_abs(AbsoluteAxis::Vertical),
342 AutoRepeatStrategy::MaxRepetitionsThatDoNotOverflow,
343 |_, _| 42.42,
344 AbsoluteAxis::Vertical,
345 );
346 assert_eq!(col_count, 2);
347 assert_eq!(row_count, 4);
348 assert_eq!(auto_col_reps, 0);
349 assert_eq!(auto_row_reps, 0);
350 }
351
352 #[test]
353 fn explicit_grid_sizing_auto_fill_exact_fit() {
354 use RepetitionCount::AutoFill;
355 let grid_style: Style<DefaultCheapStr> = Style {
356 display: Display::Grid,
357 size: Size { width: length(120.0), height: length(80.0) },
358 grid_template_columns: vec![repeat(AutoFill, vec![length(40.0)])],
359 grid_template_rows: vec![repeat(AutoFill, vec![length(20.0)])],
360 ..Default::default()
361 };
362 let preferred_size = grid_style.size.map(|s| s.into_option());
363 let (auto_col_reps, col_count) = compute_explicit_grid_size_in_axis(
364 &grid_style,
365 preferred_size.get_abs(AbsoluteAxis::Horizontal),
366 AutoRepeatStrategy::MaxRepetitionsThatDoNotOverflow,
367 |_, _| 42.42,
368 AbsoluteAxis::Horizontal,
369 );
370 let (auto_row_reps, row_count) = compute_explicit_grid_size_in_axis(
371 &grid_style,
372 preferred_size.get_abs(AbsoluteAxis::Vertical),
373 AutoRepeatStrategy::MaxRepetitionsThatDoNotOverflow,
374 |_, _| 42.42,
375 AbsoluteAxis::Vertical,
376 );
377 assert_eq!(col_count, 3);
378 assert_eq!(row_count, 4);
379 assert_eq!(auto_col_reps, 3);
380 assert_eq!(auto_row_reps, 4);
381 }
382
383 #[test]
384 fn explicit_grid_sizing_auto_fill_non_exact_fit() {
385 use RepetitionCount::AutoFill;
386 let grid_style: Style<DefaultCheapStr> = Style {
387 display: Display::Grid,
388 size: Size { width: length(140.0), height: length(90.0) },
389 grid_template_columns: vec![repeat(AutoFill, vec![length(40.0)])],
390 grid_template_rows: vec![repeat(AutoFill, vec![length(20.0)])],
391 ..Default::default()
392 };
393 let preferred_size = grid_style.size.map(|s| s.into_option());
394 let (auto_col_reps, col_count) = compute_explicit_grid_size_in_axis(
395 &grid_style,
396 preferred_size.get_abs(AbsoluteAxis::Horizontal),
397 AutoRepeatStrategy::MaxRepetitionsThatDoNotOverflow,
398 |_, _| 42.42,
399 AbsoluteAxis::Horizontal,
400 );
401 let (auto_row_reps, row_count) = compute_explicit_grid_size_in_axis(
402 &grid_style,
403 preferred_size.get_abs(AbsoluteAxis::Vertical),
404 AutoRepeatStrategy::MaxRepetitionsThatDoNotOverflow,
405 |_, _| 42.42,
406 AbsoluteAxis::Vertical,
407 );
408 assert_eq!(col_count, 3);
409 assert_eq!(row_count, 4);
410 assert_eq!(auto_col_reps, 3);
411 assert_eq!(auto_row_reps, 4);
412 }
413
414 #[test]
415 fn explicit_grid_sizing_auto_fill_min_size_exact_fit() {
416 use RepetitionCount::AutoFill;
417 let grid_style: Style<DefaultCheapStr> = Style {
418 display: Display::Grid,
419 min_size: Size { width: length(120.0), height: length(80.0) },
420 grid_template_columns: vec![repeat(AutoFill, vec![length(40.0)])],
421 grid_template_rows: vec![repeat(AutoFill, vec![length(20.0)])],
422 ..Default::default()
423 };
424 let inner_container_size = Size { width: Some(120.0), height: Some(80.0) };
425 let (auto_col_reps, col_count) = compute_explicit_grid_size_in_axis(
426 &grid_style,
427 inner_container_size.get_abs(AbsoluteAxis::Horizontal),
428 AutoRepeatStrategy::MinRepetitionsThatDoOverflow,
429 |_, _| 42.42,
430 AbsoluteAxis::Horizontal,
431 );
432 let (auto_row_reps, row_count) = compute_explicit_grid_size_in_axis(
433 &grid_style,
434 inner_container_size.get_abs(AbsoluteAxis::Vertical),
435 AutoRepeatStrategy::MinRepetitionsThatDoOverflow,
436 |_, _| 42.42,
437 AbsoluteAxis::Vertical,
438 );
439 assert_eq!(col_count, 3);
440 assert_eq!(row_count, 4);
441 assert_eq!(auto_col_reps, 3);
442 assert_eq!(auto_row_reps, 4);
443 }
444
445 #[test]
446 fn explicit_grid_sizing_auto_fill_min_size_non_exact_fit() {
447 use RepetitionCount::AutoFill;
448 let grid_style: Style<DefaultCheapStr> = Style {
449 display: Display::Grid,
450 min_size: Size { width: length(140.0), height: length(90.0) },
451 grid_template_columns: vec![repeat(AutoFill, vec![length(40.0)])],
452 grid_template_rows: vec![repeat(AutoFill, vec![length(20.0)])],
453 ..Default::default()
454 };
455 let inner_container_size = Size { width: Some(140.0), height: Some(90.0) };
456 let (auto_col_reps, col_count) = compute_explicit_grid_size_in_axis(
457 &grid_style,
458 inner_container_size.get_abs(AbsoluteAxis::Horizontal),
459 AutoRepeatStrategy::MinRepetitionsThatDoOverflow,
460 |_, _| 42.42,
461 AbsoluteAxis::Horizontal,
462 );
463 let (auto_row_reps, row_count) = compute_explicit_grid_size_in_axis(
464 &grid_style,
465 inner_container_size.get_abs(AbsoluteAxis::Vertical),
466 AutoRepeatStrategy::MinRepetitionsThatDoOverflow,
467 |_, _| 42.42,
468 AbsoluteAxis::Vertical,
469 );
470 assert_eq!(col_count, 4);
471 assert_eq!(row_count, 5);
472 assert_eq!(auto_col_reps, 4);
473 assert_eq!(auto_row_reps, 5);
474 }
475
476 #[test]
477 fn explicit_grid_sizing_auto_fill_multiple_repeated_tracks() {
478 use RepetitionCount::AutoFill;
479 let grid_style: Style<DefaultCheapStr> = Style {
480 display: Display::Grid,
481 size: Size { width: length(140.0), height: length(100.0) },
482 grid_template_columns: vec![repeat(AutoFill, vec![length(40.0), length(20.0)])],
483 grid_template_rows: vec![repeat(AutoFill, vec![length(20.0), length(10.0)])],
484 ..Default::default()
485 };
486 let preferred_size = grid_style.size.map(|s| s.into_option());
487 let (auto_col_reps, col_count) = compute_explicit_grid_size_in_axis(
488 &grid_style,
489 preferred_size.get_abs(AbsoluteAxis::Horizontal),
490 AutoRepeatStrategy::MaxRepetitionsThatDoNotOverflow,
491 |_, _| 42.42,
492 AbsoluteAxis::Horizontal,
493 );
494 let (auto_row_reps, row_count) = compute_explicit_grid_size_in_axis(
495 &grid_style,
496 preferred_size.get_abs(AbsoluteAxis::Vertical),
497 AutoRepeatStrategy::MaxRepetitionsThatDoNotOverflow,
498 |_, _| 42.42,
499 AbsoluteAxis::Vertical,
500 );
501 assert_eq!(col_count, 4); assert_eq!(row_count, 6); assert_eq!(auto_col_reps, 2);
504 assert_eq!(auto_row_reps, 3);
505 }
506
507 #[test]
508 fn explicit_grid_sizing_auto_fill_gap() {
509 use RepetitionCount::AutoFill;
510 let grid_style: Style<DefaultCheapStr> = Style {
511 display: Display::Grid,
512 size: Size { width: length(140.0), height: length(100.0) },
513 grid_template_columns: vec![repeat(AutoFill, vec![length(40.0)])],
514 grid_template_rows: vec![repeat(AutoFill, vec![length(20.0)])],
515 gap: length(20.0),
516 ..Default::default()
517 };
518 let preferred_size = grid_style.size.map(|s| s.into_option());
519 let (auto_col_reps, col_count) = compute_explicit_grid_size_in_axis(
520 &grid_style,
521 preferred_size.get_abs(AbsoluteAxis::Horizontal),
522 AutoRepeatStrategy::MaxRepetitionsThatDoNotOverflow,
523 |_, _| 42.42,
524 AbsoluteAxis::Horizontal,
525 );
526 let (auto_row_reps, row_count) = compute_explicit_grid_size_in_axis(
527 &grid_style,
528 preferred_size.get_abs(AbsoluteAxis::Vertical),
529 AutoRepeatStrategy::MaxRepetitionsThatDoNotOverflow,
530 |_, _| 42.42,
531 AbsoluteAxis::Vertical,
532 );
533 assert_eq!(col_count, 2); assert_eq!(row_count, 3); assert_eq!(auto_col_reps, 2);
536 assert_eq!(auto_row_reps, 3);
537 }
538
539 #[test]
540 fn explicit_grid_sizing_no_defined_size() {
541 use RepetitionCount::AutoFill;
542 let grid_style: Style<DefaultCheapStr> = Style {
543 display: Display::Grid,
544 grid_template_columns: vec![repeat(AutoFill, vec![length(40.0), percent(0.5), length(20.0)])],
545 grid_template_rows: vec![repeat(AutoFill, vec![length(20.0)])],
546 gap: length(20.0),
547 ..Default::default()
548 };
549 let preferred_size = grid_style.size.map(|s| s.into_option());
550 let (auto_col_reps, col_count) = compute_explicit_grid_size_in_axis(
551 &grid_style,
552 preferred_size.get_abs(AbsoluteAxis::Horizontal),
553 AutoRepeatStrategy::MinRepetitionsThatDoOverflow,
554 |_, _| 42.42,
555 AbsoluteAxis::Horizontal,
556 );
557 let (auto_row_reps, row_count) = compute_explicit_grid_size_in_axis(
558 &grid_style,
559 preferred_size.get_abs(AbsoluteAxis::Vertical),
560 AutoRepeatStrategy::MinRepetitionsThatDoOverflow,
561 |_, _| 42.42,
562 AbsoluteAxis::Vertical,
563 );
564 assert_eq!(col_count, 3);
565 assert_eq!(row_count, 1);
566 assert_eq!(auto_col_reps, 1);
567 assert_eq!(auto_row_reps, 1);
568 }
569
570 #[test]
571 fn explicit_grid_sizing_mix_repeated_and_non_repeated() {
572 use RepetitionCount::AutoFill;
573 let grid_style: Style<DefaultCheapStr> = Style {
574 display: Display::Grid,
575 size: Size { width: length(140.0), height: length(100.0) },
576 grid_template_columns: vec![length(20.0), repeat(AutoFill, vec![length(40.0)])],
577 grid_template_rows: vec![length(40.0), repeat(AutoFill, vec![length(20.0)])],
578 gap: length(20.0),
579 ..Default::default()
580 };
581 let preferred_size = grid_style.size.map(|s| s.into_option());
582 let (auto_col_reps, col_count) = compute_explicit_grid_size_in_axis(
583 &grid_style,
584 preferred_size.get_abs(AbsoluteAxis::Horizontal),
585 AutoRepeatStrategy::MaxRepetitionsThatDoNotOverflow,
586 |_, _| 42.42,
587 AbsoluteAxis::Horizontal,
588 );
589 let (auto_row_reps, row_count) = compute_explicit_grid_size_in_axis(
590 &grid_style,
591 preferred_size.get_abs(AbsoluteAxis::Vertical),
592 AutoRepeatStrategy::MaxRepetitionsThatDoNotOverflow,
593 |_, _| 42.42,
594 AbsoluteAxis::Vertical,
595 );
596 assert_eq!(col_count, 3); assert_eq!(row_count, 2); assert_eq!(auto_col_reps, 2);
599 assert_eq!(auto_row_reps, 1);
600 }
601
602 #[test]
603 fn explicit_grid_sizing_mix_with_padding() {
604 use RepetitionCount::AutoFill;
605 let grid_style: Style<DefaultCheapStr> = Style {
606 display: Display::Grid,
607 size: Size { width: length(120.0), height: length(120.0) },
608 padding: Rect { left: length(10.0), right: length(10.0), top: length(20.0), bottom: length(20.0) },
609 grid_template_columns: vec![repeat(AutoFill, vec![length(20.0)])],
610 grid_template_rows: vec![repeat(AutoFill, vec![length(20.0)])],
611 ..Default::default()
612 };
613 let inner_container_size = Size { width: Some(100.0), height: Some(80.0) };
614 let (auto_col_reps, col_count) = compute_explicit_grid_size_in_axis(
615 &grid_style,
616 inner_container_size.get_abs(AbsoluteAxis::Horizontal),
617 AutoRepeatStrategy::MaxRepetitionsThatDoNotOverflow,
618 |_, _| 42.42,
619 AbsoluteAxis::Horizontal,
620 );
621 let (auto_row_reps, row_count) = compute_explicit_grid_size_in_axis(
622 &grid_style,
623 inner_container_size.get_abs(AbsoluteAxis::Vertical),
624 AutoRepeatStrategy::MaxRepetitionsThatDoNotOverflow,
625 |_, _| 42.42,
626 AbsoluteAxis::Vertical,
627 );
628 assert_eq!(col_count, 5); assert_eq!(row_count, 4); assert_eq!(auto_col_reps, 5);
631 assert_eq!(auto_row_reps, 4);
632 }
633
634 #[test]
635 fn test_initialize_grid_tracks() {
636 let minpx0 = MinTrackSizingFunction::from_length(0.0);
637 let minpx20 = MinTrackSizingFunction::from_length(20.0);
638 let minpx100 = MinTrackSizingFunction::from_length(100.0);
639
640 let maxpx0 = MaxTrackSizingFunction::from_length(0.0);
641 let maxpx20 = MaxTrackSizingFunction::from_length(20.0);
642 let maxpx100 = MaxTrackSizingFunction::from_length(100.0);
643
644 let grid_style: Style<DefaultCheapStr> = Style {
646 display: Display::Grid,
647 gap: length(20.0),
648 grid_template_columns: vec![length(100.0), minmax(length(100.0), fr(2.0)), fr(1.0)],
649 grid_auto_columns: vec![auto(), length(100.0)],
650 ..Default::default()
651 };
652 let track_counts = TrackCounts {
653 negative_implicit: 3,
654 explicit: grid_style.grid_template_columns.len() as u16,
655 positive_implicit: 3,
656 };
657
658 let mut tracks = Vec::new();
660 initialize_grid_tracks(&mut tracks, track_counts, &grid_style, AbsoluteAxis::Horizontal, |_| false);
661
662 let expected = vec![
664 (GridTrackKind::Gutter, minpx0, maxpx0),
666 (GridTrackKind::Track, minpx100, maxpx100),
668 (GridTrackKind::Gutter, minpx20, maxpx20),
669 (GridTrackKind::Track, auto(), auto()),
670 (GridTrackKind::Gutter, minpx20, maxpx20),
671 (GridTrackKind::Track, minpx100, maxpx100),
672 (GridTrackKind::Gutter, minpx20, maxpx20),
673 (GridTrackKind::Track, minpx100, maxpx100),
675 (GridTrackKind::Gutter, minpx20, maxpx20),
676 (GridTrackKind::Track, minpx100, MaxTrackSizingFunction::from_fr(2.0)), (GridTrackKind::Gutter, minpx20, maxpx20),
678 (GridTrackKind::Track, auto(), MaxTrackSizingFunction::from_fr(1.0)), (GridTrackKind::Gutter, minpx20, maxpx20),
680 (GridTrackKind::Track, auto(), auto()),
682 (GridTrackKind::Gutter, minpx20, maxpx20),
683 (GridTrackKind::Track, minpx100, maxpx100),
684 (GridTrackKind::Gutter, minpx20, maxpx20),
685 (GridTrackKind::Track, auto(), auto()),
686 (GridTrackKind::Gutter, minpx0, maxpx0),
687 ];
688
689 assert_eq!(tracks.len(), expected.len(), "Number of tracks doesn't match");
690
691 for (idx, (actual, (kind, min, max))) in tracks.into_iter().zip(expected).enumerate() {
692 assert_eq!(actual.kind, kind, "Track {idx} (0-based index)");
693 assert_eq!(actual.min_track_sizing_function, min, "Track {idx} (0-based index)");
694 assert_eq!(actual.max_track_sizing_function, max, "Track {idx} (0-based index)");
695 }
696 }
697}