diff --git a/examples/modal/src/main.rs b/examples/modal/src/main.rs index 54555684a0..42be150580 100644 --- a/examples/modal/src/main.rs +++ b/examples/modal/src/main.rs @@ -276,7 +276,7 @@ mod modal { cursor_position: Point, viewport: &Rectangle, ) { - self.base.as_widget().draw( + self.base.as_widget_mut().draw( &state.children[0], renderer, theme, @@ -424,7 +424,7 @@ mod modal { }, ); - self.content.as_widget().draw( + self.content.as_widget_mut().draw( self.tree, renderer, theme, diff --git a/examples/toast/src/main.rs b/examples/toast/src/main.rs index e74b3ee62c..f5264ae623 100644 --- a/examples/toast/src/main.rs +++ b/examples/toast/src/main.rs @@ -414,7 +414,7 @@ mod toast { cursor_position: Point, viewport: &Rectangle, ) { - self.content.as_widget().draw( + self.content.as_widget_mut().draw( &state.children[0], renderer, theme, @@ -597,7 +597,7 @@ mod toast { .zip(self.state.iter()) .zip(layout.children()) { - child.as_widget().draw( + child.as_widget_mut().draw( state, renderer, theme, diff --git a/graphics/src/renderer.rs b/graphics/src/renderer.rs index 34b6eb1d3e..5312951b7a 100644 --- a/graphics/src/renderer.rs +++ b/graphics/src/renderer.rs @@ -55,10 +55,10 @@ where fn layout( &mut self, - element: &Element<'_, Message, Self>, + element: &mut Element<'_, Message, Self>, limits: &layout::Limits, ) -> layout::Node { - let layout = element.as_widget().layout(self, limits); + let layout = element.as_widget_mut().layout(self, limits); self.backend.trim_measurements(); diff --git a/lazy/src/component.rs b/lazy/src/component.rs index b23da9f7b4..a27ebb3526 100644 --- a/lazy/src/component.rs +++ b/lazy/src/component.rs @@ -333,7 +333,7 @@ where viewport: &Rectangle, ) { self.with_element(|element| { - element.as_widget().draw( + element.as_widget_mut().draw( &tree.children[0], renderer, theme, diff --git a/lazy/src/lazy.rs b/lazy/src/lazy.rs index 5e909a498c..cd9720e9c3 100644 --- a/lazy/src/lazy.rs +++ b/lazy/src/lazy.rs @@ -213,7 +213,7 @@ where viewport: &Rectangle, ) { self.with_element(|element| { - element.as_widget().draw( + element.as_widget_mut().draw( &tree.children[0], renderer, theme, diff --git a/lazy/src/responsive.rs b/lazy/src/responsive.rs index 57c07de119..9ddab1370a 100644 --- a/lazy/src/responsive.rs +++ b/lazy/src/responsive.rs @@ -216,7 +216,7 @@ where layout, &self.view, |tree, renderer, layout, element| { - element.as_widget().draw( + element.as_widget_mut().draw( tree, renderer, theme, diff --git a/native/src/element.rs b/native/src/element.rs index 0a677d20bb..81460a13d4 100644 --- a/native/src/element.rs +++ b/native/src/element.rs @@ -6,7 +6,7 @@ use crate::renderer; use crate::widget; use crate::widget::tree::{self, Tree}; use crate::{ - Clipboard, Color, Layout, Length, Point, Rectangle, Shell, Widget, + Clipboard, Color, Layout, Length, Point, Rectangle, Shell, Size, Widget, }; use std::any::Any; @@ -280,13 +280,21 @@ where } fn layout( - &self, + &mut self, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { self.widget.layout(renderer, limits) } + fn measure( + &mut self, + renderer: &Renderer, + limits: &layout::Limits, + ) -> Size { + self.widget.measure(renderer, limits) + } + fn operate( &self, tree: &mut Tree, @@ -377,7 +385,7 @@ where } fn draw( - &self, + &mut self, tree: &Tree, renderer: &mut Renderer, theme: &Renderer::Theme, @@ -472,7 +480,7 @@ where } fn layout( - &self, + &mut self, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { @@ -513,7 +521,7 @@ where } fn draw( - &self, + &mut self, state: &Tree, renderer: &mut Renderer, theme: &Renderer::Theme, diff --git a/native/src/layout/flex.rs b/native/src/layout/flex.rs index 5d70c2fc13..3ab6c5d0b5 100644 --- a/native/src/layout/flex.rs +++ b/native/src/layout/flex.rs @@ -54,6 +54,15 @@ impl Axis { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +/// Whether a full (recursive) layout should be performed or the size of the container measured +pub enum LayoutMode { + /// Only the size of the container needs to be measured + MeasureSize, + /// A full recursive layout should be performed + PerformLayout, +} + /// Computes the flex layout with the given axis and limits, applying spacing, /// padding and alignment to the items as needed. /// @@ -65,7 +74,8 @@ pub fn resolve( padding: Padding, spacing: f32, align_items: Alignment, - items: &[Element<'_, Message, Renderer>], + items: &mut [Element<'_, Message, Renderer>], + mode: LayoutMode, ) -> Node where Renderer: crate::Renderer, @@ -84,7 +94,7 @@ where if align_items == Alignment::Fill { let mut fill_cross = axis.cross(limits.min()); - items.iter().for_each(|child| { + items.iter_mut().for_each(|child| { let cross_fill_factor = match axis { Axis::Horizontal => child.as_widget().height(), Axis::Vertical => child.as_widget().width(), @@ -97,8 +107,8 @@ where let child_limits = Limits::new(Size::ZERO, Size::new(max_width, max_height)); - let layout = child.as_widget().layout(renderer, &child_limits); - let size = layout.size(); + let size = + child.as_widget_mut().measure(renderer, &child_limits); fill_cross = fill_cross.max(axis.cross(size)); } @@ -107,7 +117,7 @@ where cross = fill_cross; } - for (i, child) in items.iter().enumerate() { + for (i, child) in items.iter_mut().enumerate() { let fill_factor = match axis { Axis::Horizontal => child.as_widget().width(), Axis::Vertical => child.as_widget().height(), @@ -132,16 +142,27 @@ where Size::new(max_width, max_height), ); - let layout = child.as_widget().layout(renderer, &child_limits); - let size = layout.size(); + let size = match mode { + LayoutMode::MeasureSize => { + let size = + child.as_widget_mut().measure(renderer, &child_limits); + nodes[i] = Node::new(size); + size + } + LayoutMode::PerformLayout => { + let layout = + child.as_widget_mut().layout(renderer, &child_limits); + let size = layout.size(); + nodes[i] = layout; + size + } + }; available -= axis.main(size); if align_items != Alignment::Fill { cross = cross.max(axis.cross(size)); } - - nodes[i] = layout; } else { fill_sum += fill_factor; } @@ -149,7 +170,7 @@ where let remaining = available.max(0.0); - for (i, child) in items.iter().enumerate() { + for (i, child) in items.iter_mut().enumerate() { let fill_factor = match axis { Axis::Horizontal => child.as_widget().width(), Axis::Vertical => child.as_widget().height(), @@ -181,13 +202,25 @@ where Size::new(max_width, max_height), ); - let layout = child.as_widget().layout(renderer, &child_limits); + let size = match mode { + LayoutMode::MeasureSize => { + let size = + child.as_widget_mut().measure(renderer, &child_limits); + nodes[i] = Node::new(size); + size + } + LayoutMode::PerformLayout => { + let layout = + child.as_widget_mut().layout(renderer, &child_limits); + let size = layout.size(); + nodes[i] = layout; + size + } + }; if align_items != Alignment::Fill { - cross = cross.max(axis.cross(layout.size())); + cross = cross.max(axis.cross(size)); } - - nodes[i] = layout; } } diff --git a/native/src/layout/node.rs b/native/src/layout/node.rs index e0c7dcb2fd..7cad9fe3a3 100644 --- a/native/src/layout/node.rs +++ b/native/src/layout/node.rs @@ -36,11 +36,16 @@ impl Node { self.bounds } - /// Returns the children of the [`Node`]. + /// Returns a view into the children of the [`Node`]. pub fn children(&self) -> &[Node] { &self.children } + /// Consumes the [`Node`] and returns the children of the [`Node`]. + pub fn into_children(self) -> Vec { + self.children + } + /// Aligns the [`Node`] in the given space. pub fn align( &mut self, @@ -81,6 +86,12 @@ impl Node { self.bounds.y = position.y; } + /// Set the [`Node`] to the given size. + pub fn set_size(&mut self, size: Size) { + self.bounds.width = size.width; + self.bounds.height = size.height; + } + /// Translates the [`Node`] by the given translation. pub fn translate(self, translation: Vector) -> Self { Self { diff --git a/native/src/overlay.rs b/native/src/overlay.rs index 6cada41655..d3964a99a8 100644 --- a/native/src/overlay.rs +++ b/native/src/overlay.rs @@ -28,7 +28,7 @@ where /// /// [`Node`]: layout::Node fn layout( - &self, + &mut self, renderer: &Renderer, bounds: Size, position: Point, @@ -36,7 +36,7 @@ where /// Draws the [`Overlay`] using the associated `Renderer`. fn draw( - &self, + &mut self, renderer: &mut Renderer, theme: &Renderer::Theme, style: &renderer::Style, diff --git a/native/src/overlay/element.rs b/native/src/overlay/element.rs index 237d25d175..3c44254a07 100644 --- a/native/src/overlay/element.rs +++ b/native/src/overlay/element.rs @@ -54,7 +54,7 @@ where /// Computes the layout of the [`Element`] in the given bounds. pub fn layout( - &self, + &mut self, renderer: &Renderer, bounds: Size, translation: Vector, @@ -101,7 +101,7 @@ where /// Draws the [`Element`] and its children using the given [`Layout`]. pub fn draw( - &self, + &mut self, renderer: &mut Renderer, theme: &Renderer::Theme, style: &renderer::Style, @@ -147,7 +147,7 @@ where Renderer: crate::Renderer, { fn layout( - &self, + &mut self, renderer: &Renderer, bounds: Size, position: Point, @@ -253,7 +253,7 @@ where } fn draw( - &self, + &mut self, renderer: &mut Renderer, theme: &Renderer::Theme, style: &renderer::Style, diff --git a/native/src/overlay/group.rs b/native/src/overlay/group.rs index 1126f0cf11..c2ffc32f30 100644 --- a/native/src/overlay/group.rs +++ b/native/src/overlay/group.rs @@ -63,7 +63,7 @@ where Renderer: crate::Renderer, { fn layout( - &self, + &mut self, renderer: &Renderer, bounds: Size, position: Point, @@ -73,7 +73,7 @@ where layout::Node::with_children( bounds, self.children - .iter() + .iter_mut() .map(|child| child.layout(renderer, bounds, translation)) .collect(), ) @@ -105,14 +105,14 @@ where } fn draw( - &self, + &mut self, renderer: &mut Renderer, theme: &::Theme, style: &renderer::Style, layout: Layout<'_>, cursor_position: Point, ) { - for (child, layout) in self.children.iter().zip(layout.children()) { + for (child, layout) in self.children.iter_mut().zip(layout.children()) { child.draw(renderer, theme, style, layout, cursor_position); } } diff --git a/native/src/overlay/menu.rs b/native/src/overlay/menu.rs index 50f741efd0..fd01fab0b8 100644 --- a/native/src/overlay/menu.rs +++ b/native/src/overlay/menu.rs @@ -200,7 +200,7 @@ where Renderer::Theme: StyleSheet + container::StyleSheet, { fn layout( - &self, + &mut self, renderer: &Renderer, bounds: Size, position: Point, @@ -269,7 +269,7 @@ where } fn draw( - &self, + &mut self, renderer: &mut Renderer, theme: &Renderer::Theme, style: &renderer::Style, @@ -331,7 +331,7 @@ where } fn layout( - &self, + &mut self, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { @@ -436,7 +436,7 @@ where } fn draw( - &self, + &mut self, _state: &Tree, renderer: &mut Renderer, theme: &Renderer::Theme, diff --git a/native/src/renderer.rs b/native/src/renderer.rs index 2ac7898298..84e04083d5 100644 --- a/native/src/renderer.rs +++ b/native/src/renderer.rs @@ -18,10 +18,10 @@ pub trait Renderer: Sized { /// after layouting. For instance, trimming the measurements cache. fn layout( &mut self, - element: &Element<'_, Message, Self>, + element: &mut Element<'_, Message, Self>, limits: &layout::Limits, ) -> layout::Node { - element.as_widget().layout(self, limits) + element.as_widget_mut().layout(self, limits) } /// Draws the primitives recorded in the given closure in a new layer. diff --git a/native/src/user_interface.rs b/native/src/user_interface.rs index 68ccda55dd..53f2b9cafc 100644 --- a/native/src/user_interface.rs +++ b/native/src/user_interface.rs @@ -97,13 +97,13 @@ 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()); - let base = - renderer.layout(&root, &layout::Limits::new(Size::ZERO, bounds)); + let base = renderer + .layout(&mut root, &layout::Limits::new(Size::ZERO, bounds)); UserInterface { root, @@ -236,7 +236,7 @@ where let _ = ManuallyDrop::into_inner(manual_overlay); self.base = renderer.layout( - &self.root, + &mut self.root, &layout::Limits::new(Size::ZERO, self.bounds), ); @@ -320,7 +320,7 @@ where shell.revalidate_layout(|| { self.base = renderer.layout( - &self.root, + &mut self.root, &layout::Limits::new(Size::ZERO, self.bounds), ); @@ -431,7 +431,7 @@ where let viewport = Rectangle::with_size(self.bounds); - let base_cursor = if let Some(overlay) = self + let base_cursor = if let Some(mut overlay) = self .root .as_widget_mut() .overlay(&mut self.state, Layout::new(&self.base), renderer) @@ -455,7 +455,7 @@ where cursor_position }; - self.root.as_widget().draw( + self.root.as_widget_mut().draw( &self.state, renderer, theme, @@ -490,7 +490,7 @@ where .and_then(|layout| { root.as_widget_mut() .overlay(&mut self.state, Layout::new(base), renderer) - .map(|overlay| { + .map(|mut overlay| { let overlay_interaction = overlay.mouse_interaction( Layout::new(layout), cursor_position, diff --git a/native/src/widget.rs b/native/src/widget.rs index 2b3ca7be07..ab8466fe20 100644 --- a/native/src/widget.rs +++ b/native/src/widget.rs @@ -92,7 +92,7 @@ use crate::layout; use crate::mouse; use crate::overlay; use crate::renderer; -use crate::{Clipboard, Layout, Length, Point, Rectangle, Shell}; +use crate::{Clipboard, Layout, Length, Point, Rectangle, Shell, Size}; /// A component that displays information and allows interaction. /// @@ -131,14 +131,25 @@ where /// This [`layout::Node`] is used by the runtime to compute the [`Layout`] of the /// user interface. fn layout( - &self, + &mut self, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node; + /// Returns the intrinsic (content based) [`Size`] of the [`Widget`]. + /// + /// This [`Size`] is used by the parent widget to compute a final size for the widget + fn measure( + &mut self, + renderer: &Renderer, + limits: &layout::Limits, + ) -> Size { + self.layout(renderer, limits).size() + } + /// Draws the [`Widget`] using the associated `Renderer`. fn draw( - &self, + &mut self, state: &Tree, renderer: &mut Renderer, theme: &Renderer::Theme, diff --git a/native/src/widget/button.rs b/native/src/widget/button.rs index 3938717305..0397617e7e 100644 --- a/native/src/widget/button.rs +++ b/native/src/widget/button.rs @@ -149,7 +149,7 @@ where } fn layout( - &self, + &mut self, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { @@ -160,7 +160,7 @@ where self.height, self.padding, |renderer, limits| { - self.content.as_widget().layout(renderer, limits) + self.content.as_widget_mut().layout(renderer, limits) }, ) } @@ -215,7 +215,7 @@ where } fn draw( - &self, + &mut self, tree: &Tree, renderer: &mut Renderer, theme: &Renderer::Theme, @@ -237,7 +237,7 @@ where || tree.state.downcast_ref::(), ); - self.content.as_widget().draw( + self.content.as_widget_mut().draw( &tree.children[0], renderer, theme, diff --git a/native/src/widget/checkbox.rs b/native/src/widget/checkbox.rs index 9b69e574f0..7cfc9ac2bb 100644 --- a/native/src/widget/checkbox.rs +++ b/native/src/widget/checkbox.rs @@ -164,7 +164,7 @@ where } fn layout( - &self, + &mut self, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { @@ -228,7 +228,7 @@ where } fn draw( - &self, + &mut self, _tree: &Tree, renderer: &mut Renderer, theme: &Renderer::Theme, diff --git a/native/src/widget/column.rs b/native/src/widget/column.rs index ebe579d5b7..2024c91623 100644 --- a/native/src/widget/column.rs +++ b/native/src/widget/column.rs @@ -7,7 +7,7 @@ use crate::renderer; use crate::widget::{Operation, Tree}; use crate::{ Alignment, Clipboard, Element, Layout, Length, Padding, Pixels, Point, - Rectangle, Shell, Widget, + Rectangle, Shell, Size, Widget, }; /// A container that distributes its contents vertically. @@ -121,7 +121,7 @@ where } fn layout( - &self, + &mut self, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { @@ -137,10 +137,34 @@ where self.padding, self.spacing, self.align_items, - &self.children, + &mut self.children, + layout::flex::LayoutMode::PerformLayout, ) } + fn measure( + &mut self, + renderer: &Renderer, + limits: &layout::Limits, + ) -> Size { + let limits = limits + .max_width(self.max_width) + .width(self.width) + .height(self.height); + + layout::flex::resolve( + layout::flex::Axis::Vertical, + renderer, + &limits, + self.padding, + self.spacing as f32, + self.align_items, + &mut self.children, + layout::flex::LayoutMode::MeasureSize, + ) + .size() + } + fn operate( &self, tree: &mut Tree, @@ -215,7 +239,7 @@ where } fn draw( - &self, + &mut self, tree: &Tree, renderer: &mut Renderer, theme: &Renderer::Theme, @@ -226,11 +250,11 @@ where ) { for ((child, state), layout) in self .children - .iter() + .iter_mut() .zip(&tree.children) .zip(layout.children()) { - child.as_widget().draw( + child.as_widget_mut().draw( state, renderer, theme, diff --git a/native/src/widget/container.rs b/native/src/widget/container.rs index b77bf50d23..a274e0add1 100644 --- a/native/src/widget/container.rs +++ b/native/src/widget/container.rs @@ -8,7 +8,7 @@ use crate::renderer; use crate::widget::{self, Operation, Tree}; use crate::{ Background, Clipboard, Color, Element, Layout, Length, Padding, Pixels, - Point, Rectangle, Shell, Widget, + Point, Rectangle, Shell, Size, Widget, }; pub use iced_style::container::{Appearance, StyleSheet}; @@ -126,6 +126,16 @@ where self.style = style.into(); self } + + /// Computes limits for layout based on parent limits and own sizes + fn compute_limits(&self, parent_limits: &layout::Limits) -> layout::Limits { + parent_limits + .loose() + .max_width(self.max_width) + .max_height(self.max_height) + .width(self.width) + .height(self.height) + } } impl<'a, Message, Renderer> Widget @@ -151,26 +161,37 @@ where } fn layout( - &self, + &mut self, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { layout( renderer, - limits, - self.width, - self.height, - self.max_width, - self.max_height, + &self.compute_limits(limits), self.padding, self.horizontal_alignment, self.vertical_alignment, |renderer, limits| { - self.content.as_widget().layout(renderer, limits) + self.content.as_widget_mut().layout(renderer, limits) }, ) } + fn measure( + &mut self, + renderer: &Renderer, + limits: &layout::Limits, + ) -> Size { + let limits = self.compute_limits(limits); + let content_size = self + .content + .as_widget_mut() + .measure(renderer, &limits.pad(self.padding).loose()); + let padding = self.padding.fit(content_size, limits.max()); + let size = limits.pad(padding).resolve(content_size).pad(padding); + size + } + fn operate( &self, tree: &mut Tree, @@ -230,7 +251,7 @@ where } fn draw( - &self, + &mut self, tree: &Tree, renderer: &mut Renderer, theme: &Renderer::Theme, @@ -243,7 +264,7 @@ where draw_background(renderer, &style, layout.bounds()); - self.content.as_widget().draw( + self.content.as_widget_mut().draw( &tree.children[0], renderer, theme, @@ -290,22 +311,11 @@ where pub fn layout( renderer: &Renderer, limits: &layout::Limits, - width: Length, - height: Length, - max_width: f32, - max_height: f32, padding: Padding, horizontal_alignment: alignment::Horizontal, vertical_alignment: alignment::Vertical, layout_content: impl FnOnce(&Renderer, &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(renderer, &limits.pad(padding).loose()); let padding = padding.fit(content.size(), limits.max()); let size = limits.pad(padding).resolve(content.size()); diff --git a/native/src/widget/image.rs b/native/src/widget/image.rs index 73257a747f..48ad91b14f 100644 --- a/native/src/widget/image.rs +++ b/native/src/widget/image.rs @@ -164,7 +164,7 @@ where } fn layout( - &self, + &mut self, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { @@ -179,7 +179,7 @@ where } fn draw( - &self, + &mut self, _state: &Tree, renderer: &mut Renderer, _theme: &Renderer::Theme, diff --git a/native/src/widget/image/viewer.rs b/native/src/widget/image/viewer.rs index 1f8d5d7a49..379bfaabff 100644 --- a/native/src/widget/image/viewer.rs +++ b/native/src/widget/image/viewer.rs @@ -104,7 +104,7 @@ where } fn layout( - &self, + &mut self, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { @@ -295,7 +295,7 @@ where } fn draw( - &self, + &mut self, tree: &Tree, renderer: &mut Renderer, _theme: &Renderer::Theme, diff --git a/native/src/widget/pane_grid.rs b/native/src/widget/pane_grid.rs index bcb17ebddc..bbcce3799b 100644 --- a/native/src/widget/pane_grid.rs +++ b/native/src/widget/pane_grid.rs @@ -274,18 +274,20 @@ where } fn layout( - &self, + &mut self, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { + let (content_layout, content_iter) = + self.contents.layout_and_mut_iterator(); layout( renderer, limits, - self.contents.layout(), + content_layout, self.width, self.height, self.spacing, - self.contents.iter(), + content_iter, |content, renderer, limits| content.layout(renderer, limits), ) } @@ -400,7 +402,7 @@ where } fn draw( - &self, + &mut self, tree: &Tree, renderer: &mut Renderer, theme: &Renderer::Theme, @@ -409,9 +411,11 @@ where cursor_position: Point, viewport: &Rectangle, ) { + let (content_layout, content_iter) = + self.contents.layout_and_mut_iterator(); draw( tree.state.downcast_ref(), - self.contents.layout(), + content_layout, layout, cursor_position, renderer, @@ -421,8 +425,7 @@ where self.spacing, self.on_resize.as_ref().map(|(leeway, _)| *leeway), &self.style, - self.contents - .iter() + content_iter .zip(&tree.children) .map(|((pane, content), tree)| (pane, (content, tree))), |(content, tree), @@ -985,6 +988,24 @@ impl<'a, T> Contents<'a, T> { } } + fn layout_and_mut_iterator( + &mut self, + ) -> (&Node, Box + '_>) { + match self { + Contents::All(contents, state) => { + let layout = state.layout(); + let iter = Box::new( + contents.iter_mut().map(|(pane, content)| (*pane, content)), + ); + (layout, iter) + } + Contents::Maximized(pane, content, layout) => { + let iter = Box::new(std::iter::once((*pane, content))); + (layout, iter) + } + } + } + fn is_maximized(&self) -> bool { matches!(self, Self::Maximized(..)) } diff --git a/native/src/widget/pane_grid/content.rs b/native/src/widget/pane_grid/content.rs index c9b0df078f..e23a3865b8 100644 --- a/native/src/widget/pane_grid/content.rs +++ b/native/src/widget/pane_grid/content.rs @@ -89,7 +89,7 @@ where /// /// [`Renderer`]: crate::Renderer pub fn draw( - &self, + &mut self, tree: &Tree, renderer: &mut Renderer, theme: &Renderer::Theme, @@ -108,14 +108,14 @@ where container::draw_background(renderer, &style, bounds); } - if let Some(title_bar) = &self.title_bar { + if let Some(title_bar) = &mut self.title_bar { let mut children = layout.children(); let title_bar_layout = children.next().unwrap(); let body_layout = children.next().unwrap(); let show_controls = bounds.contains(cursor_position); - self.body.as_widget().draw( + self.body.as_widget_mut().draw( &tree.children[0], renderer, theme, @@ -136,7 +136,7 @@ where show_controls, ); } else { - self.body.as_widget().draw( + self.body.as_widget_mut().draw( &tree.children[0], renderer, theme, @@ -149,11 +149,11 @@ where } pub(crate) fn layout( - &self, + &mut self, 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 @@ -161,7 +161,7 @@ where let title_bar_size = title_bar_layout.size(); - let mut body_layout = self.body.as_widget().layout( + let mut body_layout = self.body.as_widget_mut().layout( renderer, &layout::Limits::new( Size::ZERO, @@ -179,7 +179,7 @@ where vec![title_bar_layout, body_layout], ) } else { - self.body.as_widget().layout(renderer, limits) + self.body.as_widget_mut().layout(renderer, limits) } } diff --git a/native/src/widget/pane_grid/title_bar.rs b/native/src/widget/pane_grid/title_bar.rs index 107078ef07..c234f9eb7d 100644 --- a/native/src/widget/pane_grid/title_bar.rs +++ b/native/src/widget/pane_grid/title_bar.rs @@ -116,7 +116,7 @@ where /// /// [`Renderer`]: crate::Renderer pub fn draw( - &self, + &mut self, tree: &Tree, renderer: &mut Renderer, theme: &Renderer::Theme, @@ -143,7 +143,7 @@ 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 { if show_controls || self.always_show_controls { let controls_layout = children.next().unwrap(); if title_layout.bounds().width + controls_layout.bounds().width @@ -152,7 +152,7 @@ where show_title = false; } - controls.as_widget().draw( + controls.as_widget_mut().draw( &tree.children[1], renderer, theme, @@ -165,7 +165,7 @@ where } if show_title { - self.content.as_widget().draw( + self.content.as_widget_mut().draw( &tree.children[0], renderer, theme, @@ -212,7 +212,7 @@ where } pub(crate) fn layout( - &self, + &mut self, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { @@ -221,14 +221,14 @@ where let title_layout = self .content - .as_widget() + .as_widget_mut() .layout(renderer, &layout::Limits::new(Size::ZERO, max_size)); let title_size = title_layout.size(); - let mut node = if let Some(controls) = &self.controls { + let mut node = if let Some(controls) = &mut self.controls { let mut controls_layout = controls - .as_widget() + .as_widget_mut() .layout(renderer, &layout::Limits::new(Size::ZERO, max_size)); let controls_size = controls_layout.size(); diff --git a/native/src/widget/pick_list.rs b/native/src/widget/pick_list.rs index 17528db40b..cf1d5f98c1 100644 --- a/native/src/widget/pick_list.rs +++ b/native/src/widget/pick_list.rs @@ -153,7 +153,7 @@ where } fn layout( - &self, + &mut self, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { @@ -203,7 +203,7 @@ where } fn draw( - &self, + &mut self, tree: &Tree, renderer: &mut Renderer, theme: &Renderer::Theme, diff --git a/native/src/widget/progress_bar.rs b/native/src/widget/progress_bar.rs index dd46fa76ce..bf92dc326e 100644 --- a/native/src/widget/progress_bar.rs +++ b/native/src/widget/progress_bar.rs @@ -91,7 +91,7 @@ where } fn layout( - &self, + &mut self, _renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { @@ -105,7 +105,7 @@ where } fn draw( - &self, + &mut self, _state: &Tree, renderer: &mut Renderer, theme: &Renderer::Theme, diff --git a/native/src/widget/radio.rs b/native/src/widget/radio.rs index 9daddfbc75..7ad861a8ae 100644 --- a/native/src/widget/radio.rs +++ b/native/src/widget/radio.rs @@ -155,7 +155,7 @@ where } fn layout( - &self, + &mut self, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { @@ -211,7 +211,7 @@ where } fn draw( - &self, + &mut self, _state: &Tree, renderer: &mut Renderer, theme: &Renderer::Theme, diff --git a/native/src/widget/row.rs b/native/src/widget/row.rs index 286c1c2d8c..6d0ee54e06 100644 --- a/native/src/widget/row.rs +++ b/native/src/widget/row.rs @@ -7,7 +7,7 @@ use crate::renderer; use crate::widget::{Operation, Tree}; use crate::{ Alignment, Clipboard, Element, Length, Padding, Pixels, Point, Rectangle, - Shell, Widget, + Shell, Size, Widget, }; /// A container that distributes its contents horizontally. @@ -113,7 +113,7 @@ where } fn layout( - &self, + &mut self, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { @@ -126,8 +126,29 @@ where self.padding, self.spacing, self.align_items, - &self.children, + &mut self.children, + layout::flex::LayoutMode::PerformLayout, + ) + } + + fn measure( + &mut self, + renderer: &Renderer, + limits: &layout::Limits, + ) -> Size { + let limits = limits.width(self.width).height(self.height); + + layout::flex::resolve( + layout::flex::Axis::Horizontal, + renderer, + &limits, + self.padding, + self.spacing as f32, + self.align_items, + &mut self.children, + layout::flex::LayoutMode::MeasureSize, ) + .size() } fn operate( @@ -204,7 +225,7 @@ where } fn draw( - &self, + &mut self, tree: &Tree, renderer: &mut Renderer, theme: &Renderer::Theme, @@ -215,11 +236,11 @@ where ) { for ((child, state), layout) in self .children - .iter() + .iter_mut() .zip(&tree.children) .zip(layout.children()) { - child.as_widget().draw( + child.as_widget_mut().draw( state, renderer, theme, diff --git a/native/src/widget/rule.rs b/native/src/widget/rule.rs index 1ab6a0d300..fc0f2a4578 100644 --- a/native/src/widget/rule.rs +++ b/native/src/widget/rule.rs @@ -70,7 +70,7 @@ where } fn layout( - &self, + &mut self, _renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { @@ -80,7 +80,7 @@ where } fn draw( - &self, + &mut self, _state: &Tree, renderer: &mut Renderer, theme: &Renderer::Theme, diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs index c1df8c39dc..cb446a0654 100644 --- a/native/src/widget/scrollable.rs +++ b/native/src/widget/scrollable.rs @@ -181,7 +181,7 @@ where } fn layout( - &self, + &mut self, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { @@ -192,7 +192,7 @@ where self.height, self.horizontal.is_some(), |renderer, limits| { - self.content.as_widget().layout(renderer, limits) + self.content.as_widget_mut().layout(renderer, limits) }, ) } @@ -256,7 +256,7 @@ where } fn draw( - &self, + &mut self, tree: &Tree, renderer: &mut Renderer, theme: &Renderer::Theme, @@ -275,7 +275,7 @@ where self.horizontal.as_ref(), &self.style, |renderer, layout, cursor_position, viewport| { - self.content.as_widget().draw( + self.content.as_widget_mut().draw( &tree.children[0], renderer, theme, diff --git a/native/src/widget/slider.rs b/native/src/widget/slider.rs index d10797bb8b..099c7e4f32 100644 --- a/native/src/widget/slider.rs +++ b/native/src/widget/slider.rs @@ -168,7 +168,7 @@ where } fn layout( - &self, + &mut self, _renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { @@ -203,7 +203,7 @@ where } fn draw( - &self, + &mut self, tree: &Tree, renderer: &mut Renderer, theme: &Renderer::Theme, diff --git a/native/src/widget/space.rs b/native/src/widget/space.rs index a6fc977e01..62a9934fcf 100644 --- a/native/src/widget/space.rs +++ b/native/src/widget/space.rs @@ -52,7 +52,7 @@ where } fn layout( - &self, + &mut self, _renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { @@ -62,7 +62,7 @@ where } fn draw( - &self, + &mut self, _state: &Tree, _renderer: &mut Renderer, _theme: &Renderer::Theme, diff --git a/native/src/widget/svg.rs b/native/src/widget/svg.rs index f5ed0a6c88..31d6af4048 100644 --- a/native/src/widget/svg.rs +++ b/native/src/widget/svg.rs @@ -104,7 +104,7 @@ where } fn layout( - &self, + &mut self, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { @@ -137,7 +137,7 @@ where } fn draw( - &self, + &mut self, _state: &Tree, renderer: &mut Renderer, theme: &Renderer::Theme, diff --git a/native/src/widget/text.rs b/native/src/widget/text.rs index 3fee48f25b..5ea7ca4007 100644 --- a/native/src/widget/text.rs +++ b/native/src/widget/text.rs @@ -128,7 +128,7 @@ where } fn layout( - &self, + &mut self, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { @@ -147,7 +147,7 @@ where } fn draw( - &self, + &mut self, _state: &Tree, renderer: &mut Renderer, theme: &Renderer::Theme, diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index ee0473ea78..baff5ff44b 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -219,7 +219,7 @@ where } fn layout( - &self, + &mut self, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { @@ -268,7 +268,7 @@ where } fn draw( - &self, + &mut self, tree: &Tree, renderer: &mut Renderer, theme: &Renderer::Theme, diff --git a/native/src/widget/toggler.rs b/native/src/widget/toggler.rs index a434af65ea..47da726ccc 100644 --- a/native/src/widget/toggler.rs +++ b/native/src/widget/toggler.rs @@ -147,7 +147,7 @@ where } fn layout( - &self, + &mut self, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { @@ -216,7 +216,7 @@ where } fn draw( - &self, + &mut self, _state: &Tree, renderer: &mut Renderer, theme: &Renderer::Theme, diff --git a/native/src/widget/tooltip.rs b/native/src/widget/tooltip.rs index 2a24c05566..5be26e253e 100644 --- a/native/src/widget/tooltip.rs +++ b/native/src/widget/tooltip.rs @@ -123,11 +123,11 @@ where } fn layout( - &self, + &mut self, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { - self.content.as_widget().layout(renderer, limits) + self.content.as_widget_mut().layout(renderer, limits) } fn on_event( @@ -169,7 +169,7 @@ where } fn draw( - &self, + &mut self, tree: &Tree, renderer: &mut Renderer, theme: &Renderer::Theme, @@ -178,7 +178,7 @@ where cursor_position: Point, viewport: &Rectangle, ) { - self.content.as_widget().draw( + self.content.as_widget_mut().draw( &tree.children[0], renderer, theme, @@ -188,7 +188,7 @@ where viewport, ); - let tooltip = &self.tooltip; + let tooltip = &mut self.tooltip; draw( renderer, @@ -202,10 +202,11 @@ where self.padding, self.snap_within_viewport, &self.style, - |renderer, limits| { + tooltip, + |tooltip, renderer, limits| { Widget::<(), Renderer>::layout(tooltip, renderer, limits) }, - |renderer, defaults, layout, cursor_position, viewport| { + |tooltip, renderer, defaults, layout, cursor_position, viewport| { Widget::<(), Renderer>::draw( tooltip, &Tree::empty(), @@ -264,7 +265,7 @@ pub enum Position { } /// Draws a [`Tooltip`]. -pub fn draw( +pub fn draw( renderer: &mut Renderer, theme: &Renderer::Theme, inherited_style: &renderer::Style, @@ -276,8 +277,14 @@ pub fn draw( padding: f32, snap_within_viewport: bool, style: &::Style, - layout_text: impl FnOnce(&Renderer, &layout::Limits) -> layout::Node, + tooltip: &mut Tooltip, + layout_text: impl FnOnce( + &mut Tooltip, + &Renderer, + &layout::Limits, + ) -> layout::Node, draw_text: impl FnOnce( + &mut Tooltip, &mut Renderer, &renderer::Style, Layout<'_>, @@ -285,6 +292,7 @@ pub fn draw( &Rectangle, ), ) where + Tooltip: Widget<(), Renderer>, Renderer: crate::Renderer, Renderer::Theme: container::StyleSheet, { @@ -300,6 +308,7 @@ pub fn draw( }; let text_layout = layout_text( + tooltip, renderer, &layout::Limits::new( Size::ZERO, @@ -370,6 +379,7 @@ pub fn draw( container::draw_background(renderer, &style, tooltip_bounds); draw_text( + tooltip, renderer, &defaults, Layout::with_offset( diff --git a/native/src/widget/vertical_slider.rs b/native/src/widget/vertical_slider.rs index 0e2f5fc9e7..8863bd1e74 100644 --- a/native/src/widget/vertical_slider.rs +++ b/native/src/widget/vertical_slider.rs @@ -162,7 +162,7 @@ where } fn layout( - &self, + &mut self, _renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { @@ -197,7 +197,7 @@ where } fn draw( - &self, + &mut self, tree: &Tree, renderer: &mut Renderer, theme: &Renderer::Theme,