diff --git a/core/src/element.rs b/core/src/element.rs index a3f60127..349aecb6 100644 --- a/core/src/element.rs +++ b/core/src/element.rs @@ -9,7 +9,7 @@ use crate::{ Vector, Widget, }; -use std::borrow::Borrow; +use std::borrow::{Borrow, BorrowMut}; /// A generic [`Widget`]. /// @@ -239,6 +239,37 @@ impl<'a, Message, Theme, Renderer> } } +impl<'a, Message, Theme, Renderer> + Borrow + 'a> + for &mut Element<'a, Message, Theme, Renderer> +{ + fn borrow(&self) -> &(dyn Widget + 'a) { + self.widget.borrow() + } +} + +impl<'a, Message, Theme, Renderer> + BorrowMut + 'a> + for Element<'a, Message, Theme, Renderer> +{ + fn borrow_mut( + &mut self, + ) -> &mut (dyn Widget + 'a) { + self.widget.borrow_mut() + } +} + +impl<'a, Message, Theme, Renderer> + BorrowMut + 'a> + for &mut Element<'a, Message, Theme, Renderer> +{ + fn borrow_mut( + &mut self, + ) -> &mut (dyn Widget + 'a) { + self.widget.borrow_mut() + } +} + struct Map<'a, A, B, Theme, Renderer> { widget: Box + 'a>, mapper: Box B + 'a>, @@ -278,7 +309,7 @@ where self.widget.children() } - fn diff(&self, tree: &mut Tree) { + fn diff(&mut self, tree: &mut Tree) { self.widget.diff(tree); } @@ -291,7 +322,7 @@ where } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, @@ -300,7 +331,7 @@ where } fn operate( - &self, + &mut self, tree: &mut Tree, layout: Layout<'_>, renderer: &Renderer, @@ -421,12 +452,12 @@ where self.element.widget.children() } - fn diff(&self, tree: &mut Tree) { + fn diff(&mut self, tree: &mut Tree) { self.element.widget.diff(tree); } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, @@ -435,7 +466,7 @@ where } fn operate( - &self, + &mut self, state: &mut Tree, layout: Layout<'_>, renderer: &Renderer, @@ -554,7 +585,7 @@ where } fn layout( - &self, + &mut self, _tree: &mut Tree, _renderer: &Renderer, _limits: &layout::Limits, diff --git a/core/src/layout/flex.rs b/core/src/layout/flex.rs index f178a993..3f28f0d9 100644 --- a/core/src/layout/flex.rs +++ b/core/src/layout/flex.rs @@ -68,7 +68,7 @@ pub fn resolve( padding: Padding, spacing: f32, align_items: Alignment, - items: &[Element<'_, Message, Theme, Renderer>], + items: &mut [Element<'_, Message, Theme, Renderer>], trees: &mut [widget::Tree], ) -> Node where @@ -95,7 +95,8 @@ where // We lay out non-fluid elements in the main axis. // If we need to compress the cross axis, then we skip any of these elements // that are also fluid in the cross axis. - for (i, (child, tree)) in items.iter().zip(trees.iter_mut()).enumerate() { + for (i, (child, tree)) in items.iter_mut().zip(trees.iter_mut()).enumerate() + { let (fill_main_factor, fill_cross_factor) = { let size = child.as_widget().size(); @@ -117,7 +118,7 @@ where Limits::new(Size::ZERO, Size::new(max_width, max_height)); let layout = - child.as_widget().layout(tree, renderer, &child_limits); + child.as_widget_mut().layout(tree, renderer, &child_limits); let size = layout.size(); available -= axis.main(size); @@ -141,7 +142,8 @@ where // We can defer the layout of any elements that have a fixed size in the main axis, // allowing them to use the cross calculations of the next pass. if cross_compress && some_fill_cross { - for (i, (child, tree)) in items.iter().zip(trees.iter_mut()).enumerate() + for (i, (child, tree)) in + items.iter_mut().zip(trees.iter_mut()).enumerate() { let (main_size, cross_size) = { let size = child.as_widget().size(); @@ -161,7 +163,7 @@ where Limits::new(Size::ZERO, Size::new(max_width, max_height)); let layout = - child.as_widget().layout(tree, renderer, &child_limits); + child.as_widget_mut().layout(tree, renderer, &child_limits); let size = layout.size(); available -= axis.main(size); @@ -186,7 +188,8 @@ where // THIRD PASS // We lay out the elements that are fluid in the main axis. // We use the remaining space to evenly allocate space based on fill factors. - for (i, (child, tree)) in items.iter().zip(trees.iter_mut()).enumerate() { + for (i, (child, tree)) in items.iter_mut().zip(trees.iter_mut()).enumerate() + { let (fill_main_factor, fill_cross_factor) = { let size = child.as_widget().size(); @@ -225,7 +228,7 @@ where ); let layout = - child.as_widget().layout(tree, renderer, &child_limits); + child.as_widget_mut().layout(tree, renderer, &child_limits); cross = cross.max(axis.cross(layout.size())); nodes[i] = layout; @@ -237,7 +240,7 @@ where // These are elements that must be compressed in their cross axis and have // a fixed length in the main axis. if cross_compress && some_fill_cross { - for (i, (child, tree)) in items.iter().zip(trees).enumerate() { + for (i, (child, tree)) in items.iter_mut().zip(trees).enumerate() { let (main_size, cross_size) = { let size = child.as_widget().size(); @@ -255,7 +258,7 @@ where Limits::new(Size::ZERO, Size::new(max_width, max_height)); let layout = - child.as_widget().layout(tree, renderer, &child_limits); + child.as_widget_mut().layout(tree, renderer, &child_limits); let size = layout.size(); cross = cross.max(axis.cross(size)); diff --git a/core/src/layout/limits.rs b/core/src/layout/limits.rs index 1aaed526..2bff8a55 100644 --- a/core/src/layout/limits.rs +++ b/core/src/layout/limits.rs @@ -6,6 +6,7 @@ use crate::{Length, Size}; pub struct Limits { min: Size, max: Size, + compress: Size, } impl Limits { @@ -13,11 +14,16 @@ impl Limits { pub const NONE: Limits = Limits { min: Size::ZERO, max: Size::INFINITE, + compress: Size::new(false, false), }; /// Creates new [`Limits`] with the given minimum and maximum [`Size`]. pub const fn new(min: Size, max: Size) -> Limits { - Limits { min, max } + Limits { + min, + max, + compress: Size::new(false, false), + } } /// Returns the minimum [`Size`] of the [`Limits`]. @@ -33,13 +39,17 @@ impl Limits { /// Applies a width constraint to the current [`Limits`]. pub fn width(mut self, width: impl Into) -> Limits { match width.into() { - Length::Shrink | Length::Fill | Length::FillPortion(_) => {} + Length::Shrink => { + self.compress.width = true; + } 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.compress.width = false; } + Length::Fill | Length::FillPortion(_) => {} } self @@ -48,14 +58,18 @@ impl Limits { /// Applies a height constraint to the current [`Limits`]. pub fn height(mut self, height: impl Into) -> Limits { match height.into() { - Length::Shrink | Length::Fill | Length::FillPortion(_) => {} + Length::Shrink => { + self.compress.height = true; + } 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.compress.height = false; } + Length::Fill | Length::FillPortion(_) => {} } self @@ -103,7 +117,11 @@ impl Limits { (self.max().height - size.height).max(0.0), ); - Limits { min, max } + Limits { + min, + max, + compress: self.compress, + } } /// Removes the minimum width constraint for the current [`Limits`]. @@ -111,6 +129,7 @@ impl Limits { Limits { min: Size::ZERO, max: self.max, + compress: self.compress, } } @@ -124,21 +143,23 @@ impl Limits { intrinsic_size: Size, ) -> Size { let width = match width.into() { - Length::Fill | Length::FillPortion(_) => self.max.width, + Length::Fill | Length::FillPortion(_) if !self.compress.width => { + 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) - } + _ => intrinsic_size.width.min(self.max.width).max(self.min.width), }; let height = match height.into() { - Length::Fill | Length::FillPortion(_) => self.max.height, + Length::Fill | Length::FillPortion(_) if !self.compress.height => { + self.max.height + } Length::Fixed(amount) => { amount.min(self.max.height).max(self.min.height) } - Length::Shrink => intrinsic_size + _ => intrinsic_size .height .min(self.max.height) .max(self.min.height), diff --git a/core/src/widget.rs b/core/src/widget.rs index 655c010b..9316dba1 100644 --- a/core/src/widget.rs +++ b/core/src/widget.rs @@ -58,7 +58,7 @@ where /// This [`layout::Node`] is used by the runtime to compute the [`Layout`] of the /// user interface. fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, @@ -96,13 +96,13 @@ where } /// Reconciles the [`Widget`] with the provided [`Tree`]. - fn diff(&self, tree: &mut Tree) { + fn diff(&mut self, tree: &mut Tree) { tree.children.clear(); } /// Applies an [`Operation`] to the [`Widget`]. fn operate( - &self, + &mut self, _state: &mut Tree, _layout: Layout<'_>, _renderer: &Renderer, diff --git a/core/src/widget/text.rs b/core/src/widget/text.rs index 24966211..c1f1e87e 100644 --- a/core/src/widget/text.rs +++ b/core/src/widget/text.rs @@ -207,7 +207,7 @@ where } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, @@ -245,7 +245,7 @@ where } fn operate( - &self, + &mut self, _state: &mut Tree, layout: Layout<'_>, _renderer: &Renderer, diff --git a/core/src/widget/tree.rs b/core/src/widget/tree.rs index 2600cfc6..20b55360 100644 --- a/core/src/widget/tree.rs +++ b/core/src/widget/tree.rs @@ -2,7 +2,7 @@ use crate::Widget; use std::any::{self, Any}; -use std::borrow::Borrow; +use std::borrow::{Borrow, BorrowMut}; use std::fmt; /// A persistent state widget tree. @@ -56,12 +56,12 @@ impl Tree { /// [`Widget::diff`]: crate::Widget::diff pub fn diff<'a, Message, Theme, Renderer>( &mut self, - new: impl Borrow + 'a>, + mut new: impl BorrowMut + 'a>, ) where Renderer: crate::Renderer, { - if self.tag == new.borrow().tag() { - new.borrow().diff(self); + if self.tag == new.borrow_mut().tag() { + new.borrow_mut().diff(self); } else { *self = Self::new(new); } @@ -70,13 +70,15 @@ impl Tree { /// Reconciles the children of the tree with the provided list of widgets. pub fn diff_children<'a, Message, Theme, Renderer>( &mut self, - new_children: &[impl Borrow + 'a>], + new_children: &mut [impl BorrowMut< + dyn Widget + 'a, + >], ) where Renderer: crate::Renderer, { self.diff_children_custom( new_children, - |tree, widget| tree.diff(widget.borrow()), + |tree, widget| tree.diff(widget.borrow_mut()), |widget| Self::new(widget.borrow()), ); } @@ -85,8 +87,8 @@ impl Tree { /// logic both for diffing and creating new widget state. pub fn diff_children_custom( &mut self, - new_children: &[T], - diff: impl Fn(&mut Tree, &T), + new_children: &mut [T], + diff: impl Fn(&mut Tree, &mut T), new_state: impl Fn(&T) -> Self, ) { if self.children.len() > new_children.len() { @@ -94,7 +96,7 @@ impl Tree { } for (child_state, new) in - self.children.iter_mut().zip(new_children.iter()) + self.children.iter_mut().zip(new_children.iter_mut()) { diff(child_state, new); } @@ -114,8 +116,8 @@ impl Tree { /// `maybe_changed` closure. pub fn diff_children_custom_with_search( current_children: &mut Vec, - new_children: &[T], - diff: impl Fn(&mut Tree, &T), + new_children: &mut [T], + diff: impl Fn(&mut Tree, &mut T), maybe_changed: impl Fn(usize) -> bool, new_state: impl Fn(&T) -> Tree, ) { @@ -183,7 +185,7 @@ pub fn diff_children_custom_with_search( // TODO: Merge loop with extend logic (?) for (child_state, new) in - current_children.iter_mut().zip(new_children.iter()) + current_children.iter_mut().zip(new_children.iter_mut()) { diff(child_state, new); } diff --git a/examples/custom_quad/src/main.rs b/examples/custom_quad/src/main.rs index 4ea58511..fdc3c0c2 100644 --- a/examples/custom_quad/src/main.rs +++ b/examples/custom_quad/src/main.rs @@ -175,7 +175,7 @@ mod quad { } fn layout( - &self, + &mut self, _tree: &mut widget::Tree, _renderer: &Renderer, _limits: &layout::Limits, diff --git a/examples/custom_widget/src/main.rs b/examples/custom_widget/src/main.rs index e5db6139..c44775be 100644 --- a/examples/custom_widget/src/main.rs +++ b/examples/custom_widget/src/main.rs @@ -33,7 +33,7 @@ mod circle { } fn layout( - &self, + &mut self, _tree: &mut widget::Tree, _renderer: &Renderer, _limits: &layout::Limits, diff --git a/examples/geometry/src/main.rs b/examples/geometry/src/main.rs index f1025675..1334a52f 100644 --- a/examples/geometry/src/main.rs +++ b/examples/geometry/src/main.rs @@ -27,7 +27,7 @@ mod rainbow { } fn layout( - &self, + &mut self, _tree: &mut widget::Tree, _renderer: &Renderer, limits: &layout::Limits, diff --git a/examples/loading_spinners/src/circular.rs b/examples/loading_spinners/src/circular.rs index 24293138..c5d6df6f 100644 --- a/examples/loading_spinners/src/circular.rs +++ b/examples/loading_spinners/src/circular.rs @@ -253,7 +253,7 @@ where } fn layout( - &self, + &mut self, _tree: &mut Tree, _renderer: &Renderer, limits: &layout::Limits, diff --git a/examples/loading_spinners/src/linear.rs b/examples/loading_spinners/src/linear.rs index a6713c7a..e9b4a20e 100644 --- a/examples/loading_spinners/src/linear.rs +++ b/examples/loading_spinners/src/linear.rs @@ -167,7 +167,7 @@ where } fn layout( - &self, + &mut self, _tree: &mut Tree, _renderer: &Renderer, limits: &layout::Limits, diff --git a/examples/loupe/src/main.rs b/examples/loupe/src/main.rs index c141e758..ebd7a44f 100644 --- a/examples/loupe/src/main.rs +++ b/examples/loupe/src/main.rs @@ -87,8 +87,8 @@ mod loupe { self.content.as_widget().children() } - fn diff(&self, tree: &mut widget::Tree) { - self.content.as_widget().diff(tree); + fn diff(&mut self, tree: &mut widget::Tree) { + self.content.as_widget_mut().diff(tree); } fn size(&self) -> Size { @@ -96,12 +96,12 @@ mod loupe { } fn layout( - &self, + &mut self, tree: &mut widget::Tree, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { - self.content.as_widget().layout(tree, renderer, limits) + self.content.as_widget_mut().layout(tree, renderer, limits) } fn draw( diff --git a/examples/pane_grid/Cargo.toml b/examples/pane_grid/Cargo.toml index fd3e133c..c1756a65 100644 --- a/examples/pane_grid/Cargo.toml +++ b/examples/pane_grid/Cargo.toml @@ -7,4 +7,4 @@ publish = false [dependencies] iced.workspace = true -iced.features = ["debug", "lazy"] +iced.features = ["debug"] diff --git a/examples/toast/src/main.rs b/examples/toast/src/main.rs index b4e93a32..d1be0c09 100644 --- a/examples/toast/src/main.rs +++ b/examples/toast/src/main.rs @@ -287,12 +287,12 @@ mod toast { } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { - self.content.as_widget().layout( + self.content.as_widget_mut().layout( &mut tree.children[0], renderer, limits, @@ -314,7 +314,7 @@ mod toast { .collect() } - fn diff(&self, tree: &mut Tree) { + fn diff(&mut self, tree: &mut Tree) { let instants = tree.state.downcast_mut::>>(); // Invalidating removed instants to None allows us to remove @@ -336,21 +336,21 @@ mod toast { } tree.diff_children( - &std::iter::once(&self.content) - .chain(self.toasts.iter()) + &mut std::iter::once(&mut self.content) + .chain(self.toasts.iter_mut()) .collect::>(), ); } fn operate( - &self, + &mut self, state: &mut Tree, layout: Layout<'_>, renderer: &Renderer, operation: &mut dyn Operation, ) { operation.container(None, layout.bounds(), &mut |operation| { - self.content.as_widget().operate( + self.content.as_widget_mut().operate( &mut state.children[0], layout, renderer, @@ -582,12 +582,12 @@ mod toast { ) { operation.container(None, layout.bounds(), &mut |operation| { self.toasts - .iter() + .iter_mut() .zip(self.state.iter_mut()) .zip(layout.children()) .for_each(|((child, state), layout)| { child - .as_widget() + .as_widget_mut() .operate(state, layout, renderer, operation); }); }); diff --git a/runtime/src/user_interface.rs b/runtime/src/user_interface.rs index 482ffafa..6e32d10f 100644 --- a/runtime/src/user_interface.rs +++ b/runtime/src/user_interface.rs @@ -97,12 +97,12 @@ where cache: Cache, renderer: &mut Renderer, ) -> Self { - let root = root.into(); + let mut root = root.into(); let Cache { mut state } = cache; - state.diff(root.as_widget()); + state.diff(root.as_widget_mut()); - let base = root.as_widget().layout( + let base = root.as_widget_mut().layout( &mut state, renderer, &layout::Limits::new(Size::ZERO, bounds), @@ -234,7 +234,7 @@ where if shell.is_layout_invalid() { drop(maybe_overlay); - self.base = self.root.as_widget().layout( + self.base = self.root.as_widget_mut().layout( &mut self.state, renderer, &layout::Limits::new(Size::ZERO, self.bounds), @@ -335,7 +335,7 @@ where input_method.merge(shell.input_method()); shell.revalidate_layout(|| { - self.base = self.root.as_widget().layout( + self.base = self.root.as_widget_mut().layout( &mut self.state, renderer, &layout::Limits::new(Size::ZERO, self.bounds), @@ -539,7 +539,7 @@ where ) { let viewport = Rectangle::with_size(self.bounds); - self.root.as_widget().operate( + self.root.as_widget_mut().operate( &mut self.state, Layout::new(&self.base), renderer, diff --git a/widget/src/button.rs b/widget/src/button.rs index ac4a27cb..2ae1508b 100644 --- a/widget/src/button.rs +++ b/widget/src/button.rs @@ -223,8 +223,8 @@ where vec![Tree::new(&self.content)] } - fn diff(&self, tree: &mut Tree) { - tree.diff_children(std::slice::from_ref(&self.content)); + fn diff(&mut self, tree: &mut Tree) { + tree.diff_children(std::slice::from_mut(&mut self.content)); } fn size(&self) -> Size { @@ -235,7 +235,7 @@ where } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, @@ -246,7 +246,7 @@ where self.height, self.padding, |limits| { - self.content.as_widget().layout( + self.content.as_widget_mut().layout( &mut tree.children[0], renderer, limits, @@ -256,14 +256,14 @@ where } fn operate( - &self, + &mut self, tree: &mut Tree, layout: Layout<'_>, renderer: &Renderer, operation: &mut dyn Operation, ) { operation.container(None, layout.bounds(), &mut |operation| { - self.content.as_widget().operate( + self.content.as_widget_mut().operate( &mut tree.children[0], layout.children().next().unwrap(), renderer, diff --git a/widget/src/canvas.rs b/widget/src/canvas.rs index 50acade5..b1b6ac13 100644 --- a/widget/src/canvas.rs +++ b/widget/src/canvas.rs @@ -207,7 +207,7 @@ where } fn layout( - &self, + &mut self, _tree: &mut Tree, _renderer: &Renderer, limits: &layout::Limits, diff --git a/widget/src/checkbox.rs b/widget/src/checkbox.rs index 42ef89fd..32e81538 100644 --- a/widget/src/checkbox.rs +++ b/widget/src/checkbox.rs @@ -269,7 +269,7 @@ where } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, @@ -447,7 +447,7 @@ where } fn operate( - &self, + &mut self, _state: &mut Tree, layout: Layout<'_>, _renderer: &Renderer, diff --git a/widget/src/column.rs b/widget/src/column.rs index 6c126048..bcbbe49e 100644 --- a/widget/src/column.rs +++ b/widget/src/column.rs @@ -194,8 +194,8 @@ where self.children.iter().map(Tree::new).collect() } - fn diff(&self, tree: &mut Tree) { - tree.diff_children(&self.children); + fn diff(&mut self, tree: &mut Tree) { + tree.diff_children(&mut self.children); } fn size(&self) -> Size { @@ -206,7 +206,7 @@ where } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, @@ -222,13 +222,13 @@ where self.padding, self.spacing, self.align, - &self.children, + &mut self.children, &mut tree.children, ) } fn operate( - &self, + &mut self, tree: &mut Tree, layout: Layout<'_>, renderer: &Renderer, @@ -236,12 +236,12 @@ where ) { operation.container(None, layout.bounds(), &mut |operation| { self.children - .iter() + .iter_mut() .zip(&mut tree.children) .zip(layout.children()) .for_each(|((child, state), layout)| { child - .as_widget() + .as_widget_mut() .operate(state, layout, renderer, operation); }); }); diff --git a/widget/src/combo_box.rs b/widget/src/combo_box.rs index 581a4fcd..86533c3a 100644 --- a/widget/src/combo_box.rs +++ b/widget/src/combo_box.rs @@ -471,7 +471,7 @@ where } fn layout( - &self, + &mut self, tree: &mut widget::Tree, renderer: &Renderer, limits: &layout::Limits, @@ -509,7 +509,7 @@ where vec![widget::Tree::new(&self.text_input as &dyn Widget<_, _, _>)] } - fn diff(&self, _tree: &mut widget::Tree) { + fn diff(&mut self, _tree: &mut widget::Tree) { // do nothing so the children don't get cleared } diff --git a/widget/src/container.rs b/widget/src/container.rs index ab332b32..97502b17 100644 --- a/widget/src/container.rs +++ b/widget/src/container.rs @@ -247,8 +247,8 @@ where self.content.as_widget().children() } - fn diff(&self, tree: &mut Tree) { - self.content.as_widget().diff(tree); + fn diff(&mut self, tree: &mut Tree) { + self.content.as_widget_mut().diff(tree); } fn size(&self) -> Size { @@ -259,7 +259,7 @@ where } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, @@ -273,12 +273,14 @@ where self.padding, self.horizontal_alignment, self.vertical_alignment, - |limits| self.content.as_widget().layout(tree, renderer, limits), + |limits| { + self.content.as_widget_mut().layout(tree, renderer, limits) + }, ) } fn operate( - &self, + &mut self, tree: &mut Tree, layout: Layout<'_>, renderer: &Renderer, @@ -288,7 +290,7 @@ where self.id.as_ref().map(|id| &id.0), layout.bounds(), &mut |operation| { - self.content.as_widget().operate( + self.content.as_widget_mut().operate( tree, layout.children().next().unwrap(), renderer, diff --git a/widget/src/float.rs b/widget/src/float.rs index b61b4319..a7eaf5bb 100644 --- a/widget/src/float.rs +++ b/widget/src/float.rs @@ -103,8 +103,8 @@ where self.content.as_widget().children() } - fn diff(&self, tree: &mut widget::Tree) { - self.content.as_widget().diff(tree); + fn diff(&mut self, tree: &mut widget::Tree) { + self.content.as_widget_mut().diff(tree); } fn size(&self) -> Size { @@ -116,12 +116,12 @@ where } fn layout( - &self, + &mut self, tree: &mut widget::Tree, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { - self.content.as_widget().layout(tree, renderer, limits) + self.content.as_widget_mut().layout(tree, renderer, limits) } fn update( @@ -197,14 +197,14 @@ where } fn operate( - &self, + &mut self, state: &mut widget::Tree, layout: Layout<'_>, renderer: &Renderer, operation: &mut dyn widget::Operation, ) { self.content - .as_widget() + .as_widget_mut() .operate(state, layout, renderer, operation); } diff --git a/widget/src/grid.rs b/widget/src/grid.rs index 4a08dc55..5bf2bf6b 100644 --- a/widget/src/grid.rs +++ b/widget/src/grid.rs @@ -158,8 +158,8 @@ where self.children.iter().map(Tree::new).collect() } - fn diff(&self, tree: &mut Tree) { - tree.diff_children(&self.children); + fn diff(&mut self, tree: &mut Tree) { + tree.diff_children(&mut self.children); } fn size(&self) -> Size { @@ -176,7 +176,7 @@ where } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, @@ -220,10 +220,10 @@ where let mut row_height = 0.0f32; for (i, (child, tree)) in - self.children.iter().zip(&mut tree.children).enumerate() + self.children.iter_mut().zip(&mut tree.children).enumerate() { let node = child - .as_widget() + .as_widget_mut() .layout(tree, renderer, &cell_limits) .move_to((x, y)); @@ -251,7 +251,7 @@ where } fn operate( - &self, + &mut self, tree: &mut Tree, layout: Layout<'_>, renderer: &Renderer, @@ -259,12 +259,12 @@ where ) { operation.container(None, layout.bounds(), &mut |operation| { self.children - .iter() + .iter_mut() .zip(&mut tree.children) .zip(layout.children()) .for_each(|((child, state), layout)| { child - .as_widget() + .as_widget_mut() .operate(state, layout, renderer, operation); }); }); diff --git a/widget/src/helpers.rs b/widget/src/helpers.rs index 6815c3fc..b1d29127 100644 --- a/widget/src/helpers.rs +++ b/widget/src/helpers.rs @@ -6,7 +6,7 @@ use crate::container::{self, Container}; use crate::core; use crate::core::widget::operation::{self, Operation}; use crate::core::window; -use crate::core::{Element, Length, Pixels, Widget}; +use crate::core::{Element, Length, Pixels, Size, Widget}; use crate::float::{self, Float}; use crate::keyed; use crate::overlay; @@ -25,7 +25,9 @@ use crate::text_input::{self, TextInput}; use crate::toggler::{self, Toggler}; use crate::tooltip::{self, Tooltip}; use crate::vertical_slider::{self, VerticalSlider}; -use crate::{Column, Grid, MouseArea, Pin, Row, Sensor, Space, Stack, Themer}; +use crate::{ + Column, Grid, MouseArea, Pin, Responsive, Row, Sensor, Space, Stack, Themer, +}; use std::borrow::Borrow; use std::ops::RangeInclusive; @@ -596,8 +598,8 @@ where self.content.as_widget().children() } - fn diff(&self, tree: &mut Tree) { - self.content.as_widget().diff(tree); + fn diff(&mut self, tree: &mut Tree) { + self.content.as_widget_mut().diff(tree); } fn size(&self) -> Size { @@ -609,12 +611,12 @@ where } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { - self.content.as_widget().layout(tree, renderer, limits) + self.content.as_widget_mut().layout(tree, renderer, limits) } fn draw( @@ -633,14 +635,14 @@ where } fn operate( - &self, + &mut self, state: &mut Tree, layout: Layout<'_>, renderer: &Renderer, operation: &mut dyn operation::Operation, ) { self.content - .as_widget() + .as_widget_mut() .operate(state, layout, renderer, operation); } @@ -759,8 +761,8 @@ where vec![Tree::new(&self.base), Tree::new(&self.top)] } - fn diff(&self, tree: &mut Tree) { - tree.diff_children(&[&self.base, &self.top]); + fn diff(&mut self, tree: &mut Tree) { + tree.diff_children(&mut [&mut self.base, &mut self.top]); } fn size(&self) -> Size { @@ -772,18 +774,18 @@ where } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { - let base = self.base.as_widget().layout( + let base = self.base.as_widget_mut().layout( &mut tree.children[0], renderer, limits, ); - let top = self.top.as_widget().layout( + let top = self.top.as_widget_mut().layout( &mut tree.children[1], renderer, &layout::Limits::new(Size::ZERO, base.size()), @@ -834,18 +836,20 @@ where } fn operate( - &self, + &mut self, tree: &mut Tree, layout: Layout<'_>, renderer: &Renderer, operation: &mut dyn operation::Operation, ) { - let children = [&self.base, &self.top] + let children = [&mut self.base, &mut self.top] .into_iter() .zip(layout.children().zip(&mut tree.children)); for (child, (layout, tree)) in children { - child.as_widget().operate(tree, layout, renderer, operation); + child + .as_widget_mut() + .operate(tree, layout, renderer, operation); } } @@ -2138,3 +2142,18 @@ where { Float::new(content) } + +/// Creates a new [`Responsive`] widget with a closure that produces its +/// contents. +/// +/// The `view` closure will receive the maximum available space for +/// the [`Responsive`] during layout. You can use this [`Size`] to +/// conditionally build the contents. +pub fn responsive<'a, Message, Theme, Renderer>( + f: impl Fn(Size) -> Element<'a, Message, Theme, Renderer> + 'a, +) -> Responsive<'a, Message, Theme, Renderer> +where + Renderer: core::Renderer, +{ + Responsive::new(f) +} diff --git a/widget/src/image.rs b/widget/src/image.rs index f8546b16..3b29e4f5 100644 --- a/widget/src/image.rs +++ b/widget/src/image.rs @@ -386,7 +386,7 @@ where } fn layout( - &self, + &mut self, _tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, diff --git a/widget/src/image/viewer.rs b/widget/src/image/viewer.rs index 811241a9..205f84d5 100644 --- a/widget/src/image/viewer.rs +++ b/widget/src/image/viewer.rs @@ -117,7 +117,7 @@ where } fn layout( - &self, + &mut self, _tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, diff --git a/widget/src/keyed/column.rs b/widget/src/keyed/column.rs index a774c239..907ae479 100644 --- a/widget/src/keyed/column.rs +++ b/widget/src/keyed/column.rs @@ -222,7 +222,7 @@ where self.children.iter().map(Tree::new).collect() } - fn diff(&self, tree: &mut Tree) { + fn diff(&mut self, tree: &mut Tree) { let Tree { state, children, .. } = tree; @@ -231,8 +231,8 @@ where tree::diff_children_custom_with_search( children, - &self.children, - |tree, child| child.as_widget().diff(tree), + &mut self.children, + |tree, child| child.as_widget_mut().diff(tree), |index| { self.keys.get(index).or_else(|| self.keys.last()).copied() != Some(state.keys[index]) @@ -253,7 +253,7 @@ where } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, @@ -272,13 +272,13 @@ where self.padding, self.spacing, self.align_items, - &self.children, + &mut self.children, &mut tree.children, ) } fn operate( - &self, + &mut self, tree: &mut Tree, layout: Layout<'_>, renderer: &Renderer, @@ -286,12 +286,12 @@ where ) { operation.container(None, layout.bounds(), &mut |operation| { self.children - .iter() + .iter_mut() .zip(&mut tree.children) .zip(layout.children()) .for_each(|((child, state), layout)| { child - .as_widget() + .as_widget_mut() .operate(state, layout, renderer, operation); }); }); diff --git a/widget/src/lazy.rs b/widget/src/lazy.rs index b538b460..b67ba56c 100644 --- a/widget/src/lazy.rs +++ b/widget/src/lazy.rs @@ -2,11 +2,9 @@ pub(crate) mod helpers; pub mod component; -pub mod responsive; #[allow(deprecated)] pub use component::Component; -pub use responsive::Responsive; mod cache; @@ -127,7 +125,7 @@ where self.with_element(|element| vec![Tree::new(element.as_widget())]) } - fn diff(&self, tree: &mut Tree) { + fn diff(&mut self, tree: &mut Tree) { let current = tree .state .downcast_mut::>(); @@ -146,8 +144,8 @@ where current.element = Rc::new(RefCell::new(Some(element))); (*self.element.borrow_mut()) = Some(current.element.clone()); - self.with_element(|element| { - tree.diff_children(std::slice::from_ref(&element.as_widget())); + self.with_element_mut(|element| { + tree.diff_children(std::slice::from_mut(element)); }); } else { (*self.element.borrow_mut()) = Some(current.element.clone()); @@ -166,27 +164,29 @@ where } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { - self.with_element(|element| { - element - .as_widget() - .layout(&mut tree.children[0], renderer, limits) + self.with_element_mut(|element| { + element.as_widget_mut().layout( + &mut tree.children[0], + renderer, + limits, + ) }) } fn operate( - &self, + &mut self, tree: &mut Tree, layout: Layout<'_>, renderer: &Renderer, operation: &mut dyn widget::Operation, ) { - self.with_element(|element| { - element.as_widget().operate( + self.with_element_mut(|element| { + element.as_widget_mut().operate( &mut tree.children[0], layout, renderer, diff --git a/widget/src/lazy/component.rs b/widget/src/lazy/component.rs index 8bd04d64..c40be4d1 100644 --- a/widget/src/lazy/component.rs +++ b/widget/src/lazy/component.rs @@ -147,13 +147,13 @@ where Renderer: renderer::Renderer, { fn diff_self(&self) { - self.with_element(|element| { + self.with_element_mut(|element| { self.tree .borrow_mut() .borrow_mut() .as_mut() .unwrap() - .diff_children(std::slice::from_ref(&element)); + .diff_children(std::slice::from_mut(element)); }); } @@ -279,7 +279,7 @@ where vec![] } - fn diff(&self, tree: &mut Tree) { + fn diff(&mut self, tree: &mut Tree) { let tree = tree.state.downcast_ref::>>>(); *self.tree.borrow_mut() = tree.clone(); self.rebuild_element_if_necessary(); @@ -299,15 +299,15 @@ where } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { let t = tree.state.downcast_mut::>>>(); - self.with_element(|element| { - element.as_widget().layout( + self.with_element_mut(|element| { + element.as_widget_mut().layout( &mut t.borrow_mut().as_mut().unwrap().children[0], renderer, limits, @@ -378,7 +378,7 @@ where } fn operate( - &self, + &mut self, tree: &mut Tree, layout: Layout<'_>, renderer: &Renderer, @@ -387,8 +387,8 @@ where self.rebuild_element_with_operation(layout, operation); let tree = tree.state.downcast_mut::>>>(); - self.with_element(|element| { - element.as_widget().operate( + self.with_element_mut(|element| { + element.as_widget_mut().operate( &mut tree.borrow_mut().as_mut().unwrap().children[0], layout, renderer, diff --git a/widget/src/lazy/helpers.rs b/widget/src/lazy/helpers.rs index 52e690ff..7e7601cb 100644 --- a/widget/src/lazy/helpers.rs +++ b/widget/src/lazy/helpers.rs @@ -1,10 +1,10 @@ -use crate::core::{self, Element, Size}; +use crate::core::{self, Element}; use crate::lazy::component; use std::hash::Hash; #[allow(deprecated)] -pub use crate::lazy::{Component, Lazy, Responsive}; +pub use crate::lazy::{Component, Lazy}; /// Creates a new [`Lazy`] widget with the given data `Dependency` and a /// closure that can turn this data into a widget tree. @@ -41,19 +41,3 @@ where { component::view(component) } - -/// Creates a new [`Responsive`] widget with a closure that produces its -/// contents. -/// -/// 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, Theme, Renderer>( - f: impl Fn(Size) -> Element<'a, Message, Theme, Renderer> + 'a, -) -> Responsive<'a, Message, Theme, Renderer> -where - Renderer: core::Renderer, -{ - Responsive::new(f) -} diff --git a/widget/src/lazy/responsive.rs b/widget/src/lazy/responsive.rs deleted file mode 100644 index 4e90a178..00000000 --- a/widget/src/lazy/responsive.rs +++ /dev/null @@ -1,461 +0,0 @@ -use crate::core::layout::{self, Layout}; -use crate::core::mouse; -use crate::core::overlay; -use crate::core::renderer; -use crate::core::widget; -use crate::core::widget::tree::{self, Tree}; -use crate::core::{ - self, Clipboard, Element, Event, Length, Point, Rectangle, Shell, Size, - Vector, Widget, -}; -use crate::horizontal_space; -use crate::runtime::overlay::Nested; - -use ouroboros::self_referencing; -use std::cell::{RefCell, RefMut}; -use std::marker::PhantomData; -use std::ops::Deref; - -/// A widget that is aware of its dimensions. -/// -/// A [`Responsive`] widget will always try to fill all the available space of -/// its parent. -#[cfg(feature = "lazy")] -#[allow(missing_debug_implementations)] -pub struct Responsive< - 'a, - Message, - Theme = crate::Theme, - Renderer = crate::Renderer, -> { - view: Box Element<'a, Message, Theme, Renderer> + 'a>, - content: RefCell>, -} - -impl<'a, Message, Theme, Renderer> Responsive<'a, Message, Theme, Renderer> -where - Renderer: core::Renderer, -{ - /// Creates a new [`Responsive`] widget with a closure that produces its - /// contents. - /// - /// 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. - pub fn new( - view: impl Fn(Size) -> Element<'a, Message, Theme, Renderer> + 'a, - ) -> Self { - Self { - view: Box::new(view), - content: RefCell::new(Content { - size: Size::ZERO, - layout: None, - is_layout_invalid: true, - element: Element::new(horizontal_space().width(0)), - }), - } - } -} - -struct Content<'a, Message, Theme, Renderer> { - size: Size, - layout: Option, - is_layout_invalid: bool, - element: Element<'a, Message, Theme, Renderer>, -} - -impl<'a, Message, Theme, Renderer> Content<'a, Message, Theme, Renderer> -where - Renderer: core::Renderer, -{ - fn layout(&mut self, tree: &mut Tree, renderer: &Renderer) { - if self.layout.is_none() || self.is_layout_invalid { - self.layout = Some(self.element.as_widget().layout( - tree, - renderer, - &layout::Limits::new(Size::ZERO, self.size), - )); - self.is_layout_invalid = false; - } - } - - fn update( - &mut self, - tree: &mut Tree, - new_size: Size, - view: &dyn Fn(Size) -> Element<'a, Message, Theme, Renderer>, - ) { - if self.size != new_size { - self.element = view(new_size); - self.size = new_size; - self.layout = None; - - tree.diff(&self.element); - } else { - let is_tree_empty = - tree.tag == tree::Tag::stateless() && tree.children.is_empty(); - - if is_tree_empty { - self.layout = None; - tree.diff(&self.element); - } - } - } - - fn resolve( - &mut self, - tree: &mut Tree, - renderer: R, - layout: Layout<'_>, - view: &dyn Fn(Size) -> Element<'a, Message, Theme, Renderer>, - f: impl FnOnce( - &mut Tree, - R, - Layout<'_>, - &mut Element<'a, Message, Theme, Renderer>, - ) -> T, - ) -> T - where - R: Deref, - { - self.update(tree, layout.bounds().size(), view); - self.layout(tree, renderer.deref()); - - let content_layout = Layout::with_offset( - layout.position() - Point::ORIGIN, - self.layout.as_ref().unwrap(), - ); - - f(tree, renderer, content_layout, &mut self.element) - } -} - -struct State { - tree: RefCell, -} - -impl Widget - for Responsive<'_, Message, Theme, Renderer> -where - Renderer: core::Renderer, -{ - fn tag(&self) -> tree::Tag { - tree::Tag::of::() - } - - fn state(&self) -> tree::State { - tree::State::new(State { - tree: RefCell::new(Tree::empty()), - }) - } - - fn size(&self) -> Size { - Size { - width: Length::Fill, - height: Length::Fill, - } - } - - fn layout( - &self, - _tree: &mut Tree, - _renderer: &Renderer, - limits: &layout::Limits, - ) -> layout::Node { - layout::Node::new(limits.max()) - } - - fn operate( - &self, - tree: &mut Tree, - layout: Layout<'_>, - renderer: &Renderer, - operation: &mut dyn widget::Operation, - ) { - let state = tree.state.downcast_mut::(); - let mut content = self.content.borrow_mut(); - - content.resolve( - &mut state.tree.borrow_mut(), - renderer, - layout, - &self.view, - |tree, renderer, layout, element| { - element - .as_widget() - .operate(tree, layout, renderer, operation); - }, - ); - } - - fn update( - &mut self, - tree: &mut Tree, - event: &Event, - layout: Layout<'_>, - cursor: mouse::Cursor, - renderer: &Renderer, - clipboard: &mut dyn Clipboard, - shell: &mut Shell<'_, Message>, - viewport: &Rectangle, - ) { - let state = tree.state.downcast_mut::(); - let mut content = self.content.borrow_mut(); - - let mut local_messages = vec![]; - let mut local_shell = Shell::new(&mut local_messages); - - content.resolve( - &mut state.tree.borrow_mut(), - renderer, - layout, - &self.view, - |tree, renderer, layout, element| { - element.as_widget_mut().update( - tree, - event, - layout, - cursor, - renderer, - clipboard, - &mut local_shell, - viewport, - ); - }, - ); - - if local_shell.is_layout_invalid() { - content.layout = None; - } - - shell.merge(local_shell, std::convert::identity); - } - - fn draw( - &self, - tree: &Tree, - renderer: &mut Renderer, - theme: &Theme, - style: &renderer::Style, - layout: Layout<'_>, - cursor: mouse::Cursor, - viewport: &Rectangle, - ) { - let state = tree.state.downcast_ref::(); - let mut content = self.content.borrow_mut(); - - content.resolve( - &mut state.tree.borrow_mut(), - renderer, - layout, - &self.view, - |tree, renderer, layout, element| { - element.as_widget().draw( - tree, renderer, theme, style, layout, cursor, viewport, - ); - }, - ); - } - - fn mouse_interaction( - &self, - tree: &Tree, - layout: Layout<'_>, - cursor: mouse::Cursor, - viewport: &Rectangle, - renderer: &Renderer, - ) -> mouse::Interaction { - let state = tree.state.downcast_ref::(); - let mut content = self.content.borrow_mut(); - - content.resolve( - &mut state.tree.borrow_mut(), - renderer, - layout, - &self.view, - |tree, renderer, layout, element| { - element - .as_widget() - .mouse_interaction(tree, layout, cursor, viewport, renderer) - }, - ) - } - - fn overlay<'b>( - &'b mut self, - tree: &'b mut Tree, - layout: Layout<'b>, - renderer: &Renderer, - viewport: &Rectangle, - translation: Vector, - ) -> Option> { - use std::ops::DerefMut; - - let state = tree.state.downcast_ref::(); - - let overlay = OverlayBuilder { - content: self.content.borrow_mut(), - tree: state.tree.borrow_mut(), - types: PhantomData, - overlay_builder: |content: &mut RefMut< - '_, - Content<'_, _, _, _>, - >, - tree| { - content.update(tree, layout.bounds().size(), &self.view); - content.layout(tree, renderer); - - let Content { - element, - layout: content_layout_node, - is_layout_invalid, - .. - } = content.deref_mut(); - - let content_layout = Layout::with_offset( - layout.bounds().position() - Point::ORIGIN, - content_layout_node.as_ref().unwrap(), - ); - - ( - element - .as_widget_mut() - .overlay( - tree, - content_layout, - renderer, - viewport, - translation, - ) - .map(|overlay| RefCell::new(Nested::new(overlay))), - is_layout_invalid, - ) - }, - } - .build(); - - if overlay.with_overlay(|(overlay, _layout)| overlay.is_some()) { - Some(overlay::Element::new(Box::new(overlay))) - } else { - None - } - } -} - -impl<'a, Message, Theme, Renderer> - From> - for Element<'a, Message, Theme, Renderer> -where - Message: 'a, - Theme: 'a, - Renderer: core::Renderer + 'a, -{ - fn from(responsive: Responsive<'a, Message, Theme, Renderer>) -> Self { - Self::new(responsive) - } -} - -#[self_referencing] -struct Overlay<'a, 'b, Message, Theme, Renderer> { - content: RefMut<'a, Content<'b, Message, Theme, Renderer>>, - tree: RefMut<'a, Tree>, - types: PhantomData, - - #[borrows(mut content, mut tree)] - #[not_covariant] - overlay: ( - Option>>, - &'this mut bool, - ), -} - -impl Overlay<'_, '_, Message, Theme, Renderer> { - fn with_overlay_maybe( - &self, - f: impl FnOnce(&mut Nested<'_, Message, Theme, Renderer>) -> T, - ) -> Option { - self.with_overlay(|(overlay, _layout)| { - overlay.as_ref().map(|nested| (f)(&mut nested.borrow_mut())) - }) - } - - fn with_overlay_mut_maybe( - &mut self, - f: impl FnOnce(&mut Nested<'_, Message, Theme, Renderer>) -> T, - ) -> Option { - self.with_overlay_mut(|(overlay, _layout)| { - overlay.as_mut().map(|nested| (f)(nested.get_mut())) - }) - } -} - -impl overlay::Overlay - for Overlay<'_, '_, Message, Theme, Renderer> -where - Renderer: core::Renderer, -{ - fn layout(&mut self, renderer: &Renderer, bounds: Size) -> layout::Node { - self.with_overlay_maybe(|overlay| overlay.layout(renderer, bounds)) - .unwrap_or_default() - } - - fn draw( - &self, - renderer: &mut Renderer, - theme: &Theme, - style: &renderer::Style, - layout: Layout<'_>, - cursor: mouse::Cursor, - ) { - let _ = self.with_overlay_maybe(|overlay| { - overlay.draw(renderer, theme, style, layout, cursor); - }); - } - - fn mouse_interaction( - &self, - layout: Layout<'_>, - cursor: mouse::Cursor, - renderer: &Renderer, - ) -> mouse::Interaction { - self.with_overlay_maybe(|overlay| { - overlay.mouse_interaction(layout, cursor, renderer) - }) - .unwrap_or_default() - } - - fn update( - &mut self, - event: &Event, - layout: Layout<'_>, - cursor: mouse::Cursor, - renderer: &Renderer, - clipboard: &mut dyn Clipboard, - shell: &mut Shell<'_, Message>, - ) { - let mut is_layout_invalid = false; - - let _ = self.with_overlay_mut_maybe(|overlay| { - overlay.update(event, layout, cursor, renderer, clipboard, shell); - - is_layout_invalid = shell.is_layout_invalid(); - }); - - if is_layout_invalid { - self.with_overlay_mut(|(_overlay, layout)| { - **layout = true; - }); - } - } - - fn operate( - &mut self, - layout: Layout<'_>, - renderer: &Renderer, - operation: &mut dyn widget::Operation, - ) { - let _ = self.with_overlay_mut_maybe(|overlay| { - overlay.operate(layout, renderer, operation); - }); - } -} diff --git a/widget/src/lib.rs b/widget/src/lib.rs index d08a92f9..3818c92f 100644 --- a/widget/src/lib.rs +++ b/widget/src/lib.rs @@ -12,6 +12,7 @@ mod action; mod column; mod mouse_area; mod pin; +mod responsive; mod space; mod stack; mod themer; @@ -78,6 +79,8 @@ pub use progress_bar::ProgressBar; #[doc(no_inline)] pub use radio::Radio; #[doc(no_inline)] +pub use responsive::Responsive; +#[doc(no_inline)] pub use row::Row; #[doc(no_inline)] pub use rule::Rule; diff --git a/widget/src/mouse_area.rs b/widget/src/mouse_area.rs index fefa68d5..e7ce47b5 100644 --- a/widget/src/mouse_area.rs +++ b/widget/src/mouse_area.rs @@ -181,8 +181,8 @@ where vec![Tree::new(&self.content)] } - fn diff(&self, tree: &mut Tree) { - tree.diff_children(std::slice::from_ref(&self.content)); + fn diff(&mut self, tree: &mut Tree) { + tree.diff_children(std::slice::from_mut(&mut self.content)); } fn size(&self) -> Size { @@ -190,24 +190,26 @@ where } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { - self.content - .as_widget() - .layout(&mut tree.children[0], renderer, limits) + self.content.as_widget_mut().layout( + &mut tree.children[0], + renderer, + limits, + ) } fn operate( - &self, + &mut self, tree: &mut Tree, layout: Layout<'_>, renderer: &Renderer, operation: &mut dyn Operation, ) { - self.content.as_widget().operate( + self.content.as_widget_mut().operate( &mut tree.children[0], layout, renderer, diff --git a/widget/src/overlay/menu.rs b/widget/src/overlay/menu.rs index 741dbf15..e84ae858 100644 --- a/widget/src/overlay/menu.rs +++ b/widget/src/overlay/menu.rs @@ -205,7 +205,7 @@ where class, } = menu; - let list = Scrollable::new(List { + let mut list = Scrollable::new(List { options, hovered_option, on_selected, @@ -218,7 +218,7 @@ where class, }); - state.tree.diff(&list as &dyn Widget<_, _, _>); + state.tree.diff(&mut list as &mut dyn Widget<_, _, _>); Self { position, @@ -369,7 +369,7 @@ where } fn layout( - &self, + &mut self, _tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, diff --git a/widget/src/pane_grid.rs b/widget/src/pane_grid.rs index 158c265b..3dd0c941 100644 --- a/widget/src/pane_grid.rs +++ b/widget/src/pane_grid.rs @@ -378,7 +378,7 @@ where self.contents.iter().map(Content::state).collect() } - fn diff(&self, tree: &mut Tree) { + fn diff(&mut self, tree: &mut Tree) { let Memory { order, .. } = tree.state.downcast_ref(); // `Pane` always increments and is iterated by Ord so new @@ -401,7 +401,7 @@ where }); tree.diff_children_custom( - &self.contents, + &mut self.contents, |state, content| content.diff(state), Content::state, ); @@ -418,7 +418,7 @@ where } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, @@ -432,20 +432,19 @@ where let children = self .panes - .iter() - .copied() - .zip(&self.contents) + .iter_mut() + .zip(&mut self.contents) .zip(tree.children.iter_mut()) .filter_map(|((pane, content), tree)| { if self .internal .maximized() - .is_some_and(|maximized| maximized != pane) + .is_some_and(|maximized| maximized != *pane) { return Some(layout::Node::new(Size::ZERO)); } - let region = regions.get(&pane)?; + let region = regions.get(pane)?; let size = Size::new(region.width, region.height); let node = content.layout( @@ -462,7 +461,7 @@ where } fn operate( - &self, + &mut self, tree: &mut Tree, layout: Layout<'_>, renderer: &Renderer, @@ -470,15 +469,14 @@ where ) { operation.container(None, layout.bounds(), &mut |operation| { self.panes - .iter() - .copied() - .zip(&self.contents) + .iter_mut() + .zip(&mut self.contents) .zip(&mut tree.children) .zip(layout.children()) .filter(|(((pane, _), _), _)| { self.internal .maximized() - .is_none_or(|maximized| *pane == maximized) + .is_none_or(|maximized| **pane == maximized) }) .for_each(|(((_, content), state), layout)| { content.operate(state, layout, renderer, operation); diff --git a/widget/src/pane_grid/content.rs b/widget/src/pane_grid/content.rs index 8800d13b..00f0d060 100644 --- a/widget/src/pane_grid/content.rs +++ b/widget/src/pane_grid/content.rs @@ -91,13 +91,13 @@ where } } - pub(super) fn diff(&self, tree: &mut Tree) { + pub(super) fn diff(&mut self, tree: &mut Tree) { if tree.children.len() == 2 { - if let Some(title_bar) = self.title_bar.as_ref() { + if let Some(title_bar) = self.title_bar.as_mut() { title_bar.diff(&mut tree.children[1]); } - tree.children[0].diff(&self.body); + tree.children[0].diff(&mut self.body); } else { *tree = self.state(); } @@ -165,12 +165,12 @@ where } pub(crate) fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { - if let Some(title_bar) = &self.title_bar { + if let Some(title_bar) = &mut self.title_bar { let max_size = limits.max(); let title_bar_layout = title_bar.layout( @@ -181,7 +181,7 @@ where let title_bar_size = title_bar_layout.size(); - let body_layout = self.body.as_widget().layout( + let body_layout = self.body.as_widget_mut().layout( &mut tree.children[0], renderer, &layout::Limits::new( @@ -201,7 +201,7 @@ where ], ) } else { - self.body.as_widget().layout( + self.body.as_widget_mut().layout( &mut tree.children[0], renderer, limits, @@ -210,13 +210,13 @@ where } pub(crate) fn operate( - &self, + &mut self, tree: &mut Tree, layout: Layout<'_>, renderer: &Renderer, operation: &mut dyn widget::Operation, ) { - let body_layout = if let Some(title_bar) = &self.title_bar { + let body_layout = if let Some(title_bar) = &mut self.title_bar { let mut children = layout.children(); title_bar.operate( @@ -231,7 +231,7 @@ where layout }; - self.body.as_widget().operate( + self.body.as_widget_mut().operate( &mut tree.children[0], body_layout, renderer, diff --git a/widget/src/pane_grid/title_bar.rs b/widget/src/pane_grid/title_bar.rs index e47f4a10..598cbcf5 100644 --- a/widget/src/pane_grid/title_bar.rs +++ b/widget/src/pane_grid/title_bar.rs @@ -128,17 +128,17 @@ where } } - pub(super) fn diff(&self, tree: &mut Tree) { + pub(super) fn diff(&mut self, tree: &mut Tree) { if tree.children.len() == 3 { - if let Some(controls) = self.controls.as_ref() { - if let Some(compact) = controls.compact.as_ref() { + if let Some(controls) = self.controls.as_mut() { + if let Some(compact) = controls.compact.as_mut() { tree.children[2].diff(compact); } - tree.children[1].diff(&controls.full); + tree.children[1].diff(&mut controls.full); } - tree.children[0].diff(&self.content); + tree.children[0].diff(&mut self.content); } else { *tree = self.state(); } @@ -274,7 +274,7 @@ where } pub(crate) fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, @@ -282,7 +282,7 @@ where let limits = limits.shrink(self.padding); let max_size = limits.max(); - let title_layout = self.content.as_widget().layout( + let title_layout = self.content.as_widget_mut().layout( &mut tree.children[0], renderer, &layout::Limits::new(Size::ZERO, max_size), @@ -290,8 +290,8 @@ where let title_size = title_layout.size(); - let node = if let Some(controls) = &self.controls { - let controls_layout = controls.full.as_widget().layout( + let node = if let Some(controls) = &mut self.controls { + let controls_layout = controls.full.as_widget_mut().layout( &mut tree.children[1], renderer, &layout::Limits::new(Size::ZERO, max_size), @@ -300,8 +300,8 @@ where if title_layout.bounds().width + controls_layout.bounds().width > max_size.width { - if let Some(compact) = controls.compact.as_ref() { - let compact_layout = compact.as_widget().layout( + if let Some(compact) = controls.compact.as_mut() { + let compact_layout = compact.as_widget_mut().layout( &mut tree.children[2], renderer, &layout::Limits::new(Size::ZERO, max_size), @@ -369,7 +369,7 @@ where } pub(crate) fn operate( - &self, + &mut self, tree: &mut Tree, layout: Layout<'_>, renderer: &Renderer, @@ -382,16 +382,16 @@ where let title_layout = children.next().unwrap(); let mut show_title = true; - if let Some(controls) = &self.controls { + if let Some(controls) = &mut self.controls { let controls_layout = children.next().unwrap(); if title_layout.bounds().width + controls_layout.bounds().width > padded.bounds().width { - if let Some(compact) = controls.compact.as_ref() { + if let Some(compact) = controls.compact.as_mut() { let compact_layout = children.next().unwrap(); - compact.as_widget().operate( + compact.as_widget_mut().operate( &mut tree.children[2], compact_layout, renderer, @@ -400,7 +400,7 @@ where } else { show_title = false; - controls.full.as_widget().operate( + controls.full.as_widget_mut().operate( &mut tree.children[1], controls_layout, renderer, @@ -408,7 +408,7 @@ where ); } } else { - controls.full.as_widget().operate( + controls.full.as_widget_mut().operate( &mut tree.children[1], controls_layout, renderer, @@ -418,7 +418,7 @@ where }; if show_title { - self.content.as_widget().operate( + self.content.as_widget_mut().operate( &mut tree.children[0], title_layout, renderer, diff --git a/widget/src/pick_list.rs b/widget/src/pick_list.rs index 4076d7f7..86dbdaf6 100644 --- a/widget/src/pick_list.rs +++ b/widget/src/pick_list.rs @@ -348,7 +348,7 @@ where } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, diff --git a/widget/src/pin.rs b/widget/src/pin.rs index 539bf2c1..f4a1c667 100644 --- a/widget/src/pin.rs +++ b/widget/src/pin.rs @@ -127,8 +127,8 @@ where self.content.as_widget().children() } - fn diff(&self, tree: &mut widget::Tree) { - self.content.as_widget().diff(tree); + fn diff(&mut self, tree: &mut widget::Tree) { + self.content.as_widget_mut().diff(tree); } fn size(&self) -> Size { @@ -139,7 +139,7 @@ where } fn layout( - &self, + &mut self, tree: &mut widget::Tree, renderer: &Renderer, limits: &layout::Limits, @@ -151,7 +151,7 @@ where let node = self .content - .as_widget() + .as_widget_mut() .layout(tree, renderer, &layout::Limits::new(Size::ZERO, available)) .move_to(self.position); @@ -160,13 +160,13 @@ where } fn operate( - &self, + &mut self, tree: &mut widget::Tree, layout: Layout<'_>, renderer: &Renderer, operation: &mut dyn widget::Operation, ) { - self.content.as_widget().operate( + self.content.as_widget_mut().operate( tree, layout.children().next().unwrap(), renderer, diff --git a/widget/src/progress_bar.rs b/widget/src/progress_bar.rs index a9b4eb65..d364f5df 100644 --- a/widget/src/progress_bar.rs +++ b/widget/src/progress_bar.rs @@ -157,7 +157,7 @@ where } fn layout( - &self, + &mut self, _tree: &mut Tree, _renderer: &Renderer, limits: &layout::Limits, diff --git a/widget/src/qr_code.rs b/widget/src/qr_code.rs index 07bb0c50..e8a278fd 100644 --- a/widget/src/qr_code.rs +++ b/widget/src/qr_code.rs @@ -136,7 +136,7 @@ where } fn layout( - &self, + &mut self, _tree: &mut Tree, _renderer: &Renderer, _limits: &layout::Limits, diff --git a/widget/src/radio.rs b/widget/src/radio.rs index fab29f56..3bb2e806 100644 --- a/widget/src/radio.rs +++ b/widget/src/radio.rs @@ -290,7 +290,7 @@ where } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, diff --git a/widget/src/responsive.rs b/widget/src/responsive.rs new file mode 100644 index 00000000..6bb86a12 --- /dev/null +++ b/widget/src/responsive.rs @@ -0,0 +1,213 @@ +use crate::core::layout::{self, Layout}; +use crate::core::mouse; +use crate::core::overlay; +use crate::core::renderer; +use crate::core::widget; +use crate::core::widget::tree::{self, Tree}; +use crate::core::{ + self, Clipboard, Element, Event, Length, Rectangle, Shell, Size, Vector, + Widget, +}; +use crate::horizontal_space; + +/// A widget that is aware of its dimensions. +/// +/// A [`Responsive`] widget will always try to fill all the available space of +/// its parent. +#[allow(missing_debug_implementations)] +pub struct Responsive< + 'a, + Message, + Theme = crate::Theme, + Renderer = crate::Renderer, +> { + view: Box Element<'a, Message, Theme, Renderer> + 'a>, + width: Length, + height: Length, + content: Element<'a, Message, Theme, Renderer>, +} + +impl<'a, Message, Theme, Renderer> Responsive<'a, Message, Theme, Renderer> +where + Renderer: core::Renderer, +{ + /// Creates a new [`Responsive`] widget with a closure that produces its + /// contents. + /// + /// The `view` closure will receive the maximum available space for + /// the [`Responsive`] during layout. You can use this [`Size`] to + /// conditionally build the contents. + pub fn new( + view: impl Fn(Size) -> Element<'a, Message, Theme, Renderer> + 'a, + ) -> Self { + Self { + view: Box::new(view), + width: Length::Fill, + height: Length::Fill, + content: Element::new(horizontal_space().width(0)), + } + } + + /// Sets the width of the [`Responsive`]. + pub fn width(mut self, width: impl Into) -> Self { + self.width = width.into(); + self + } + + /// Sets the height of the [`Responsive`]. + pub fn height(mut self, height: impl Into) -> Self { + self.height = height.into(); + self + } +} + +impl Widget + for Responsive<'_, Message, Theme, Renderer> +where + Renderer: core::Renderer, +{ + fn tag(&self) -> tree::Tag { + struct Marker; + tree::Tag::of::() + } + + fn diff(&mut self, _tree: &mut Tree) { + // Diff is deferred to layout + } + + fn size(&self) -> Size { + Size { + width: self.width, + height: self.height, + } + } + + fn layout( + &mut self, + tree: &mut Tree, + renderer: &Renderer, + limits: &layout::Limits, + ) -> layout::Node { + let limits = limits.width(self.width).height(self.height); + let size = limits.max(); + + self.content = (self.view)(size); + tree.diff_children(std::slice::from_mut(&mut self.content)); + + let node = self.content.as_widget_mut().layout( + &mut tree.children[0], + renderer, + &limits.loose(), + ); + + let size = limits.resolve(self.width, self.height, node.size()); + + layout::Node::with_children(size, vec![node]) + } + + fn update( + &mut self, + tree: &mut Tree, + event: &Event, + layout: Layout<'_>, + cursor: mouse::Cursor, + renderer: &Renderer, + clipboard: &mut dyn Clipboard, + shell: &mut Shell<'_, Message>, + viewport: &Rectangle, + ) { + self.content.as_widget_mut().update( + &mut tree.children[0], + event, + layout.children().next().unwrap(), + cursor, + renderer, + clipboard, + shell, + viewport, + ); + } + + fn draw( + &self, + tree: &Tree, + renderer: &mut Renderer, + theme: &Theme, + style: &renderer::Style, + layout: Layout<'_>, + cursor: mouse::Cursor, + viewport: &Rectangle, + ) { + self.content.as_widget().draw( + &tree.children[0], + renderer, + theme, + style, + layout.children().next().unwrap(), + cursor, + viewport, + ); + } + + fn mouse_interaction( + &self, + tree: &Tree, + layout: Layout<'_>, + cursor: mouse::Cursor, + viewport: &Rectangle, + renderer: &Renderer, + ) -> mouse::Interaction { + self.content.as_widget().mouse_interaction( + &tree.children[0], + layout.children().next().unwrap(), + cursor, + viewport, + renderer, + ) + } + + fn operate( + &mut self, + tree: &mut Tree, + layout: Layout<'_>, + renderer: &Renderer, + operation: &mut dyn widget::Operation, + ) { + self.content.as_widget_mut().operate( + &mut tree.children[0], + layout.children().next().unwrap(), + renderer, + operation, + ); + } + + fn overlay<'a>( + &'a mut self, + tree: &'a mut Tree, + layout: Layout<'a>, + renderer: &Renderer, + viewport: &Rectangle, + translation: Vector, + ) -> Option> { + self.content.as_widget_mut().overlay( + &mut tree.children[0], + layout.children().next().unwrap(), + renderer, + viewport, + translation, + ) + } +} + +impl<'a, Message, Theme, Renderer> + From> + for Element<'a, Message, Theme, Renderer> +where + Message: 'a, + Theme: 'a, + Renderer: core::Renderer + 'a, +{ + fn from(responsive: Responsive<'a, Message, Theme, Renderer>) -> Self { + Self::new(responsive) + } +} diff --git a/widget/src/row.rs b/widget/src/row.rs index 101e51d8..2ee3d345 100644 --- a/widget/src/row.rs +++ b/widget/src/row.rs @@ -196,8 +196,8 @@ where self.children.iter().map(Tree::new).collect() } - fn diff(&self, tree: &mut Tree) { - tree.diff_children(&self.children); + fn diff(&mut self, tree: &mut Tree) { + tree.diff_children(&mut self.children); } fn size(&self) -> Size { @@ -208,7 +208,7 @@ where } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, @@ -222,13 +222,13 @@ where self.padding, self.spacing, self.align, - &self.children, + &mut self.children, &mut tree.children, ) } fn operate( - &self, + &mut self, tree: &mut Tree, layout: Layout<'_>, renderer: &Renderer, @@ -236,12 +236,12 @@ where ) { operation.container(None, layout.bounds(), &mut |operation| { self.children - .iter() + .iter_mut() .zip(&mut tree.children) .zip(layout.children()) .for_each(|((child, state), layout)| { child - .as_widget() + .as_widget_mut() .operate(state, layout, renderer, operation); }); }); @@ -398,7 +398,7 @@ where self.row.children() } - fn diff(&self, tree: &mut Tree) { + fn diff(&mut self, tree: &mut Tree) { self.row.diff(tree); } @@ -407,7 +407,7 @@ where } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, @@ -449,8 +449,8 @@ where } }; - for (i, child) in self.row.children.iter().enumerate() { - let node = child.as_widget().layout( + for (i, child) in self.row.children.iter_mut().enumerate() { + let node = child.as_widget_mut().layout( &mut tree.children[i], renderer, &limits, @@ -528,7 +528,7 @@ where } fn operate( - &self, + &mut self, tree: &mut Tree, layout: Layout<'_>, renderer: &Renderer, diff --git a/widget/src/rule.rs b/widget/src/rule.rs index d70109bc..163d2757 100644 --- a/widget/src/rule.rs +++ b/widget/src/rule.rs @@ -112,7 +112,7 @@ where } fn layout( - &self, + &mut self, _tree: &mut Tree, _renderer: &Renderer, limits: &layout::Limits, diff --git a/widget/src/scrollable.rs b/widget/src/scrollable.rs index baff578e..0b0b6f9b 100644 --- a/widget/src/scrollable.rs +++ b/widget/src/scrollable.rs @@ -409,8 +409,8 @@ where vec![Tree::new(&self.content)] } - fn diff(&self, tree: &mut Tree) { - tree.diff_children(std::slice::from_ref(&self.content)); + fn diff(&mut self, tree: &mut Tree) { + tree.diff_children(std::slice::from_mut(&mut self.content)); } fn size(&self) -> Size { @@ -421,7 +421,7 @@ where } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, @@ -453,7 +453,7 @@ where ), ); - self.content.as_widget().layout( + self.content.as_widget_mut().layout( &mut tree.children[0], renderer, &child_limits, @@ -527,7 +527,7 @@ where } fn operate( - &self, + &mut self, tree: &mut Tree, layout: Layout<'_>, renderer: &Renderer, @@ -553,7 +553,7 @@ where self.id.as_ref().map(|id| &id.0), bounds, &mut |operation| { - self.content.as_widget().operate( + self.content.as_widget_mut().operate( &mut tree.children[0], layout.children().next().unwrap(), renderer, diff --git a/widget/src/sensor.rs b/widget/src/sensor.rs index ff5e6fd6..fd7a3510 100644 --- a/widget/src/sensor.rs +++ b/widget/src/sensor.rs @@ -184,8 +184,8 @@ where vec![Tree::new(&self.content)] } - fn diff(&self, tree: &mut Tree) { - tree.diff_children(&[&self.content]); + fn diff(&mut self, tree: &mut Tree) { + tree.diff_children(std::slice::from_mut(&mut self.content)); } fn update( @@ -287,14 +287,16 @@ where } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { - self.content - .as_widget() - .layout(&mut tree.children[0], renderer, limits) + self.content.as_widget_mut().layout( + &mut tree.children[0], + renderer, + limits, + ) } fn draw( @@ -319,13 +321,13 @@ where } fn operate( - &self, + &mut self, tree: &mut Tree, layout: core::Layout<'_>, renderer: &Renderer, operation: &mut dyn widget::Operation, ) { - self.content.as_widget().operate( + self.content.as_widget_mut().operate( &mut tree.children[0], layout, renderer, diff --git a/widget/src/shader.rs b/widget/src/shader.rs index 6d532e59..cf165e59 100644 --- a/widget/src/shader.rs +++ b/widget/src/shader.rs @@ -77,7 +77,7 @@ where } fn layout( - &self, + &mut self, _tree: &mut Tree, _renderer: &Renderer, limits: &layout::Limits, diff --git a/widget/src/slider.rs b/widget/src/slider.rs index 74225436..db6bc175 100644 --- a/widget/src/slider.rs +++ b/widget/src/slider.rs @@ -234,7 +234,7 @@ where } fn layout( - &self, + &mut self, _tree: &mut Tree, _renderer: &Renderer, limits: &layout::Limits, diff --git a/widget/src/space.rs b/widget/src/space.rs index 35bb30c4..949ea3ce 100644 --- a/widget/src/space.rs +++ b/widget/src/space.rs @@ -65,7 +65,7 @@ where } fn layout( - &self, + &mut self, _tree: &mut Tree, _renderer: &Renderer, limits: &layout::Limits, diff --git a/widget/src/stack.rs b/widget/src/stack.rs index 16e82678..63a6b97e 100644 --- a/widget/src/stack.rs +++ b/widget/src/stack.rs @@ -146,8 +146,8 @@ where self.children.iter().map(Tree::new).collect() } - fn diff(&self, tree: &mut Tree) { - tree.diff_children(&self.children); + fn diff(&mut self, tree: &mut Tree) { + tree.diff_children(&mut self.children); } fn size(&self) -> Size { @@ -158,7 +158,7 @@ where } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, @@ -173,7 +173,7 @@ where )); } - let base = self.children[0].as_widget().layout( + let base = self.children[0].as_widget_mut().layout( &mut tree.children[0], renderer, &limits, @@ -183,18 +183,21 @@ where let limits = layout::Limits::new(Size::ZERO, size); let nodes = std::iter::once(base) - .chain(self.children[1..].iter().zip(&mut tree.children[1..]).map( - |(layer, tree)| { - layer.as_widget().layout(tree, renderer, &limits) - }, - )) + .chain( + self.children[1..] + .iter_mut() + .zip(&mut tree.children[1..]) + .map(|(layer, tree)| { + layer.as_widget_mut().layout(tree, renderer, &limits) + }), + ) .collect(); layout::Node::with_children(size, nodes) } fn operate( - &self, + &mut self, tree: &mut Tree, layout: Layout<'_>, renderer: &Renderer, @@ -202,12 +205,12 @@ where ) { operation.container(None, layout.bounds(), &mut |operation| { self.children - .iter() + .iter_mut() .zip(&mut tree.children) .zip(layout.children()) .for_each(|((child, state), layout)| { child - .as_widget() + .as_widget_mut() .operate(state, layout, renderer, operation); }); }); diff --git a/widget/src/svg.rs b/widget/src/svg.rs index 72ead4f9..ab69b2dc 100644 --- a/widget/src/svg.rs +++ b/widget/src/svg.rs @@ -162,7 +162,7 @@ where } fn layout( - &self, + &mut self, _tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, diff --git a/widget/src/table.rs b/widget/src/table.rs index 03537f9a..97083835 100644 --- a/widget/src/table.rs +++ b/widget/src/table.rs @@ -227,12 +227,12 @@ where .collect() } - fn diff(&self, state: &mut widget::Tree) { - state.diff_children(&self.cells); + fn diff(&mut self, state: &mut widget::Tree) { + state.diff_children(&mut self.cells); } fn layout( - &self, + &mut self, tree: &mut widget::Tree, renderer: &Renderer, limits: &layout::Limits, @@ -265,7 +265,7 @@ where let mut y = self.padding_y; for (i, (cell, state)) in - self.cells.iter().zip(&mut tree.children).enumerate() + self.cells.iter_mut().zip(&mut tree.children).enumerate() { let row = i / columns; let column = i % columns; @@ -306,7 +306,7 @@ where ) .width(width); - let layout = cell.as_widget().layout(state, renderer, &limits); + let layout = cell.as_widget_mut().layout(state, renderer, &limits); let size = limits.resolve(width, Length::Shrink, layout.size()); metrics.columns[column] = metrics.columns[column].max(size.width); @@ -344,7 +344,7 @@ where let mut y = self.padding_y; for (i, (cell, state)) in - self.cells.iter().zip(&mut tree.children).enumerate() + self.cells.iter_mut().zip(&mut tree.children).enumerate() { let row = i / columns; let column = i % columns; @@ -396,7 +396,7 @@ where ) .width(width); - let layout = cell.as_widget().layout(state, renderer, &limits); + let layout = cell.as_widget_mut().layout(state, renderer, &limits); let size = limits.resolve( if let Length::Fixed(_) = width { width @@ -581,7 +581,7 @@ where } fn operate( - &self, + &mut self, tree: &mut widget::Tree, layout: Layout<'_>, renderer: &Renderer, @@ -589,11 +589,12 @@ where ) { for ((cell, state), layout) in self .cells - .iter() + .iter_mut() .zip(&mut tree.children) .zip(layout.children()) { - cell.as_widget().operate(state, layout, renderer, operation); + cell.as_widget_mut() + .operate(state, layout, renderer, operation); } } diff --git a/widget/src/text/rich.rs b/widget/src/text/rich.rs index 9e7eaddf..e11f406b 100644 --- a/widget/src/text/rich.rs +++ b/widget/src/text/rich.rs @@ -225,7 +225,7 @@ where } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, diff --git a/widget/src/text_editor.rs b/widget/src/text_editor.rs index 3657c817..33666935 100644 --- a/widget/src/text_editor.rs +++ b/widget/src/text_editor.rs @@ -597,7 +597,7 @@ where } fn layout( - &self, + &mut self, tree: &mut widget::Tree, renderer: &Renderer, limits: &layout::Limits, @@ -1051,7 +1051,7 @@ where } fn operate( - &self, + &mut self, tree: &mut widget::Tree, layout: Layout<'_>, _renderer: &Renderer, diff --git a/widget/src/text_input.rs b/widget/src/text_input.rs index fa3dd770..1a4f8a99 100644 --- a/widget/src/text_input.rs +++ b/widget/src/text_input.rs @@ -297,7 +297,7 @@ where /// /// [`Renderer`]: text::Renderer pub fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, @@ -654,7 +654,7 @@ where tree::State::new(State::::new()) } - fn diff(&self, tree: &mut Tree) { + fn diff(&mut self, tree: &mut Tree) { let state = tree.state.downcast_mut::>(); // Stop pasting if input becomes disabled @@ -671,7 +671,7 @@ where } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, @@ -680,7 +680,7 @@ where } fn operate( - &self, + &mut self, tree: &mut Tree, layout: Layout<'_>, _renderer: &Renderer, diff --git a/widget/src/themer.rs b/widget/src/themer.rs index 693b8486..a089d1d5 100644 --- a/widget/src/themer.rs +++ b/widget/src/themer.rs @@ -81,8 +81,8 @@ where self.content.as_widget().children() } - fn diff(&self, tree: &mut Tree) { - self.content.as_widget().diff(tree); + fn diff(&mut self, tree: &mut Tree) { + self.content.as_widget_mut().diff(tree); } fn size(&self) -> Size { @@ -90,23 +90,23 @@ where } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { - self.content.as_widget().layout(tree, renderer, limits) + self.content.as_widget_mut().layout(tree, renderer, limits) } fn operate( - &self, + &mut self, tree: &mut Tree, layout: Layout<'_>, renderer: &Renderer, operation: &mut dyn Operation, ) { self.content - .as_widget() + .as_widget_mut() .operate(tree, layout, renderer, operation); } diff --git a/widget/src/toggler.rs b/widget/src/toggler.rs index 13385317..0ad2d22c 100644 --- a/widget/src/toggler.rs +++ b/widget/src/toggler.rs @@ -270,7 +270,7 @@ where } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, diff --git a/widget/src/tooltip.rs b/widget/src/tooltip.rs index f3dea455..782258da 100644 --- a/widget/src/tooltip.rs +++ b/widget/src/tooltip.rs @@ -155,10 +155,10 @@ where ] } - fn diff(&self, tree: &mut widget::Tree) { - tree.diff_children(&[ - self.content.as_widget(), - self.tooltip.as_widget(), + fn diff(&mut self, tree: &mut widget::Tree) { + tree.diff_children(&mut [ + self.content.as_widget_mut(), + self.tooltip.as_widget_mut(), ]); } @@ -179,14 +179,16 @@ where } fn layout( - &self, + &mut self, tree: &mut widget::Tree, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { - self.content - .as_widget() - .layout(&mut tree.children[0], renderer, limits) + self.content.as_widget_mut().layout( + &mut tree.children[0], + renderer, + limits, + ) } fn update( @@ -294,7 +296,7 @@ where let tooltip = if let State::Hovered { cursor_position } = *state { Some(overlay::Element::new(Box::new(Overlay { position: layout.position() + translation, - tooltip: &self.tooltip, + tooltip: &mut self.tooltip, state: children.next().unwrap(), cursor_position, content_bounds: layout.bounds(), @@ -366,7 +368,7 @@ where Renderer: text::Renderer, { position: Point, - tooltip: &'b Element<'a, Message, Theme, Renderer>, + tooltip: &'b mut Element<'a, Message, Theme, Renderer>, state: &'b mut widget::Tree, cursor_position: Point, content_bounds: Rectangle, @@ -386,7 +388,7 @@ where fn layout(&mut self, renderer: &Renderer, bounds: Size) -> layout::Node { let viewport = Rectangle::with_size(bounds); - let tooltip_layout = self.tooltip.as_widget().layout( + let tooltip_layout = self.tooltip.as_widget_mut().layout( self.state, renderer, &layout::Limits::new( diff --git a/widget/src/vertical_slider.rs b/widget/src/vertical_slider.rs index c262eb8e..8e8ca1c0 100644 --- a/widget/src/vertical_slider.rs +++ b/widget/src/vertical_slider.rs @@ -238,7 +238,7 @@ where } fn layout( - &self, + &mut self, _tree: &mut Tree, _renderer: &Renderer, limits: &layout::Limits,