Remove width from backlog and last region
This commit is contained in:
parent
bdb1c008f2
commit
0a1916c1e4
@ -200,6 +200,7 @@ impl PackedNode {
|
||||
}
|
||||
|
||||
impl Layout for PackedNode {
|
||||
#[track_caller]
|
||||
fn layout(
|
||||
&self,
|
||||
ctx: &mut LayoutContext,
|
||||
@ -219,8 +220,12 @@ impl Layout for PackedNode {
|
||||
state.finish()
|
||||
};
|
||||
|
||||
// This is not written with `unwrap_or_else`, because then the
|
||||
// #[track_caller] annotation doesn't work.
|
||||
#[cfg(feature = "layout-cache")]
|
||||
ctx.layout_cache.get(hash, regions).unwrap_or_else(|| {
|
||||
if let Some(frames) = ctx.layout_cache.get(hash, regions) {
|
||||
frames
|
||||
} else {
|
||||
ctx.level += 1;
|
||||
let frames = self.node.layout(ctx, regions, styles);
|
||||
ctx.level -= 1;
|
||||
@ -240,7 +245,7 @@ impl Layout for PackedNode {
|
||||
|
||||
ctx.layout_cache.insert(hash, entry);
|
||||
frames
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn pack(self) -> PackedNode {
|
||||
|
@ -7,10 +7,11 @@ pub struct Regions {
|
||||
pub current: Size,
|
||||
/// The base size for relative sizing.
|
||||
pub base: Size,
|
||||
/// An iterator of followup regions.
|
||||
pub backlog: std::vec::IntoIter<Size>,
|
||||
/// The final region that is repeated once the backlog is drained.
|
||||
pub last: Option<Size>,
|
||||
/// The height of followup regions. The width is the same for all regions.
|
||||
pub backlog: std::vec::IntoIter<Length>,
|
||||
/// The height of the final region that is repeated once the backlog is
|
||||
/// drained. The width is the same for all regions.
|
||||
pub last: Option<Length>,
|
||||
/// Whether nodes should expand to fill the regions instead of shrinking to
|
||||
/// fit the content.
|
||||
pub expand: Spec<bool>,
|
||||
@ -34,19 +35,33 @@ impl Regions {
|
||||
current: size,
|
||||
base,
|
||||
backlog: vec![].into_iter(),
|
||||
last: Some(size),
|
||||
last: Some(size.y),
|
||||
expand,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create new regions where all sizes are mapped with `f`.
|
||||
///
|
||||
/// Note that since all regions must have the same width, the width returned
|
||||
/// by `f` is ignored for the backlog and the final region.
|
||||
pub fn map<F>(&self, mut f: F) -> Self
|
||||
where
|
||||
F: FnMut(Size) -> Size,
|
||||
{
|
||||
let mut regions = self.clone();
|
||||
regions.mutate(|s| *s = f(*s));
|
||||
regions
|
||||
let x = self.current.x;
|
||||
Self {
|
||||
current: f(self.current),
|
||||
base: f(self.base),
|
||||
backlog: self
|
||||
.backlog
|
||||
.as_slice()
|
||||
.iter()
|
||||
.map(|&y| f(Size::new(x, y)).y)
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter(),
|
||||
last: self.last.map(|y| f(Size::new(x, y)).y),
|
||||
expand: self.expand,
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether the current region is full and a region break is called for.
|
||||
@ -58,14 +73,15 @@ impl Regions {
|
||||
///
|
||||
/// If this is true, calling `next()` will have no effect.
|
||||
pub fn in_last(&self) -> bool {
|
||||
self.backlog.len() == 0 && self.last.map_or(true, |size| self.current == size)
|
||||
self.backlog.len() == 0
|
||||
&& self.last.map_or(true, |height| self.current.y == height)
|
||||
}
|
||||
|
||||
/// Advance to the next region if there is any.
|
||||
pub fn next(&mut self) {
|
||||
if let Some(size) = self.backlog.next().or(self.last) {
|
||||
self.current = size;
|
||||
self.base = size;
|
||||
if let Some(height) = self.backlog.next().or(self.last) {
|
||||
self.current.y = height;
|
||||
self.base.y = height;
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,17 +92,11 @@ impl Regions {
|
||||
let first = std::iter::once((self.current, self.base));
|
||||
let backlog = self.backlog.as_slice().iter();
|
||||
let last = self.last.iter().cycle();
|
||||
first.chain(backlog.chain(last).map(|&s| (s, s)))
|
||||
}
|
||||
|
||||
/// Mutate all contained sizes in place.
|
||||
pub fn mutate<F>(&mut self, mut f: F)
|
||||
where
|
||||
F: FnMut(&mut Size),
|
||||
{
|
||||
f(&mut self.current);
|
||||
f(&mut self.base);
|
||||
self.last.as_mut().map(|x| f(x));
|
||||
self.backlog.as_mut_slice().iter_mut().for_each(f);
|
||||
first.chain(backlog.chain(last).map(|&height| {
|
||||
(
|
||||
Size::new(self.current.x, height),
|
||||
Size::new(self.base.x, height),
|
||||
)
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
@ -38,63 +38,40 @@ impl Layout for ColumnsNode {
|
||||
regions: &Regions,
|
||||
styles: StyleChain,
|
||||
) -> Vec<Constrained<Arc<Frame>>> {
|
||||
let columns = self.columns.get();
|
||||
|
||||
// Separating the infinite space into infinite columns does not make
|
||||
// much sense. Note that this line assumes that no infinitely wide
|
||||
// region will follow if the first region's width is finite.
|
||||
// much sense.
|
||||
if regions.current.x.is_infinite() {
|
||||
return self.child.layout(ctx, regions, styles);
|
||||
}
|
||||
|
||||
// Gutter width for each region. (Can be different because the relative
|
||||
// component is calculated seperately for each region.)
|
||||
let mut gutters = vec![];
|
||||
// Determine the width of the gutter and each column.
|
||||
let columns = self.columns.get();
|
||||
let gutter = styles.get(Self::GUTTER).resolve(regions.base.x);
|
||||
let width = (regions.current.x - gutter * (columns - 1) as f64) / columns as f64;
|
||||
|
||||
// Sizes of all columns resulting from `region.current`,
|
||||
// `region.backlog` and `regions.last`.
|
||||
let mut sizes = vec![];
|
||||
// Create the pod regions.
|
||||
let pod = Regions {
|
||||
current: Size::new(width, regions.current.y),
|
||||
base: Size::new(width, regions.base.y),
|
||||
backlog: std::iter::once(®ions.current.y)
|
||||
.chain(regions.backlog.as_slice())
|
||||
.flat_map(|&height| std::iter::repeat(height).take(columns))
|
||||
.skip(1)
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter(),
|
||||
last: regions.last,
|
||||
expand: Spec::new(true, regions.expand.y),
|
||||
};
|
||||
|
||||
for (current, base) in regions
|
||||
.iter()
|
||||
.take(1 + regions.backlog.len() + regions.last.iter().len())
|
||||
{
|
||||
let gutter = styles.get(Self::GUTTER).resolve(base.x);
|
||||
let width = (current.x - gutter * (columns - 1) as f64) / columns as f64;
|
||||
let size = Size::new(width, current.y);
|
||||
gutters.push(gutter);
|
||||
sizes.extend(std::iter::repeat(size).take(columns));
|
||||
}
|
||||
|
||||
let first = sizes.remove(0);
|
||||
let mut pod = Regions::one(
|
||||
first,
|
||||
Size::new(first.x, regions.base.y),
|
||||
Spec::new(true, regions.expand.y),
|
||||
);
|
||||
|
||||
// Retrieve elements for the last region from the vectors.
|
||||
let last_gutter = regions.last.map(|_| {
|
||||
let gutter = gutters.pop().unwrap();
|
||||
let size = sizes.drain(sizes.len() - columns ..).next().unwrap();
|
||||
pod.last = Some(size);
|
||||
gutter
|
||||
});
|
||||
|
||||
pod.backlog = sizes.into_iter();
|
||||
|
||||
let mut finished = vec![];
|
||||
// Layout the children.
|
||||
let mut frames = self.child.layout(ctx, &pod, styles).into_iter();
|
||||
|
||||
let dir = styles.get(ParNode::DIR);
|
||||
let total_regions = (frames.len() as f32 / columns as f32).ceil() as usize;
|
||||
let mut finished = vec![];
|
||||
|
||||
// Stitch together the columns for each region.
|
||||
for ((current, base), gutter) in regions
|
||||
.iter()
|
||||
.take(total_regions)
|
||||
.zip(gutters.into_iter().chain(last_gutter.into_iter().cycle()))
|
||||
{
|
||||
for (current, base) in regions.iter().take(total_regions) {
|
||||
// The height should be the parent height if the node shall expand.
|
||||
// Otherwise its the maximum column height for the frame. In that
|
||||
// case, the frame is first created with zero height and then
|
||||
|
@ -386,9 +386,10 @@ impl<'a> GridLayouter<'a> {
|
||||
// Determine the size for each region of the row.
|
||||
for (x, &rcol) in self.rcols.iter().enumerate() {
|
||||
if let Some(node) = self.cell(x, y) {
|
||||
// All widths should be `rcol` except the base for auto columns.
|
||||
let mut pod = self.regions.clone();
|
||||
pod.mutate(|size| size.x = rcol);
|
||||
pod.current.x = rcol;
|
||||
|
||||
// All widths should be `rcol` except the base for auto columns.
|
||||
if self.cols[x] == TrackSizing::Auto {
|
||||
pod.base.x = self.regions.base.x;
|
||||
}
|
||||
@ -513,18 +514,15 @@ impl<'a> GridLayouter<'a> {
|
||||
// Prepare regions.
|
||||
let size = Size::new(self.used.x, heights[0]);
|
||||
let mut pod = Regions::one(size, self.regions.base, Spec::splat(true));
|
||||
pod.backlog = heights[1 ..]
|
||||
.iter()
|
||||
.map(|&h| Size::new(self.used.x, h))
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter();
|
||||
pod.backlog = heights[1 ..].to_vec().into_iter();
|
||||
|
||||
// Layout the row.
|
||||
let mut pos = Point::zero();
|
||||
for (x, &rcol) in self.rcols.iter().enumerate() {
|
||||
if let Some(node) = self.cell(x, y) {
|
||||
pod.current.x = rcol;
|
||||
|
||||
// All widths should be `rcol` except the base for auto columns.
|
||||
pod.mutate(|size| size.x = rcol);
|
||||
if self.cols[x] == TrackSizing::Auto {
|
||||
pod.base.x = self.regions.base.x;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user