Skip to main content

taffy/compute/grid/types/
grid_track.rs

1//! Contains GridTrack used to represent a single grid track (row/column) during layout
2use crate::{
3    prelude::TaffyZero,
4    style::{LengthPercentage, MaxTrackSizingFunction, MinTrackSizingFunction},
5    util::sys::f32_min,
6};
7
8/// Whether a GridTrack represents an actual track or a gutter.
9#[derive(Copy, Clone, Debug, PartialEq)]
10pub(in super::super) enum GridTrackKind {
11    /// Track is an actual track
12    Track,
13    /// Track is a gutter (aka grid line) (aka gap)
14    Gutter, // { name: Option<u16> },
15}
16
17/// Internal sizing information for a single grid track (row/column)
18/// Gutters between tracks are sized similarly to actual tracks, so they
19/// are also represented by this struct
20#[derive(Debug, Clone)]
21pub(in super::super) struct GridTrack {
22    #[allow(dead_code)] // Used in tests + may be useful in future
23    /// Whether the track is a full track, a gutter, or a placeholder that has not yet been initialised
24    pub kind: GridTrackKind,
25
26    /// Whether the track is a collapsed track/gutter. Collapsed tracks are effectively treated as if
27    /// they don't exist for the purposes of grid sizing. Gutters between collapsed tracks are also collapsed.
28    pub is_collapsed: bool,
29
30    /// The minimum track sizing function of the track
31    pub min_track_sizing_function: MinTrackSizingFunction,
32
33    /// The maximum track sizing function of the track
34    pub max_track_sizing_function: MaxTrackSizingFunction,
35
36    /// The distance of the start of the track from the start of the grid container
37    pub offset: f32,
38
39    /// The size (width/height as applicable) of the track
40    pub base_size: f32,
41
42    /// A temporary scratch value when sizing tracks
43    /// Note: can be infinity
44    pub growth_limit: f32,
45
46    /// A temporary scratch value when sizing tracks. Is used as an additional amount to add to the
47    /// estimate for the available space in the opposite axis when content sizing items
48    pub content_alignment_adjustment: f32,
49
50    /// A temporary scratch value when "distributing space" to avoid clobbering planned increase variable
51    pub item_incurred_increase: f32,
52    /// A temporary scratch value when "distributing space" to avoid clobbering the main variable
53    pub base_size_planned_increase: f32,
54    /// A temporary scratch value when "distributing space" to avoid clobbering the main variable
55    pub growth_limit_planned_increase: f32,
56    /// A temporary scratch value when "distributing space"
57    /// See: https://www.w3.org/TR/css3-grid-layout/#infinitely-growable
58    pub infinitely_growable: bool,
59
60    /// The resolved `fit-content()` limit of the max track sizing function (infinity if it is not `fit-content()`
61    /// or the limit cannot be resolved). Resolved once per track sizing pass by `resolve_fit_content_limit`.
62    pub fit_content_limit: f32,
63}
64
65impl GridTrack {
66    /// GridTrack constructor with all configuration parameters for the other constructors exposed
67    const fn new_with_kind(
68        kind: GridTrackKind,
69        min_track_sizing_function: MinTrackSizingFunction,
70        max_track_sizing_function: MaxTrackSizingFunction,
71    ) -> GridTrack {
72        GridTrack {
73            kind,
74            is_collapsed: false,
75            min_track_sizing_function,
76            max_track_sizing_function,
77            offset: 0.0,
78            base_size: 0.0,
79            growth_limit: 0.0,
80            content_alignment_adjustment: 0.0,
81            item_incurred_increase: 0.0,
82            base_size_planned_increase: 0.0,
83            growth_limit_planned_increase: 0.0,
84            infinitely_growable: false,
85            fit_content_limit: f32::INFINITY,
86        }
87    }
88
89    /// Create new GridTrack representing an actual track (not a gutter)
90    pub const fn new(
91        min_track_sizing_function: MinTrackSizingFunction,
92        max_track_sizing_function: MaxTrackSizingFunction,
93    ) -> GridTrack {
94        Self::new_with_kind(GridTrackKind::Track, min_track_sizing_function, max_track_sizing_function)
95    }
96
97    /// Create a new GridTrack representing a gutter
98    pub fn gutter(size: LengthPercentage) -> GridTrack {
99        Self::new_with_kind(
100            GridTrackKind::Gutter,
101            MinTrackSizingFunction::from(size),
102            MaxTrackSizingFunction::from(size),
103        )
104    }
105
106    /// Mark a GridTrack as collapsed. Also sets both of the track's sizing functions
107    /// to fixed zero-sized sizing functions.
108    pub fn collapse(&mut self) {
109        self.is_collapsed = true;
110        self.min_track_sizing_function = MinTrackSizingFunction::ZERO;
111        self.max_track_sizing_function = MaxTrackSizingFunction::ZERO;
112        self.fit_content_limit = f32::INFINITY;
113    }
114
115    #[inline(always)]
116    /// Returns true if the track is flexible (has a Flex MaxTrackSizingFunction), else false.
117    pub fn is_flexible(&self) -> bool {
118        self.max_track_sizing_function.is_fr()
119    }
120
121    #[inline(always)]
122    /// Returns true if the track is flexible (has a Flex MaxTrackSizingFunction), else false.
123    pub fn uses_percentage(&self) -> bool {
124        self.min_track_sizing_function.uses_percentage() || self.max_track_sizing_function.uses_percentage()
125    }
126
127    #[inline(always)]
128    /// Returns true if the track has an intrinsic min and or max sizing function
129    pub fn has_intrinsic_sizing_function(&self) -> bool {
130        self.min_track_sizing_function.is_intrinsic() || self.max_track_sizing_function.is_intrinsic()
131    }
132
133    /// Cache the `fit-content()` limit of the max track sizing function (if any), resolved against the
134    /// container's inner size in this axis. Percentage and calc() limits resolve to infinity if that size is
135    /// indefinite, as do tracks which are not `fit-content()`.
136    #[inline]
137    pub fn resolve_fit_content_limit(
138        &mut self,
139        axis_inner_node_size: Option<f32>,
140        calc_resolver: impl Fn(*const (), f32) -> f32,
141    ) {
142        self.fit_content_limit = self
143            .max_track_sizing_function
144            .fit_content_limit(axis_inner_node_size, calc_resolver)
145            .unwrap_or(f32::INFINITY);
146    }
147
148    #[inline(always)]
149    /// Returns the resolved `fit-content()` limit of the track (infinity if the track is not `fit-content()`)
150    pub fn fit_content_limit(&self) -> f32 {
151        self.fit_content_limit
152    }
153
154    #[inline]
155    /// Returns the track's growth limit, capped by its `fit-content()` limit (if any)
156    pub fn fit_content_limited_growth_limit(&self) -> f32 {
157        f32_min(self.growth_limit, self.fit_content_limit)
158    }
159
160    #[inline]
161    /// Returns the track's flex factor if it is a flex track, else 0.
162    pub fn flex_factor(&self) -> f32 {
163        if self.max_track_sizing_function.is_fr() {
164            self.max_track_sizing_function.0.value()
165        } else {
166            0.0
167        }
168    }
169}