diff options
author | 2024-01-09 06:35:33 +0100 | |
---|---|---|
committer | 2024-01-10 10:01:49 +0100 | |
commit | d62bb8193c1c43f565fcc5c52293d564c91e215d (patch) | |
tree | 7f2d33d2f18a3dfb4e4e8e46b4e968523ca43bc6 /core/src | |
parent | d24e50c1a61eee7bca887224ad583eca60e14d32 (diff) | |
download | iced-d62bb8193c1c43f565fcc5c52293d564c91e215d.tar.gz iced-d62bb8193c1c43f565fcc5c52293d564c91e215d.tar.bz2 iced-d62bb8193c1c43f565fcc5c52293d564c91e215d.zip |
Introduce useful helpers in `layout` module
Diffstat (limited to 'core/src')
-rw-r--r-- | core/src/layout.rs | 94 | ||||
-rw-r--r-- | core/src/layout/flex.rs | 2 | ||||
-rw-r--r-- | core/src/layout/limits.rs | 7 | ||||
-rw-r--r-- | core/src/layout/node.rs | 10 | ||||
-rw-r--r-- | core/src/point.rs | 20 | ||||
-rw-r--r-- | core/src/widget/text.rs | 43 |
6 files changed, 139 insertions, 37 deletions
diff --git a/core/src/layout.rs b/core/src/layout.rs index 277473fe..95720aba 100644 --- a/core/src/layout.rs +++ b/core/src/layout.rs @@ -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)], + ) +} diff --git a/core/src/layout/flex.rs b/core/src/layout/flex.rs index 2a12d57f..cf3e1340 100644 --- a/core/src/layout/flex.rs +++ b/core/src/layout/flex.rs @@ -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) diff --git a/core/src/layout/limits.rs b/core/src/layout/limits.rs index eef4c4c9..7fbc7b9d 100644 --- a/core/src/layout/limits.rs +++ b/core/src/layout/limits.rs @@ -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, diff --git a/core/src/layout/node.rs b/core/src/layout/node.rs index 00087431..40c71436 100644 --- a/core/src/layout/node.rs +++ b/core/src/layout/node.rs @@ -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 diff --git a/core/src/point.rs b/core/src/point.rs index ef42852f..cea57518 100644 --- a/core/src/point.rs +++ b/core/src/point.rs @@ -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] } } diff --git a/core/src/widget/text.rs b/core/src/widget/text.rs index fe3b77d3..4cabc7ce 100644 --- a/core/src/widget/text.rs +++ b/core/src/widget/text.rs @@ -206,28 +206,27 @@ pub fn layout<Renderer>( where Renderer: text::Renderer, { - let limits = limits.width(width).height(height); - let bounds = limits.max(); - - let size = size.unwrap_or_else(|| renderer.default_size()); - let font = font.unwrap_or_else(|| renderer.default_font()); - - let State(ref mut paragraph) = state; - - 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) + 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 State(ref mut paragraph) = state; + + paragraph.update(text::Text { + content, + bounds, + size, + line_height, + font, + horizontal_alignment, + vertical_alignment, + shaping, + }); + + paragraph.min_bounds() + }) } /// Draws text using the same logic as the [`Text`] widget. |