diff --git a/src/library/layout/grid.rs b/src/library/layout/grid.rs index 1028188e3..8ecac636f 100644 --- a/src/library/layout/grid.rs +++ b/src/library/layout/grid.rs @@ -39,6 +39,7 @@ impl Layout for GridNode { ) -> TypResult>> { // Prepare grid layout by unifying content and gutter tracks. let layouter = GridLayouter::new( + ctx, self.tracks.as_deref(), self.gutter.as_deref(), &self.cells, @@ -47,7 +48,7 @@ impl Layout for GridNode { ); // Measure the columns and layout the grid row-by-row. - layouter.layout(ctx) + layouter.layout() } } @@ -91,7 +92,9 @@ castable! { /// Performs grid layout. pub struct GridLayouter<'a> { - /// The grid cells. + /// The core context. + ctx: &'a mut Context, + /// The grid cells. cells: &'a [LayoutNode], /// The column tracks including gutter tracks. cols: Vec, @@ -130,6 +133,7 @@ impl<'a> GridLayouter<'a> { /// /// This prepares grid layout by unifying content and gutter tracks. pub fn new( + ctx: &'a mut Context, tracks: Spec<&[TrackSizing]>, gutter: Spec<&[TrackSizing]>, cells: &'a [LayoutNode], @@ -183,6 +187,7 @@ impl<'a> GridLayouter<'a> { regions.expand = Spec::new(true, false); Self { + ctx, cells, cols, rows, @@ -198,19 +203,19 @@ impl<'a> GridLayouter<'a> { } /// Determines the columns sizes and then layouts the grid row-by-row. - pub fn layout(mut self, ctx: &mut Context) -> TypResult>> { - self.measure_columns(ctx)?; + pub fn layout(mut self) -> TypResult>> { + self.measure_columns()?; for y in 0 .. self.rows.len() { // Skip to next region if current one is full, but only for content // rows, not for gutter rows. if y % 2 == 0 && self.regions.is_full() { - self.finish_region(ctx)?; + self.finish_region()?; } match self.rows[y] { - TrackSizing::Auto => self.layout_auto_row(ctx, y)?, - TrackSizing::Relative(v) => self.layout_relative_row(ctx, v, y)?, + TrackSizing::Auto => self.layout_auto_row(y)?, + TrackSizing::Relative(v) => self.layout_relative_row(v, y)?, TrackSizing::Fractional(v) => { self.lrows.push(Row::Fr(v, y)); self.fr += v; @@ -218,12 +223,12 @@ impl<'a> GridLayouter<'a> { } } - self.finish_region(ctx)?; + self.finish_region()?; Ok(self.finished) } /// Determine all column sizes. - fn measure_columns(&mut self, ctx: &mut Context) -> TypResult<()> { + fn measure_columns(&mut self) -> TypResult<()> { // Sum of sizes of resolved relative tracks. let mut rel = Length::zero(); @@ -249,7 +254,7 @@ impl<'a> GridLayouter<'a> { let available = self.regions.first.x - rel; if available >= Length::zero() { // Determine size of auto columns. - let (auto, count) = self.measure_auto_columns(ctx, available)?; + let (auto, count) = self.measure_auto_columns(available)?; // If there is remaining space, distribute it to fractional columns, // otherwise shrink auto columns. @@ -270,11 +275,7 @@ impl<'a> GridLayouter<'a> { } /// Measure the size that is available to auto columns. - fn measure_auto_columns( - &mut self, - ctx: &mut Context, - available: Length, - ) -> TypResult<(Length, usize)> { + fn measure_auto_columns(&mut self, available: Length) -> TypResult<(Length, usize)> { let mut auto = Length::zero(); let mut count = 0; @@ -300,7 +301,7 @@ impl<'a> GridLayouter<'a> { v.resolve(self.styles).relative_to(self.regions.base.y); } - let frame = node.layout(ctx, &pod, self.styles)?.remove(0); + let frame = node.layout(self.ctx, &pod, self.styles)?.remove(0); resolved.set_max(frame.size.x); } } @@ -354,7 +355,7 @@ impl<'a> GridLayouter<'a> { /// Layout a row with automatic height. Such a row may break across multiple /// regions. - fn layout_auto_row(&mut self, ctx: &mut Context, y: usize) -> TypResult<()> { + fn layout_auto_row(&mut self, y: usize) -> TypResult<()> { let mut resolved: Vec = vec![]; // Determine the size for each region of the row. @@ -370,7 +371,7 @@ impl<'a> GridLayouter<'a> { } let mut sizes = node - .layout(ctx, &pod, self.styles)? + .layout(self.ctx, &pod, self.styles)? .into_iter() .map(|frame| frame.size.y); @@ -393,7 +394,7 @@ impl<'a> GridLayouter<'a> { // Layout into a single region. if let &[first] = resolved.as_slice() { - let frame = self.layout_single_row(ctx, first, y)?; + let frame = self.layout_single_row(first, y)?; self.push_row(frame); return Ok(()); } @@ -408,12 +409,12 @@ impl<'a> GridLayouter<'a> { } // Layout into multiple regions. - let frames = self.layout_multi_row(ctx, &resolved, y)?; + let frames = self.layout_multi_row(&resolved, y)?; let len = frames.len(); for (i, frame) in frames.into_iter().enumerate() { self.push_row(frame); if i + 1 < len { - self.finish_region(ctx)?; + self.finish_region()?; } } @@ -422,19 +423,14 @@ impl<'a> GridLayouter<'a> { /// Layout a row with relative height. Such a row cannot break across /// multiple regions, but it may force a region break. - fn layout_relative_row( - &mut self, - ctx: &mut Context, - v: Relative, - y: usize, - ) -> TypResult<()> { + fn layout_relative_row(&mut self, v: Relative, y: usize) -> TypResult<()> { let resolved = v.resolve(self.styles).relative_to(self.regions.base.y); - let frame = self.layout_single_row(ctx, resolved, y)?; + let frame = self.layout_single_row(resolved, y)?; // Skip to fitting region. let height = frame.size.y; while !self.regions.first.y.fits(height) && !self.regions.in_last() { - self.finish_region(ctx)?; + self.finish_region()?; // Don't skip multiple regions for gutter and don't push a row. if y % 2 == 1 { @@ -448,12 +444,7 @@ impl<'a> GridLayouter<'a> { } /// Layout a row with fixed height and return its frame. - fn layout_single_row( - &self, - ctx: &mut Context, - height: Length, - y: usize, - ) -> TypResult { + fn layout_single_row(&mut self, height: Length, y: usize) -> TypResult { let mut output = Frame::new(Size::new(self.used.x, height)); let mut pos = Point::zero(); @@ -468,7 +459,7 @@ impl<'a> GridLayouter<'a> { .select(self.regions.base, size); let pod = Regions::one(size, base, Spec::splat(true)); - let frame = node.layout(ctx, &pod, self.styles)?.remove(0); + let frame = node.layout(self.ctx, &pod, self.styles)?.remove(0); output.push_frame(pos, frame); } @@ -480,8 +471,7 @@ impl<'a> GridLayouter<'a> { /// Layout a row spanning multiple regions. fn layout_multi_row( - &self, - ctx: &mut Context, + &mut self, heights: &[Length], y: usize, ) -> TypResult> { @@ -509,7 +499,7 @@ impl<'a> GridLayouter<'a> { } // Push the layouted frames into the individual output frames. - let frames = node.layout(ctx, &pod, self.styles)?; + let frames = node.layout(self.ctx, &pod, self.styles)?; for (output, frame) in outputs.iter_mut().zip(frames) { output.push_frame(pos, frame); } @@ -529,7 +519,7 @@ impl<'a> GridLayouter<'a> { } /// Finish rows for one region. - fn finish_region(&mut self, ctx: &mut Context) -> TypResult<()> { + fn finish_region(&mut self) -> TypResult<()> { // Determine the size of the grid in this region, expanding fully if // there are fr rows. let mut size = self.used; @@ -548,7 +538,7 @@ impl<'a> GridLayouter<'a> { Row::Fr(v, y) => { let remaining = self.full - self.used.y; let height = v.share(self.fr, remaining); - self.layout_single_row(ctx, height, y)? + self.layout_single_row(height, y)? } };