Introduce useful helpers in layout module
This commit is contained in:
parent
d24e50c1a6
commit
d62bb8193c
26 changed files with 189 additions and 127 deletions
|
|
@ -7,7 +7,7 @@ pub mod flex;
|
|||
pub use limits::Limits;
|
||||
pub use node::Node;
|
||||
|
||||
use crate::{Point, Rectangle, Size, Vector};
|
||||
use crate::{Length, Padding, Point, Rectangle, Size, Vector};
|
||||
|
||||
/// The bounds of a [`Node`] and its children, using absolute coordinates.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
|
|
@ -96,3 +96,95 @@ pub fn next_to_each_other(
|
|||
],
|
||||
)
|
||||
}
|
||||
|
||||
/// Computes the resulting [`Node`] that fits the [`Limits`] given
|
||||
/// some width and height requirements and no intrinsic size.
|
||||
pub fn atomic(
|
||||
limits: &Limits,
|
||||
width: impl Into<Length>,
|
||||
height: impl Into<Length>,
|
||||
) -> Node {
|
||||
let width = width.into();
|
||||
let height = height.into();
|
||||
|
||||
Node::new(limits.resolve(width, height, Size::ZERO))
|
||||
}
|
||||
|
||||
/// Computes the resulting [`Node`] that fits the [`Limits`] given
|
||||
/// some width and height requirements and a closure that produces
|
||||
/// the intrinsic [`Size`] inside the given [`Limits`].
|
||||
pub fn sized(
|
||||
limits: &Limits,
|
||||
width: impl Into<Length>,
|
||||
height: impl Into<Length>,
|
||||
f: impl FnOnce(&Limits) -> Size,
|
||||
) -> Node {
|
||||
let width = width.into();
|
||||
let height = height.into();
|
||||
|
||||
let limits = limits.width(width).height(height);
|
||||
let intrinsic_size = f(&limits);
|
||||
|
||||
Node::new(limits.resolve(width, height, intrinsic_size))
|
||||
}
|
||||
|
||||
/// Computes the resulting [`Node`] that fits the [`Limits`] given
|
||||
/// some width and height requirements and a closure that produces
|
||||
/// the content [`Node`] inside the given [`Limits`].
|
||||
pub fn contained(
|
||||
limits: &Limits,
|
||||
width: impl Into<Length>,
|
||||
height: impl Into<Length>,
|
||||
f: impl FnOnce(&Limits) -> Node,
|
||||
) -> Node {
|
||||
let width = width.into();
|
||||
let height = height.into();
|
||||
|
||||
let limits = limits.width(width).height(height);
|
||||
let content = f(&limits);
|
||||
|
||||
Node::with_children(
|
||||
limits.resolve(width, height, content.size()),
|
||||
vec![content],
|
||||
)
|
||||
}
|
||||
|
||||
/// Computes the [`Node`] that fits the [`Limits`] given some width, height, and
|
||||
/// [`Padding`] requirements and a closure that produces the content [`Node`]
|
||||
/// inside the given [`Limits`].
|
||||
pub fn padded(
|
||||
limits: &Limits,
|
||||
width: impl Into<Length>,
|
||||
height: impl Into<Length>,
|
||||
padding: impl Into<Padding>,
|
||||
layout: impl FnOnce(&Limits) -> Node,
|
||||
) -> Node {
|
||||
positioned(limits, width, height, padding, layout, |content, _| content)
|
||||
}
|
||||
|
||||
/// Computes a [`padded`] [`Node`] with a positioning step.
|
||||
pub fn positioned(
|
||||
limits: &Limits,
|
||||
width: impl Into<Length>,
|
||||
height: impl Into<Length>,
|
||||
padding: impl Into<Padding>,
|
||||
layout: impl FnOnce(&Limits) -> Node,
|
||||
position: impl FnOnce(Node, Size) -> Node,
|
||||
) -> Node {
|
||||
let width = width.into();
|
||||
let height = height.into();
|
||||
let padding = padding.into();
|
||||
|
||||
let limits = limits.width(width).height(height);
|
||||
let content = layout(&limits.shrink(padding));
|
||||
let padding = padding.fit(content.size(), limits.max());
|
||||
|
||||
let size = limits
|
||||
.shrink(padding)
|
||||
.resolve(width, height, content.size());
|
||||
|
||||
Node::with_children(
|
||||
size.expand(padding),
|
||||
vec![position(content.move_to((padding.left, padding.top)), size)],
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -239,9 +239,9 @@ where
|
|||
|
||||
let (intrinsic_width, intrinsic_height) = axis.pack(main - pad.0, cross);
|
||||
let size = limits.resolve(
|
||||
Size::new(intrinsic_width, intrinsic_height),
|
||||
width,
|
||||
height,
|
||||
Size::new(intrinsic_width, intrinsic_height),
|
||||
);
|
||||
|
||||
Node::with_children(size.expand(padding), nodes)
|
||||
|
|
|
|||
|
|
@ -114,13 +114,14 @@ impl Limits {
|
|||
}
|
||||
}
|
||||
|
||||
/// Computes the resulting [`Size`] that fits the [`Limits`] given the
|
||||
/// intrinsic size of some content.
|
||||
/// Computes the resulting [`Size`] that fits the [`Limits`] given
|
||||
/// some width and height requirements and the intrinsic size of
|
||||
/// some content.
|
||||
pub fn resolve(
|
||||
&self,
|
||||
intrinsic_size: Size,
|
||||
width: impl Into<Length>,
|
||||
height: impl Into<Length>,
|
||||
intrinsic_size: Size,
|
||||
) -> Size {
|
||||
let width = match width.into() {
|
||||
Length::Fill | Length::FillPortion(_) => self.max.width,
|
||||
|
|
|
|||
|
|
@ -89,19 +89,23 @@ impl Node {
|
|||
}
|
||||
|
||||
/// Moves the [`Node`] to the given position.
|
||||
pub fn move_to(mut self, position: Point) -> Self {
|
||||
pub fn move_to(mut self, position: impl Into<Point>) -> Self {
|
||||
self.move_to_mut(position);
|
||||
self
|
||||
}
|
||||
|
||||
/// Mutable reference version of [`move_to`].
|
||||
pub fn move_to_mut(&mut self, position: Point) {
|
||||
pub fn move_to_mut(&mut self, position: impl Into<Point>) {
|
||||
let position = position.into();
|
||||
|
||||
self.bounds.x = position.x;
|
||||
self.bounds.y = position.y;
|
||||
}
|
||||
|
||||
/// Translates the [`Node`] by the given translation.
|
||||
pub fn translate(self, translation: Vector) -> Self {
|
||||
pub fn translate(self, translation: impl Into<Vector>) -> Self {
|
||||
let translation = translation.into();
|
||||
|
||||
Self {
|
||||
bounds: self.bounds + translation,
|
||||
..self
|
||||
|
|
|
|||
|
|
@ -36,20 +36,26 @@ impl<T: Num> Point<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<[f32; 2]> for Point {
|
||||
fn from([x, y]: [f32; 2]) -> Self {
|
||||
impl<T> From<[T; 2]> for Point<T>
|
||||
where
|
||||
T: Num,
|
||||
{
|
||||
fn from([x, y]: [T; 2]) -> Self {
|
||||
Point { x, y }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u16; 2]> for Point<u16> {
|
||||
fn from([x, y]: [u16; 2]) -> Self {
|
||||
Point::new(x, y)
|
||||
impl<T> From<(T, T)> for Point<T>
|
||||
where
|
||||
T: Num,
|
||||
{
|
||||
fn from((x, y): (T, T)) -> Self {
|
||||
Self { x, y }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Point> for [f32; 2] {
|
||||
fn from(point: Point) -> [f32; 2] {
|
||||
impl<T> From<Point<T>> for [T; 2] {
|
||||
fn from(point: Point<T>) -> [T; 2] {
|
||||
[point.x, point.y]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -206,28 +206,27 @@ pub fn layout<Renderer>(
|
|||
where
|
||||
Renderer: text::Renderer,
|
||||
{
|
||||
let limits = limits.width(width).height(height);
|
||||
let bounds = limits.max();
|
||||
layout::sized(limits, width, height, |limits| {
|
||||
let bounds = limits.max();
|
||||
|
||||
let size = size.unwrap_or_else(|| renderer.default_size());
|
||||
let font = font.unwrap_or_else(|| renderer.default_font());
|
||||
let size = size.unwrap_or_else(|| renderer.default_size());
|
||||
let font = font.unwrap_or_else(|| renderer.default_font());
|
||||
|
||||
let State(ref mut paragraph) = state;
|
||||
let State(ref mut paragraph) = state;
|
||||
|
||||
paragraph.update(text::Text {
|
||||
content,
|
||||
bounds,
|
||||
size,
|
||||
line_height,
|
||||
font,
|
||||
horizontal_alignment,
|
||||
vertical_alignment,
|
||||
shaping,
|
||||
});
|
||||
paragraph.update(text::Text {
|
||||
content,
|
||||
bounds,
|
||||
size,
|
||||
line_height,
|
||||
font,
|
||||
horizontal_alignment,
|
||||
vertical_alignment,
|
||||
shaping,
|
||||
});
|
||||
|
||||
let size = limits.resolve(paragraph.min_bounds(), width, height);
|
||||
|
||||
layout::Node::new(size)
|
||||
paragraph.min_bounds()
|
||||
})
|
||||
}
|
||||
|
||||
/// Draws text using the same logic as the [`Text`] widget.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue