summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector@hecrj.dev>2024-01-16 12:02:42 +0100
committerLibravatar Héctor Ramón Jiménez <hector@hecrj.dev>2024-01-16 12:02:42 +0100
commit534c7dd7b0bc515c31b6de87b4aa6a35b44c46a0 (patch)
tree0ddc8f1b681cbade7e47293bd46a362896aa538a /core
parent17135cbd56316f31167eb62e026839450506573f (diff)
parentc4ba657de86d7606587dad5124f435141258f570 (diff)
downloadiced-534c7dd7b0bc515c31b6de87b4aa6a35b44c46a0.tar.gz
iced-534c7dd7b0bc515c31b6de87b4aa6a35b44c46a0.tar.bz2
iced-534c7dd7b0bc515c31b6de87b4aa6a35b44c46a0.zip
Merge branch 'master' into update-winit
Diffstat (limited to 'core')
-rw-r--r--core/src/element.rs18
-rw-r--r--core/src/layout.rs106
-rw-r--r--core/src/layout/flex.rs117
-rw-r--r--core/src/layout/limits.rs88
-rw-r--r--core/src/layout/node.rs35
-rw-r--r--core/src/length.rs18
-rw-r--r--core/src/padding.rs6
-rw-r--r--core/src/point.rs20
-rw-r--r--core/src/size.rs24
-rw-r--r--core/src/widget.rs15
-rw-r--r--core/src/widget/text.rs58
-rw-r--r--core/src/window/event.rs2
12 files changed, 350 insertions, 157 deletions
diff --git a/core/src/element.rs b/core/src/element.rs
index dea111af..8b510218 100644
--- a/core/src/element.rs
+++ b/core/src/element.rs
@@ -6,7 +6,7 @@ use crate::renderer;
use crate::widget;
use crate::widget::tree::{self, Tree};
use crate::{
- Clipboard, Color, Layout, Length, Rectangle, Shell, Vector, Widget,
+ Clipboard, Color, Layout, Length, Rectangle, Shell, Size, Vector, Widget,
};
use std::any::Any;
@@ -296,12 +296,8 @@ where
self.widget.diff(tree);
}
- fn width(&self) -> Length {
- self.widget.width()
- }
-
- fn height(&self) -> Length {
- self.widget.height()
+ fn size(&self) -> Size<Length> {
+ self.widget.size()
}
fn layout(
@@ -466,12 +462,8 @@ impl<'a, Message, Renderer> Widget<Message, Renderer>
where
Renderer: crate::Renderer,
{
- fn width(&self) -> Length {
- self.element.widget.width()
- }
-
- fn height(&self) -> Length {
- self.element.widget.height()
+ fn size(&self) -> Size<Length> {
+ self.element.widget.size()
}
fn tag(&self) -> tree::Tag {
diff --git a/core/src/layout.rs b/core/src/layout.rs
index caf315b6..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)]
@@ -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,106 @@ 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)),
+ ],
+ )
+}
+
+/// 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 c02b63d8..3358ef3d 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)]
@@ -47,7 +47,7 @@ impl Axis {
}
}
- fn pack(&self, main: f32, cross: f32) -> (f32, f32) {
+ fn pack<T>(&self, main: T, cross: T) -> (T, T) {
match self {
Axis::Horizontal => (main, cross),
Axis::Vertical => (cross, main),
@@ -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,26 +74,64 @@ 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 fill_main_sum = 0;
+ let mut cross = match axis {
+ Axis::Horizontal => match height {
+ Length::Shrink => 0.0,
+ _ => max_cross,
+ },
+ Axis::Vertical => match width {
+ Length::Shrink => 0.0,
+ _ => max_cross,
+ },
+ };
+
let mut available = axis.main(limits.max()) - total_spacing;
let mut nodes: Vec<Node> = Vec::with_capacity(items.len());
nodes.resize(items.len(), Node::default());
for (i, (child, tree)) in items.iter().zip(trees.iter_mut()).enumerate() {
- let fill_factor = match axis {
- Axis::Horizontal => child.as_widget().width(),
- Axis::Vertical => child.as_widget().height(),
+ let (fill_main_factor, fill_cross_factor) = {
+ let size = child.as_widget().size();
+
+ axis.pack(size.width.fill_factor(), size.height.fill_factor())
+ };
+
+ if fill_main_factor == 0 {
+ if fill_cross_factor == 0 {
+ let (max_width, max_height) = axis.pack(available, max_cross);
+
+ let child_limits =
+ Limits::new(Size::ZERO, Size::new(max_width, max_height));
+
+ let layout =
+ child.as_widget().layout(tree, renderer, &child_limits);
+ let size = layout.size();
+
+ available -= axis.main(size);
+ cross = cross.max(axis.cross(size));
+
+ nodes[i] = layout;
+ }
+ } else {
+ fill_main_sum += fill_main_factor;
}
- .fill_factor();
+ }
- if fill_factor == 0 {
- let (max_width, max_height) = axis.pack(available, max_cross);
+ for (i, (child, tree)) in items.iter().zip(trees.iter_mut()).enumerate() {
+ let (fill_main_factor, fill_cross_factor) = {
+ let size = child.as_widget().size();
+
+ axis.pack(size.width.fill_factor(), size.height.fill_factor())
+ };
+
+ if fill_main_factor == 0 && fill_cross_factor != 0 {
+ let (max_width, max_height) = axis.pack(available, cross);
let child_limits =
Limits::new(Size::ZERO, Size::new(max_width, max_height));
@@ -101,34 +141,47 @@ where
let size = layout.size();
available -= axis.main(size);
- cross = cross.max(axis.cross(size));
+ cross = cross.max(axis.cross(layout.size()));
nodes[i] = layout;
- } else {
- fill_sum += fill_factor;
}
}
- 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 {
- Axis::Horizontal => child.as_widget().width(),
- Axis::Vertical => child.as_widget().height(),
- }
- .fill_factor();
+ let (fill_main_factor, fill_cross_factor) = {
+ let size = child.as_widget().size();
+
+ axis.pack(size.width.fill_factor(), size.height.fill_factor())
+ };
+
+ if fill_main_factor != 0 {
+ let max_main =
+ remaining * fill_main_factor as f32 / fill_main_sum as f32;
- if fill_factor != 0 {
- let max_main = remaining * fill_factor as f32 / fill_sum as f32;
let min_main = if max_main.is_infinite() {
0.0
} else {
max_main
};
- let (min_width, min_height) =
- axis.pack(min_main, axis.cross(limits.min()));
+ let max_cross = if fill_cross_factor == 0 {
+ max_cross
+ } else {
+ cross
+ };
+ let (min_width, min_height) = axis.pack(min_main, 0.0);
let (max_width, max_height) = axis.pack(max_main, max_cross);
let child_limits = Limits::new(
@@ -154,18 +207,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),
@@ -178,8 +231,12 @@ where
main += axis.main(size);
}
- let (width, height) = axis.pack(main - pad.0, cross);
- let size = limits.resolve(Size::new(width, height));
+ let (intrinsic_width, intrinsic_height) = axis.pack(main - pad.0, cross);
+ let size = limits.resolve(
+ width,
+ height,
+ Size::new(intrinsic_width, intrinsic_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..7fbc7b9d 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,39 @@ 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
+ /// 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,
+ width: impl Into<Length>,
+ height: impl Into<Length>,
+ intrinsic_size: Size,
+ ) -> 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..5743a9bd 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 [`Self::align`].
+ pub fn align_mut(
&mut self,
horizontal_alignment: Alignment,
vertical_alignment: Alignment,
@@ -70,13 +89,23 @@ impl Node {
}
/// Moves the [`Node`] to the given position.
- pub fn move_to(&mut self, position: Point) {
+ pub fn move_to(mut self, position: impl Into<Point>) -> Self {
+ self.move_to_mut(position);
+ self
+ }
+
+ /// Mutable reference version of [`Self::move_to`].
+ 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/length.rs b/core/src/length.rs
index 3adb996e..4c139895 100644
--- a/core/src/length.rs
+++ b/core/src/length.rs
@@ -36,6 +36,24 @@ impl Length {
Length::Fixed(_) => 0,
}
}
+
+ /// Returns `true` iff the [`Length`] is either [`Length::Fill`] or
+ // [`Length::FillPortion`].
+ pub fn is_fill(&self) -> bool {
+ self.fill_factor() != 0
+ }
+
+ /// Returns the "fluid" variant of the [`Length`].
+ ///
+ /// Specifically:
+ /// - [`Length::Shrink`] if [`Length::Shrink`] or [`Length::Fixed`].
+ /// - [`Length::Fill`] otherwise.
+ pub fn fluid(&self) -> Length {
+ match self {
+ Length::Fill | Length::FillPortion(_) => Length::Fill,
+ Length::Shrink | Length::Fixed(_) => Length::Shrink,
+ }
+ }
}
impl From<Pixels> for Length {
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/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/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.rs b/core/src/widget.rs
index 294d5984..7f5632ae 100644
--- a/core/src/widget.rs
+++ b/core/src/widget.rs
@@ -15,7 +15,7 @@ use crate::layout::{self, Layout};
use crate::mouse;
use crate::overlay;
use crate::renderer;
-use crate::{Clipboard, Length, Rectangle, Shell};
+use crate::{Clipboard, Length, Rectangle, Shell, Size};
/// A component that displays information and allows interaction.
///
@@ -43,11 +43,16 @@ pub trait Widget<Message, Renderer>
where
Renderer: crate::Renderer,
{
- /// Returns the width of the [`Widget`].
- fn width(&self) -> Length;
+ /// Returns the [`Size`] of the [`Widget`] in lengths.
+ fn size(&self) -> Size<Length>;
- /// Returns the height of the [`Widget`].
- fn height(&self) -> Length;
+ /// Returns a [`Size`] hint for laying out the [`Widget`].
+ ///
+ /// This hint may be used by some widget containers to adjust their sizing strategy
+ /// during construction.
+ fn size_hint(&self) -> Size<Length> {
+ self.size()
+ }
/// Returns the [`layout::Node`] of the [`Widget`].
///
diff --git a/core/src/widget/text.rs b/core/src/widget/text.rs
index e020b030..4cabc7ce 100644
--- a/core/src/widget/text.rs
+++ b/core/src/widget/text.rs
@@ -5,7 +5,9 @@ use crate::mouse;
use crate::renderer;
use crate::text::{self, Paragraph};
use crate::widget::tree::{self, Tree};
-use crate::{Color, Element, Layout, Length, Pixels, Point, Rectangle, Widget};
+use crate::{
+ Color, Element, Layout, Length, Pixels, Point, Rectangle, Size, Widget,
+};
use std::borrow::Cow;
@@ -134,12 +136,11 @@ where
tree::State::new(State(Renderer::Paragraph::default()))
}
- fn width(&self) -> Length {
- self.width
- }
-
- fn height(&self) -> Length {
- self.height
+ fn size(&self) -> Size<Length> {
+ Size {
+ width: self.width,
+ height: self.height,
+ }
}
fn layout(
@@ -205,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());
-
- 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.
diff --git a/core/src/window/event.rs b/core/src/window/event.rs
index b9ee7aca..a14d127f 100644
--- a/core/src/window/event.rs
+++ b/core/src/window/event.rs
@@ -58,7 +58,7 @@ pub enum Event {
/// for each file separately.
FileHovered(PathBuf),
- /// A file has beend dropped into the window.
+ /// A file has been dropped into the window.
///
/// When the user drops multiple files at once, this event will be emitted
/// for each file separately.