summaryrefslogtreecommitdiffstats
path: root/widget
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 /widget
parent17135cbd56316f31167eb62e026839450506573f (diff)
parentc4ba657de86d7606587dad5124f435141258f570 (diff)
downloadiced-534c7dd7b0bc515c31b6de87b4aa6a35b44c46a0.tar.gz
iced-534c7dd7b0bc515c31b6de87b4aa6a35b44c46a0.tar.bz2
iced-534c7dd7b0bc515c31b6de87b4aa6a35b44c46a0.zip
Merge branch 'master' into update-winit
Diffstat (limited to 'widget')
-rw-r--r--widget/src/button.rs34
-rw-r--r--widget/src/canvas.rs21
-rw-r--r--widget/src/checkbox.rs11
-rw-r--r--widget/src/column.rs59
-rw-r--r--widget/src/combo_box.rs12
-rw-r--r--widget/src/container.rs53
-rw-r--r--widget/src/helpers.rs25
-rw-r--r--widget/src/image.rs13
-rw-r--r--widget/src/image/viewer.rs20
-rw-r--r--widget/src/keyed/column.rs60
-rw-r--r--widget/src/lazy.rs11
-rw-r--r--widget/src/lazy/component.rs11
-rw-r--r--widget/src/lazy/helpers.rs3
-rw-r--r--widget/src/lazy/responsive.rs11
-rw-r--r--widget/src/mouse_area.rs10
-rw-r--r--widget/src/overlay/menu.rs23
-rw-r--r--widget/src/pane_grid.rs89
-rw-r--r--widget/src/pane_grid/content.rs9
-rw-r--r--widget/src/pane_grid/state.rs17
-rw-r--r--widget/src/pane_grid/title_bar.rs18
-rw-r--r--widget/src/pick_list.rs24
-rw-r--r--widget/src/progress_bar.rs23
-rw-r--r--widget/src/qr_code.rs11
-rw-r--r--widget/src/radio.rs11
-rw-r--r--widget/src/row.rs58
-rw-r--r--widget/src/rule.rs15
-rw-r--r--widget/src/scrollable.rs50
-rw-r--r--widget/src/shader.rs16
-rw-r--r--widget/src/slider.rs16
-rw-r--r--widget/src/space.rs15
-rw-r--r--widget/src/svg.rs16
-rw-r--r--widget/src/text_editor.rs15
-rw-r--r--widget/src/text_input.rs122
-rw-r--r--widget/src/toggler.rs11
-rw-r--r--widget/src/tooltip.rs16
-rw-r--r--widget/src/vertical_slider.rs16
36 files changed, 498 insertions, 447 deletions
diff --git a/widget/src/button.rs b/widget/src/button.rs
index 384a3156..0ebb8dcc 100644
--- a/widget/src/button.rs
+++ b/widget/src/button.rs
@@ -10,8 +10,8 @@ use crate::core::touch;
use crate::core::widget::tree::{self, Tree};
use crate::core::widget::Operation;
use crate::core::{
- Background, Clipboard, Color, Element, Layout, Length, Padding, Point,
- Rectangle, Shell, Vector, Widget,
+ Background, Clipboard, Color, Element, Layout, Length, Padding, Rectangle,
+ Shell, Size, Vector, Widget,
};
pub use iced_style::button::{Appearance, StyleSheet};
@@ -71,11 +71,14 @@ where
{
/// Creates a new [`Button`] with the given content.
pub fn new(content: impl Into<Element<'a, Message, Renderer>>) -> Self {
+ let content = content.into();
+ let size = content.as_widget().size_hint();
+
Button {
- content: content.into(),
+ content,
on_press: None,
- width: Length::Shrink,
- height: Length::Shrink,
+ width: size.width.fluid(),
+ height: size.height.fluid(),
padding: Padding::new(5.0),
style: <Renderer::Theme as StyleSheet>::Style::default(),
}
@@ -149,12 +152,11 @@ where
tree.diff_children(std::slice::from_ref(&self.content));
}
- 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(
@@ -431,15 +433,7 @@ pub fn layout(
padding: Padding,
layout_content: impl FnOnce(&layout::Limits) -> layout::Node,
) -> layout::Node {
- let limits = limits.width(width).height(height);
-
- let mut content = layout_content(&limits.pad(padding));
- 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));
-
- layout::Node::with_children(size, vec![content])
+ layout::padded(limits, width, height, padding, layout_content)
}
/// Returns the [`mouse::Interaction`] of a [`Button`].
diff --git a/widget/src/canvas.rs b/widget/src/canvas.rs
index 390f4d92..4e42a671 100644
--- a/widget/src/canvas.rs
+++ b/widget/src/canvas.rs
@@ -14,8 +14,9 @@ use crate::core::layout::{self, Layout};
use crate::core::mouse;
use crate::core::renderer;
use crate::core::widget::tree::{self, Tree};
-use crate::core::{Clipboard, Element, Shell, Widget};
-use crate::core::{Length, Rectangle, Size, Vector};
+use crate::core::{
+ Clipboard, Element, Length, Rectangle, Shell, Size, Vector, Widget,
+};
use crate::graphics::geometry;
use std::marker::PhantomData;
@@ -119,12 +120,11 @@ where
tree::State::new(P::State::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(
@@ -133,10 +133,7 @@ where
_renderer: &Renderer,
limits: &layout::Limits,
) -> layout::Node {
- let limits = limits.width(self.width).height(self.height);
- let size = limits.resolve(Size::ZERO);
-
- layout::Node::new(size)
+ layout::atomic(limits, self.width, self.height)
}
fn on_event(
diff --git a/widget/src/checkbox.rs b/widget/src/checkbox.rs
index a0d9559b..0353b3ad 100644
--- a/widget/src/checkbox.rs
+++ b/widget/src/checkbox.rs
@@ -174,12 +174,11 @@ where
tree::State::new(widget::text::State::<Renderer::Paragraph>::default())
}
- fn width(&self) -> Length {
- self.width
- }
-
- fn height(&self) -> Length {
- Length::Shrink
+ fn size(&self) -> Size<Length> {
+ Size {
+ width: self.width,
+ height: Length::Shrink,
+ }
}
fn layout(
diff --git a/widget/src/column.rs b/widget/src/column.rs
index abb522be..d6eea84b 100644
--- a/widget/src/column.rs
+++ b/widget/src/column.rs
@@ -7,7 +7,7 @@ use crate::core::renderer;
use crate::core::widget::{Operation, Tree};
use crate::core::{
Alignment, Clipboard, Element, Layout, Length, Padding, Pixels, Rectangle,
- Shell, Widget,
+ Shell, Size, Widget,
};
/// A container that distributes its contents vertically.
@@ -22,16 +22,12 @@ pub struct Column<'a, Message, Renderer = crate::Renderer> {
children: Vec<Element<'a, Message, Renderer>>,
}
-impl<'a, Message, Renderer> Column<'a, Message, Renderer> {
+impl<'a, Message, Renderer> Column<'a, Message, Renderer>
+where
+ Renderer: crate::core::Renderer,
+{
/// Creates an empty [`Column`].
pub fn new() -> Self {
- Self::with_children(Vec::new())
- }
-
- /// Creates a [`Column`] with the given elements.
- pub fn with_children(
- children: Vec<Element<'a, Message, Renderer>>,
- ) -> Self {
Column {
spacing: 0.0,
padding: Padding::ZERO,
@@ -39,10 +35,17 @@ impl<'a, Message, Renderer> Column<'a, Message, Renderer> {
height: Length::Shrink,
max_width: f32::INFINITY,
align_items: Alignment::Start,
- children,
+ children: Vec::new(),
}
}
+ /// Creates a [`Column`] with the given elements.
+ pub fn with_children(
+ children: impl IntoIterator<Item = Element<'a, Message, Renderer>>,
+ ) -> Self {
+ children.into_iter().fold(Self::new(), Self::push)
+ }
+
/// Sets the vertical spacing _between_ elements.
///
/// Custom margins per element do not exist in iced. You should use this
@@ -88,12 +91,26 @@ impl<'a, Message, Renderer> Column<'a, Message, Renderer> {
mut self,
child: impl Into<Element<'a, Message, Renderer>>,
) -> Self {
- self.children.push(child.into());
+ let child = child.into();
+ let size = child.as_widget().size_hint();
+
+ if size.width.is_fill() {
+ self.width = Length::Fill;
+ }
+
+ if size.height.is_fill() {
+ self.height = Length::Fill;
+ }
+
+ self.children.push(child);
self
}
}
-impl<'a, Message, Renderer> Default for Column<'a, Message, Renderer> {
+impl<'a, Message, Renderer> Default for Column<'a, Message, Renderer>
+where
+ Renderer: crate::core::Renderer,
+{
fn default() -> Self {
Self::new()
}
@@ -112,12 +129,11 @@ where
tree.diff_children(&self.children);
}
- 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(
@@ -126,15 +142,14 @@ where
renderer: &Renderer,
limits: &layout::Limits,
) -> layout::Node {
- let limits = limits
- .max_width(self.max_width)
- .width(self.width)
- .height(self.height);
+ let limits = limits.max_width(self.max_width);
layout::flex::resolve(
layout::flex::Axis::Vertical,
renderer,
&limits,
+ self.width,
+ self.height,
self.padding,
self.spacing,
self.align_items,
diff --git a/widget/src/combo_box.rs b/widget/src/combo_box.rs
index 31ec27fc..1b2fa947 100644
--- a/widget/src/combo_box.rs
+++ b/widget/src/combo_box.rs
@@ -8,7 +8,9 @@ use crate::core::renderer;
use crate::core::text;
use crate::core::time::Instant;
use crate::core::widget::{self, Widget};
-use crate::core::{Clipboard, Element, Length, Padding, Rectangle, Shell};
+use crate::core::{
+ Clipboard, Element, Length, Padding, Rectangle, Shell, Size,
+};
use crate::overlay::menu;
use crate::text::LineHeight;
use crate::{container, scrollable, text_input, TextInput};
@@ -297,12 +299,8 @@ where
+ scrollable::StyleSheet
+ menu::StyleSheet,
{
- fn width(&self) -> Length {
- Widget::<TextInputEvent, Renderer>::width(&self.text_input)
- }
-
- fn height(&self) -> Length {
- Widget::<TextInputEvent, Renderer>::height(&self.text_input)
+ fn size(&self) -> Size<Length> {
+ Widget::<TextInputEvent, Renderer>::size(&self.text_input)
}
fn layout(
diff --git a/widget/src/container.rs b/widget/src/container.rs
index 5dd7705b..cffb0458 100644
--- a/widget/src/container.rs
+++ b/widget/src/container.rs
@@ -46,17 +46,20 @@ where
where
T: Into<Element<'a, Message, Renderer>>,
{
+ let content = content.into();
+ let size = content.as_widget().size_hint();
+
Container {
id: None,
padding: Padding::ZERO,
- width: Length::Shrink,
- height: Length::Shrink,
+ width: size.width.fluid(),
+ height: size.height.fluid(),
max_width: f32::INFINITY,
max_height: f32::INFINITY,
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Top,
style: Default::default(),
- content: content.into(),
+ content,
}
}
@@ -152,12 +155,11 @@ where
self.content.as_widget().diff(tree);
}
- 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(
@@ -311,25 +313,20 @@ pub fn layout(
vertical_alignment: alignment::Vertical,
layout_content: impl FnOnce(&layout::Limits) -> layout::Node,
) -> layout::Node {
- let limits = limits
- .loose()
- .max_width(max_width)
- .max_height(max_height)
- .width(width)
- .height(height);
-
- let mut content = layout_content(&limits.pad(padding).loose());
- let padding = padding.fit(content.size(), limits.max());
- let size = limits.pad(padding).resolve(content.size());
-
- content.move_to(Point::new(padding.left, padding.top));
- content.align(
- Alignment::from(horizontal_alignment),
- Alignment::from(vertical_alignment),
- size,
- );
-
- layout::Node::with_children(size.pad(padding), vec![content])
+ layout::positioned(
+ &limits.max_width(max_width).max_height(max_height),
+ width,
+ height,
+ padding,
+ |limits| layout_content(&limits.loose()),
+ |content, size| {
+ content.align(
+ Alignment::from(horizontal_alignment),
+ Alignment::from(vertical_alignment),
+ size,
+ )
+ },
+ )
}
/// Draws the background of a [`Container`] given its [`Appearance`] and its `bounds`.
diff --git a/widget/src/helpers.rs b/widget/src/helpers.rs
index 115198fb..498dd76c 100644
--- a/widget/src/helpers.rs
+++ b/widget/src/helpers.rs
@@ -34,7 +34,7 @@ macro_rules! column {
$crate::Column::new()
);
($($x:expr),+ $(,)?) => (
- $crate::Column::with_children(vec![$($crate::core::Element::from($x)),+])
+ $crate::Column::with_children([$($crate::core::Element::from($x)),+])
);
}
@@ -47,7 +47,7 @@ macro_rules! row {
$crate::Row::new()
);
($($x:expr),+ $(,)?) => (
- $crate::Row::with_children(vec![$($crate::core::Element::from($x)),+])
+ $crate::Row::with_children([$($crate::core::Element::from($x)),+])
);
}
@@ -65,9 +65,12 @@ where
}
/// Creates a new [`Column`] with the given children.
-pub fn column<Message, Renderer>(
- children: Vec<Element<'_, Message, Renderer>>,
-) -> Column<'_, Message, Renderer> {
+pub fn column<'a, Message, Renderer>(
+ children: impl IntoIterator<Item = Element<'a, Message, Renderer>>,
+) -> Column<'a, Message, Renderer>
+where
+ Renderer: core::Renderer,
+{
Column::with_children(children)
}
@@ -77,6 +80,7 @@ pub fn keyed_column<'a, Key, Message, Renderer>(
) -> keyed::Column<'a, Key, Message, Renderer>
where
Key: Copy + PartialEq,
+ Renderer: core::Renderer,
{
keyed::Column::with_children(children)
}
@@ -84,9 +88,12 @@ where
/// Creates a new [`Row`] with the given children.
///
/// [`Row`]: crate::Row
-pub fn row<Message, Renderer>(
- children: Vec<Element<'_, Message, Renderer>>,
-) -> Row<'_, Message, Renderer> {
+pub fn row<'a, Message, Renderer>(
+ children: impl IntoIterator<Item = Element<'a, Message, Renderer>>,
+) -> Row<'a, Message, Renderer>
+where
+ Renderer: core::Renderer,
+{
Row::with_children(children)
}
@@ -264,7 +271,7 @@ pub fn pick_list<'a, Message, Renderer, T>(
on_selected: impl Fn(T) -> Message + 'a,
) -> PickList<'a, T, Message, Renderer>
where
- T: ToString + Eq + 'static,
+ T: ToString + PartialEq + 'static,
[T]: ToOwned<Owned = Vec<T>>,
Renderer: core::text::Renderer,
Renderer::Theme: pick_list::StyleSheet
diff --git a/widget/src/image.rs b/widget/src/image.rs
index 67699102..e906ac13 100644
--- a/widget/src/image.rs
+++ b/widget/src/image.rs
@@ -99,7 +99,7 @@ where
};
// 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(width, height, image_size);
// The uncropped size of the image when fit to the bounds above
let full_size = content_fit.fit(image_size, raw_size);
@@ -164,12 +164,11 @@ where
Renderer: image::Renderer<Handle = Handle>,
Handle: Clone + Hash,
{
- 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(
diff --git a/widget/src/image/viewer.rs b/widget/src/image/viewer.rs
index 68015ba8..98080577 100644
--- a/widget/src/image/viewer.rs
+++ b/widget/src/image/viewer.rs
@@ -97,12 +97,11 @@ where
tree::State::new(State::new())
}
- 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(
@@ -113,10 +112,11 @@ where
) -> layout::Node {
let Size { width, height } = renderer.dimensions(&self.handle);
- let mut size = limits
- .width(self.width)
- .height(self.height)
- .resolve(Size::new(width as f32, height as f32));
+ let mut size = limits.resolve(
+ self.width,
+ self.height,
+ Size::new(width as f32, height as f32),
+ );
let expansion_size = if height > width {
self.width
diff --git a/widget/src/keyed/column.rs b/widget/src/keyed/column.rs
index 0ef82407..7f05a81e 100644
--- a/widget/src/keyed/column.rs
+++ b/widget/src/keyed/column.rs
@@ -8,7 +8,7 @@ use crate::core::widget::tree::{self, Tree};
use crate::core::widget::Operation;
use crate::core::{
Alignment, Clipboard, Element, Layout, Length, Padding, Pixels, Rectangle,
- Shell, Widget,
+ Shell, Size, Widget,
};
/// A container that distributes its contents vertically.
@@ -30,26 +30,10 @@ where
impl<'a, Key, Message, Renderer> Column<'a, Key, Message, Renderer>
where
Key: Copy + PartialEq,
+ Renderer: crate::core::Renderer,
{
/// Creates an empty [`Column`].
pub fn new() -> Self {
- Self::with_children(Vec::new())
- }
-
- /// Creates a [`Column`] with the given elements.
- pub fn with_children(
- children: impl IntoIterator<Item = (Key, Element<'a, Message, Renderer>)>,
- ) -> Self {
- let (keys, children) = children.into_iter().fold(
- (Vec::new(), Vec::new()),
- |(mut keys, mut children), (key, child)| {
- keys.push(key);
- children.push(child);
-
- (keys, children)
- },
- );
-
Column {
spacing: 0.0,
padding: Padding::ZERO,
@@ -57,11 +41,20 @@ where
height: Length::Shrink,
max_width: f32::INFINITY,
align_items: Alignment::Start,
- keys,
- children,
+ keys: Vec::new(),
+ children: Vec::new(),
}
}
+ /// Creates a [`Column`] with the given elements.
+ pub fn with_children(
+ children: impl IntoIterator<Item = (Key, Element<'a, Message, Renderer>)>,
+ ) -> Self {
+ children
+ .into_iter()
+ .fold(Self::new(), |column, (key, child)| column.push(key, child))
+ }
+
/// Sets the vertical spacing _between_ elements.
///
/// Custom margins per element do not exist in iced. You should use this
@@ -108,8 +101,19 @@ where
key: Key,
child: impl Into<Element<'a, Message, Renderer>>,
) -> Self {
+ let child = child.into();
+ let size = child.as_widget().size_hint();
+
+ if size.width.is_fill() {
+ self.width = Length::Fill;
+ }
+
+ if size.height.is_fill() {
+ self.height = Length::Fill;
+ }
+
self.keys.push(key);
- self.children.push(child.into());
+ self.children.push(child);
self
}
}
@@ -117,6 +121,7 @@ where
impl<'a, Key, Message, Renderer> Default for Column<'a, Key, Message, Renderer>
where
Key: Copy + PartialEq,
+ Renderer: crate::core::Renderer,
{
fn default() -> Self {
Self::new()
@@ -173,12 +178,11 @@ where
}
}
- 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(
@@ -196,6 +200,8 @@ where
layout::flex::Axis::Vertical,
renderer,
&limits,
+ self.width,
+ self.height,
self.padding,
self.spacing,
self.align_items,
diff --git a/widget/src/lazy.rs b/widget/src/lazy.rs
index 167a055d..e9edbb4c 100644
--- a/widget/src/lazy.rs
+++ b/widget/src/lazy.rs
@@ -142,12 +142,15 @@ where
}
}
- fn width(&self) -> Length {
- self.with_element(|element| element.as_widget().width())
+ fn size(&self) -> Size<Length> {
+ self.with_element(|element| element.as_widget().size())
}
- fn height(&self) -> Length {
- self.with_element(|element| element.as_widget().height())
+ fn size_hint(&self) -> Size<Length> {
+ Size {
+ width: Length::Shrink,
+ height: Length::Shrink,
+ }
}
fn layout(
diff --git a/widget/src/lazy/component.rs b/widget/src/lazy/component.rs
index ad0c3823..3684e0c9 100644
--- a/widget/src/lazy/component.rs
+++ b/widget/src/lazy/component.rs
@@ -244,12 +244,15 @@ where
self.rebuild_element_if_necessary();
}
- fn width(&self) -> Length {
- self.with_element(|element| element.as_widget().width())
+ fn size(&self) -> Size<Length> {
+ self.with_element(|element| element.as_widget().size())
}
- fn height(&self) -> Length {
- self.with_element(|element| element.as_widget().height())
+ fn size_hint(&self) -> Size<Length> {
+ Size {
+ width: Length::Shrink,
+ height: Length::Shrink,
+ }
}
fn layout(
diff --git a/widget/src/lazy/helpers.rs b/widget/src/lazy/helpers.rs
index 8ca9cb86..5dc60d52 100644
--- a/widget/src/lazy/helpers.rs
+++ b/widget/src/lazy/helpers.rs
@@ -6,6 +6,7 @@ use std::hash::Hash;
/// Creates a new [`Lazy`] widget with the given data `Dependency` and a
/// closure that can turn this data into a widget tree.
+#[cfg(feature = "lazy")]
pub fn lazy<'a, Message, Renderer, Dependency, View>(
dependency: Dependency,
view: impl Fn(&Dependency) -> View + 'a,
@@ -19,6 +20,7 @@ where
/// Turns an implementor of [`Component`] into an [`Element`] that can be
/// embedded in any application.
+#[cfg(feature = "lazy")]
pub fn component<'a, C, Message, Renderer>(
component: C,
) -> Element<'a, Message, Renderer>
@@ -37,6 +39,7 @@ where
/// The `view` closure will be provided with the current [`Size`] of
/// the [`Responsive`] widget and, therefore, can be used to build the
/// contents of the widget in a responsive way.
+#[cfg(feature = "lazy")]
pub fn responsive<'a, Message, Renderer>(
f: impl Fn(Size) -> Element<'a, Message, Renderer> + 'a,
) -> Responsive<'a, Message, Renderer>
diff --git a/widget/src/lazy/responsive.rs b/widget/src/lazy/responsive.rs
index 86d37b6c..1df0866f 100644
--- a/widget/src/lazy/responsive.rs
+++ b/widget/src/lazy/responsive.rs
@@ -135,12 +135,11 @@ where
})
}
- fn width(&self) -> Length {
- Length::Fill
- }
-
- fn height(&self) -> Length {
- Length::Fill
+ fn size(&self) -> Size<Length> {
+ Size {
+ width: Length::Fill,
+ height: Length::Fill,
+ }
}
fn layout(
diff --git a/widget/src/mouse_area.rs b/widget/src/mouse_area.rs
index 3a5b01a3..87cac3a7 100644
--- a/widget/src/mouse_area.rs
+++ b/widget/src/mouse_area.rs
@@ -8,7 +8,7 @@ use crate::core::renderer;
use crate::core::touch;
use crate::core::widget::{tree, Operation, Tree};
use crate::core::{
- Clipboard, Element, Layout, Length, Rectangle, Shell, Widget,
+ Clipboard, Element, Layout, Length, Rectangle, Shell, Size, Widget,
};
/// Emit messages on mouse events.
@@ -110,12 +110,8 @@ where
tree.diff_children(std::slice::from_ref(&self.content));
}
- fn width(&self) -> Length {
- self.content.as_widget().width()
- }
-
- fn height(&self) -> Length {
- self.content.as_widget().height()
+ fn size(&self) -> Size<Length> {
+ self.content.as_widget().size()
}
fn layout(
diff --git a/widget/src/overlay/menu.rs b/widget/src/overlay/menu.rs
index e45b44ae..f83eebea 100644
--- a/widget/src/overlay/menu.rs
+++ b/widget/src/overlay/menu.rs
@@ -254,15 +254,14 @@ where
)
.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 {
position + Vector::new(0.0, self.target_height)
} else {
- position - Vector::new(0.0, node.size().height)
- });
-
- node
+ position - Vector::new(0.0, size.height)
+ })
}
fn on_event(
@@ -343,12 +342,11 @@ where
Renderer: text::Renderer,
Renderer::Theme: StyleSheet,
{
- fn width(&self) -> Length {
- Length::Fill
- }
-
- fn height(&self) -> Length {
- Length::Shrink
+ fn size(&self) -> Size<Length> {
+ Size {
+ width: Length::Fill,
+ height: Length::Shrink,
+ }
}
fn layout(
@@ -359,7 +357,6 @@ where
) -> layout::Node {
use std::f32;
- let limits = limits.width(Length::Fill).height(Length::Shrink);
let text_size =
self.text_size.unwrap_or_else(|| renderer.default_size());
@@ -372,7 +369,7 @@ where
* self.options.len() as f32,
);
- limits.resolve(intrinsic)
+ limits.resolve(Length::Fill, Length::Shrink, intrinsic)
};
layout::Node::new(size)
diff --git a/widget/src/pane_grid.rs b/widget/src/pane_grid.rs
index 2d25a543..cf1f0455 100644
--- a/widget/src/pane_grid.rs
+++ b/widget/src/pane_grid.rs
@@ -265,12 +265,11 @@ where
}
}
- 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(
@@ -490,8 +489,7 @@ pub fn layout<Renderer, T>(
&layout::Limits,
) -> layout::Node,
) -> layout::Node {
- let limits = limits.width(width).height(height);
- let size = limits.resolve(Size::ZERO);
+ let size = limits.resolve(width, height, Size::ZERO);
let regions = node.pane_regions(spacing, size);
let children = contents
@@ -500,16 +498,14 @@ pub fn layout<Renderer, T>(
let region = regions.get(&pane)?;
let size = Size::new(region.width, region.height);
- let mut node = layout_content(
+ let node = layout_content(
content,
tree,
renderer,
&layout::Limits::new(size, size),
);
- node.move_to(Point::new(region.x, region.y));
-
- Some(node)
+ Some(node.move_to(Point::new(region.x, region.y)))
})
.collect();
@@ -531,6 +527,8 @@ pub fn update<'a, Message, T: Draggable>(
on_drag: &Option<Box<dyn Fn(DragEvent) -> Message + 'a>>,
on_resize: &Option<(f32, Box<dyn Fn(ResizeEvent) -> Message + 'a>)>,
) -> event::Status {
+ const DRAG_DEADBAND_DISTANCE: f32 = 10.0;
+
let mut event_status = event::Status::Ignored;
match event {
@@ -572,7 +570,6 @@ pub fn update<'a, Message, T: Draggable>(
shell,
contents,
on_click,
- on_drag,
);
}
}
@@ -584,7 +581,6 @@ pub fn update<'a, Message, T: Draggable>(
shell,
contents,
on_click,
- on_drag,
);
}
}
@@ -637,7 +633,49 @@ pub fn update<'a, Message, T: Draggable>(
}
Event::Mouse(mouse::Event::CursorMoved { .. })
| Event::Touch(touch::Event::FingerMoved { .. }) => {
- if let Some((_, on_resize)) = on_resize {
+ if let Some((_, origin)) = action.clicked_pane() {
+ if let Some(on_drag) = &on_drag {
+ let bounds = layout.bounds();
+
+ if let Some(cursor_position) = cursor.position_over(bounds)
+ {
+ let mut clicked_region = contents
+ .zip(layout.children())
+ .filter(|(_, layout)| {
+ layout.bounds().contains(cursor_position)
+ });
+
+ if let Some(((pane, content), layout)) =
+ clicked_region.next()
+ {
+ if content
+ .can_be_dragged_at(layout, cursor_position)
+ {
+ let pane_position = layout.position();
+
+ let new_origin = cursor_position
+ - Vector::new(
+ pane_position.x,
+ pane_position.y,
+ );
+
+ if new_origin.distance(origin)
+ > DRAG_DEADBAND_DISTANCE
+ {
+ *action = state::Action::Dragging {
+ pane,
+ origin,
+ };
+
+ shell.publish(on_drag(DragEvent::Picked {
+ pane,
+ }));
+ }
+ }
+ }
+ }
+ }
+ } else if let Some((_, on_resize)) = on_resize {
if let Some((split, _)) = action.picked_split() {
let bounds = layout.bounds();
@@ -712,7 +750,6 @@ fn click_pane<'a, Message, T>(
shell: &mut Shell<'_, Message>,
contents: impl Iterator<Item = (Pane, T)>,
on_click: &Option<Box<dyn Fn(Pane) -> Message + 'a>>,
- on_drag: &Option<Box<dyn Fn(DragEvent) -> Message + 'a>>,
) where
T: Draggable,
{
@@ -720,23 +757,15 @@ fn click_pane<'a, Message, T>(
.zip(layout.children())
.filter(|(_, layout)| layout.bounds().contains(cursor_position));
- if let Some(((pane, content), layout)) = clicked_region.next() {
+ if let Some(((pane, _), layout)) = clicked_region.next() {
if let Some(on_click) = &on_click {
shell.publish(on_click(pane));
}
- if let Some(on_drag) = &on_drag {
- if content.can_be_dragged_at(layout, cursor_position) {
- let pane_position = layout.position();
-
- let origin = cursor_position
- - Vector::new(pane_position.x, pane_position.y);
-
- *action = state::Action::Dragging { pane, origin };
-
- shell.publish(on_drag(DragEvent::Picked { pane }));
- }
- }
+ let pane_position = layout.position();
+ let origin =
+ cursor_position - Vector::new(pane_position.x, pane_position.y);
+ *action = state::Action::Clicking { pane, origin };
}
}
@@ -749,7 +778,7 @@ pub fn mouse_interaction(
spacing: f32,
resize_leeway: Option<f32>,
) -> Option<mouse::Interaction> {
- if action.picked_pane().is_some() {
+ if action.clicked_pane().is_some() || action.picked_pane().is_some() {
return Some(mouse::Interaction::Grabbing);
}
diff --git a/widget/src/pane_grid/content.rs b/widget/src/pane_grid/content.rs
index 826ea663..ee00f186 100644
--- a/widget/src/pane_grid/content.rs
+++ b/widget/src/pane_grid/content.rs
@@ -165,7 +165,7 @@ where
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],
renderer,
&layout::Limits::new(
@@ -177,11 +177,12 @@ where
),
);
- body_layout.move_to(Point::new(0.0, title_bar_size.height));
-
layout::Node::with_children(
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 {
self.body.as_widget().layout(
diff --git a/widget/src/pane_grid/state.rs b/widget/src/pane_grid/state.rs
index 481cd770..5d1fe254 100644
--- a/widget/src/pane_grid/state.rs
+++ b/widget/src/pane_grid/state.rs
@@ -403,6 +403,15 @@ pub enum Action {
///
/// [`PaneGrid`]: super::PaneGrid
Idle,
+ /// A [`Pane`] in the [`PaneGrid`] is being clicked.
+ ///
+ /// [`PaneGrid`]: super::PaneGrid
+ Clicking {
+ /// The [`Pane`] being clicked.
+ pane: Pane,
+ /// The starting [`Point`] of the click interaction.
+ origin: Point,
+ },
/// A [`Pane`] in the [`PaneGrid`] is being dragged.
///
/// [`PaneGrid`]: super::PaneGrid
@@ -432,6 +441,14 @@ impl Action {
}
}
+ /// Returns the current [`Pane`] that is being clicked, if any.
+ pub fn clicked_pane(&self) -> Option<(Pane, Point)> {
+ match *self {
+ Action::Clicking { pane, origin, .. } => Some((pane, origin)),
+ _ => None,
+ }
+ }
+
/// Returns the current [`Split`] that is being dragged, if any.
pub fn picked_split(&self) -> Option<(Split, Axis)> {
match *self {
diff --git a/widget/src/pane_grid/title_bar.rs b/widget/src/pane_grid/title_bar.rs
index f4dbb6b1..eb21b743 100644
--- a/widget/src/pane_grid/title_bar.rs
+++ b/widget/src/pane_grid/title_bar.rs
@@ -217,7 +217,7 @@ where
renderer: &Renderer,
limits: &layout::Limits,
) -> layout::Node {
- let limits = limits.pad(self.padding);
+ let limits = limits.shrink(self.padding);
let max_size = limits.max();
let title_layout = self.content.as_widget().layout(
@@ -228,8 +228,8 @@ where
let title_size = title_layout.size();
- let mut node = if let Some(controls) = &self.controls {
- let mut controls_layout = controls.as_widget().layout(
+ let node = if let Some(controls) = &self.controls {
+ let controls_layout = controls.as_widget().layout(
&mut tree.children[1],
renderer,
&layout::Limits::new(Size::ZERO, max_size),
@@ -240,11 +240,13 @@ where
let height = title_size.height.max(controls_size.height);
- controls_layout.move_to(Point::new(space_before_controls, 0.0));
-
layout::Node::with_children(
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 {
layout::Node::with_children(
@@ -253,9 +255,7 @@ where
)
};
- node.move_to(Point::new(self.padding.left, self.padding.top));
-
- layout::Node::with_children(node.size().pad(self.padding), vec![node])
+ layout::Node::container(node, self.padding)
}
pub(crate) fn operate(
diff --git a/widget/src/pick_list.rs b/widget/src/pick_list.rs
index 022ca8d9..2e3aab6f 100644
--- a/widget/src/pick_list.rs
+++ b/widget/src/pick_list.rs
@@ -45,7 +45,7 @@ where
impl<'a, T: 'a, Message, Renderer> PickList<'a, T, Message, Renderer>
where
- T: ToString + Eq,
+ T: ToString + PartialEq,
[T]: ToOwned<Owned = Vec<T>>,
Renderer: text::Renderer,
Renderer::Theme: StyleSheet
@@ -145,7 +145,7 @@ where
impl<'a, T: 'a, Message, Renderer> Widget<Message, Renderer>
for PickList<'a, T, Message, Renderer>
where
- T: Clone + ToString + Eq + 'static,
+ T: Clone + ToString + PartialEq + 'static,
[T]: ToOwned<Owned = Vec<T>>,
Message: 'a,
Renderer: text::Renderer + 'a,
@@ -164,12 +164,11 @@ where
tree::State::new(State::<Renderer::Paragraph>::new())
}
- fn width(&self) -> Length {
- self.width
- }
-
- fn height(&self) -> Length {
- Length::Shrink
+ fn size(&self) -> Size<Length> {
+ Size {
+ width: self.width,
+ height: Length::Shrink,
+ }
}
fn layout(
@@ -282,7 +281,7 @@ where
impl<'a, T: 'a, Message, Renderer> From<PickList<'a, T, Message, Renderer>>
for Element<'a, Message, Renderer>
where
- T: Clone + ToString + Eq + 'static,
+ T: Clone + ToString + PartialEq + 'static,
[T]: ToOwned<Owned = Vec<T>>,
Message: 'a,
Renderer: text::Renderer + 'a,
@@ -393,7 +392,6 @@ where
{
use std::f32;
- let limits = limits.width(width).height(Length::Shrink).pad(padding);
let font = font.unwrap_or_else(|| renderer.default_font());
let text_size = text_size.unwrap_or_else(|| renderer.default_size());
@@ -451,7 +449,11 @@ where
f32::from(text_line_height.to_absolute(text_size)),
);
- limits.resolve(intrinsic).pad(padding)
+ limits
+ .width(width)
+ .shrink(padding)
+ .resolve(width, Length::Shrink, intrinsic)
+ .expand(padding)
};
layout::Node::new(size)
diff --git a/widget/src/progress_bar.rs b/widget/src/progress_bar.rs
index 07de72d5..15f1277b 100644
--- a/widget/src/progress_bar.rs
+++ b/widget/src/progress_bar.rs
@@ -85,12 +85,11 @@ where
Renderer: crate::core::Renderer,
Renderer::Theme: StyleSheet,
{
- fn width(&self) -> Length {
- self.width
- }
-
- fn height(&self) -> Length {
- self.height.unwrap_or(Length::Fixed(Self::DEFAULT_HEIGHT))
+ fn size(&self) -> Size<Length> {
+ Size {
+ width: self.width,
+ height: self.height.unwrap_or(Length::Fixed(Self::DEFAULT_HEIGHT)),
+ }
}
fn layout(
@@ -99,13 +98,11 @@ where
_renderer: &Renderer,
limits: &layout::Limits,
) -> layout::Node {
- let limits = limits
- .width(self.width)
- .height(self.height.unwrap_or(Length::Fixed(Self::DEFAULT_HEIGHT)));
-
- let size = limits.resolve(Size::ZERO);
-
- layout::Node::new(size)
+ layout::atomic(
+ limits,
+ self.width,
+ self.height.unwrap_or(Length::Fixed(Self::DEFAULT_HEIGHT)),
+ )
}
fn draw(
diff --git a/widget/src/qr_code.rs b/widget/src/qr_code.rs
index 1dc4da7f..a229eb59 100644
--- a/widget/src/qr_code.rs
+++ b/widget/src/qr_code.rs
@@ -50,12 +50,11 @@ impl<'a> QRCode<'a> {
}
impl<'a, Message, Theme> Widget<Message, Renderer<Theme>> for QRCode<'a> {
- fn width(&self) -> Length {
- Length::Shrink
- }
-
- fn height(&self) -> Length {
- Length::Shrink
+ fn size(&self) -> Size<Length> {
+ Size {
+ width: Length::Shrink,
+ height: Length::Shrink,
+ }
}
fn layout(
diff --git a/widget/src/radio.rs b/widget/src/radio.rs
index ae2365dd..f91b20b1 100644
--- a/widget/src/radio.rs
+++ b/widget/src/radio.rs
@@ -201,12 +201,11 @@ where
tree::State::new(widget::text::State::<Renderer::Paragraph>::default())
}
- fn width(&self) -> Length {
- self.width
- }
-
- fn height(&self) -> Length {
- Length::Shrink
+ fn size(&self) -> Size<Length> {
+ Size {
+ width: self.width,
+ height: Length::Shrink,
+ }
}
fn layout(
diff --git a/widget/src/row.rs b/widget/src/row.rs
index d52b8c43..90fd2926 100644
--- a/widget/src/row.rs
+++ b/widget/src/row.rs
@@ -7,7 +7,7 @@ use crate::core::renderer;
use crate::core::widget::{Operation, Tree};
use crate::core::{
Alignment, Clipboard, Element, Length, Padding, Pixels, Rectangle, Shell,
- Widget,
+ Size, Widget,
};
/// A container that distributes its contents horizontally.
@@ -21,26 +21,29 @@ pub struct Row<'a, Message, Renderer = crate::Renderer> {
children: Vec<Element<'a, Message, Renderer>>,
}
-impl<'a, Message, Renderer> Row<'a, Message, Renderer> {
+impl<'a, Message, Renderer> Row<'a, Message, Renderer>
+where
+ Renderer: crate::core::Renderer,
+{
/// Creates an empty [`Row`].
pub fn new() -> Self {
- Self::with_children(Vec::new())
- }
-
- /// Creates a [`Row`] with the given elements.
- pub fn with_children(
- children: Vec<Element<'a, Message, Renderer>>,
- ) -> Self {
Row {
spacing: 0.0,
padding: Padding::ZERO,
width: Length::Shrink,
height: Length::Shrink,
align_items: Alignment::Start,
- children,
+ children: Vec::new(),
}
}
+ /// Creates a [`Row`] with the given elements.
+ pub fn with_children(
+ children: impl IntoIterator<Item = Element<'a, Message, Renderer>>,
+ ) -> Self {
+ children.into_iter().fold(Self::new(), Self::push)
+ }
+
/// Sets the horizontal spacing _between_ elements.
///
/// Custom margins per element do not exist in iced. You should use this
@@ -80,12 +83,26 @@ impl<'a, Message, Renderer> Row<'a, Message, Renderer> {
mut self,
child: impl Into<Element<'a, Message, Renderer>>,
) -> Self {
- self.children.push(child.into());
+ let child = child.into();
+ let size = child.as_widget().size_hint();
+
+ if size.width.is_fill() {
+ self.width = Length::Fill;
+ }
+
+ if size.height.is_fill() {
+ self.height = Length::Fill;
+ }
+
+ self.children.push(child);
self
}
}
-impl<'a, Message, Renderer> Default for Row<'a, Message, Renderer> {
+impl<'a, Message, Renderer> Default for Row<'a, Message, Renderer>
+where
+ Renderer: crate::core::Renderer,
+{
fn default() -> Self {
Self::new()
}
@@ -104,12 +121,11 @@ where
tree.diff_children(&self.children);
}
- 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(
@@ -118,12 +134,12 @@ where
renderer: &Renderer,
limits: &layout::Limits,
) -> layout::Node {
- let limits = limits.width(self.width).height(self.height);
-
layout::flex::resolve(
layout::flex::Axis::Horizontal,
renderer,
- &limits,
+ limits,
+ self.width,
+ self.height,
self.padding,
self.spacing,
self.align_items,
diff --git a/widget/src/rule.rs b/widget/src/rule.rs
index b5c5fa55..cded9cb1 100644
--- a/widget/src/rule.rs
+++ b/widget/src/rule.rs
@@ -62,12 +62,11 @@ where
Renderer: crate::core::Renderer,
Renderer::Theme: StyleSheet,
{
- 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(
@@ -76,9 +75,7 @@ where
_renderer: &Renderer,
limits: &layout::Limits,
) -> layout::Node {
- let limits = limits.width(self.width).height(self.height);
-
- layout::Node::new(limits.resolve(Size::ZERO))
+ layout::atomic(limits, self.width, self.height)
}
fn draw(
diff --git a/widget/src/scrollable.rs b/widget/src/scrollable.rs
index 49aed2f0..70db490a 100644
--- a/widget/src/scrollable.rs
+++ b/widget/src/scrollable.rs
@@ -220,12 +220,11 @@ where
tree.diff_children(std::slice::from_ref(&self.content));
}
- 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(
@@ -470,28 +469,25 @@ pub fn layout<Renderer>(
direction: &Direction,
layout_content: impl FnOnce(&Renderer, &layout::Limits) -> layout::Node,
) -> layout::Node {
- let limits = limits.width(width).height(height);
-
- let child_limits = layout::Limits::new(
- Size::new(limits.min().width, limits.min().height),
- Size::new(
- if direction.horizontal().is_some() {
- f32::INFINITY
- } else {
- limits.max().width
- },
- if direction.vertical().is_some() {
- f32::MAX
- } else {
- limits.max().height
- },
- ),
- );
-
- let content = layout_content(renderer, &child_limits);
- let size = limits.resolve(content.size());
+ layout::contained(limits, width, height, |limits| {
+ let child_limits = layout::Limits::new(
+ Size::new(limits.min().width, limits.min().height),
+ Size::new(
+ if direction.horizontal().is_some() {
+ f32::INFINITY
+ } else {
+ limits.max().width
+ },
+ if direction.vertical().is_some() {
+ f32::MAX
+ } else {
+ limits.max().height
+ },
+ ),
+ );
- layout::Node::with_children(size, vec![content])
+ layout_content(renderer, &child_limits)
+ })
}
/// Processes an [`Event`] and updates the [`State`] of a [`Scrollable`]
diff --git a/widget/src/shader.rs b/widget/src/shader.rs
index 8e334693..16b68c55 100644
--- a/widget/src/shader.rs
+++ b/widget/src/shader.rs
@@ -70,12 +70,11 @@ where
tree::State::new(P::State::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(
@@ -84,10 +83,7 @@ where
_renderer: &Renderer,
limits: &layout::Limits,
) -> layout::Node {
- let limits = limits.width(self.width).height(self.height);
- let size = limits.resolve(Size::ZERO);
-
- layout::Node::new(size)
+ layout::atomic(limits, self.width, self.height)
}
fn on_event(
diff --git a/widget/src/slider.rs b/widget/src/slider.rs
index ac0982c8..1bc94661 100644
--- a/widget/src/slider.rs
+++ b/widget/src/slider.rs
@@ -159,12 +159,11 @@ where
tree::State::new(State::new())
}
- fn width(&self) -> Length {
- self.width
- }
-
- fn height(&self) -> Length {
- Length::Shrink
+ fn size(&self) -> Size<Length> {
+ Size {
+ width: self.width,
+ height: Length::Shrink,
+ }
}
fn layout(
@@ -173,10 +172,7 @@ where
_renderer: &Renderer,
limits: &layout::Limits,
) -> layout::Node {
- let limits = limits.width(self.width).height(self.height);
- let size = limits.resolve(Size::ZERO);
-
- layout::Node::new(size)
+ layout::atomic(limits, self.width, self.height)
}
fn on_event(
diff --git a/widget/src/space.rs b/widget/src/space.rs
index e5a8f169..eef990d1 100644
--- a/widget/src/space.rs
+++ b/widget/src/space.rs
@@ -45,12 +45,11 @@ impl<Message, Renderer> Widget<Message, Renderer> for Space
where
Renderer: core::Renderer,
{
- 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(
@@ -59,9 +58,7 @@ where
_renderer: &Renderer,
limits: &layout::Limits,
) -> layout::Node {
- let limits = limits.width(self.width).height(self.height);
-
- layout::Node::new(limits.resolve(Size::ZERO))
+ layout::atomic(limits, self.width, self.height)
}
fn draw(
diff --git a/widget/src/svg.rs b/widget/src/svg.rs
index 2d01d1ab..830abb0f 100644
--- a/widget/src/svg.rs
+++ b/widget/src/svg.rs
@@ -96,12 +96,11 @@ where
Renderer: svg::Renderer,
Renderer::Theme: iced_style::svg::StyleSheet,
{
- 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(
@@ -115,10 +114,7 @@ where
let image_size = Size::new(width as f32, height as f32);
// The size to be available to the widget prior to `Shrink`ing
- let raw_size = limits
- .width(self.width)
- .height(self.height)
- .resolve(image_size);
+ let raw_size = limits.resolve(self.width, self.height, image_size);
// The uncropped size of the image when fit to the bounds above
let full_size = self.content_fit.fit(image_size, raw_size);
diff --git a/widget/src/text_editor.rs b/widget/src/text_editor.rs
index 3c0a1806..b95a45e4 100644
--- a/widget/src/text_editor.rs
+++ b/widget/src/text_editor.rs
@@ -9,7 +9,7 @@ use crate::core::text::highlighter::{self, Highlighter};
use crate::core::text::{self, LineHeight};
use crate::core::widget::{self, Widget};
use crate::core::{
- Clipboard, Color, Element, Length, Padding, Pixels, Rectangle, Shell,
+ Clipboard, Color, Element, Length, Padding, Pixels, Rectangle, Shell, Size,
Vector,
};
@@ -316,12 +316,11 @@ where
})
}
- 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(
@@ -350,7 +349,7 @@ where
}
internal.editor.update(
- limits.pad(self.padding).max(),
+ limits.shrink(self.padding).max(),
self.font.unwrap_or_else(|| renderer.default_font()),
self.text_size.unwrap_or_else(|| renderer.default_size()),
self.line_height,
diff --git a/widget/src/text_input.rs b/widget/src/text_input.rs
index 8ba4bd71..8d28e8ee 100644
--- a/widget/src/text_input.rs
+++ b/widget/src/text_input.rs
@@ -283,12 +283,11 @@ where
}
}
- fn width(&self) -> Length {
- self.width
- }
-
- fn height(&self) -> Length {
- Length::Shrink
+ fn size(&self) -> Size<Length> {
+ Size {
+ width: self.width,
+ height: Length::Shrink,
+ }
}
fn layout(
@@ -506,14 +505,11 @@ where
{
let font = font.unwrap_or_else(|| renderer.default_font());
let text_size = size.unwrap_or_else(|| renderer.default_size());
-
let padding = padding.fit(Size::ZERO, limits.max());
- let limits = limits
- .width(width)
- .pad(padding)
- .height(line_height.to_absolute(text_size));
+ let height = line_height.to_absolute(text_size);
- let text_bounds = limits.resolve(Size::ZERO);
+ let limits = limits.width(width).shrink(padding);
+ let text_bounds = limits.resolve(width, height, Size::ZERO);
let placeholder_text = Text {
font,
@@ -552,41 +548,41 @@ where
let icon_width = state.icon.min_width();
- let mut text_node = layout::Node::new(
- text_bounds - Size::new(icon_width + icon.spacing, 0.0),
- );
-
- 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(
+ let (text_position, icon_position) = match icon.side {
+ Side::Left => (
+ Point::new(
padding.left + icon_width + icon.spacing,
padding.top,
- ));
-
- icon_node.move_to(Point::new(padding.left, padding.top));
- }
- Side::Right => {
- text_node.move_to(Point::new(padding.left, padding.top));
-
- icon_node.move_to(Point::new(
+ ),
+ Point::new(padding.left, padding.top),
+ ),
+ Side::Right => (
+ Point::new(padding.left, padding.top),
+ Point::new(
padding.left + text_bounds.width - icon_width,
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(
- text_bounds.pad(padding),
+ text_bounds.expand(padding),
vec![text_node, icon_node],
)
} else {
- let mut text = layout::Node::new(text_bounds);
- text.move_to(Point::new(padding.left, padding.top));
+ let text = layout::Node::new(text_bounds)
+ .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])
}
}
@@ -1192,31 +1188,39 @@ pub fn draw<Renderer>(
(None, 0.0)
};
- if let Some((cursor, color)) = cursor {
- renderer.with_translation(Vector::new(-offset, 0.0), |renderer| {
- renderer.fill_quad(cursor, color);
- });
+ let draw = |renderer: &mut Renderer, viewport| {
+ if let Some((cursor, color)) = cursor {
+ renderer.with_translation(Vector::new(-offset, 0.0), |renderer| {
+ renderer.fill_quad(cursor, color);
+ });
+ } else {
+ renderer.with_translation(Vector::ZERO, |_| {});
+ }
+
+ renderer.fill_paragraph(
+ if text.is_empty() {
+ &state.placeholder
+ } else {
+ &state.value
+ },
+ Point::new(text_bounds.x, text_bounds.center_y())
+ - Vector::new(offset, 0.0),
+ if text.is_empty() {
+ theme.placeholder_color(style)
+ } else if is_disabled {
+ theme.disabled_color(style)
+ } else {
+ theme.value_color(style)
+ },
+ viewport,
+ );
+ };
+
+ if cursor.is_some() {
+ renderer.with_layer(text_bounds, |renderer| draw(renderer, *viewport));
} else {
- renderer.with_translation(Vector::ZERO, |_| {});
+ draw(renderer, text_bounds);
}
-
- renderer.fill_paragraph(
- if text.is_empty() {
- &state.placeholder
- } else {
- &state.value
- },
- Point::new(text_bounds.x, text_bounds.center_y())
- - Vector::new(offset, 0.0),
- if text.is_empty() {
- theme.placeholder_color(style)
- } else if is_disabled {
- theme.disabled_color(style)
- } else {
- theme.value_color(style)
- },
- text_bounds,
- );
}
/// Computes the current [`mouse::Interaction`] of the [`TextInput`].
diff --git a/widget/src/toggler.rs b/widget/src/toggler.rs
index d8723080..941159ea 100644
--- a/widget/src/toggler.rs
+++ b/widget/src/toggler.rs
@@ -168,12 +168,11 @@ where
tree::State::new(widget::text::State::<Renderer::Paragraph>::default())
}
- fn width(&self) -> Length {
- self.width
- }
-
- fn height(&self) -> Length {
- Length::Shrink
+ fn size(&self) -> Size<Length> {
+ Size {
+ width: self.width,
+ height: Length::Shrink,
+ }
}
fn layout(
diff --git a/widget/src/tooltip.rs b/widget/src/tooltip.rs
index 9e102c56..d09a9255 100644
--- a/widget/src/tooltip.rs
+++ b/widget/src/tooltip.rs
@@ -64,6 +64,12 @@ where
self
}
+ /// Sets the [`text::Shaping`] strategy of the [`Tooltip`].
+ pub fn text_shaping(mut self, shaping: text::Shaping) -> Self {
+ self.tooltip = self.tooltip.shaping(shaping);
+ self
+ }
+
/// Sets the font of the [`Tooltip`].
///
/// [`Font`]: Renderer::Font
@@ -125,12 +131,8 @@ where
widget::tree::Tag::of::<State>()
}
- fn width(&self) -> Length {
- self.content.as_widget().width()
- }
-
- fn height(&self) -> Length {
- self.content.as_widget().height()
+ fn size(&self) -> Size<Length> {
+ self.content.as_widget().size()
}
fn layout(
@@ -347,7 +349,7 @@ where
.then(|| viewport.size())
.unwrap_or(Size::INFINITY),
)
- .pad(Padding::new(self.padding)),
+ .shrink(Padding::new(self.padding)),
);
let text_bounds = text_layout.bounds();
diff --git a/widget/src/vertical_slider.rs b/widget/src/vertical_slider.rs
index 01d3359c..a3029d76 100644
--- a/widget/src/vertical_slider.rs
+++ b/widget/src/vertical_slider.rs
@@ -156,12 +156,11 @@ where
tree::State::new(State::new())
}
- fn width(&self) -> Length {
- Length::Shrink
- }
-
- fn height(&self) -> Length {
- self.height
+ fn size(&self) -> Size<Length> {
+ Size {
+ width: Length::Shrink,
+ height: self.height,
+ }
}
fn layout(
@@ -170,10 +169,7 @@ where
_renderer: &Renderer,
limits: &layout::Limits,
) -> layout::Node {
- let limits = limits.width(self.width).height(self.height);
- let size = limits.resolve(Size::ZERO);
-
- layout::Node::new(size)
+ layout::atomic(limits, self.width, self.height)
}
fn on_event(