diff options
author | 2023-03-16 20:23:25 +0100 | |
---|---|---|
committer | 2024-01-04 06:51:21 +0100 | |
commit | 0655a20ad119e2e9790afcc45039fd4ac0e7d432 (patch) | |
tree | 0ce316e386e5b47b6ca80fe16f0a384ef05ff4e8 /core/src | |
parent | 68c0484b5cf6f572e4cb0bf72c22c1a93dbb654e (diff) | |
download | iced-0655a20ad119e2e9790afcc45039fd4ac0e7d432.tar.gz iced-0655a20ad119e2e9790afcc45039fd4ac0e7d432.tar.bz2 iced-0655a20ad119e2e9790afcc45039fd4ac0e7d432.zip |
Make `Shrink` have priority over `Fill` in layout
Diffstat (limited to 'core/src')
-rw-r--r-- | core/src/layout.rs | 12 | ||||
-rw-r--r-- | core/src/layout/flex.rs | 29 | ||||
-rw-r--r-- | core/src/layout/limits.rs | 83 | ||||
-rw-r--r-- | core/src/layout/node.rs | 29 | ||||
-rw-r--r-- | core/src/padding.rs | 6 | ||||
-rw-r--r-- | core/src/size.rs | 24 | ||||
-rw-r--r-- | core/src/widget/text.rs | 2 |
7 files changed, 107 insertions, 78 deletions
diff --git a/core/src/layout.rs b/core/src/layout.rs index caf315b6..277473fe 100644 --- a/core/src/layout.rs +++ b/core/src/layout.rs @@ -71,12 +71,12 @@ pub fn next_to_each_other( left: impl FnOnce(&Limits) -> Node, right: impl FnOnce(&Limits) -> Node, ) -> Node { - let mut left_node = left(limits); + let left_node = left(limits); let left_size = left_node.size(); let right_limits = limits.shrink(Size::new(left_size.width + spacing, 0.0)); - let mut right_node = right(&right_limits); + let right_node = right(&right_limits); let right_size = right_node.size(); let (left_y, right_y) = if left_size.height > right_size.height { @@ -85,14 +85,14 @@ pub fn next_to_each_other( ((right_size.height - left_size.height) / 2.0, 0.0) }; - left_node.move_to(Point::new(0.0, left_y)); - right_node.move_to(Point::new(left_size.width + spacing, right_y)); - Node::with_children( Size::new( left_size.width + spacing + right_size.width, left_size.height.max(right_size.height), ), - vec![left_node, right_node], + vec![ + left_node.move_to(Point::new(0.0, left_y)), + right_node.move_to(Point::new(left_size.width + spacing, right_y)), + ], ) } diff --git a/core/src/layout/flex.rs b/core/src/layout/flex.rs index c02b63d8..738dc81d 100644 --- a/core/src/layout/flex.rs +++ b/core/src/layout/flex.rs @@ -20,7 +20,7 @@ use crate::Element; use crate::layout::{Limits, Node}; use crate::widget; -use crate::{Alignment, Padding, Point, Size}; +use crate::{Alignment, Length, Padding, Point, Size}; /// The main axis of a flex layout. #[derive(Debug)] @@ -63,6 +63,8 @@ pub fn resolve<Message, Renderer>( axis: Axis, renderer: &Renderer, limits: &Limits, + width: Length, + height: Length, padding: Padding, spacing: f32, align_items: Alignment, @@ -72,12 +74,12 @@ pub fn resolve<Message, Renderer>( where Renderer: crate::Renderer, { - let limits = limits.pad(padding); + let limits = limits.width(width).height(height).shrink(padding); let total_spacing = spacing * items.len().saturating_sub(1) as f32; let max_cross = axis.cross(limits.max()); let mut fill_sum = 0; - let mut cross = axis.cross(limits.min()).max(axis.cross(limits.fill())); + let mut cross = 0.0f32; let mut available = axis.main(limits.max()) - total_spacing; let mut nodes: Vec<Node> = Vec::with_capacity(items.len()); @@ -109,7 +111,16 @@ where } } - let remaining = available.max(0.0); + let remaining = match axis { + Axis::Horizontal => match width { + Length::Shrink => 0.0, + _ => available.max(0.0), + }, + Axis::Vertical => match height { + Length::Shrink => 0.0, + _ => available.max(0.0), + }, + }; for (i, (child, tree)) in items.iter().zip(trees).enumerate() { let fill_factor = match axis { @@ -154,18 +165,18 @@ where let (x, y) = axis.pack(main, pad.1); - node.move_to(Point::new(x, y)); + node.move_to_mut(Point::new(x, y)); match axis { Axis::Horizontal => { - node.align( + node.align_mut( Alignment::Start, align_items, Size::new(0.0, cross), ); } Axis::Vertical => { - node.align( + node.align_mut( align_items, Alignment::Start, Size::new(cross, 0.0), @@ -179,7 +190,7 @@ where } let (width, height) = axis.pack(main - pad.0, cross); - let size = limits.resolve(Size::new(width, height)); + let size = limits.resolve(Size::new(width, height), width, height); - Node::with_children(size.pad(padding), nodes) + Node::with_children(size.expand(padding), nodes) } diff --git a/core/src/layout/limits.rs b/core/src/layout/limits.rs index 39a3d98b..eef4c4c9 100644 --- a/core/src/layout/limits.rs +++ b/core/src/layout/limits.rs @@ -1,12 +1,11 @@ #![allow(clippy::manual_clamp)] -use crate::{Length, Padding, Size}; +use crate::{Length, Size}; /// A set of size constraints for layouting. #[derive(Debug, Clone, Copy, PartialEq)] pub struct Limits { min: Size, max: Size, - fill: Size, } impl Limits { @@ -14,16 +13,11 @@ impl Limits { pub const NONE: Limits = Limits { min: Size::ZERO, max: Size::INFINITY, - fill: Size::INFINITY, }; /// Creates new [`Limits`] with the given minimum and maximum [`Size`]. pub const fn new(min: Size, max: Size) -> Limits { - Limits { - min, - max, - fill: Size::INFINITY, - } + Limits { min, max } } /// Returns the minimum [`Size`] of the [`Limits`]. @@ -36,26 +30,15 @@ impl Limits { self.max } - /// Returns the fill [`Size`] of the [`Limits`]. - pub fn fill(&self) -> Size { - self.fill - } - /// Applies a width constraint to the current [`Limits`]. pub fn width(mut self, width: impl Into<Length>) -> Limits { match width.into() { - Length::Shrink => { - self.fill.width = self.min.width; - } - Length::Fill | Length::FillPortion(_) => { - self.fill.width = self.fill.width.min(self.max.width); - } + Length::Shrink | Length::Fill | Length::FillPortion(_) => {} Length::Fixed(amount) => { let new_width = amount.min(self.max.width).max(self.min.width); self.min.width = new_width; self.max.width = new_width; - self.fill.width = new_width; } } @@ -65,19 +48,13 @@ impl Limits { /// Applies a height constraint to the current [`Limits`]. pub fn height(mut self, height: impl Into<Length>) -> Limits { match height.into() { - Length::Shrink => { - self.fill.height = self.min.height; - } - Length::Fill | Length::FillPortion(_) => { - self.fill.height = self.fill.height.min(self.max.height); - } + Length::Shrink | Length::Fill | Length::FillPortion(_) => {} Length::Fixed(amount) => { let new_height = amount.min(self.max.height).max(self.min.height); self.min.height = new_height; self.max.height = new_height; - self.fill.height = new_height; } } @@ -112,13 +89,10 @@ impl Limits { self } - /// Shrinks the current [`Limits`] to account for the given padding. - pub fn pad(&self, padding: Padding) -> Limits { - self.shrink(Size::new(padding.horizontal(), padding.vertical())) - } - /// Shrinks the current [`Limits`] by the given [`Size`]. - pub fn shrink(&self, size: Size) -> Limits { + pub fn shrink(&self, size: impl Into<Size>) -> Limits { + let size = size.into(); + let min = Size::new( (self.min().width - size.width).max(0.0), (self.min().height - size.height).max(0.0), @@ -129,12 +103,7 @@ impl Limits { (self.max().height - size.height).max(0.0), ); - let fill = Size::new( - (self.fill.width - size.width).max(0.0), - (self.fill.height - size.height).max(0.0), - ); - - Limits { min, max, fill } + Limits { min, max } } /// Removes the minimum width constraint for the current [`Limits`]. @@ -142,22 +111,38 @@ impl Limits { Limits { min: Size::ZERO, max: self.max, - fill: self.fill, } } /// Computes the resulting [`Size`] that fits the [`Limits`] given the /// intrinsic size of some content. - pub fn resolve(&self, intrinsic_size: Size) -> Size { - Size::new( - intrinsic_size - .width - .min(self.max.width) - .max(self.fill.width), - intrinsic_size + pub fn resolve( + &self, + intrinsic_size: Size, + width: impl Into<Length>, + height: impl Into<Length>, + ) -> Size { + let width = match width.into() { + Length::Fill | Length::FillPortion(_) => self.max.width, + Length::Fixed(amount) => { + amount.min(self.max.width).max(self.min.width) + } + Length::Shrink => { + intrinsic_size.width.min(self.max.width).max(self.min.width) + } + }; + + let height = match height.into() { + Length::Fill | Length::FillPortion(_) => self.max.height, + Length::Fixed(amount) => { + amount.min(self.max.height).max(self.min.height) + } + Length::Shrink => intrinsic_size .height .min(self.max.height) - .max(self.fill.height), - ) + .max(self.min.height), + }; + + Size::new(width, height) } } diff --git a/core/src/layout/node.rs b/core/src/layout/node.rs index 2b44a7d5..00087431 100644 --- a/core/src/layout/node.rs +++ b/core/src/layout/node.rs @@ -1,4 +1,4 @@ -use crate::{Alignment, Point, Rectangle, Size, Vector}; +use crate::{Alignment, Padding, Point, Rectangle, Size, Vector}; /// The bounds of an element and its children. #[derive(Debug, Clone, Default)] @@ -26,6 +26,14 @@ impl Node { } } + /// Creates a new [`Node`] that wraps a single child with some [`Padding`]. + pub fn container(child: Self, padding: Padding) -> Self { + Self::with_children( + child.bounds.size().expand(padding), + vec![child.move_to(Point::new(padding.left, padding.top))], + ) + } + /// Returns the [`Size`] of the [`Node`]. pub fn size(&self) -> Size { Size::new(self.bounds.width, self.bounds.height) @@ -43,6 +51,17 @@ impl Node { /// Aligns the [`Node`] in the given space. pub fn align( + mut self, + horizontal_alignment: Alignment, + vertical_alignment: Alignment, + space: Size, + ) -> Self { + self.align_mut(horizontal_alignment, vertical_alignment, space); + self + } + + /// Mutable reference version of [`align`]. + pub fn align_mut( &mut self, horizontal_alignment: Alignment, vertical_alignment: Alignment, @@ -70,7 +89,13 @@ impl Node { } /// Moves the [`Node`] to the given position. - pub fn move_to(&mut self, position: Point) { + pub fn move_to(mut self, position: Point) -> Self { + self.move_to_mut(position); + self + } + + /// Mutable reference version of [`move_to`]. + pub fn move_to_mut(&mut self, position: Point) { self.bounds.x = position.x; self.bounds.y = position.y; } diff --git a/core/src/padding.rs b/core/src/padding.rs index 0b1bba13..a63f6e29 100644 --- a/core/src/padding.rs +++ b/core/src/padding.rs @@ -154,3 +154,9 @@ impl From<[f32; 4]> for Padding { } } } + +impl From<Padding> for Size { + fn from(padding: Padding) -> Self { + Self::new(padding.horizontal(), padding.vertical()) + } +} diff --git a/core/src/size.rs b/core/src/size.rs index 7ef2f602..90e50d13 100644 --- a/core/src/size.rs +++ b/core/src/size.rs @@ -1,4 +1,4 @@ -use crate::{Padding, Vector}; +use crate::Vector; /// An amount of space in 2 dimensions. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -26,15 +26,7 @@ impl Size { /// A [`Size`] with infinite width and height. pub const INFINITY: Size = Size::new(f32::INFINITY, f32::INFINITY); - /// Increments the [`Size`] to account for the given padding. - pub fn pad(&self, padding: Padding) -> Self { - Size { - width: self.width + padding.horizontal(), - height: self.height + padding.vertical(), - } - } - - /// Returns the minimum of each component of this size and another + /// Returns the minimum of each component of this size and another. pub fn min(self, other: Self) -> Self { Size { width: self.width.min(other.width), @@ -42,13 +34,23 @@ impl Size { } } - /// Returns the maximum of each component of this size and another + /// Returns the maximum of each component of this size and another. pub fn max(self, other: Self) -> Self { Size { width: self.width.max(other.width), height: self.height.max(other.height), } } + + /// Expands this [`Size`] by the given amount. + pub fn expand(self, other: impl Into<Size>) -> Self { + let other = other.into(); + + Size { + width: self.width + other.width, + height: self.height + other.height, + } + } } impl From<[f32; 2]> for Size { diff --git a/core/src/widget/text.rs b/core/src/widget/text.rs index e020b030..e47e4178 100644 --- a/core/src/widget/text.rs +++ b/core/src/widget/text.rs @@ -224,7 +224,7 @@ where shaping, }); - let size = limits.resolve(paragraph.min_bounds()); + let size = limits.resolve(paragraph.min_bounds(), width, height); layout::Node::new(size) } |