Make Shrink have priority over Fill in layout

This commit is contained in:
Héctor Ramón Jiménez 2023-03-16 20:23:25 +01:00 committed by Héctor Ramón Jiménez
parent 68c0484b5c
commit 0655a20ad1
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
46 changed files with 264 additions and 273 deletions

View file

@ -71,12 +71,12 @@ pub fn next_to_each_other(
left: impl FnOnce(&Limits) -> Node, left: impl FnOnce(&Limits) -> Node,
right: impl FnOnce(&Limits) -> Node, right: impl FnOnce(&Limits) -> Node,
) -> Node { ) -> Node {
let mut left_node = left(limits); let left_node = left(limits);
let left_size = left_node.size(); let left_size = left_node.size();
let right_limits = limits.shrink(Size::new(left_size.width + spacing, 0.0)); 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 right_size = right_node.size();
let (left_y, right_y) = if left_size.height > right_size.height { 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) ((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( Node::with_children(
Size::new( Size::new(
left_size.width + spacing + right_size.width, left_size.width + spacing + right_size.width,
left_size.height.max(right_size.height), 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)),
],
) )
} }

View file

@ -20,7 +20,7 @@ use crate::Element;
use crate::layout::{Limits, Node}; use crate::layout::{Limits, Node};
use crate::widget; use crate::widget;
use crate::{Alignment, Padding, Point, Size}; use crate::{Alignment, Length, Padding, Point, Size};
/// The main axis of a flex layout. /// The main axis of a flex layout.
#[derive(Debug)] #[derive(Debug)]
@ -63,6 +63,8 @@ pub fn resolve<Message, Renderer>(
axis: Axis, axis: Axis,
renderer: &Renderer, renderer: &Renderer,
limits: &Limits, limits: &Limits,
width: Length,
height: Length,
padding: Padding, padding: Padding,
spacing: f32, spacing: f32,
align_items: Alignment, align_items: Alignment,
@ -72,12 +74,12 @@ pub fn resolve<Message, Renderer>(
where where
Renderer: crate::Renderer, 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 total_spacing = spacing * items.len().saturating_sub(1) as f32;
let max_cross = axis.cross(limits.max()); let max_cross = axis.cross(limits.max());
let mut fill_sum = 0; 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 available = axis.main(limits.max()) - total_spacing;
let mut nodes: Vec<Node> = Vec::with_capacity(items.len()); 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() { for (i, (child, tree)) in items.iter().zip(trees).enumerate() {
let fill_factor = match axis { let fill_factor = match axis {
@ -154,18 +165,18 @@ where
let (x, y) = axis.pack(main, pad.1); 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 { match axis {
Axis::Horizontal => { Axis::Horizontal => {
node.align( node.align_mut(
Alignment::Start, Alignment::Start,
align_items, align_items,
Size::new(0.0, cross), Size::new(0.0, cross),
); );
} }
Axis::Vertical => { Axis::Vertical => {
node.align( node.align_mut(
align_items, align_items,
Alignment::Start, Alignment::Start,
Size::new(cross, 0.0), Size::new(cross, 0.0),
@ -179,7 +190,7 @@ where
} }
let (width, height) = axis.pack(main - pad.0, cross); 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)
} }

View file

@ -1,12 +1,11 @@
#![allow(clippy::manual_clamp)] #![allow(clippy::manual_clamp)]
use crate::{Length, Padding, Size}; use crate::{Length, Size};
/// A set of size constraints for layouting. /// A set of size constraints for layouting.
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub struct Limits { pub struct Limits {
min: Size, min: Size,
max: Size, max: Size,
fill: Size,
} }
impl Limits { impl Limits {
@ -14,16 +13,11 @@ impl Limits {
pub const NONE: Limits = Limits { pub const NONE: Limits = Limits {
min: Size::ZERO, min: Size::ZERO,
max: Size::INFINITY, max: Size::INFINITY,
fill: Size::INFINITY,
}; };
/// Creates new [`Limits`] with the given minimum and maximum [`Size`]. /// Creates new [`Limits`] with the given minimum and maximum [`Size`].
pub const fn new(min: Size, max: Size) -> Limits { pub const fn new(min: Size, max: Size) -> Limits {
Limits { Limits { min, max }
min,
max,
fill: Size::INFINITY,
}
} }
/// Returns the minimum [`Size`] of the [`Limits`]. /// Returns the minimum [`Size`] of the [`Limits`].
@ -36,26 +30,15 @@ impl Limits {
self.max self.max
} }
/// Returns the fill [`Size`] of the [`Limits`].
pub fn fill(&self) -> Size {
self.fill
}
/// Applies a width constraint to the current [`Limits`]. /// Applies a width constraint to the current [`Limits`].
pub fn width(mut self, width: impl Into<Length>) -> Limits { pub fn width(mut self, width: impl Into<Length>) -> Limits {
match width.into() { match width.into() {
Length::Shrink => { Length::Shrink | Length::Fill | Length::FillPortion(_) => {}
self.fill.width = self.min.width;
}
Length::Fill | Length::FillPortion(_) => {
self.fill.width = self.fill.width.min(self.max.width);
}
Length::Fixed(amount) => { Length::Fixed(amount) => {
let new_width = amount.min(self.max.width).max(self.min.width); let new_width = amount.min(self.max.width).max(self.min.width);
self.min.width = new_width; self.min.width = new_width;
self.max.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`]. /// Applies a height constraint to the current [`Limits`].
pub fn height(mut self, height: impl Into<Length>) -> Limits { pub fn height(mut self, height: impl Into<Length>) -> Limits {
match height.into() { match height.into() {
Length::Shrink => { Length::Shrink | Length::Fill | Length::FillPortion(_) => {}
self.fill.height = self.min.height;
}
Length::Fill | Length::FillPortion(_) => {
self.fill.height = self.fill.height.min(self.max.height);
}
Length::Fixed(amount) => { Length::Fixed(amount) => {
let new_height = let new_height =
amount.min(self.max.height).max(self.min.height); amount.min(self.max.height).max(self.min.height);
self.min.height = new_height; self.min.height = new_height;
self.max.height = new_height; self.max.height = new_height;
self.fill.height = new_height;
} }
} }
@ -112,13 +89,10 @@ impl Limits {
self 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`]. /// 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( let min = Size::new(
(self.min().width - size.width).max(0.0), (self.min().width - size.width).max(0.0),
(self.min().height - size.height).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), (self.max().height - size.height).max(0.0),
); );
let fill = Size::new( Limits { min, max }
(self.fill.width - size.width).max(0.0),
(self.fill.height - size.height).max(0.0),
);
Limits { min, max, fill }
} }
/// Removes the minimum width constraint for the current [`Limits`]. /// Removes the minimum width constraint for the current [`Limits`].
@ -142,22 +111,38 @@ impl Limits {
Limits { Limits {
min: Size::ZERO, min: Size::ZERO,
max: self.max, max: self.max,
fill: self.fill,
} }
} }
/// Computes the resulting [`Size`] that fits the [`Limits`] given the /// Computes the resulting [`Size`] that fits the [`Limits`] given the
/// intrinsic size of some content. /// intrinsic size of some content.
pub fn resolve(&self, intrinsic_size: Size) -> Size { pub fn resolve(
Size::new( &self,
intrinsic_size intrinsic_size: Size,
.width width: impl Into<Length>,
.min(self.max.width) height: impl Into<Length>,
.max(self.fill.width), ) -> Size {
intrinsic_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 .height
.min(self.max.height) .min(self.max.height)
.max(self.fill.height), .max(self.min.height),
) };
Size::new(width, height)
} }
} }

View file

@ -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. /// The bounds of an element and its children.
#[derive(Debug, Clone, Default)] #[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`]. /// Returns the [`Size`] of the [`Node`].
pub fn size(&self) -> Size { pub fn size(&self) -> Size {
Size::new(self.bounds.width, self.bounds.height) Size::new(self.bounds.width, self.bounds.height)
@ -43,6 +51,17 @@ impl Node {
/// Aligns the [`Node`] in the given space. /// Aligns the [`Node`] in the given space.
pub fn align( 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, &mut self,
horizontal_alignment: Alignment, horizontal_alignment: Alignment,
vertical_alignment: Alignment, vertical_alignment: Alignment,
@ -70,7 +89,13 @@ impl Node {
} }
/// Moves the [`Node`] to the given position. /// 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.x = position.x;
self.bounds.y = position.y; self.bounds.y = position.y;
} }

View file

@ -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())
}
}

View file

@ -1,4 +1,4 @@
use crate::{Padding, Vector}; use crate::Vector;
/// An amount of space in 2 dimensions. /// An amount of space in 2 dimensions.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@ -26,15 +26,7 @@ impl Size {
/// A [`Size`] with infinite width and height. /// A [`Size`] with infinite width and height.
pub const INFINITY: Size = Size::new(f32::INFINITY, f32::INFINITY); pub const INFINITY: Size = Size::new(f32::INFINITY, f32::INFINITY);
/// Increments the [`Size`] to account for the given padding. /// Returns the minimum of each component of this size and another.
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
pub fn min(self, other: Self) -> Self { pub fn min(self, other: Self) -> Self {
Size { Size {
width: self.width.min(other.width), 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 { pub fn max(self, other: Self) -> Self {
Size { Size {
width: self.width.max(other.width), width: self.width.max(other.width),
height: self.height.max(other.height), 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 { impl From<[f32; 2]> for Size {

View file

@ -224,7 +224,7 @@ where
shaping, shaping,
}); });
let size = limits.resolve(paragraph.min_bounds()); let size = limits.resolve(paragraph.min_bounds(), width, height);
layout::Node::new(size) layout::Node::new(size)
} }

View file

@ -146,7 +146,8 @@ impl Application for GameOfLife {
.view() .view()
.map(move |message| Message::Grid(message, version)), .map(move |message| Message::Grid(message, version)),
controls, controls,
]; ]
.height(Length::Fill);
container(content) container(content)
.width(Length::Fill) .width(Length::Fill)
@ -178,7 +179,6 @@ fn view_controls<'a>(
slider(1.0..=1000.0, speed as f32, Message::SpeedChanged), slider(1.0..=1000.0, speed as f32, Message::SpeedChanged),
text(format!("x{speed}")).size(16), text(format!("x{speed}")).size(16),
] ]
.width(Length::Fill)
.align_items(Alignment::Center) .align_items(Alignment::Center)
.spacing(10); .spacing(10);

View file

@ -30,7 +30,7 @@ mod rainbow {
_renderer: &Renderer, _renderer: &Renderer,
limits: &layout::Limits, limits: &layout::Limits,
) -> layout::Node { ) -> layout::Node {
let size = limits.width(Length::Fill).resolve(Size::ZERO); let size = limits.resolve(Size::ZERO, Length::Fill, Length::Shrink);
layout::Node::new(Size::new(size.width, size.width)) layout::Node::new(Size::new(size.width, size.width))
} }

View file

@ -81,32 +81,25 @@ impl Program for Controls {
); );
Row::new() Row::new()
.width(Length::Fill)
.height(Length::Fill) .height(Length::Fill)
.align_items(Alignment::End) .align_items(Alignment::End)
.push( .push(
Column::new() Column::new().align_items(Alignment::End).push(
.width(Length::Fill) Column::new()
.align_items(Alignment::End) .padding(10)
.push( .spacing(10)
Column::new() .push(Text::new("Background color").style(Color::WHITE))
.padding(10) .push(sliders)
.spacing(10) .push(
.push( Text::new(format!("{background_color:?}"))
Text::new("Background color") .size(14)
.style(Color::WHITE), .style(Color::WHITE),
) )
.push(sliders) .push(
.push( text_input("Placeholder", text)
Text::new(format!("{background_color:?}")) .on_input(Message::TextChanged),
.size(14) ),
.style(Color::WHITE), ),
)
.push(
text_input("Placeholder", text)
.on_input(Message::TextChanged),
),
),
) )
.into() .into()
} }

View file

@ -259,7 +259,7 @@ where
limits: &layout::Limits, limits: &layout::Limits,
) -> layout::Node { ) -> layout::Node {
let limits = limits.width(self.size).height(self.size); let limits = limits.width(self.size).height(self.size);
let size = limits.resolve(Size::ZERO); let size = limits.resolve(Size::ZERO, self.size, self.size);
layout::Node::new(size) layout::Node::new(size)
} }

View file

@ -180,7 +180,7 @@ where
limits: &layout::Limits, limits: &layout::Limits,
) -> layout::Node { ) -> layout::Node {
let limits = limits.width(self.width).height(self.height); let limits = limits.width(self.width).height(self.height);
let size = limits.resolve(Size::ZERO); let size = limits.resolve(Size::ZERO, self.width, self.height);
layout::Node::new(size) layout::Node::new(size)
} }

View file

@ -420,17 +420,14 @@ mod modal {
.width(Length::Fill) .width(Length::Fill)
.height(Length::Fill); .height(Length::Fill);
let mut child = self let child = self
.content .content
.as_widget() .as_widget()
.layout(self.tree, renderer, &limits); .layout(self.tree, renderer, &limits)
.align(Alignment::Center, Alignment::Center, limits.max());
child.align(Alignment::Center, Alignment::Center, limits.max()); layout::Node::with_children(self.size, vec![child])
.move_to(position)
let mut node = layout::Node::with_children(self.size, vec![child]);
node.move_to(position);
node
} }
fn on_event( fn on_event(

View file

@ -297,7 +297,6 @@ fn view_content<'a>(
text(format!("{}x{}", size.width, size.height)).size(24), text(format!("{}x{}", size.width, size.height)).size(24),
controls, controls,
] ]
.width(Length::Fill)
.spacing(10) .spacing(10)
.align_items(Alignment::Center); .align_items(Alignment::Center);

View file

@ -48,7 +48,6 @@ impl Sandbox for Example {
pick_list, pick_list,
vertical_space(600), vertical_space(600),
] ]
.width(Length::Fill)
.align_items(Alignment::Center) .align_items(Alignment::Center)
.spacing(10); .spacing(10);

View file

@ -147,35 +147,30 @@ impl Application for ScrollableDemo {
text("Scroller width:"), text("Scroller width:"),
scroller_width_slider, scroller_width_slider,
] ]
.spacing(10) .spacing(10);
.width(Length::Fill);
let scroll_orientation_controls = column(vec![ let scroll_orientation_controls = column![
text("Scrollbar direction:").into(), text("Scrollbar direction:"),
radio( radio(
"Vertical", "Vertical",
Direction::Vertical, Direction::Vertical,
Some(self.scrollable_direction), Some(self.scrollable_direction),
Message::SwitchDirection, Message::SwitchDirection,
) ),
.into(),
radio( radio(
"Horizontal", "Horizontal",
Direction::Horizontal, Direction::Horizontal,
Some(self.scrollable_direction), Some(self.scrollable_direction),
Message::SwitchDirection, Message::SwitchDirection,
) ),
.into(),
radio( radio(
"Both!", "Both!",
Direction::Multi, Direction::Multi,
Some(self.scrollable_direction), Some(self.scrollable_direction),
Message::SwitchDirection, Message::SwitchDirection,
) ),
.into(), ]
]) .spacing(10);
.spacing(10)
.width(Length::Fill);
let scroll_alignment_controls = column(vec![ let scroll_alignment_controls = column(vec![
text("Scrollable alignment:").into(), text("Scrollable alignment:").into(),
@ -194,16 +189,14 @@ impl Application for ScrollableDemo {
) )
.into(), .into(),
]) ])
.spacing(10) .spacing(10);
.width(Length::Fill);
let scroll_controls = row![ let scroll_controls = row![
scroll_slider_controls, scroll_slider_controls,
scroll_orientation_controls, scroll_orientation_controls,
scroll_alignment_controls scroll_alignment_controls
] ]
.spacing(20) .spacing(20);
.width(Length::Fill);
let scroll_to_end_button = || { let scroll_to_end_button = || {
button("Scroll to end") button("Scroll to end")
@ -229,7 +222,6 @@ impl Application for ScrollableDemo {
text("End!"), text("End!"),
scroll_to_beginning_button(), scroll_to_beginning_button(),
] ]
.width(Length::Fill)
.align_items(Alignment::Center) .align_items(Alignment::Center)
.padding([40, 0, 40, 0]) .padding([40, 0, 40, 0])
.spacing(40), .spacing(40),
@ -341,7 +333,6 @@ impl Application for ScrollableDemo {
let content: Element<Message> = let content: Element<Message> =
column![scroll_controls, scrollable_content, progress_bars] column![scroll_controls, scrollable_content, progress_bars]
.width(Length::Fill)
.height(Length::Fill) .height(Length::Fill)
.align_items(Alignment::Center) .align_items(Alignment::Center)
.spacing(10) .spacing(10)

View file

@ -79,12 +79,10 @@ impl Application for SierpinskiEmulator {
row![ row![
text(format!("Iteration: {:?}", self.graph.iteration)), text(format!("Iteration: {:?}", self.graph.iteration)),
slider(0..=10000, self.graph.iteration, Message::IterationSet) slider(0..=10000, self.graph.iteration, Message::IterationSet)
.width(Length::Fill)
] ]
.padding(10) .padding(10)
.spacing(20), .spacing(20),
] ]
.width(Length::Fill)
.align_items(iced::Alignment::Center) .align_items(iced::Alignment::Center)
.into() .into()
} }

View file

@ -104,10 +104,11 @@ impl Sandbox for Styling {
let progress_bar = progress_bar(0.0..=100.0, self.slider_value); let progress_bar = progress_bar(0.0..=100.0, self.slider_value);
let scrollable = scrollable( let scrollable = scrollable(column![
column!["Scroll me!", vertical_space(800), "You did it!"] "Scroll me!",
.width(Length::Fill), vertical_space(800),
) "You did it!"
])
.width(Length::Fill) .width(Length::Fill)
.height(100); .height(100);

View file

@ -63,7 +63,6 @@ impl Sandbox for Tiger {
container(apply_color_filter).width(Length::Fill).center_x() container(apply_color_filter).width(Length::Fill).center_x()
] ]
.spacing(20) .spacing(20)
.width(Length::Fill)
.height(Length::Fill), .height(Length::Fill),
) )
.width(Length::Fill) .width(Length::Fill)

View file

@ -106,9 +106,7 @@ impl Application for App {
fn view<'a>(&'a self) -> Element<'a, Message> { fn view<'a>(&'a self) -> Element<'a, Message> {
let subtitle = |title, content: Element<'a, Message>| { let subtitle = |title, content: Element<'a, Message>| {
column![text(title).size(14), content] column![text(title).size(14), content].spacing(5)
.width(Length::Fill)
.spacing(5)
}; };
let mut add_toast = button("Add Toast"); let mut add_toast = button("Add Toast");
@ -153,14 +151,11 @@ impl Application for App {
Message::Timeout Message::Timeout
) )
.step(1.0) .step(1.0)
.width(Length::Fill)
] ]
.spacing(5) .spacing(5)
.into() .into()
), ),
column![add_toast] column![add_toast].align_items(Alignment::End)
.width(Length::Fill)
.align_items(Alignment::End)
] ]
.spacing(10) .spacing(10)
.max_width(200), .max_width(200),
@ -513,14 +508,14 @@ mod toast {
position: Point, position: Point,
_translation: Vector, _translation: Vector,
) -> layout::Node { ) -> layout::Node {
let limits = layout::Limits::new(Size::ZERO, bounds) let limits = layout::Limits::new(Size::ZERO, bounds);
.width(Length::Fill)
.height(Length::Fill);
layout::flex::resolve( layout::flex::resolve(
layout::flex::Axis::Vertical, layout::flex::Axis::Vertical,
renderer, renderer,
&limits, &limits,
Length::Fill,
Length::Fill,
10.into(), 10.into(),
10.0, 10.0,
Alignment::End, Alignment::End,

View file

@ -692,11 +692,7 @@ fn ferris<'a>(
} }
fn button<'a, Message: Clone>(label: &str) -> Button<'a, Message> { fn button<'a, Message: Clone>(label: &str) -> Button<'a, Message> {
iced::widget::button( iced::widget::button(text(label)).padding([12, 24])
text(label).horizontal_alignment(alignment::Horizontal::Center),
)
.padding(12)
.width(100)
} }
fn color_slider<'a>( fn color_slider<'a>(

View file

@ -116,7 +116,6 @@ impl Application for WebSocket {
.map(Element::from) .map(Element::from)
.collect(), .collect(),
) )
.width(Length::Fill)
.spacing(10), .spacing(10),
) )
.id(MESSAGE_LOG.clone()) .id(MESSAGE_LOG.clone())
@ -149,7 +148,6 @@ impl Application for WebSocket {
}; };
column![message_log, new_message_input] column![message_log, new_message_input]
.width(Length::Fill)
.height(Length::Fill) .height(Length::Fill)
.padding(20) .padding(20)
.spacing(10) .spacing(10)

View file

@ -433,13 +433,18 @@ pub fn layout(
) -> layout::Node { ) -> layout::Node {
let limits = limits.width(width).height(height); let limits = limits.width(width).height(height);
let mut content = layout_content(&limits.pad(padding)); let content = layout_content(&limits.shrink(padding));
let padding = padding.fit(content.size(), limits.max()); let padding = padding.fit(content.size(), limits.max());
let size = limits.pad(padding).resolve(content.size()).pad(padding);
content.move_to(Point::new(padding.left, padding.top)); let size = limits
.shrink(padding)
.resolve(content.size(), width, height)
.expand(padding);
layout::Node::with_children(size, vec![content]) layout::Node::with_children(
size,
vec![content.move_to(Point::new(padding.left, padding.top))],
)
} }
/// Returns the [`mouse::Interaction`] of a [`Button`]. /// Returns the [`mouse::Interaction`] of a [`Button`].

View file

@ -133,8 +133,7 @@ where
_renderer: &Renderer, _renderer: &Renderer,
limits: &layout::Limits, limits: &layout::Limits,
) -> layout::Node { ) -> layout::Node {
let limits = limits.width(self.width).height(self.height); let size = limits.resolve(Size::ZERO, self.width, self.height);
let size = limits.resolve(Size::ZERO);
layout::Node::new(size) layout::Node::new(size)
} }

View file

@ -35,7 +35,7 @@ impl<'a, Message, Renderer> Column<'a, Message, Renderer> {
Column { Column {
spacing: 0.0, spacing: 0.0,
padding: Padding::ZERO, padding: Padding::ZERO,
width: Length::Shrink, width: Length::Fill,
height: Length::Shrink, height: Length::Shrink,
max_width: f32::INFINITY, max_width: f32::INFINITY,
align_items: Alignment::Start, align_items: Alignment::Start,
@ -126,15 +126,14 @@ where
renderer: &Renderer, renderer: &Renderer,
limits: &layout::Limits, limits: &layout::Limits,
) -> layout::Node { ) -> layout::Node {
let limits = limits let limits = limits.max_width(self.max_width);
.max_width(self.max_width)
.width(self.width)
.height(self.height);
layout::flex::resolve( layout::flex::resolve(
layout::flex::Axis::Vertical, layout::flex::Axis::Vertical,
renderer, renderer,
&limits, &limits,
self.width,
self.height,
self.padding, self.padding,
self.spacing, self.spacing,
self.align_items, self.align_items,

View file

@ -312,24 +312,27 @@ pub fn layout(
layout_content: impl FnOnce(&layout::Limits) -> layout::Node, layout_content: impl FnOnce(&layout::Limits) -> layout::Node,
) -> layout::Node { ) -> layout::Node {
let limits = limits let limits = limits
.loose()
.max_width(max_width)
.max_height(max_height)
.width(width) .width(width)
.height(height); .height(height)
.max_width(max_width)
.max_height(max_height);
let mut content = layout_content(&limits.pad(padding).loose()); let content = layout_content(&limits.shrink(padding).loose());
let padding = padding.fit(content.size(), limits.max()); let padding = padding.fit(content.size(), limits.max());
let size = limits.pad(padding).resolve(content.size()); let size = limits
.shrink(padding)
.resolve(content.size(), width, height);
content.move_to(Point::new(padding.left, padding.top)); layout::Node::with_children(
content.align( size.expand(padding),
Alignment::from(horizontal_alignment), vec![content
Alignment::from(vertical_alignment), .move_to(Point::new(padding.left, padding.top))
size, .align(
); Alignment::from(horizontal_alignment),
Alignment::from(vertical_alignment),
layout::Node::with_children(size.pad(padding), vec![content]) size,
)],
)
} }
/// Draws the background of a [`Container`] given its [`Appearance`] and its `bounds`. /// Draws the background of a [`Container`] given its [`Appearance`] and its `bounds`.

View file

@ -99,7 +99,7 @@ where
}; };
// The size to be available to the widget prior to `Shrink`ing // The size to be available to the widget prior to `Shrink`ing
let raw_size = limits.width(width).height(height).resolve(image_size); let raw_size = limits.resolve(image_size, width, height);
// The uncropped size of the image when fit to the bounds above // The uncropped size of the image when fit to the bounds above
let full_size = content_fit.fit(image_size, raw_size); let full_size = content_fit.fit(image_size, raw_size);

View file

@ -113,10 +113,11 @@ where
) -> layout::Node { ) -> layout::Node {
let Size { width, height } = renderer.dimensions(&self.handle); let Size { width, height } = renderer.dimensions(&self.handle);
let mut size = limits let mut size = limits.resolve(
.width(self.width) Size::new(width as f32, height as f32),
.height(self.height) self.width,
.resolve(Size::new(width as f32, height as f32)); self.height,
);
let expansion_size = if height > width { let expansion_size = if height > width {
self.width self.width

View file

@ -196,6 +196,8 @@ where
layout::flex::Axis::Vertical, layout::flex::Axis::Vertical,
renderer, renderer,
&limits, &limits,
self.width,
self.height,
self.padding, self.padding,
self.spacing, self.spacing,
self.align_items, self.align_items,

View file

@ -254,15 +254,14 @@ where
) )
.width(self.width); .width(self.width);
let mut node = self.container.layout(self.state, renderer, &limits); let node = self.container.layout(self.state, renderer, &limits);
let size = node.size();
node.move_to(if space_below > space_above { node.move_to(if space_below > space_above {
position + Vector::new(0.0, self.target_height) position + Vector::new(0.0, self.target_height)
} else { } else {
position - Vector::new(0.0, node.size().height) position - Vector::new(0.0, size.height)
}); })
node
} }
fn on_event( fn on_event(
@ -359,7 +358,6 @@ where
) -> layout::Node { ) -> layout::Node {
use std::f32; use std::f32;
let limits = limits.width(Length::Fill).height(Length::Shrink);
let text_size = let text_size =
self.text_size.unwrap_or_else(|| renderer.default_size()); self.text_size.unwrap_or_else(|| renderer.default_size());
@ -372,7 +370,7 @@ where
* self.options.len() as f32, * self.options.len() as f32,
); );
limits.resolve(intrinsic) limits.resolve(intrinsic, Length::Fill, Length::Shrink)
}; };
layout::Node::new(size) layout::Node::new(size)

View file

@ -490,8 +490,7 @@ pub fn layout<Renderer, T>(
&layout::Limits, &layout::Limits,
) -> layout::Node, ) -> layout::Node,
) -> layout::Node { ) -> layout::Node {
let limits = limits.width(width).height(height); let size = limits.resolve(Size::ZERO, width, height);
let size = limits.resolve(Size::ZERO);
let regions = node.pane_regions(spacing, size); let regions = node.pane_regions(spacing, size);
let children = contents let children = contents
@ -500,16 +499,14 @@ pub fn layout<Renderer, T>(
let region = regions.get(&pane)?; let region = regions.get(&pane)?;
let size = Size::new(region.width, region.height); let size = Size::new(region.width, region.height);
let mut node = layout_content( let node = layout_content(
content, content,
tree, tree,
renderer, renderer,
&layout::Limits::new(size, size), &layout::Limits::new(size, size),
); );
node.move_to(Point::new(region.x, region.y)); Some(node.move_to(Point::new(region.x, region.y)))
Some(node)
}) })
.collect(); .collect();

View file

@ -165,7 +165,7 @@ where
let title_bar_size = title_bar_layout.size(); let title_bar_size = title_bar_layout.size();
let mut body_layout = self.body.as_widget().layout( let body_layout = self.body.as_widget().layout(
&mut tree.children[0], &mut tree.children[0],
renderer, renderer,
&layout::Limits::new( &layout::Limits::new(
@ -177,11 +177,12 @@ where
), ),
); );
body_layout.move_to(Point::new(0.0, title_bar_size.height));
layout::Node::with_children( layout::Node::with_children(
max_size, max_size,
vec![title_bar_layout, body_layout], vec![
title_bar_layout,
body_layout.move_to(Point::new(0.0, title_bar_size.height)),
],
) )
} else { } else {
self.body.as_widget().layout( self.body.as_widget().layout(

View file

@ -217,7 +217,7 @@ where
renderer: &Renderer, renderer: &Renderer,
limits: &layout::Limits, limits: &layout::Limits,
) -> layout::Node { ) -> layout::Node {
let limits = limits.pad(self.padding); let limits = limits.shrink(self.padding);
let max_size = limits.max(); let max_size = limits.max();
let title_layout = self.content.as_widget().layout( let title_layout = self.content.as_widget().layout(
@ -228,8 +228,8 @@ where
let title_size = title_layout.size(); let title_size = title_layout.size();
let mut node = if let Some(controls) = &self.controls { let node = if let Some(controls) = &self.controls {
let mut controls_layout = controls.as_widget().layout( let controls_layout = controls.as_widget().layout(
&mut tree.children[1], &mut tree.children[1],
renderer, renderer,
&layout::Limits::new(Size::ZERO, max_size), &layout::Limits::new(Size::ZERO, max_size),
@ -240,11 +240,13 @@ where
let height = title_size.height.max(controls_size.height); let height = title_size.height.max(controls_size.height);
controls_layout.move_to(Point::new(space_before_controls, 0.0));
layout::Node::with_children( layout::Node::with_children(
Size::new(max_size.width, height), Size::new(max_size.width, height),
vec![title_layout, controls_layout], vec![
title_layout,
controls_layout
.move_to(Point::new(space_before_controls, 0.0)),
],
) )
} else { } else {
layout::Node::with_children( layout::Node::with_children(
@ -253,9 +255,7 @@ where
) )
}; };
node.move_to(Point::new(self.padding.left, self.padding.top)); layout::Node::container(node, self.padding)
layout::Node::with_children(node.size().pad(self.padding), vec![node])
} }
pub(crate) fn operate( pub(crate) fn operate(

View file

@ -393,7 +393,7 @@ where
{ {
use std::f32; use std::f32;
let limits = limits.width(width).height(Length::Shrink).pad(padding); let limits = limits.width(width).height(Length::Shrink);
let font = font.unwrap_or_else(|| renderer.default_font()); let font = font.unwrap_or_else(|| renderer.default_font());
let text_size = text_size.unwrap_or_else(|| renderer.default_size()); let text_size = text_size.unwrap_or_else(|| renderer.default_size());
@ -451,7 +451,10 @@ where
f32::from(text_line_height.to_absolute(text_size)), f32::from(text_line_height.to_absolute(text_size)),
); );
limits.resolve(intrinsic).pad(padding) limits
.shrink(padding)
.resolve(intrinsic, width, Length::Shrink)
.expand(padding)
}; };
layout::Node::new(size) layout::Node::new(size)

View file

@ -99,11 +99,11 @@ where
_renderer: &Renderer, _renderer: &Renderer,
limits: &layout::Limits, limits: &layout::Limits,
) -> layout::Node { ) -> layout::Node {
let limits = limits let size = limits.resolve(
.width(self.width) Size::ZERO,
.height(self.height.unwrap_or(Length::Fixed(Self::DEFAULT_HEIGHT))); self.width,
self.height.unwrap_or(Length::Fixed(Self::DEFAULT_HEIGHT)),
let size = limits.resolve(Size::ZERO); );
layout::Node::new(size) layout::Node::new(size)
} }

View file

@ -34,7 +34,7 @@ impl<'a, Message, Renderer> Row<'a, Message, Renderer> {
Row { Row {
spacing: 0.0, spacing: 0.0,
padding: Padding::ZERO, padding: Padding::ZERO,
width: Length::Shrink, width: Length::Fill,
height: Length::Shrink, height: Length::Shrink,
align_items: Alignment::Start, align_items: Alignment::Start,
children, children,
@ -118,12 +118,12 @@ where
renderer: &Renderer, renderer: &Renderer,
limits: &layout::Limits, limits: &layout::Limits,
) -> layout::Node { ) -> layout::Node {
let limits = limits.width(self.width).height(self.height);
layout::flex::resolve( layout::flex::resolve(
layout::flex::Axis::Horizontal, layout::flex::Axis::Horizontal,
renderer, renderer,
&limits, &limits,
self.width,
self.height,
self.padding, self.padding,
self.spacing, self.spacing,
self.align_items, self.align_items,

View file

@ -76,9 +76,7 @@ where
_renderer: &Renderer, _renderer: &Renderer,
limits: &layout::Limits, limits: &layout::Limits,
) -> layout::Node { ) -> layout::Node {
let limits = limits.width(self.width).height(self.height); layout::Node::new(limits.resolve(Size::ZERO, self.width, self.height))
layout::Node::new(limits.resolve(Size::ZERO))
} }
fn draw( fn draw(

View file

@ -489,7 +489,7 @@ pub fn layout<Renderer>(
); );
let content = layout_content(renderer, &child_limits); let content = layout_content(renderer, &child_limits);
let size = limits.resolve(content.size()); let size = limits.resolve(content.size(), width, height);
layout::Node::with_children(size, vec![content]) layout::Node::with_children(size, vec![content])
} }

View file

@ -85,7 +85,7 @@ where
limits: &layout::Limits, limits: &layout::Limits,
) -> layout::Node { ) -> layout::Node {
let limits = limits.width(self.width).height(self.height); let limits = limits.width(self.width).height(self.height);
let size = limits.resolve(Size::ZERO); let size = limits.resolve(Size::ZERO, self.width, self.height);
layout::Node::new(size) layout::Node::new(size)
} }

View file

@ -173,8 +173,7 @@ where
_renderer: &Renderer, _renderer: &Renderer,
limits: &layout::Limits, limits: &layout::Limits,
) -> layout::Node { ) -> layout::Node {
let limits = limits.width(self.width).height(self.height); let size = limits.resolve(Size::ZERO, self.width, self.height);
let size = limits.resolve(Size::ZERO);
layout::Node::new(size) layout::Node::new(size)
} }

View file

@ -59,9 +59,7 @@ where
_renderer: &Renderer, _renderer: &Renderer,
limits: &layout::Limits, limits: &layout::Limits,
) -> layout::Node { ) -> layout::Node {
let limits = limits.width(self.width).height(self.height); layout::Node::new(limits.resolve(Size::ZERO, self.width, self.height))
layout::Node::new(limits.resolve(Size::ZERO))
} }
fn draw( fn draw(

View file

@ -115,10 +115,7 @@ where
let image_size = Size::new(width as f32, height as f32); let image_size = Size::new(width as f32, height as f32);
// The size to be available to the widget prior to `Shrink`ing // The size to be available to the widget prior to `Shrink`ing
let raw_size = limits let raw_size = limits.resolve(image_size, self.width, self.height);
.width(self.width)
.height(self.height)
.resolve(image_size);
// The uncropped size of the image when fit to the bounds above // The uncropped size of the image when fit to the bounds above
let full_size = self.content_fit.fit(image_size, raw_size); let full_size = self.content_fit.fit(image_size, raw_size);

View file

@ -350,7 +350,7 @@ where
} }
internal.editor.update( internal.editor.update(
limits.pad(self.padding).max(), limits.shrink(self.padding).max(),
self.font.unwrap_or_else(|| renderer.default_font()), self.font.unwrap_or_else(|| renderer.default_font()),
self.text_size.unwrap_or_else(|| renderer.default_size()), self.text_size.unwrap_or_else(|| renderer.default_size()),
self.line_height, self.line_height,

View file

@ -506,14 +506,11 @@ where
{ {
let font = font.unwrap_or_else(|| renderer.default_font()); let font = font.unwrap_or_else(|| renderer.default_font());
let text_size = size.unwrap_or_else(|| renderer.default_size()); let text_size = size.unwrap_or_else(|| renderer.default_size());
let padding = padding.fit(Size::ZERO, limits.max()); let padding = padding.fit(Size::ZERO, limits.max());
let limits = limits let height = line_height.to_absolute(text_size);
.width(width)
.pad(padding)
.height(line_height.to_absolute(text_size));
let text_bounds = limits.resolve(Size::ZERO); let limits = limits.width(width).shrink(padding).height(height);
let text_bounds = limits.resolve(Size::ZERO, width, height);
let placeholder_text = Text { let placeholder_text = Text {
font, font,
@ -552,41 +549,41 @@ where
let icon_width = state.icon.min_width(); let icon_width = state.icon.min_width();
let mut text_node = layout::Node::new( let (text_position, icon_position) = match icon.side {
text_bounds - Size::new(icon_width + icon.spacing, 0.0), Side::Left => (
); Point::new(
let mut icon_node =
layout::Node::new(Size::new(icon_width, text_bounds.height));
match icon.side {
Side::Left => {
text_node.move_to(Point::new(
padding.left + icon_width + icon.spacing, padding.left + icon_width + icon.spacing,
padding.top, padding.top,
)); ),
Point::new(padding.left, padding.top),
icon_node.move_to(Point::new(padding.left, padding.top)); ),
} Side::Right => (
Side::Right => { Point::new(padding.left, padding.top),
text_node.move_to(Point::new(padding.left, padding.top)); Point::new(
icon_node.move_to(Point::new(
padding.left + text_bounds.width - icon_width, padding.left + text_bounds.width - icon_width,
padding.top, padding.top,
)); ),
} ),
}; };
let text_node = layout::Node::new(
text_bounds - Size::new(icon_width + icon.spacing, 0.0),
)
.move_to(text_position);
let icon_node =
layout::Node::new(Size::new(icon_width, text_bounds.height))
.move_to(icon_position);
layout::Node::with_children( layout::Node::with_children(
text_bounds.pad(padding), text_bounds.expand(padding),
vec![text_node, icon_node], vec![text_node, icon_node],
) )
} else { } else {
let mut text = layout::Node::new(text_bounds); let text = layout::Node::new(text_bounds)
text.move_to(Point::new(padding.left, padding.top)); .move_to(Point::new(padding.left, padding.top));
layout::Node::with_children(text_bounds.pad(padding), vec![text]) layout::Node::with_children(text_bounds.expand(padding), vec![text])
} }
} }

View file

@ -353,7 +353,7 @@ where
.then(|| viewport.size()) .then(|| viewport.size())
.unwrap_or(Size::INFINITY), .unwrap_or(Size::INFINITY),
) )
.pad(Padding::new(self.padding)), .shrink(Padding::new(self.padding)),
); );
let text_bounds = text_layout.bounds(); let text_bounds = text_layout.bounds();

View file

@ -170,8 +170,7 @@ where
_renderer: &Renderer, _renderer: &Renderer,
limits: &layout::Limits, limits: &layout::Limits,
) -> layout::Node { ) -> layout::Node {
let limits = limits.width(self.width).height(self.height); let size = limits.resolve(Size::ZERO, self.width, self.height);
let size = limits.resolve(Size::ZERO);
layout::Node::new(size) layout::Node::new(size)
} }