summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-05-17 15:23:04 +0200
committerLaurenz <laurmaedje@gmail.com>2021-05-17 15:23:04 +0200
commit24c4a746bc68874f2d1b0d1b726596930acaadcf (patch)
tree8288a78ab53c4d07952f0975ff5166068d4f4526 /src
parent1003d320d40aa46a0a3fba49b09425ead1b4b584 (diff)
Move aspect ratio into stack
Diffstat (limited to 'src')
-rw-r--r--src/exec/context.rs2
-rw-r--r--src/layout/fixed.rs20
-rw-r--r--src/layout/mod.rs19
-rw-r--r--src/layout/stack.rs20
-rw-r--r--src/library/shapes.rs23
5 files changed, 41 insertions, 43 deletions
diff --git a/src/exec/context.rs b/src/exec/context.rs
index d33d62ef..7dc51796 100644
--- a/src/exec/context.rs
+++ b/src/exec/context.rs
@@ -197,7 +197,7 @@ impl StackBuilder {
children.extend(last.any());
children.push(par);
}
- StackNode { dirs, children }
+ StackNode { dirs, aspect: None, children }
}
}
diff --git a/src/layout/fixed.rs b/src/layout/fixed.rs
index 5905fa95..a42eab5a 100644
--- a/src/layout/fixed.rs
+++ b/src/layout/fixed.rs
@@ -7,10 +7,6 @@ pub struct FixedNode {
pub width: Option<Linear>,
/// The fixed height, if any.
pub height: Option<Linear>,
- /// The fixed aspect ratio between width and height, if any.
- ///
- /// The resulting frame will satisfy `width = aspect * height`.
- pub aspect: Option<f64>,
/// The child node whose size to fix.
pub child: AnyNode,
}
@@ -18,21 +14,13 @@ pub struct FixedNode {
impl Layout for FixedNode {
fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Vec<Frame> {
let Areas { current, full, .. } = areas;
-
- let full = Size::new(
- self.width.map(|w| w.resolve(full.width)).unwrap_or(current.width),
- self.height.map(|h| h.resolve(full.height)).unwrap_or(current.height),
+ let size = Size::new(
+ self.width.map_or(current.width, |w| w.resolve(full.width)),
+ self.height.map_or(current.height, |h| h.resolve(full.height)),
);
- let mut size = full;
- if let Some(aspect) = self.aspect {
- // Shrink the size to ensure that the aspect ratio can be satisfied.
- let width = size.width.min(aspect * size.height);
- size = Size::new(width, width / aspect);
- }
-
let fixed = Spec::new(self.width.is_some(), self.height.is_some());
- let areas = Areas::once(size, full, fixed).with_aspect(self.aspect);
+ let areas = Areas::once(size, size, fixed);
self.child.layout(ctx, &areas)
}
}
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index dad378f5..cb138753 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -155,10 +155,6 @@ pub struct Areas {
///
/// If this is false, the frame will shrink to fit its content.
pub fixed: Spec<bool>,
- /// The aspect ratio the resulting frame should respect.
- ///
- /// This property is only handled by the stack layouter.
- pub aspect: Option<f64>,
}
impl Areas {
@@ -170,7 +166,6 @@ impl Areas {
backlog: vec![],
last: None,
fixed,
- aspect: None,
}
}
@@ -182,16 +177,9 @@ impl Areas {
backlog: vec![],
last: Some(size),
fixed,
- aspect: None,
}
}
- /// Builder-style method for setting the aspect ratio.
- pub fn with_aspect(mut self, aspect: Option<f64>) -> Self {
- self.aspect = aspect;
- self
- }
-
/// Map all areas.
pub fn map<F>(&self, mut f: F) -> Self
where
@@ -203,7 +191,6 @@ impl Areas {
backlog: self.backlog.iter().copied().map(|s| f(s)).collect(),
last: self.last.map(f),
fixed: self.fixed,
- aspect: self.aspect,
}
}
@@ -224,4 +211,10 @@ impl Areas {
self.current.is_nan() || size.is_nan() || self.current == size
})
}
+
+ /// Shrink `current` to ensure that the aspect ratio can be satisfied.
+ pub fn apply_aspect_ratio(&mut self, ratio: f64) {
+ let Size { width, height } = self.current;
+ self.current = Size::new(width.min(ratio * height), height.min(width / ratio));
+ }
}
diff --git a/src/layout/stack.rs b/src/layout/stack.rs
index a73abeeb..463f38a7 100644
--- a/src/layout/stack.rs
+++ b/src/layout/stack.rs
@@ -8,6 +8,10 @@ pub struct StackNode {
/// The children are stacked along the `main` direction. The `cross`
/// direction is required for aligning the children.
pub dirs: Gen<Dir>,
+ /// The fixed aspect ratio between width and height, if any.
+ ///
+ /// The resulting frames will satisfy `width = aspect * height`.
+ pub aspect: Option<f64>,
/// The nodes to be stacked.
pub children: Vec<StackChild>,
}
@@ -23,7 +27,7 @@ pub enum StackChild {
impl Layout for StackNode {
fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Vec<Frame> {
- let mut layouter = StackLayouter::new(self.dirs, areas.clone());
+ let mut layouter = StackLayouter::new(self.dirs, self.aspect, areas.clone());
for child in &self.children {
match *child {
StackChild::Spacing(amount) => layouter.push_spacing(amount),
@@ -52,6 +56,7 @@ impl From<StackNode> for AnyNode {
struct StackLayouter {
dirs: Gen<Dir>,
+ aspect: Option<f64>,
main: SpecAxis,
areas: Areas,
finished: Vec<Frame>,
@@ -61,9 +66,14 @@ struct StackLayouter {
}
impl StackLayouter {
- fn new(dirs: Gen<Dir>, areas: Areas) -> Self {
+ fn new(dirs: Gen<Dir>, aspect: Option<f64>, mut areas: Areas) -> Self {
+ if let Some(aspect) = aspect {
+ areas.apply_aspect_ratio(aspect);
+ }
+
Self {
dirs,
+ aspect,
main: dirs.main.axis(),
areas,
finished: vec![],
@@ -112,7 +122,7 @@ impl StackLayouter {
if fixed.vertical { full.height } else { used.height },
);
- if let Some(aspect) = self.areas.aspect {
+ if let Some(aspect) = self.aspect {
let width = size
.width
.max(aspect * size.height)
@@ -162,6 +172,10 @@ impl StackLayouter {
self.areas.next();
self.ruler = Align::Start;
self.size = Gen::ZERO;
+
+ if let Some(aspect) = self.aspect {
+ self.areas.apply_aspect_ratio(aspect);
+ }
}
fn finish(mut self) -> Vec<Frame> {
diff --git a/src/library/shapes.rs b/src/library/shapes.rs
index 6c6a2f0b..c87a0ac3 100644
--- a/src/library/shapes.rs
+++ b/src/library/shapes.rs
@@ -59,17 +59,19 @@ fn rect_impl(
body: TemplateValue,
) -> Value {
Value::template(name, move |ctx| {
- let child = ctx.exec_group(&body).into();
- let node = FixedNode { width, height, aspect, child };
+ let mut stack = ctx.exec_group(&body);
+ stack.aspect = aspect;
+
+ let fixed = FixedNode { width, height, child: stack.into() };
if let Some(color) = fill {
ctx.push(BackgroundNode {
shape: BackgroundShape::Rect,
fill: Fill::Color(color),
- child: node.into(),
+ child: fixed.into(),
});
} else {
- ctx.push(node);
+ ctx.push(fixed);
}
})
}
@@ -133,14 +135,15 @@ fn ellipse_impl(
// perfectly into the ellipse.
const PAD: f64 = 0.5 - SQRT_2 / 4.0;
- let child = ctx.exec_group(&body).into();
- let node = FixedNode {
+ let mut stack = ctx.exec_group(&body);
+ stack.aspect = aspect;
+
+ let fixed = FixedNode {
width,
height,
- aspect,
child: PadNode {
padding: Sides::uniform(Relative::new(PAD).into()),
- child,
+ child: stack.into(),
}
.into(),
};
@@ -149,10 +152,10 @@ fn ellipse_impl(
ctx.push(BackgroundNode {
shape: BackgroundShape::Ellipse,
fill: Fill::Color(color),
- child: node.into(),
+ child: fixed.into(),
});
} else {
- ctx.push(node);
+ ctx.push(fixed);
}
})
}