diff options
| author | 2024-01-09 06:35:33 +0100 | |
|---|---|---|
| committer | 2024-01-10 10:01:49 +0100 | |
| commit | d62bb8193c1c43f565fcc5c52293d564c91e215d (patch) | |
| tree | 7f2d33d2f18a3dfb4e4e8e46b4e968523ca43bc6 | |
| parent | d24e50c1a61eee7bca887224ad583eca60e14d32 (diff) | |
| download | iced-d62bb8193c1c43f565fcc5c52293d564c91e215d.tar.gz iced-d62bb8193c1c43f565fcc5c52293d564c91e215d.tar.bz2 iced-d62bb8193c1c43f565fcc5c52293d564c91e215d.zip | |
Introduce useful helpers in `layout` module
| -rw-r--r-- | core/src/layout.rs | 94 | ||||
| -rw-r--r-- | core/src/layout/flex.rs | 2 | ||||
| -rw-r--r-- | core/src/layout/limits.rs | 7 | ||||
| -rw-r--r-- | core/src/layout/node.rs | 10 | ||||
| -rw-r--r-- | core/src/point.rs | 20 | ||||
| -rw-r--r-- | core/src/widget/text.rs | 43 | ||||
| -rw-r--r-- | examples/geometry/src/main.rs | 4 | ||||
| -rw-r--r-- | examples/loading_spinners/src/circular.rs | 5 | ||||
| -rw-r--r-- | examples/loading_spinners/src/linear.rs | 5 | ||||
| -rw-r--r-- | widget/src/button.rs | 19 | ||||
| -rw-r--r-- | widget/src/canvas.rs | 4 | ||||
| -rw-r--r-- | widget/src/container.rs | 28 | ||||
| -rw-r--r-- | widget/src/image.rs | 2 | ||||
| -rw-r--r-- | widget/src/image/viewer.rs | 2 | ||||
| -rw-r--r-- | widget/src/overlay/menu.rs | 2 | ||||
| -rw-r--r-- | widget/src/pane_grid.rs | 2 | ||||
| -rw-r--r-- | widget/src/pick_list.rs | 5 | ||||
| -rw-r--r-- | widget/src/progress_bar.rs | 8 | ||||
| -rw-r--r-- | widget/src/rule.rs | 2 | ||||
| -rw-r--r-- | widget/src/scrollable.rs | 39 | ||||
| -rw-r--r-- | widget/src/shader.rs | 5 | ||||
| -rw-r--r-- | widget/src/slider.rs | 4 | ||||
| -rw-r--r-- | widget/src/space.rs | 2 | ||||
| -rw-r--r-- | widget/src/svg.rs | 2 | ||||
| -rw-r--r-- | widget/src/text_input.rs | 4 | ||||
| -rw-r--r-- | widget/src/vertical_slider.rs | 4 | 
26 files changed, 193 insertions, 131 deletions
| diff --git a/core/src/layout.rs b/core/src/layout.rs index 277473fe..95720aba 100644 --- a/core/src/layout.rs +++ b/core/src/layout.rs @@ -7,7 +7,7 @@ pub mod flex;  pub use limits::Limits;  pub use node::Node; -use crate::{Point, Rectangle, Size, Vector}; +use crate::{Length, Padding, Point, Rectangle, Size, Vector};  /// The bounds of a [`Node`] and its children, using absolute coordinates.  #[derive(Debug, Clone, Copy)] @@ -96,3 +96,95 @@ pub fn next_to_each_other(          ],      )  } + +/// Computes the resulting [`Node`] that fits the [`Limits`] given +/// some width and height requirements and no intrinsic size. +pub fn atomic( +    limits: &Limits, +    width: impl Into<Length>, +    height: impl Into<Length>, +) -> Node { +    let width = width.into(); +    let height = height.into(); + +    Node::new(limits.resolve(width, height, Size::ZERO)) +} + +/// Computes the resulting [`Node`] that fits the [`Limits`] given +/// some width and height requirements and a closure that produces +/// the intrinsic [`Size`] inside the given [`Limits`]. +pub fn sized( +    limits: &Limits, +    width: impl Into<Length>, +    height: impl Into<Length>, +    f: impl FnOnce(&Limits) -> Size, +) -> Node { +    let width = width.into(); +    let height = height.into(); + +    let limits = limits.width(width).height(height); +    let intrinsic_size = f(&limits); + +    Node::new(limits.resolve(width, height, intrinsic_size)) +} + +/// Computes the resulting [`Node`] that fits the [`Limits`] given +/// some width and height requirements and a closure that produces +/// the content [`Node`] inside the given [`Limits`]. +pub fn contained( +    limits: &Limits, +    width: impl Into<Length>, +    height: impl Into<Length>, +    f: impl FnOnce(&Limits) -> Node, +) -> Node { +    let width = width.into(); +    let height = height.into(); + +    let limits = limits.width(width).height(height); +    let content = f(&limits); + +    Node::with_children( +        limits.resolve(width, height, content.size()), +        vec![content], +    ) +} + +/// Computes the [`Node`] that fits the [`Limits`] given some width, height, and +/// [`Padding`] requirements and a closure that produces the content [`Node`] +/// inside the given [`Limits`]. +pub fn padded( +    limits: &Limits, +    width: impl Into<Length>, +    height: impl Into<Length>, +    padding: impl Into<Padding>, +    layout: impl FnOnce(&Limits) -> Node, +) -> Node { +    positioned(limits, width, height, padding, layout, |content, _| content) +} + +/// Computes a [`padded`] [`Node`] with a positioning step. +pub fn positioned( +    limits: &Limits, +    width: impl Into<Length>, +    height: impl Into<Length>, +    padding: impl Into<Padding>, +    layout: impl FnOnce(&Limits) -> Node, +    position: impl FnOnce(Node, Size) -> Node, +) -> Node { +    let width = width.into(); +    let height = height.into(); +    let padding = padding.into(); + +    let limits = limits.width(width).height(height); +    let content = layout(&limits.shrink(padding)); +    let padding = padding.fit(content.size(), limits.max()); + +    let size = limits +        .shrink(padding) +        .resolve(width, height, content.size()); + +    Node::with_children( +        size.expand(padding), +        vec![position(content.move_to((padding.left, padding.top)), size)], +    ) +} diff --git a/core/src/layout/flex.rs b/core/src/layout/flex.rs index 2a12d57f..cf3e1340 100644 --- a/core/src/layout/flex.rs +++ b/core/src/layout/flex.rs @@ -239,9 +239,9 @@ where      let (intrinsic_width, intrinsic_height) = axis.pack(main - pad.0, cross);      let size = limits.resolve( -        Size::new(intrinsic_width, intrinsic_height),          width,          height, +        Size::new(intrinsic_width, intrinsic_height),      );      Node::with_children(size.expand(padding), nodes) diff --git a/core/src/layout/limits.rs b/core/src/layout/limits.rs index eef4c4c9..7fbc7b9d 100644 --- a/core/src/layout/limits.rs +++ b/core/src/layout/limits.rs @@ -114,13 +114,14 @@ impl Limits {          }      } -    /// Computes the resulting [`Size`] that fits the [`Limits`] given the -    /// intrinsic size of some content. +    /// Computes the resulting [`Size`] that fits the [`Limits`] given +    /// some width and height requirements and the intrinsic size of +    /// some content.      pub fn resolve(          &self, -        intrinsic_size: Size,          width: impl Into<Length>,          height: impl Into<Length>, +        intrinsic_size: Size,      ) -> Size {          let width = match width.into() {              Length::Fill | Length::FillPortion(_) => self.max.width, diff --git a/core/src/layout/node.rs b/core/src/layout/node.rs index 00087431..40c71436 100644 --- a/core/src/layout/node.rs +++ b/core/src/layout/node.rs @@ -89,19 +89,23 @@ impl Node {      }      /// Moves the [`Node`] to the given position. -    pub fn move_to(mut self, position: Point) -> Self { +    pub fn move_to(mut self, position: impl Into<Point>) -> Self {          self.move_to_mut(position);          self      }      /// Mutable reference version of [`move_to`]. -    pub fn move_to_mut(&mut self, position: Point) { +    pub fn move_to_mut(&mut self, position: impl Into<Point>) { +        let position = position.into(); +          self.bounds.x = position.x;          self.bounds.y = position.y;      }      /// Translates the [`Node`] by the given translation. -    pub fn translate(self, translation: Vector) -> Self { +    pub fn translate(self, translation: impl Into<Vector>) -> Self { +        let translation = translation.into(); +          Self {              bounds: self.bounds + translation,              ..self diff --git a/core/src/point.rs b/core/src/point.rs index ef42852f..cea57518 100644 --- a/core/src/point.rs +++ b/core/src/point.rs @@ -36,20 +36,26 @@ impl<T: Num> Point<T> {      }  } -impl From<[f32; 2]> for Point { -    fn from([x, y]: [f32; 2]) -> Self { +impl<T> From<[T; 2]> for Point<T> +where +    T: Num, +{ +    fn from([x, y]: [T; 2]) -> Self {          Point { x, y }      }  } -impl From<[u16; 2]> for Point<u16> { -    fn from([x, y]: [u16; 2]) -> Self { -        Point::new(x, y) +impl<T> From<(T, T)> for Point<T> +where +    T: Num, +{ +    fn from((x, y): (T, T)) -> Self { +        Self { x, y }      }  } -impl From<Point> for [f32; 2] { -    fn from(point: Point) -> [f32; 2] { +impl<T> From<Point<T>> for [T; 2] { +    fn from(point: Point<T>) -> [T; 2] {          [point.x, point.y]      }  } diff --git a/core/src/widget/text.rs b/core/src/widget/text.rs index fe3b77d3..4cabc7ce 100644 --- a/core/src/widget/text.rs +++ b/core/src/widget/text.rs @@ -206,28 +206,27 @@ pub fn layout<Renderer>(  where      Renderer: text::Renderer,  { -    let limits = limits.width(width).height(height); -    let bounds = limits.max(); - -    let size = size.unwrap_or_else(|| renderer.default_size()); -    let font = font.unwrap_or_else(|| renderer.default_font()); - -    let State(ref mut paragraph) = state; - -    paragraph.update(text::Text { -        content, -        bounds, -        size, -        line_height, -        font, -        horizontal_alignment, -        vertical_alignment, -        shaping, -    }); - -    let size = limits.resolve(paragraph.min_bounds(), width, height); - -    layout::Node::new(size) +    layout::sized(limits, width, height, |limits| { +        let bounds = limits.max(); + +        let size = size.unwrap_or_else(|| renderer.default_size()); +        let font = font.unwrap_or_else(|| renderer.default_font()); + +        let State(ref mut paragraph) = state; + +        paragraph.update(text::Text { +            content, +            bounds, +            size, +            line_height, +            font, +            horizontal_alignment, +            vertical_alignment, +            shaping, +        }); + +        paragraph.min_bounds() +    })  }  /// Draws text using the same logic as the [`Text`] widget. diff --git a/examples/geometry/src/main.rs b/examples/geometry/src/main.rs index d6a4c702..5cf9963d 100644 --- a/examples/geometry/src/main.rs +++ b/examples/geometry/src/main.rs @@ -29,9 +29,9 @@ mod rainbow {              _renderer: &Renderer,              limits: &layout::Limits,          ) -> layout::Node { -            let size = limits.resolve(Size::ZERO, Length::Fill, Length::Shrink); +            let width = limits.max().width; -            layout::Node::new(Size::new(size.width, size.width)) +            layout::Node::new(Size::new(width, width))          }          fn draw( diff --git a/examples/loading_spinners/src/circular.rs b/examples/loading_spinners/src/circular.rs index e80617d0..1b163585 100644 --- a/examples/loading_spinners/src/circular.rs +++ b/examples/loading_spinners/src/circular.rs @@ -257,10 +257,7 @@ where          _renderer: &iced::Renderer<Theme>,          limits: &layout::Limits,      ) -> layout::Node { -        let limits = limits.width(self.size).height(self.size); -        let size = limits.resolve(Size::ZERO, self.size, self.size); - -        layout::Node::new(size) +        layout::atomic(limits, self.size, self.size)      }      fn on_event( diff --git a/examples/loading_spinners/src/linear.rs b/examples/loading_spinners/src/linear.rs index d205d3f1..d245575c 100644 --- a/examples/loading_spinners/src/linear.rs +++ b/examples/loading_spinners/src/linear.rs @@ -178,10 +178,7 @@ where          _renderer: &Renderer,          limits: &layout::Limits,      ) -> layout::Node { -        let limits = limits.width(self.width).height(self.height); -        let size = limits.resolve(Size::ZERO, self.width, self.height); - -        layout::Node::new(size) +        layout::atomic(limits, self.width, self.height)      }      fn on_event( diff --git a/widget/src/button.rs b/widget/src/button.rs index 1ce4f662..86abee77 100644 --- a/widget/src/button.rs +++ b/widget/src/button.rs @@ -10,8 +10,8 @@ use crate::core::touch;  use crate::core::widget::tree::{self, Tree};  use crate::core::widget::Operation;  use crate::core::{ -    Background, Clipboard, Color, Element, Layout, Length, Padding, Point, -    Rectangle, Shell, Size, Vector, Widget, +    Background, Clipboard, Color, Element, Layout, Length, Padding, Rectangle, +    Shell, Size, Vector, Widget,  };  pub use iced_style::button::{Appearance, StyleSheet}; @@ -430,20 +430,7 @@ pub fn layout(      padding: Padding,      layout_content: impl FnOnce(&layout::Limits) -> layout::Node,  ) -> layout::Node { -    let limits = limits.width(width).height(height); - -    let content = layout_content(&limits.shrink(padding)); -    let padding = padding.fit(content.size(), limits.max()); - -    let size = limits -        .shrink(padding) -        .resolve(content.size(), width, height) -        .expand(padding); - -    layout::Node::with_children( -        size, -        vec![content.move_to(Point::new(padding.left, padding.top))], -    ) +    layout::padded(limits, width, height, padding, layout_content)  }  /// Returns the [`mouse::Interaction`] of a [`Button`]. diff --git a/widget/src/canvas.rs b/widget/src/canvas.rs index 2bf09eec..4e42a671 100644 --- a/widget/src/canvas.rs +++ b/widget/src/canvas.rs @@ -133,9 +133,7 @@ where          _renderer: &Renderer,          limits: &layout::Limits,      ) -> layout::Node { -        let size = limits.resolve(Size::ZERO, self.width, self.height); - -        layout::Node::new(size) +        layout::atomic(limits, self.width, self.height)      }      fn on_event( diff --git a/widget/src/container.rs b/widget/src/container.rs index 93d8daba..c98de41c 100644 --- a/widget/src/container.rs +++ b/widget/src/container.rs @@ -321,27 +321,19 @@ pub fn layout(      vertical_alignment: alignment::Vertical,      layout_content: impl FnOnce(&layout::Limits) -> layout::Node,  ) -> layout::Node { -    let limits = limits -        .width(width) -        .height(height) -        .max_width(max_width) -        .max_height(max_height); - -    let content = layout_content(&limits.shrink(padding).loose()); -    let padding = padding.fit(content.size(), limits.max()); -    let size = limits -        .shrink(padding) -        .resolve(content.size(), width, height); - -    layout::Node::with_children( -        size.expand(padding), -        vec![content -            .move_to(Point::new(padding.left, padding.top)) -            .align( +    layout::positioned( +        &limits.max_width(max_width).max_height(max_height), +        width, +        height, +        padding, +        |limits| layout_content(&limits.loose()), +        |content, size| { +            content.align(                  Alignment::from(horizontal_alignment),                  Alignment::from(vertical_alignment),                  size, -            )], +            ) +        },      )  } diff --git a/widget/src/image.rs b/widget/src/image.rs index 6750c1b3..e906ac13 100644 --- a/widget/src/image.rs +++ b/widget/src/image.rs @@ -99,7 +99,7 @@ where      };      // The size to be available to the widget prior to `Shrink`ing -    let raw_size = limits.resolve(image_size, width, height); +    let raw_size = limits.resolve(width, height, image_size);      // The uncropped size of the image when fit to the bounds above      let full_size = content_fit.fit(image_size, raw_size); diff --git a/widget/src/image/viewer.rs b/widget/src/image/viewer.rs index dc910f1f..98080577 100644 --- a/widget/src/image/viewer.rs +++ b/widget/src/image/viewer.rs @@ -113,9 +113,9 @@ where          let Size { width, height } = renderer.dimensions(&self.handle);          let mut size = limits.resolve( -            Size::new(width as f32, height as f32),              self.width,              self.height, +            Size::new(width as f32, height as f32),          );          let expansion_size = if height > width { diff --git a/widget/src/overlay/menu.rs b/widget/src/overlay/menu.rs index b9e06de8..f83eebea 100644 --- a/widget/src/overlay/menu.rs +++ b/widget/src/overlay/menu.rs @@ -369,7 +369,7 @@ where                      * self.options.len() as f32,              ); -            limits.resolve(intrinsic, Length::Fill, Length::Shrink) +            limits.resolve(Length::Fill, Length::Shrink, intrinsic)          };          layout::Node::new(size) diff --git a/widget/src/pane_grid.rs b/widget/src/pane_grid.rs index 36c785b7..cf1f0455 100644 --- a/widget/src/pane_grid.rs +++ b/widget/src/pane_grid.rs @@ -489,7 +489,7 @@ pub fn layout<Renderer, T>(          &layout::Limits,      ) -> layout::Node,  ) -> layout::Node { -    let size = limits.resolve(Size::ZERO, width, height); +    let size = limits.resolve(width, height, Size::ZERO);      let regions = node.pane_regions(spacing, size);      let children = contents diff --git a/widget/src/pick_list.rs b/widget/src/pick_list.rs index d83b0624..2576a1e8 100644 --- a/widget/src/pick_list.rs +++ b/widget/src/pick_list.rs @@ -392,7 +392,6 @@ where  {      use std::f32; -    let limits = limits.width(width).height(Length::Shrink);      let font = font.unwrap_or_else(|| renderer.default_font());      let text_size = text_size.unwrap_or_else(|| renderer.default_size()); @@ -451,8 +450,10 @@ where          );          limits +            .width(width) +            .height(Length::Shrink)              .shrink(padding) -            .resolve(intrinsic, width, Length::Shrink) +            .resolve(width, Length::Shrink, intrinsic)              .expand(padding)      }; diff --git a/widget/src/progress_bar.rs b/widget/src/progress_bar.rs index a05923a2..15f1277b 100644 --- a/widget/src/progress_bar.rs +++ b/widget/src/progress_bar.rs @@ -98,13 +98,11 @@ where          _renderer: &Renderer,          limits: &layout::Limits,      ) -> layout::Node { -        let size = limits.resolve( -            Size::ZERO, +        layout::atomic( +            limits,              self.width,              self.height.unwrap_or(Length::Fixed(Self::DEFAULT_HEIGHT)), -        ); - -        layout::Node::new(size) +        )      }      fn draw( diff --git a/widget/src/rule.rs b/widget/src/rule.rs index 4ab16c40..cded9cb1 100644 --- a/widget/src/rule.rs +++ b/widget/src/rule.rs @@ -75,7 +75,7 @@ where          _renderer: &Renderer,          limits: &layout::Limits,      ) -> layout::Node { -        layout::Node::new(limits.resolve(Size::ZERO, self.width, self.height)) +        layout::atomic(limits, self.width, self.height)      }      fn draw( diff --git a/widget/src/scrollable.rs b/widget/src/scrollable.rs index 5197afde..70db490a 100644 --- a/widget/src/scrollable.rs +++ b/widget/src/scrollable.rs @@ -469,28 +469,25 @@ pub fn layout<Renderer>(      direction: &Direction,      layout_content: impl FnOnce(&Renderer, &layout::Limits) -> layout::Node,  ) -> layout::Node { -    let limits = limits.width(width).height(height); - -    let child_limits = layout::Limits::new( -        Size::new(limits.min().width, limits.min().height), -        Size::new( -            if direction.horizontal().is_some() { -                f32::INFINITY -            } else { -                limits.max().width -            }, -            if direction.vertical().is_some() { -                f32::MAX -            } else { -                limits.max().height -            }, -        ), -    ); - -    let content = layout_content(renderer, &child_limits); -    let size = limits.resolve(content.size(), width, height); +    layout::contained(limits, width, height, |limits| { +        let child_limits = layout::Limits::new( +            Size::new(limits.min().width, limits.min().height), +            Size::new( +                if direction.horizontal().is_some() { +                    f32::INFINITY +                } else { +                    limits.max().width +                }, +                if direction.vertical().is_some() { +                    f32::MAX +                } else { +                    limits.max().height +                }, +            ), +        ); -    layout::Node::with_children(size, vec![content]) +        layout_content(renderer, &child_limits) +    })  }  /// Processes an [`Event`] and updates the [`State`] of a [`Scrollable`] diff --git a/widget/src/shader.rs b/widget/src/shader.rs index 82432c6c..16b68c55 100644 --- a/widget/src/shader.rs +++ b/widget/src/shader.rs @@ -83,10 +83,7 @@ where          _renderer: &Renderer,          limits: &layout::Limits,      ) -> layout::Node { -        let limits = limits.width(self.width).height(self.height); -        let size = limits.resolve(Size::ZERO, self.width, self.height); - -        layout::Node::new(size) +        layout::atomic(limits, self.width, self.height)      }      fn on_event( diff --git a/widget/src/slider.rs b/widget/src/slider.rs index 27588852..1bc94661 100644 --- a/widget/src/slider.rs +++ b/widget/src/slider.rs @@ -172,9 +172,7 @@ where          _renderer: &Renderer,          limits: &layout::Limits,      ) -> layout::Node { -        let size = limits.resolve(Size::ZERO, self.width, self.height); - -        layout::Node::new(size) +        layout::atomic(limits, self.width, self.height)      }      fn on_event( diff --git a/widget/src/space.rs b/widget/src/space.rs index 9fd4dcb9..eef990d1 100644 --- a/widget/src/space.rs +++ b/widget/src/space.rs @@ -58,7 +58,7 @@ where          _renderer: &Renderer,          limits: &layout::Limits,      ) -> layout::Node { -        layout::Node::new(limits.resolve(Size::ZERO, self.width, self.height)) +        layout::atomic(limits, self.width, self.height)      }      fn draw( diff --git a/widget/src/svg.rs b/widget/src/svg.rs index 75ab238a..830abb0f 100644 --- a/widget/src/svg.rs +++ b/widget/src/svg.rs @@ -114,7 +114,7 @@ where          let image_size = Size::new(width as f32, height as f32);          // The size to be available to the widget prior to `Shrink`ing -        let raw_size = limits.resolve(image_size, self.width, self.height); +        let raw_size = limits.resolve(self.width, self.height, image_size);          // The uncropped size of the image when fit to the bounds above          let full_size = self.content_fit.fit(image_size, raw_size); diff --git a/widget/src/text_input.rs b/widget/src/text_input.rs index 7e91105c..d8540658 100644 --- a/widget/src/text_input.rs +++ b/widget/src/text_input.rs @@ -508,8 +508,8 @@ where      let padding = padding.fit(Size::ZERO, limits.max());      let height = line_height.to_absolute(text_size); -    let limits = limits.width(width).shrink(padding).height(height); -    let text_bounds = limits.resolve(Size::ZERO, width, height); +    let limits = limits.width(width).shrink(padding); +    let text_bounds = limits.resolve(width, height, Size::ZERO);      let placeholder_text = Text {          font, diff --git a/widget/src/vertical_slider.rs b/widget/src/vertical_slider.rs index 35bc2fe2..a3029d76 100644 --- a/widget/src/vertical_slider.rs +++ b/widget/src/vertical_slider.rs @@ -169,9 +169,7 @@ where          _renderer: &Renderer,          limits: &layout::Limits,      ) -> layout::Node { -        let size = limits.resolve(Size::ZERO, self.width, self.height); - -        layout::Node::new(size) +        layout::atomic(limits, self.width, self.height)      }      fn on_event( | 
