use crate::geometry::Line;
use crate::style::{GenericGridPlacement, GridPlacement};
use crate::GridItemStyle;
use core::cmp::{max, min};
use super::types::TrackCounts;
use super::OriginZeroLine;
pub(crate) fn compute_grid_size_estimate<'a, S: GridItemStyle + 'a>(
explicit_col_count: u16,
explicit_row_count: u16,
child_styles_iter: impl Iterator<Item = S>,
) -> (TrackCounts, TrackCounts) {
let (col_min, col_max, col_max_span, row_min, row_max, row_max_span) =
get_known_child_positions(child_styles_iter, explicit_col_count, explicit_row_count);
let negative_implicit_inline_tracks = col_min.implied_negative_implicit_tracks();
let explicit_inline_tracks = explicit_col_count;
let mut positive_implicit_inline_tracks = col_max.implied_positive_implicit_tracks(explicit_col_count);
let negative_implicit_block_tracks = row_min.implied_negative_implicit_tracks();
let explicit_block_tracks = explicit_row_count;
let mut positive_implicit_block_tracks = row_max.implied_positive_implicit_tracks(explicit_row_count);
let tot_inline_tracks = negative_implicit_inline_tracks + explicit_inline_tracks + positive_implicit_inline_tracks;
if tot_inline_tracks < col_max_span {
positive_implicit_inline_tracks = col_max_span - explicit_inline_tracks - negative_implicit_inline_tracks;
}
let tot_block_tracks = negative_implicit_block_tracks + explicit_block_tracks + positive_implicit_block_tracks;
if tot_block_tracks < row_max_span {
positive_implicit_block_tracks = row_max_span - explicit_block_tracks - negative_implicit_block_tracks;
}
let column_counts =
TrackCounts::from_raw(negative_implicit_inline_tracks, explicit_inline_tracks, positive_implicit_inline_tracks);
let row_counts =
TrackCounts::from_raw(negative_implicit_block_tracks, explicit_block_tracks, positive_implicit_block_tracks);
(column_counts, row_counts)
}
fn get_known_child_positions<'a, S: GridItemStyle + 'a>(
children_iter: impl Iterator<Item = S>,
explicit_col_count: u16,
explicit_row_count: u16,
) -> (OriginZeroLine, OriginZeroLine, u16, OriginZeroLine, OriginZeroLine, u16) {
let (mut col_min, mut col_max, mut col_max_span) = (OriginZeroLine(0), OriginZeroLine(0), 0);
let (mut row_min, mut row_max, mut row_max_span) = (OriginZeroLine(0), OriginZeroLine(0), 0);
children_iter.for_each(|child_style| {
let (child_col_min, child_col_max, child_col_span) =
child_min_line_max_line_span(child_style.grid_column(), explicit_col_count);
let (child_row_min, child_row_max, child_row_span) =
child_min_line_max_line_span(child_style.grid_row(), explicit_row_count);
col_min = min(col_min, child_col_min);
col_max = max(col_max, child_col_max);
col_max_span = max(col_max_span, child_col_span);
row_min = min(row_min, child_row_min);
row_max = max(row_max, child_row_max);
row_max_span = max(row_max_span, child_row_span);
});
(col_min, col_max, col_max_span, row_min, row_max, row_max_span)
}
#[inline]
fn child_min_line_max_line_span(
line: Line<GridPlacement>,
explicit_track_count: u16,
) -> (OriginZeroLine, OriginZeroLine, u16) {
use GenericGridPlacement::*;
let oz_line = line.into_origin_zero(explicit_track_count);
let min = match (oz_line.start, oz_line.end) {
(Line(track1), Line(track2)) => {
if track1 == track2 {
track1
} else {
min(track1, track2)
}
}
(Line(track), Auto) => track,
(Line(track), Span(_)) => track,
(Auto, Line(track)) => track,
(Span(span), Line(track)) => track - span,
(Auto | Span(_), Auto | Span(_)) => OriginZeroLine(0),
};
let max = match (oz_line.start, oz_line.end) {
(Line(track1), Line(track2)) => {
if track1 == track2 {
track1 + 1
} else {
max(track1, track2)
}
}
(Line(track), Auto) => track + 1,
(Line(track), Span(span)) => track + span,
(Auto, Line(track)) => track,
(Span(_), Line(track)) => track,
(Auto | Span(_), Auto | Span(_)) => OriginZeroLine(0),
};
let span = match (line.start, line.end) {
(Auto | Span(_), Auto | Span(_)) => line.indefinite_span(),
_ => 1,
};
(min, max, span)
}
#[allow(clippy::bool_assert_comparison)]
#[cfg(test)]
mod tests {
mod test_child_min_max_line {
use super::super::child_min_line_max_line_span;
use super::super::OriginZeroLine;
use crate::geometry::Line;
use crate::style_helpers::*;
#[test]
fn child_min_max_line_auto() {
let (min_col, max_col, span) = child_min_line_max_line_span(Line { start: line(5), end: span(6) }, 6);
assert_eq!(min_col, OriginZeroLine(4));
assert_eq!(max_col, OriginZeroLine(10));
assert_eq!(span, 1);
}
#[test]
fn child_min_max_line_negative_track() {
let (min_col, max_col, span) = child_min_line_max_line_span(Line { start: line(-5), end: span(3) }, 6);
assert_eq!(min_col, OriginZeroLine(2));
assert_eq!(max_col, OriginZeroLine(5));
assert_eq!(span, 1);
}
}
mod test_initial_grid_sizing {
use super::super::compute_grid_size_estimate;
use crate::compute::grid::util::test_helpers::*;
use crate::style_helpers::*;
#[test]
fn explicit_grid_sizing_with_children() {
let explicit_col_count = 6;
let explicit_row_count = 8;
let child_styles = vec![
(line(1), span(2), line(2), auto()).into_grid_child(),
(line(-4), auto(), line(-2), auto()).into_grid_child(),
];
let (inline, block) =
compute_grid_size_estimate(explicit_col_count, explicit_row_count, child_styles.iter());
assert_eq!(inline.negative_implicit, 0);
assert_eq!(inline.explicit, explicit_col_count);
assert_eq!(inline.positive_implicit, 0);
assert_eq!(block.negative_implicit, 0);
assert_eq!(block.explicit, explicit_row_count);
assert_eq!(block.positive_implicit, 0);
}
#[test]
fn negative_implicit_grid_sizing() {
let explicit_col_count = 4;
let explicit_row_count = 4;
let child_styles = vec![
(line(-6), span(2), line(-8), auto()).into_grid_child(),
(line(4), auto(), line(3), auto()).into_grid_child(),
];
let (inline, block) =
compute_grid_size_estimate(explicit_col_count, explicit_row_count, child_styles.iter());
assert_eq!(inline.negative_implicit, 1);
assert_eq!(inline.explicit, explicit_col_count);
assert_eq!(inline.positive_implicit, 0);
assert_eq!(block.negative_implicit, 3);
assert_eq!(block.explicit, explicit_row_count);
assert_eq!(block.positive_implicit, 0);
}
}
}