From 2088e5d66117dd481e4c60ba6afe9ab8f3a2d4c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Tue, 12 Mar 2024 13:25:06 +0100 Subject: [PATCH 01/17] Try using closures for `Container::style` `Box` should not allocate for zero-sized types; so we should not be incurring much overhead. Just a bit of indirection. --- widget/src/container.rs | 41 +++++++++++++++++-------------- widget/src/helpers.rs | 4 +-- widget/src/pane_grid/content.rs | 12 ++++----- widget/src/pane_grid/title_bar.rs | 10 ++++---- widget/src/tooltip.rs | 15 +++++------ 5 files changed, 43 insertions(+), 39 deletions(-) diff --git a/widget/src/container.rs b/widget/src/container.rs index d606b0aaf7..f51ff8789d 100644 --- a/widget/src/container.rs +++ b/widget/src/container.rs @@ -36,7 +36,7 @@ pub struct Container< vertical_alignment: alignment::Vertical, clip: bool, content: Element<'a, Message, Theme, Renderer>, - style: Style, + style: Style<'a, Theme>, } impl<'a, Message, Theme, Renderer> Container<'a, Message, Theme, Renderer> @@ -48,15 +48,15 @@ where content: impl Into>, ) -> Self where - Theme: DefaultStyle, + Theme: DefaultStyle + 'a, { - Self::with_style(content, Theme::default_style()) + Self::with_style(content, Theme::default_style) } /// Creates a [`Container`] with the given content and style. pub fn with_style( content: impl Into>, - style: fn(&Theme, Status) -> Appearance, + style: impl Fn(&Theme, Status) -> Appearance + 'a, ) -> Self { let content = content.into(); let size = content.as_widget().size_hint(); @@ -71,8 +71,8 @@ where horizontal_alignment: alignment::Horizontal::Left, vertical_alignment: alignment::Vertical::Top, clip: false, + style: Box::new(style), content, - style, } } @@ -137,8 +137,11 @@ where } /// Sets the style of the [`Container`]. - pub fn style(mut self, style: fn(&Theme, Status) -> Appearance) -> Self { - self.style = style; + pub fn style( + mut self, + style: impl Fn(&Theme, Status) -> Appearance + 'a, + ) -> Self { + self.style = Box::new(style); self } @@ -546,41 +549,41 @@ pub enum Status { } /// The style of a [`Container`]. -pub type Style = fn(&Theme, Status) -> Appearance; +pub type Style<'a, Theme> = Box Appearance + 'a>; /// The default style of a [`Container`]. pub trait DefaultStyle { /// Returns the default style of a [`Container`]. - fn default_style() -> Style; + fn default_style(&self, status: Status) -> Appearance; } impl DefaultStyle for Theme { - fn default_style() -> Style { - transparent + fn default_style(&self, status: Status) -> Appearance { + transparent(self, status) } } impl DefaultStyle for Appearance { - fn default_style() -> Style { - |appearance, _status| *appearance + fn default_style(&self, _status: Status) -> Appearance { + *self } } impl DefaultStyle for Color { - fn default_style() -> Style { - |color, _status| Appearance::default().with_background(*color) + fn default_style(&self, _status: Status) -> Appearance { + Appearance::default().with_background(*self) } } impl DefaultStyle for Gradient { - fn default_style() -> Style { - |gradient, _status| Appearance::default().with_background(*gradient) + fn default_style(&self, _status: Status) -> Appearance { + Appearance::default().with_background(*self) } } impl DefaultStyle for gradient::Linear { - fn default_style() -> Style { - |gradient, _status| Appearance::default().with_background(*gradient) + fn default_style(&self, _status: Status) -> Appearance { + Appearance::default().with_background(*self) } } diff --git a/widget/src/helpers.rs b/widget/src/helpers.rs index 75072d2e20..89d6ef622e 100644 --- a/widget/src/helpers.rs +++ b/widget/src/helpers.rs @@ -58,7 +58,7 @@ pub fn container<'a, Message, Theme, Renderer>( content: impl Into>, ) -> Container<'a, Message, Theme, Renderer> where - Theme: container::DefaultStyle, + Theme: container::DefaultStyle + 'a, Renderer: core::Renderer, { Container::new(content) @@ -134,7 +134,7 @@ pub fn tooltip<'a, Message, Theme, Renderer>( position: tooltip::Position, ) -> crate::Tooltip<'a, Message, Theme, Renderer> where - Theme: container::DefaultStyle, + Theme: container::DefaultStyle + 'a, Renderer: core::text::Renderer, { Tooltip::new(content, tooltip, position) diff --git a/widget/src/pane_grid/content.rs b/widget/src/pane_grid/content.rs index aecec77749..98f4f99af3 100644 --- a/widget/src/pane_grid/content.rs +++ b/widget/src/pane_grid/content.rs @@ -24,7 +24,7 @@ pub struct Content< { title_bar: Option>, body: Element<'a, Message, Theme, Renderer>, - style: container::Style, + style: container::Style<'a, Theme>, } impl<'a, Message, Theme, Renderer> Content<'a, Message, Theme, Renderer> @@ -34,12 +34,12 @@ where /// Creates a new [`Content`] with the provided body. pub fn new(body: impl Into>) -> Self where - Theme: container::DefaultStyle, + Theme: container::DefaultStyle + 'a, { Self { title_bar: None, body: body.into(), - style: Theme::default_style(), + style: Box::new(Theme::default_style), } } @@ -55,9 +55,9 @@ where /// Sets the style of the [`Content`]. pub fn style( mut self, - style: fn(&Theme, container::Status) -> container::Appearance, + style: impl Fn(&Theme, container::Status) -> container::Appearance + 'a, ) -> Self { - self.style = style.into(); + self.style = Box::new(style); self } } @@ -403,7 +403,7 @@ impl<'a, T, Message, Theme, Renderer> From for Content<'a, Message, Theme, Renderer> where T: Into>, - Theme: container::DefaultStyle, + Theme: container::DefaultStyle + 'a, Renderer: crate::core::Renderer, { fn from(element: T) -> Self { diff --git a/widget/src/pane_grid/title_bar.rs b/widget/src/pane_grid/title_bar.rs index 37f0f16030..8dfea6e319 100644 --- a/widget/src/pane_grid/title_bar.rs +++ b/widget/src/pane_grid/title_bar.rs @@ -25,7 +25,7 @@ pub struct TitleBar< controls: Option>, padding: Padding, always_show_controls: bool, - style: container::Style, + style: container::Style<'a, Theme>, } impl<'a, Message, Theme, Renderer> TitleBar<'a, Message, Theme, Renderer> @@ -37,14 +37,14 @@ where content: impl Into>, ) -> Self where - Theme: container::DefaultStyle, + Theme: container::DefaultStyle + 'a, { Self { content: content.into(), controls: None, padding: Padding::ZERO, always_show_controls: false, - style: Theme::default_style(), + style: Box::new(Theme::default_style), } } @@ -66,9 +66,9 @@ where /// Sets the style of the [`TitleBar`]. pub fn style( mut self, - style: fn(&Theme, container::Status) -> container::Appearance, + style: impl Fn(&Theme, container::Status) -> container::Appearance + 'a, ) -> Self { - self.style = style.into(); + self.style = Box::new(style); self } diff --git a/widget/src/tooltip.rs b/widget/src/tooltip.rs index 8c8ee9831a..8e11ca986b 100644 --- a/widget/src/tooltip.rs +++ b/widget/src/tooltip.rs @@ -28,7 +28,7 @@ pub struct Tooltip< gap: f32, padding: f32, snap_within_viewport: bool, - style: container::Style, + style: container::Style<'a, Theme>, } impl<'a, Message, Theme, Renderer> Tooltip<'a, Message, Theme, Renderer> @@ -47,7 +47,7 @@ where position: Position, ) -> Self where - Theme: container::DefaultStyle, + Theme: container::DefaultStyle + 'a, { Tooltip { content: content.into(), @@ -56,7 +56,7 @@ where gap: 0.0, padding: Self::DEFAULT_PADDING, snap_within_viewport: true, - style: Theme::default_style(), + style: Box::new(Theme::default_style), } } @@ -81,9 +81,9 @@ where /// Sets the style of the [`Tooltip`]. pub fn style( mut self, - style: fn(&Theme, container::Status) -> container::Appearance, + style: impl Fn(&Theme, container::Status) -> container::Appearance + 'a, ) -> Self { - self.style = style.into(); + self.style = Box::new(style); self } } @@ -239,7 +239,7 @@ where positioning: self.position, gap: self.gap, padding: self.padding, - style: self.style, + style: &self.style, }))) } else { None @@ -309,7 +309,8 @@ where positioning: Position, gap: f32, padding: f32, - style: container::Style, + style: + &'b (dyn Fn(&Theme, container::Status) -> container::Appearance + 'a), } impl<'a, 'b, Message, Theme, Renderer> From 60b5822b67e569e99efc9e4176c3e6d3f859d0bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Tue, 12 Mar 2024 13:30:47 +0100 Subject: [PATCH 02/17] Use closures for `Button::style` --- widget/src/button.rs | 29 ++++++++++++++++------------- widget/src/helpers.rs | 2 +- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/widget/src/button.rs b/widget/src/button.rs index e265aa1f63..5790f811bd 100644 --- a/widget/src/button.rs +++ b/widget/src/button.rs @@ -56,7 +56,7 @@ where height: Length, padding: Padding, clip: bool, - style: Style, + style: Style<'a, Theme>, } impl<'a, Message, Theme, Renderer> Button<'a, Message, Theme, Renderer> @@ -68,7 +68,7 @@ where content: impl Into>, ) -> Self where - Theme: DefaultStyle, + Theme: DefaultStyle + 'a, { let content = content.into(); let size = content.as_widget().size_hint(); @@ -80,7 +80,7 @@ where height: size.height.fluid(), padding: DEFAULT_PADDING, clip: false, - style: Theme::default_style(), + style: Box::new(Theme::default_style), } } @@ -120,8 +120,11 @@ where } /// Sets the style variant of this [`Button`]. - pub fn style(mut self, style: fn(&Theme, Status) -> Appearance) -> Self { - self.style = style; + pub fn style( + mut self, + style: impl Fn(&Theme, Status) -> Appearance + 'a, + ) -> Self { + self.style = Box::new(style); self } @@ -439,29 +442,29 @@ impl std::default::Default for Appearance { } /// The style of a [`Button`]. -pub type Style = fn(&Theme, Status) -> Appearance; +pub type Style<'a, Theme> = Box Appearance + 'a>; /// The default style of a [`Button`]. pub trait DefaultStyle { /// Returns the default style of a [`Button`]. - fn default_style() -> Style; + fn default_style(&self, status: Status) -> Appearance; } impl DefaultStyle for Theme { - fn default_style() -> Style { - primary + fn default_style(&self, status: Status) -> Appearance { + primary(self, status) } } impl DefaultStyle for Appearance { - fn default_style() -> Style { - |appearance, _status| *appearance + fn default_style(&self, _status: Status) -> Appearance { + *self } } impl DefaultStyle for Color { - fn default_style() -> Style { - |color, _status| Appearance::default().with_background(*color) + fn default_style(&self, _status: Status) -> Appearance { + Appearance::default().with_background(*self) } } diff --git a/widget/src/helpers.rs b/widget/src/helpers.rs index 89d6ef622e..db21c8e97f 100644 --- a/widget/src/helpers.rs +++ b/widget/src/helpers.rs @@ -117,7 +117,7 @@ pub fn button<'a, Message, Theme, Renderer>( content: impl Into>, ) -> Button<'a, Message, Theme, Renderer> where - Theme: button::DefaultStyle, + Theme: button::DefaultStyle + 'a, Renderer: core::Renderer, { Button::new(content) From 66dce4865eb00f7cc7b75e64cd8a96a496916285 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Tue, 12 Mar 2024 13:34:51 +0100 Subject: [PATCH 03/17] Use closures for `Scrollable::style` --- widget/src/helpers.rs | 2 +- widget/src/scrollable.rs | 35 +++++++++++++++++------------------ 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/widget/src/helpers.rs b/widget/src/helpers.rs index db21c8e97f..e30b282924 100644 --- a/widget/src/helpers.rs +++ b/widget/src/helpers.rs @@ -104,7 +104,7 @@ pub fn scrollable<'a, Message, Theme, Renderer>( content: impl Into>, ) -> Scrollable<'a, Message, Theme, Renderer> where - Theme: scrollable::DefaultStyle, + Theme: scrollable::DefaultStyle + 'a, Renderer: core::Renderer, { Scrollable::new(content) diff --git a/widget/src/scrollable.rs b/widget/src/scrollable.rs index 3431275209..c03bbb7db1 100644 --- a/widget/src/scrollable.rs +++ b/widget/src/scrollable.rs @@ -36,7 +36,7 @@ pub struct Scrollable< direction: Direction, content: Element<'a, Message, Theme, Renderer>, on_scroll: Option Message + 'a>>, - style: Style, + style: Style<'a, Theme>, } impl<'a, Message, Theme, Renderer> Scrollable<'a, Message, Theme, Renderer> @@ -48,7 +48,7 @@ where content: impl Into>, ) -> Self where - Theme: DefaultStyle, + Theme: DefaultStyle + 'a, { Self::with_direction(content, Direction::default()) } @@ -59,20 +59,16 @@ where direction: Direction, ) -> Self where - Theme: DefaultStyle, + Theme: DefaultStyle + 'a, { - Self::with_direction_and_style( - content, - direction, - Theme::default_style(), - ) + Self::with_direction_and_style(content, direction, Theme::default_style) } /// Creates a new [`Scrollable`] with the given [`Direction`] and style. pub fn with_direction_and_style( content: impl Into>, direction: Direction, - style: fn(&Theme, Status) -> Appearance, + style: impl Fn(&Theme, Status) -> Appearance + 'a, ) -> Self { let content = content.into(); @@ -95,7 +91,7 @@ where direction, content, on_scroll: None, - style: style.into(), + style: Box::new(style), } } @@ -126,8 +122,11 @@ where } /// Sets the style of the [`Scrollable`] . - pub fn style(mut self, style: fn(&Theme, Status) -> Appearance) -> Self { - self.style = style.into(); + pub fn style( + mut self, + style: impl Fn(&Theme, Status) -> Appearance + 'a, + ) -> Self { + self.style = Box::new(style); self } } @@ -1603,23 +1602,23 @@ pub struct Scroller { } /// The style of a [`Scrollable`]. -pub type Style = fn(&Theme, Status) -> Appearance; +pub type Style<'a, Theme> = Box Appearance + 'a>; /// The default style of a [`Scrollable`]. pub trait DefaultStyle { /// Returns the default style of a [`Scrollable`]. - fn default_style() -> Style; + fn default_style(&self, status: Status) -> Appearance; } impl DefaultStyle for Theme { - fn default_style() -> Style { - default + fn default_style(&self, status: Status) -> Appearance { + default(self, status) } } impl DefaultStyle for Appearance { - fn default_style() -> Style { - |appearance, _status| *appearance + fn default_style(&self, _status: Status) -> Appearance { + *self } } From 71b9b3c3b1242dd571170fb0f8dd22760a1b4c53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Tue, 12 Mar 2024 13:41:14 +0100 Subject: [PATCH 04/17] Use closures for `Svg::style` --- examples/svg/src/main.rs | 12 ++++++------ widget/src/helpers.rs | 6 ++++-- widget/src/svg.rs | 38 +++++++++++++++++++++----------------- 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/examples/svg/src/main.rs b/examples/svg/src/main.rs index 4e23804875..0870dce438 100644 --- a/examples/svg/src/main.rs +++ b/examples/svg/src/main.rs @@ -41,12 +41,12 @@ impl Sandbox for Tiger { )); let svg = svg(handle).width(Length::Fill).height(Length::Fill).style( - if self.apply_color_filter { - |_theme, _status| svg::Appearance { - color: Some(color!(0x0000ff)), - } - } else { - |_theme, _status| svg::Appearance::default() + |_theme, _status| svg::Appearance { + color: if self.apply_color_filter { + Some(color!(0x0000ff)) + } else { + None + }, }, ); diff --git a/widget/src/helpers.rs b/widget/src/helpers.rs index e30b282924..91d5ee80f3 100644 --- a/widget/src/helpers.rs +++ b/widget/src/helpers.rs @@ -362,9 +362,11 @@ pub fn image(handle: impl Into) -> crate::Image { /// [`Svg`]: crate::Svg /// [`Handle`]: crate::svg::Handle #[cfg(feature = "svg")] -pub fn svg(handle: impl Into) -> crate::Svg +pub fn svg<'a, Theme>( + handle: impl Into, +) -> crate::Svg<'a, Theme> where - Theme: crate::svg::DefaultStyle, + Theme: crate::svg::DefaultStyle + 'a, { crate::Svg::new(handle) } diff --git a/widget/src/svg.rs b/widget/src/svg.rs index 6e61d27a2a..1ac07ade3e 100644 --- a/widget/src/svg.rs +++ b/widget/src/svg.rs @@ -20,26 +20,26 @@ pub use crate::core::svg::Handle; /// [`Svg`] images can have a considerable rendering cost when resized, /// specially when they are complex. #[allow(missing_debug_implementations)] -pub struct Svg { +pub struct Svg<'a, Theme = crate::Theme> { handle: Handle, width: Length, height: Length, content_fit: ContentFit, - style: Style, + style: Style<'a, Theme>, } -impl Svg { +impl<'a, Theme> Svg<'a, Theme> { /// Creates a new [`Svg`] from the given [`Handle`]. pub fn new(handle: impl Into) -> Self where - Theme: DefaultStyle, + Theme: DefaultStyle + 'a, { Svg { handle: handle.into(), width: Length::Fill, height: Length::Shrink, content_fit: ContentFit::Contain, - style: Theme::default_style(), + style: Box::new(Theme::default_style), } } @@ -48,7 +48,7 @@ impl Svg { #[must_use] pub fn from_path(path: impl Into) -> Self where - Theme: DefaultStyle, + Theme: DefaultStyle + 'a, { Self::new(Handle::from_path(path)) } @@ -80,13 +80,17 @@ impl Svg { /// Sets the style variant of this [`Svg`]. #[must_use] - pub fn style(mut self, style: fn(&Theme, Status) -> Appearance) -> Self { - self.style = style; + pub fn style( + mut self, + style: impl Fn(&Theme, Status) -> Appearance + 'a, + ) -> Self { + self.style = Box::new(style); self } } -impl Widget for Svg +impl<'a, Message, Theme, Renderer> Widget + for Svg<'a, Theme> where Renderer: svg::Renderer, { @@ -182,13 +186,13 @@ where } } -impl<'a, Message, Theme, Renderer> From> +impl<'a, Message, Theme, Renderer> From> for Element<'a, Message, Theme, Renderer> where Theme: 'a, Renderer: svg::Renderer + 'a, { - fn from(icon: Svg) -> Element<'a, Message, Theme, Renderer> { + fn from(icon: Svg<'a, Theme>) -> Element<'a, Message, Theme, Renderer> { Element::new(icon) } } @@ -214,22 +218,22 @@ pub struct Appearance { } /// The style of an [`Svg`]. -pub type Style = fn(&Theme, Status) -> Appearance; +pub type Style<'a, Theme> = Box Appearance + 'a>; /// The default style of an [`Svg`]. pub trait DefaultStyle { /// Returns the default style of an [`Svg`]. - fn default_style() -> Style; + fn default_style(&self, status: Status) -> Appearance; } impl DefaultStyle for Theme { - fn default_style() -> Style { - |_theme, _status| Appearance::default() + fn default_style(&self, _status: Status) -> Appearance { + Appearance::default() } } impl DefaultStyle for Appearance { - fn default_style() -> Style { - |appearance, _status| *appearance + fn default_style(&self, _status: Status) -> Appearance { + *self } } From 66f81c3429c736c5ca17d022ed1d6cdcc15e4f94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Tue, 12 Mar 2024 13:44:03 +0100 Subject: [PATCH 05/17] Use closures for `Rule::style` --- widget/src/helpers.rs | 8 ++++---- widget/src/rule.rs | 37 +++++++++++++++++++------------------ 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/widget/src/helpers.rs b/widget/src/helpers.rs index 91d5ee80f3..4bff0f169a 100644 --- a/widget/src/helpers.rs +++ b/widget/src/helpers.rs @@ -315,9 +315,9 @@ pub fn vertical_space() -> Space { /// Creates a horizontal [`Rule`] with the given height. /// /// [`Rule`]: crate::Rule -pub fn horizontal_rule(height: impl Into) -> Rule +pub fn horizontal_rule<'a, Theme>(height: impl Into) -> Rule<'a, Theme> where - Theme: rule::DefaultStyle, + Theme: rule::DefaultStyle + 'a, { Rule::horizontal(height) } @@ -325,9 +325,9 @@ where /// Creates a vertical [`Rule`] with the given width. /// /// [`Rule`]: crate::Rule -pub fn vertical_rule(width: impl Into) -> Rule +pub fn vertical_rule<'a, Theme>(width: impl Into) -> Rule<'a, Theme> where - Theme: rule::DefaultStyle, + Theme: rule::DefaultStyle + 'a, { Rule::vertical(width) } diff --git a/widget/src/rule.rs b/widget/src/rule.rs index 8580d4c7a6..9fa5f74fb1 100644 --- a/widget/src/rule.rs +++ b/widget/src/rule.rs @@ -10,48 +10,49 @@ use crate::core::{ /// Display a horizontal or vertical rule for dividing content. #[allow(missing_debug_implementations)] -pub struct Rule { +pub struct Rule<'a, Theme = crate::Theme> { width: Length, height: Length, is_horizontal: bool, - style: Style, + style: Style<'a, Theme>, } -impl Rule { +impl<'a, Theme> Rule<'a, Theme> { /// Creates a horizontal [`Rule`] with the given height. pub fn horizontal(height: impl Into) -> Self where - Theme: DefaultStyle, + Theme: DefaultStyle + 'a, { Rule { width: Length::Fill, height: Length::Fixed(height.into().0), is_horizontal: true, - style: Theme::default_style(), + style: Box::new(Theme::default_style), } } /// Creates a vertical [`Rule`] with the given width. pub fn vertical(width: impl Into) -> Self where - Theme: DefaultStyle, + Theme: DefaultStyle + 'a, { Rule { width: Length::Fixed(width.into().0), height: Length::Fill, is_horizontal: false, - style: Theme::default_style(), + style: Box::new(Theme::default_style), } } /// Sets the style of the [`Rule`]. - pub fn style(mut self, style: fn(&Theme) -> Appearance) -> Self { - self.style = style; + pub fn style(mut self, style: impl Fn(&Theme) -> Appearance + 'a) -> Self { + self.style = Box::new(style); self } } -impl Widget for Rule +impl<'a, Message, Theme, Renderer> Widget + for Rule<'a, Theme> where Renderer: crate::core::Renderer, { @@ -126,14 +127,14 @@ where } } -impl<'a, Message, Theme, Renderer> From> +impl<'a, Message, Theme, Renderer> From> for Element<'a, Message, Theme, Renderer> where Message: 'a, Theme: 'a, Renderer: 'a + crate::core::Renderer, { - fn from(rule: Rule) -> Element<'a, Message, Theme, Renderer> { + fn from(rule: Rule<'a, Theme>) -> Element<'a, Message, Theme, Renderer> { Element::new(rule) } } @@ -216,23 +217,23 @@ impl FillMode { } /// The style of a [`Rule`]. -pub type Style = fn(&Theme) -> Appearance; +pub type Style<'a, Theme> = Box Appearance + 'a>; /// The default style of a [`Rule`]. pub trait DefaultStyle { /// Returns the default style of a [`Rule`]. - fn default_style() -> Style; + fn default_style(&self) -> Appearance; } impl DefaultStyle for Theme { - fn default_style() -> Style { - default + fn default_style(&self) -> Appearance { + default(self) } } impl DefaultStyle for Appearance { - fn default_style() -> Style { - |appearance| *appearance + fn default_style(&self) -> Appearance { + *self } } From aeb72d528fce58ac94df3c015c10d6fe05f81a01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Tue, 12 Mar 2024 14:35:55 +0100 Subject: [PATCH 06/17] Use closures for `Text::style` --- core/src/widget/text.rs | 83 ++++++++++++---------------------- examples/component/src/main.rs | 10 +++- widget/src/helpers.rs | 3 +- 3 files changed, 40 insertions(+), 56 deletions(-) diff --git a/core/src/widget/text.rs b/core/src/widget/text.rs index 0305972bbc..66e2d066c6 100644 --- a/core/src/widget/text.rs +++ b/core/src/widget/text.rs @@ -6,7 +6,8 @@ use crate::renderer; use crate::text::{self, Paragraph}; use crate::widget::tree::{self, Tree}; use crate::{ - Color, Element, Layout, Length, Pixels, Point, Rectangle, Size, Widget, + Color, Element, Layout, Length, Pixels, Point, Rectangle, Size, Theme, + Widget, }; use std::borrow::Cow; @@ -28,7 +29,7 @@ where vertical_alignment: alignment::Vertical, font: Option, shaping: Shaping, - style: Style, + style: Style<'a, Theme>, } impl<'a, Theme, Renderer> Text<'a, Theme, Renderer> @@ -36,7 +37,10 @@ where Renderer: text::Renderer, { /// Create a new fragment of [`Text`] with the given contents. - pub fn new(content: impl Into>) -> Self { + pub fn new(content: impl Into>) -> Self + where + Theme: DefaultStyle + 'a, + { Text { content: content.into(), size: None, @@ -47,7 +51,7 @@ where horizontal_alignment: alignment::Horizontal::Left, vertical_alignment: alignment::Vertical::Top, shaping: Shaping::Basic, - style: Style::default(), + style: Box::new(Theme::default_style), } } @@ -72,20 +76,21 @@ where } /// Sets the style of the [`Text`]. - pub fn style(mut self, style: fn(&Theme) -> Appearance) -> Self { - self.style = Style::Themed(style); + pub fn style(mut self, style: impl Fn(&Theme) -> Appearance + 'a) -> Self { + self.style = Box::new(style); self } /// Sets the [`Color`] of the [`Text`]. - pub fn color(mut self, color: impl Into) -> Self { - self.style = Style::Colored(Some(color.into())); - self + pub fn color(self, color: impl Into) -> Self { + self.color_maybe(Some(color)) } /// Sets the [`Color`] of the [`Text`], if `Some`. pub fn color_maybe(mut self, color: Option>) -> Self { - self.style = Style::Colored(color.map(Into::into)); + let color = color.map(Into::into); + + self.style = Box::new(move |_theme| Appearance { color }); self } @@ -183,11 +188,7 @@ where viewport: &Rectangle, ) { let state = tree.state.downcast_ref::>(); - - let appearance = match self.style { - Style::Themed(f) => f(theme), - Style::Colored(color) => Appearance { color }, - }; + let appearance = (self.style)(theme); draw(renderer, style, layout, state, appearance, viewport); } @@ -290,28 +291,9 @@ where } } -impl<'a, Theme, Renderer> Clone for Text<'a, Theme, Renderer> -where - Renderer: text::Renderer, -{ - fn clone(&self) -> Self { - Self { - content: self.content.clone(), - size: self.size, - line_height: self.line_height, - width: self.width, - height: self.height, - horizontal_alignment: self.horizontal_alignment, - vertical_alignment: self.vertical_alignment, - font: self.font, - style: self.style, - shaping: self.shaping, - } - } -} - impl<'a, Theme, Renderer> From<&'a str> for Text<'a, Theme, Renderer> where + Theme: DefaultStyle + 'a, Renderer: text::Renderer, { fn from(content: &'a str) -> Self { @@ -322,7 +304,7 @@ where impl<'a, Message, Theme, Renderer> From<&'a str> for Element<'a, Message, Theme, Renderer> where - Theme: 'a, + Theme: DefaultStyle + 'a, Renderer: text::Renderer + 'a, { fn from(content: &'a str) -> Self { @@ -339,28 +321,23 @@ pub struct Appearance { pub color: Option, } -#[derive(Debug)] -enum Style { - Themed(fn(&Theme) -> Appearance), - Colored(Option), -} +/// The style of some [`Text`]. +pub type Style<'a, Theme> = Box Appearance + 'a>; -impl Clone for Style { - fn clone(&self) -> Self { - *self - } +/// The default style of some [`Text`]. +pub trait DefaultStyle { + /// Returns the default style of some [`Text`]. + fn default_style(&self) -> Appearance; } -impl Copy for Style {} - -impl Default for Style { - fn default() -> Self { - Style::Colored(None) +impl DefaultStyle for Theme { + fn default_style(&self) -> Appearance { + Appearance::default() } } -impl From Appearance> for Style { - fn from(f: fn(&Theme) -> Appearance) -> Self { - Style::Themed(f) +impl DefaultStyle for Color { + fn default_style(&self) -> Appearance { + Appearance { color: Some(*self) } } } diff --git a/examples/component/src/main.rs b/examples/component/src/main.rs index a1572b1ddf..d4f99798ca 100644 --- a/examples/component/src/main.rs +++ b/examples/component/src/main.rs @@ -83,7 +83,10 @@ mod numeric_input { impl Component for NumericInput where - Theme: button::DefaultStyle + text_input::DefaultStyle + 'static, + Theme: text::DefaultStyle + + button::DefaultStyle + + text_input::DefaultStyle + + 'static, { type State = (); type Event = Event; @@ -158,7 +161,10 @@ mod numeric_input { impl<'a, Message, Theme> From> for Element<'a, Message, Theme> where - Theme: button::DefaultStyle + text_input::DefaultStyle + 'static, + Theme: text::DefaultStyle + + button::DefaultStyle + + text_input::DefaultStyle + + 'static, Message: 'a, { fn from(numeric_input: NumericInput) -> Self { diff --git a/widget/src/helpers.rs b/widget/src/helpers.rs index 4bff0f169a..cc9bfeef59 100644 --- a/widget/src/helpers.rs +++ b/widget/src/helpers.rs @@ -14,7 +14,7 @@ use crate::rule::{self, Rule}; use crate::runtime::Command; use crate::scrollable::{self, Scrollable}; use crate::slider::{self, Slider}; -use crate::text::Text; +use crate::text::{self, Text}; use crate::text_editor::{self, TextEditor}; use crate::text_input::{self, TextInput}; use crate::toggler::{self, Toggler}; @@ -147,6 +147,7 @@ pub fn text<'a, Theme, Renderer>( text: impl ToString, ) -> Text<'a, Theme, Renderer> where + Theme: text::DefaultStyle + 'a, Renderer: core::text::Renderer, { Text::new(text.to_string()) From 58a0d5b7fff3000c46f5f2c468fce9442c78ef20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Tue, 12 Mar 2024 14:45:28 +0100 Subject: [PATCH 07/17] Use closures for `Radio::style` --- widget/src/helpers.rs | 6 +++--- widget/src/radio.rs | 41 ++++++++++++++++++++++------------------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/widget/src/helpers.rs b/widget/src/helpers.rs index cc9bfeef59..896e2c1372 100644 --- a/widget/src/helpers.rs +++ b/widget/src/helpers.rs @@ -170,15 +170,15 @@ where /// Creates a new [`Radio`]. /// /// [`Radio`]: crate::Radio -pub fn radio( +pub fn radio<'a, Message, Theme, Renderer, V>( label: impl Into, value: V, selected: Option, on_click: impl FnOnce(V) -> Message, -) -> Radio +) -> Radio<'a, Message, Theme, Renderer> where Message: Clone, - Theme: radio::DefaultStyle, + Theme: radio::DefaultStyle + 'a, Renderer: core::text::Renderer, V: Copy + Eq, { diff --git a/widget/src/radio.rs b/widget/src/radio.rs index 5e4a3c1fb7..a7b7dd036a 100644 --- a/widget/src/radio.rs +++ b/widget/src/radio.rs @@ -17,8 +17,8 @@ use crate::core::{ /// /// # Example /// ```no_run -/// # type Radio = -/// # iced_widget::Radio; +/// # type Radio<'a, Message> = +/// # iced_widget::Radio<'a, Message, iced_widget::Theme, iced_widget::renderer::Renderer>; /// # /// # use iced_widget::column; /// #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -67,7 +67,7 @@ use crate::core::{ /// let content = column![a, b, c, all]; /// ``` #[allow(missing_debug_implementations)] -pub struct Radio +pub struct Radio<'a, Message, Theme = crate::Theme, Renderer = crate::Renderer> where Renderer: text::Renderer, { @@ -81,10 +81,10 @@ where text_line_height: text::LineHeight, text_shaping: text::Shaping, font: Option, - style: Style, + style: Style<'a, Theme>, } -impl Radio +impl<'a, Message, Theme, Renderer> Radio<'a, Message, Theme, Renderer> where Message: Clone, Renderer: text::Renderer, @@ -110,7 +110,7 @@ where f: F, ) -> Self where - Theme: DefaultStyle, + Theme: DefaultStyle + 'a, V: Eq + Copy, F: FnOnce(V) -> Message, { @@ -125,7 +125,7 @@ where text_line_height: text::LineHeight::default(), text_shaping: text::Shaping::Basic, font: None, - style: Theme::default_style(), + style: Box::new(Theme::default_style), } } @@ -175,14 +175,17 @@ where } /// Sets the style of the [`Radio`] button. - pub fn style(mut self, style: fn(&Theme, Status) -> Appearance) -> Self { - self.style = style; + pub fn style( + mut self, + style: impl Fn(&Theme, Status) -> Appearance + 'a, + ) -> Self { + self.style = Box::new(style); self } } -impl Widget - for Radio +impl<'a, Message, Theme, Renderer> Widget + for Radio<'a, Message, Theme, Renderer> where Message: Clone, Renderer: text::Renderer, @@ -353,7 +356,7 @@ where } } -impl<'a, Message, Theme, Renderer> From> +impl<'a, Message, Theme, Renderer> From> for Element<'a, Message, Theme, Renderer> where Message: 'a + Clone, @@ -361,7 +364,7 @@ where Renderer: 'a + text::Renderer, { fn from( - radio: Radio, + radio: Radio<'a, Message, Theme, Renderer>, ) -> Element<'a, Message, Theme, Renderer> { Element::new(radio) } @@ -398,23 +401,23 @@ pub struct Appearance { } /// The style of a [`Radio`] button. -pub type Style = fn(&Theme, Status) -> Appearance; +pub type Style<'a, Theme> = Box Appearance + 'a>; /// The default style of a [`Radio`] button. pub trait DefaultStyle { /// Returns the default style of a [`Radio`] button. - fn default_style() -> Style; + fn default_style(&self, status: Status) -> Appearance; } impl DefaultStyle for Theme { - fn default_style() -> Style { - default + fn default_style(&self, status: Status) -> Appearance { + default(self, status) } } impl DefaultStyle for Appearance { - fn default_style() -> Style { - |appearance, _status| *appearance + fn default_style(&self, _status: Status) -> Appearance { + *self } } From afd138dba697976f61e335555b69417c4c84f7f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Tue, 12 Mar 2024 14:47:36 +0100 Subject: [PATCH 08/17] Use closures for `Slider::style` and `VerticalSlider::style` --- widget/src/helpers.rs | 4 ++-- widget/src/slider.rs | 25 ++++++++++++++----------- widget/src/vertical_slider.rs | 13 ++++++++----- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/widget/src/helpers.rs b/widget/src/helpers.rs index 896e2c1372..c3801b0971 100644 --- a/widget/src/helpers.rs +++ b/widget/src/helpers.rs @@ -240,7 +240,7 @@ pub fn slider<'a, T, Message, Theme>( where T: Copy + From + std::cmp::PartialOrd, Message: Clone, - Theme: slider::DefaultStyle, + Theme: slider::DefaultStyle + 'a, { Slider::new(range, value, on_change) } @@ -256,7 +256,7 @@ pub fn vertical_slider<'a, T, Message, Theme>( where T: Copy + From + std::cmp::PartialOrd, Message: Clone, - Theme: vertical_slider::DefaultStyle, + Theme: vertical_slider::DefaultStyle + 'a, { VerticalSlider::new(range, value, on_change) } diff --git a/widget/src/slider.rs b/widget/src/slider.rs index f3ea9bfdbc..d3b46a98c1 100644 --- a/widget/src/slider.rs +++ b/widget/src/slider.rs @@ -49,7 +49,7 @@ pub struct Slider<'a, T, Message, Theme = crate::Theme> { on_release: Option, width: Length, height: f32, - style: Style, + style: Style<'a, Theme>, } impl<'a, T, Message, Theme> Slider<'a, T, Message, Theme> @@ -70,7 +70,7 @@ where /// `Message`. pub fn new(range: RangeInclusive, value: T, on_change: F) -> Self where - Theme: DefaultStyle, + Theme: DefaultStyle + 'a, F: 'a + Fn(T) -> Message, { let value = if value >= *range.start() { @@ -95,7 +95,7 @@ where on_release: None, width: Length::Fill, height: Self::DEFAULT_HEIGHT, - style: Theme::default_style(), + style: Box::new(Theme::default_style), } } @@ -131,8 +131,11 @@ where } /// Sets the style of the [`Slider`]. - pub fn style(mut self, style: fn(&Theme, Status) -> Appearance) -> Self { - self.style = style.into(); + pub fn style( + mut self, + style: impl Fn(&Theme, Status) -> Appearance + 'a, + ) -> Self { + self.style = Box::new(style); self } @@ -547,23 +550,23 @@ pub enum HandleShape { } /// The style of a [`Slider`]. -pub type Style = fn(&Theme, Status) -> Appearance; +pub type Style<'a, Theme> = Box Appearance + 'a>; /// The default style of a [`Slider`]. pub trait DefaultStyle { /// Returns the default style of a [`Slider`]. - fn default_style() -> Style; + fn default_style(&self, status: Status) -> Appearance; } impl DefaultStyle for Theme { - fn default_style() -> Style { - default + fn default_style(&self, status: Status) -> Appearance { + default(self, status) } } impl DefaultStyle for Appearance { - fn default_style() -> Style { - |appearance, _status| *appearance + fn default_style(&self, _status: Status) -> Appearance { + *self } } diff --git a/widget/src/vertical_slider.rs b/widget/src/vertical_slider.rs index f7030584ec..2aa8f4d1f0 100644 --- a/widget/src/vertical_slider.rs +++ b/widget/src/vertical_slider.rs @@ -51,7 +51,7 @@ pub struct VerticalSlider<'a, T, Message, Theme = crate::Theme> { on_release: Option, width: f32, height: Length, - style: Style, + style: Style<'a, Theme>, } impl<'a, T, Message, Theme> VerticalSlider<'a, T, Message, Theme> @@ -72,7 +72,7 @@ where /// `Message`. pub fn new(range: RangeInclusive, value: T, on_change: F) -> Self where - Theme: DefaultStyle, + Theme: DefaultStyle + 'a, F: 'a + Fn(T) -> Message, { let value = if value >= *range.start() { @@ -97,7 +97,7 @@ where on_release: None, width: Self::DEFAULT_WIDTH, height: Length::Fill, - style: Theme::default_style(), + style: Box::new(Theme::default_style), } } @@ -133,8 +133,11 @@ where } /// Sets the style of the [`VerticalSlider`]. - pub fn style(mut self, style: fn(&Theme, Status) -> Appearance) -> Self { - self.style = style.into(); + pub fn style( + mut self, + style: impl Fn(&Theme, Status) -> Appearance + 'a, + ) -> Self { + self.style = Box::new(style); self } From 67416302180ce27c81418b71798d02b52c44e625 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Tue, 12 Mar 2024 14:51:30 +0100 Subject: [PATCH 09/17] Use closures for `QRCode::style` --- widget/src/helpers.rs | 6 ++++-- widget/src/qr_code.rs | 24 ++++++++++++------------ 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/widget/src/helpers.rs b/widget/src/helpers.rs index c3801b0971..b26736076f 100644 --- a/widget/src/helpers.rs +++ b/widget/src/helpers.rs @@ -391,9 +391,11 @@ where /// [`QRCode`]: crate::QRCode /// [`Data`]: crate::qr_code::Data #[cfg(feature = "qr_code")] -pub fn qr_code(data: &crate::qr_code::Data) -> crate::QRCode<'_, Theme> +pub fn qr_code<'a, Theme>( + data: &'a crate::qr_code::Data, +) -> crate::QRCode<'a, Theme> where - Theme: crate::qr_code::DefaultStyle, + Theme: crate::qr_code::DefaultStyle + 'a, { crate::QRCode::new(data) } diff --git a/widget/src/qr_code.rs b/widget/src/qr_code.rs index 41bcb83eae..90c0c97044 100644 --- a/widget/src/qr_code.rs +++ b/widget/src/qr_code.rs @@ -19,23 +19,23 @@ const QUIET_ZONE: usize = 2; /// A type of matrix barcode consisting of squares arranged in a grid which /// can be read by an imaging device, such as a camera. -#[derive(Debug)] +#[allow(missing_debug_implementations)] pub struct QRCode<'a, Theme = crate::Theme> { data: &'a Data, cell_size: u16, - style: Style, + style: Style<'a, Theme>, } impl<'a, Theme> QRCode<'a, Theme> { /// Creates a new [`QRCode`] with the provided [`Data`]. pub fn new(data: &'a Data) -> Self where - Theme: DefaultStyle, + Theme: DefaultStyle + 'a, { Self { data, cell_size: DEFAULT_CELL_SIZE, - style: Theme::default_style(), + style: Box::new(Theme::default_style), } } @@ -46,8 +46,8 @@ impl<'a, Theme> QRCode<'a, Theme> { } /// Sets the style of the [`QRCode`]. - pub fn style(mut self, style: fn(&Theme) -> Appearance) -> Self { - self.style = style.into(); + pub fn style(mut self, style: impl Fn(&Theme) -> Appearance + 'a) -> Self { + self.style = Box::new(style); self } } @@ -336,23 +336,23 @@ pub struct Appearance { } /// The style of a [`QRCode`]. -pub type Style = fn(&Theme) -> Appearance; +pub type Style<'a, Theme> = Box Appearance + 'a>; /// The default style of a [`QRCode`]. pub trait DefaultStyle { /// Returns the default style of a [`QRCode`]. - fn default_style() -> Style; + fn default_style(&self) -> Appearance; } impl DefaultStyle for Theme { - fn default_style() -> Style { - default + fn default_style(&self) -> Appearance { + default(self) } } impl DefaultStyle for Appearance { - fn default_style() -> Style { - |appearance| *appearance + fn default_style(&self) -> Appearance { + *self } } From d0a1da194a7311d599bda0884c973e8eed6c15d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Tue, 12 Mar 2024 14:54:28 +0100 Subject: [PATCH 10/17] Use closures for `Toggler::style` --- widget/src/helpers.rs | 2 +- widget/src/toggler.rs | 25 ++++++++++++++----------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/widget/src/helpers.rs b/widget/src/helpers.rs index b26736076f..dde6a20753 100644 --- a/widget/src/helpers.rs +++ b/widget/src/helpers.rs @@ -194,7 +194,7 @@ pub fn toggler<'a, Message, Theme, Renderer>( f: impl Fn(bool) -> Message + 'a, ) -> Toggler<'a, Message, Theme, Renderer> where - Theme: toggler::DefaultStyle, + Theme: toggler::DefaultStyle + 'a, Renderer: core::text::Renderer, { Toggler::new(label, is_checked, f) diff --git a/widget/src/toggler.rs b/widget/src/toggler.rs index 9e81ba332e..fc9e06e1d4 100644 --- a/widget/src/toggler.rs +++ b/widget/src/toggler.rs @@ -48,7 +48,7 @@ pub struct Toggler< text_shaping: text::Shaping, spacing: f32, font: Option, - style: Style, + style: Style<'a, Theme>, } impl<'a, Message, Theme, Renderer> Toggler<'a, Message, Theme, Renderer> @@ -72,7 +72,7 @@ where f: F, ) -> Self where - Theme: DefaultStyle, + Theme: 'a + DefaultStyle, F: 'a + Fn(bool) -> Message, { Toggler { @@ -87,7 +87,7 @@ where text_shaping: text::Shaping::Basic, spacing: Self::DEFAULT_SIZE / 2.0, font: None, - style: Theme::default_style(), + style: Box::new(Theme::default_style), } } @@ -145,8 +145,11 @@ where } /// Sets the style of the [`Toggler`]. - pub fn style(mut self, style: fn(&Theme, Status) -> Appearance) -> Self { - self.style = style.into(); + pub fn style( + mut self, + style: impl Fn(&Theme, Status) -> Appearance + 'a, + ) -> Self { + self.style = Box::new(style); self } } @@ -398,23 +401,23 @@ pub struct Appearance { } /// The style of a [`Toggler`]. -pub type Style = fn(&Theme, Status) -> Appearance; +pub type Style<'a, Theme> = Box Appearance + 'a>; /// The default style of a [`Toggler`]. pub trait DefaultStyle { /// Returns the default style of a [`Toggler`]. - fn default_style() -> Style; + fn default_style(&self, status: Status) -> Appearance; } impl DefaultStyle for Theme { - fn default_style() -> Style { - default + fn default_style(&self, status: Status) -> Appearance { + default(self, status) } } impl DefaultStyle for Appearance { - fn default_style() -> Style { - |appearance, _status| *appearance + fn default_style(&self, _status: Status) -> Appearance { + *self } } From 252eb88703196dd1d373fb45cbbb7ee7b85f3726 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Tue, 12 Mar 2024 14:58:06 +0100 Subject: [PATCH 11/17] Use closures for `Checkbox::style` --- examples/checkbox/src/main.rs | 11 +++++------ widget/src/checkbox.rs | 25 ++++++++++++++----------- widget/src/helpers.rs | 2 +- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/examples/checkbox/src/main.rs b/examples/checkbox/src/main.rs index 121c99ea5a..ee745c0339 100644 --- a/examples/checkbox/src/main.rs +++ b/examples/checkbox/src/main.rs @@ -63,17 +63,16 @@ impl Application for Example { let default_checkbox = checkbox("Default", self.default) .on_toggle(Message::DefaultToggled); - let styled_checkbox = |label, style| { + let styled_checkbox = |label| { checkbox(label, self.styled) .on_toggle_maybe(self.default.then_some(Message::StyledToggled)) - .style(style) }; let checkboxes = row![ - styled_checkbox("Primary", checkbox::primary), - styled_checkbox("Secondary", checkbox::secondary), - styled_checkbox("Success", checkbox::success), - styled_checkbox("Danger", checkbox::danger), + styled_checkbox("Primary").style(checkbox::primary), + styled_checkbox("Secondary").style(checkbox::secondary), + styled_checkbox("Success").style(checkbox::success), + styled_checkbox("Danger").style(checkbox::danger), ] .spacing(20); diff --git a/widget/src/checkbox.rs b/widget/src/checkbox.rs index f0c7357bbe..15fb8f5844 100644 --- a/widget/src/checkbox.rs +++ b/widget/src/checkbox.rs @@ -51,7 +51,7 @@ pub struct Checkbox< text_shaping: text::Shaping, font: Option, icon: Icon, - style: Style, + style: Style<'a, Theme>, } impl<'a, Message, Theme, Renderer> Checkbox<'a, Message, Theme, Renderer> @@ -71,7 +71,7 @@ where /// * a boolean describing whether the [`Checkbox`] is checked or not pub fn new(label: impl Into, is_checked: bool) -> Self where - Theme: DefaultStyle, + Theme: DefaultStyle + 'a, { Checkbox { is_checked, @@ -91,7 +91,7 @@ where line_height: text::LineHeight::default(), shaping: text::Shaping::Basic, }, - style: Theme::default_style(), + style: Box::new(Theme::default_style), } } @@ -174,8 +174,11 @@ where } /// Sets the style of the [`Checkbox`]. - pub fn style(mut self, style: fn(&Theme, Status) -> Appearance) -> Self { - self.style = style; + pub fn style( + mut self, + style: impl Fn(&Theme, Status) -> Appearance + 'a, + ) -> Self { + self.style = Box::new(style); self } } @@ -424,23 +427,23 @@ pub struct Appearance { } /// The style of a [`Checkbox`]. -pub type Style = fn(&Theme, Status) -> Appearance; +pub type Style<'a, Theme> = Box Appearance + 'a>; /// The default style of a [`Checkbox`]. pub trait DefaultStyle { /// Returns the default style of a [`Checkbox`]. - fn default_style() -> Style; + fn default_style(&self, status: Status) -> Appearance; } impl DefaultStyle for Theme { - fn default_style() -> Style { - primary + fn default_style(&self, status: Status) -> Appearance { + primary(self, status) } } impl DefaultStyle for Appearance { - fn default_style() -> Style { - |appearance, _status| *appearance + fn default_style(&self, _status: Status) -> Appearance { + *self } } diff --git a/widget/src/helpers.rs b/widget/src/helpers.rs index dde6a20753..7912d7b818 100644 --- a/widget/src/helpers.rs +++ b/widget/src/helpers.rs @@ -161,7 +161,7 @@ pub fn checkbox<'a, Message, Theme, Renderer>( is_checked: bool, ) -> Checkbox<'a, Message, Theme, Renderer> where - Theme: checkbox::DefaultStyle, + Theme: checkbox::DefaultStyle + 'a, Renderer: core::text::Renderer, { Checkbox::new(label, is_checked) From d1e40495410049aedb6756be1febd83bae5eee1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Tue, 12 Mar 2024 15:35:48 +0100 Subject: [PATCH 12/17] Use closures for `TextInput::style` --- widget/src/combo_box.rs | 32 +++++++++++--------------------- widget/src/helpers.rs | 4 ++-- widget/src/text_input.rs | 29 ++++++++++++++++------------- 3 files changed, 29 insertions(+), 36 deletions(-) diff --git a/widget/src/combo_box.rs b/widget/src/combo_box.rs index bddf278925..956678824f 100644 --- a/widget/src/combo_box.rs +++ b/widget/src/combo_box.rs @@ -62,7 +62,7 @@ where on_selected: impl Fn(T) -> Message + 'static, ) -> Self where - Theme: DefaultStyle, + Theme: DefaultStyle + 'a, { let style = Theme::default_style(); @@ -125,7 +125,10 @@ where } /// Sets the style of the [`ComboBox`]. - pub fn style(mut self, style: impl Into>) -> Self { + pub fn style(mut self, style: impl Into>) -> Self + where + Theme: 'a, + { let style = style.into(); self.text_input = self.text_input.style(style.text_input); @@ -761,10 +764,10 @@ where } /// The style of a [`ComboBox`]. -#[derive(Debug, PartialEq, Eq)] +#[allow(missing_debug_implementations)] pub struct Style { /// The style of the [`TextInput`] of the [`ComboBox`]. - pub text_input: fn(&Theme, text_input::Status) -> text_input::Appearance, + pub text_input: text_input::Style<'static, Theme>, /// The style of the [`Menu`] of the [`ComboBox`]. /// @@ -772,22 +775,6 @@ pub struct Style { pub menu: menu::Style, } -impl Style { - /// The default style of a [`ComboBox`]. - pub const DEFAULT: Self = Self { - text_input: text_input::default, - menu: menu::Style::::DEFAULT, - }; -} - -impl Clone for Style { - fn clone(&self) -> Self { - *self - } -} - -impl Copy for Style {} - /// The default style of a [`ComboBox`]. pub trait DefaultStyle: Sized { /// Returns the default style of a [`ComboBox`]. @@ -796,6 +783,9 @@ pub trait DefaultStyle: Sized { impl DefaultStyle for Theme { fn default_style() -> Style { - Style::::DEFAULT + Style { + text_input: Box::new(text_input::default), + menu: menu::Style::DEFAULT, + } } } diff --git a/widget/src/helpers.rs b/widget/src/helpers.rs index 7912d7b818..2606826ddc 100644 --- a/widget/src/helpers.rs +++ b/widget/src/helpers.rs @@ -209,7 +209,7 @@ pub fn text_input<'a, Message, Theme, Renderer>( ) -> TextInput<'a, Message, Theme, Renderer> where Message: Clone, - Theme: text_input::DefaultStyle, + Theme: text_input::DefaultStyle + 'a, Renderer: core::text::Renderer, { TextInput::new(placeholder, value) @@ -291,7 +291,7 @@ pub fn combo_box<'a, T, Message, Theme, Renderer>( ) -> ComboBox<'a, T, Message, Theme, Renderer> where T: std::fmt::Display + Clone, - Theme: combo_box::DefaultStyle, + Theme: combo_box::DefaultStyle + 'a, Renderer: core::text::Renderer, { ComboBox::new(state, placeholder, selection, on_selected) diff --git a/widget/src/text_input.rs b/widget/src/text_input.rs index 9ed8480a7e..b161ec74f9 100644 --- a/widget/src/text_input.rs +++ b/widget/src/text_input.rs @@ -75,7 +75,7 @@ pub struct TextInput< on_paste: Option Message + 'a>>, on_submit: Option, icon: Option>, - style: Style, + style: Style<'a, Theme>, } /// The default [`Padding`] of a [`TextInput`]. @@ -90,9 +90,9 @@ where /// its current value. pub fn new(placeholder: &str, value: &str) -> Self where - Theme: DefaultStyle, + Theme: DefaultStyle + 'a, { - Self::with_style(placeholder, value, Theme::default_style()) + Self::with_style(placeholder, value, Theme::default_style) } /// Creates a new [`TextInput`] with the given placeholder, @@ -100,7 +100,7 @@ where pub fn with_style( placeholder: &str, value: &str, - style: fn(&Theme, Status) -> Appearance, + style: impl Fn(&Theme, Status) -> Appearance + 'a, ) -> Self { TextInput { id: None, @@ -116,7 +116,7 @@ where on_paste: None, on_submit: None, icon: None, - style: style.into(), + style: Box::new(style), } } @@ -203,8 +203,11 @@ where } /// Sets the style of the [`TextInput`]. - pub fn style(mut self, style: fn(&Theme, Status) -> Appearance) -> Self { - self.style = style.into(); + pub fn style( + mut self, + style: impl Fn(&Theme, Status) -> Appearance + 'a, + ) -> Self { + self.style = Box::new(style); self } @@ -1413,23 +1416,23 @@ pub struct Appearance { } /// The style of a [`TextInput`]. -pub type Style = fn(&Theme, Status) -> Appearance; +pub type Style<'a, Theme> = Box Appearance + 'a>; /// The default style of a [`TextInput`]. pub trait DefaultStyle { /// Returns the default style of a [`TextInput`]. - fn default_style() -> Style; + fn default_style(&self, status: Status) -> Appearance; } impl DefaultStyle for Theme { - fn default_style() -> Style { - default + fn default_style(&self, status: Status) -> Appearance { + default(self, status) } } impl DefaultStyle for Appearance { - fn default_style() -> Style { - |appearance, _status| *appearance + fn default_style(&self, _status: Status) -> Appearance { + *self } } From fd7a23ca47b556ad82f2a8a9e3f849deb9f72f1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Tue, 12 Mar 2024 15:42:41 +0100 Subject: [PATCH 13/17] Use closures for `PaneGrid::style` --- widget/src/pane_grid.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/widget/src/pane_grid.rs b/widget/src/pane_grid.rs index bdeb42507d..beac0bd8a2 100644 --- a/widget/src/pane_grid.rs +++ b/widget/src/pane_grid.rs @@ -110,7 +110,7 @@ pub struct PaneGrid< on_click: Option Message + 'a>>, on_drag: Option Message + 'a>>, on_resize: Option<(f32, Box Message + 'a>)>, - style: Style, + style: Style<'a, Theme>, } impl<'a, Message, Theme, Renderer> PaneGrid<'a, Message, Theme, Renderer> @@ -126,7 +126,7 @@ where view: impl Fn(Pane, &'a T, bool) -> Content<'a, Message, Theme, Renderer>, ) -> Self where - Theme: DefaultStyle, + Theme: DefaultStyle + 'a, { let contents = if let Some((pane, pane_state)) = state.maximized.and_then(|pane| { @@ -158,7 +158,7 @@ where on_click: None, on_drag: None, on_resize: None, - style: Theme::default_style(), + style: Box::new(Theme::default_style), } } @@ -218,8 +218,8 @@ where } /// Sets the style of the [`PaneGrid`]. - pub fn style(mut self, style: fn(&Theme) -> Appearance) -> Self { - self.style = style; + pub fn style(mut self, style: impl Fn(&Theme) -> Appearance + 'a) -> Self { + self.style = Box::new(style); self } @@ -1146,23 +1146,23 @@ pub struct Line { } /// The style of a [`PaneGrid`]. -pub type Style = fn(&Theme) -> Appearance; +pub type Style<'a, Theme> = Box Appearance + 'a>; /// The default style of a [`PaneGrid`]. pub trait DefaultStyle { /// Returns the default style of a [`PaneGrid`]. - fn default_style() -> Style; + fn default_style(&self) -> Appearance; } impl DefaultStyle for Theme { - fn default_style() -> Style { - default + fn default_style(&self) -> Appearance { + default(self) } } impl DefaultStyle for Appearance { - fn default_style() -> Style { - |appearance| *appearance + fn default_style(&self) -> Appearance { + *self } } From 7a5f5b0be779e5128de05fa779693fe65e81c1e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Tue, 12 Mar 2024 15:45:21 +0100 Subject: [PATCH 14/17] Use closures for `ProgressBar::style` --- widget/src/helpers.rs | 6 +++--- widget/src/progress_bar.rs | 36 ++++++++++++++++++------------------ 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/widget/src/helpers.rs b/widget/src/helpers.rs index 2606826ddc..b23e3cb9c9 100644 --- a/widget/src/helpers.rs +++ b/widget/src/helpers.rs @@ -340,12 +340,12 @@ where /// * the current value of the [`ProgressBar`]. /// /// [`ProgressBar`]: crate::ProgressBar -pub fn progress_bar( +pub fn progress_bar<'a, Theme>( range: RangeInclusive, value: f32, -) -> ProgressBar +) -> ProgressBar<'a, Theme> where - Theme: progress_bar::DefaultStyle, + Theme: progress_bar::DefaultStyle + 'a, { ProgressBar::new(range, value) } diff --git a/widget/src/progress_bar.rs b/widget/src/progress_bar.rs index 7b0ea63f97..38d8da85b7 100644 --- a/widget/src/progress_bar.rs +++ b/widget/src/progress_bar.rs @@ -13,7 +13,7 @@ use std::ops::RangeInclusive; /// /// # Example /// ```no_run -/// # type ProgressBar = iced_widget::ProgressBar; +/// # type ProgressBar<'a> = iced_widget::ProgressBar<'a>; /// # /// let value = 50.0; /// @@ -22,15 +22,15 @@ use std::ops::RangeInclusive; /// /// ![Progress bar drawn with `iced_wgpu`](https://user-images.githubusercontent.com/18618951/71662391-a316c200-2d51-11ea-9cef-52758cab85e3.png) #[allow(missing_debug_implementations)] -pub struct ProgressBar { +pub struct ProgressBar<'a, Theme = crate::Theme> { range: RangeInclusive, value: f32, width: Length, height: Option, - style: Style, + style: Style<'a, Theme>, } -impl ProgressBar { +impl<'a, Theme> ProgressBar<'a, Theme> { /// The default height of a [`ProgressBar`]. pub const DEFAULT_HEIGHT: f32 = 30.0; @@ -41,14 +41,14 @@ impl ProgressBar { /// * the current value of the [`ProgressBar`] pub fn new(range: RangeInclusive, value: f32) -> Self where - Theme: DefaultStyle, + Theme: DefaultStyle + 'a, { ProgressBar { value: value.clamp(*range.start(), *range.end()), range, width: Length::Fill, height: None, - style: Theme::default_style(), + style: Box::new(Theme::default_style), } } @@ -65,14 +65,14 @@ impl ProgressBar { } /// Sets the style of the [`ProgressBar`]. - pub fn style(mut self, style: fn(&Theme) -> Appearance) -> Self { - self.style = style.into(); + pub fn style(mut self, style: impl Fn(&Theme) -> Appearance + 'a) -> Self { + self.style = Box::new(style); self } } -impl Widget - for ProgressBar +impl<'a, Message, Theme, Renderer> Widget + for ProgressBar<'a, Theme> where Renderer: crate::core::Renderer, { @@ -143,7 +143,7 @@ where } } -impl<'a, Message, Theme, Renderer> From> +impl<'a, Message, Theme, Renderer> From> for Element<'a, Message, Theme, Renderer> where Message: 'a, @@ -151,7 +151,7 @@ where Renderer: 'a + crate::core::Renderer, { fn from( - progress_bar: ProgressBar, + progress_bar: ProgressBar<'a, Theme>, ) -> Element<'a, Message, Theme, Renderer> { Element::new(progress_bar) } @@ -169,23 +169,23 @@ pub struct Appearance { } /// The style of a [`ProgressBar`]. -pub type Style = fn(&Theme) -> Appearance; +pub type Style<'a, Theme> = Box Appearance + 'a>; /// The default style of a [`ProgressBar`]. pub trait DefaultStyle { /// Returns the default style of a [`ProgressBar`]. - fn default_style() -> Style; + fn default_style(&self) -> Appearance; } impl DefaultStyle for Theme { - fn default_style() -> Style { - primary + fn default_style(&self) -> Appearance { + primary(self) } } impl DefaultStyle for Appearance { - fn default_style() -> Style { - |appearance| *appearance + fn default_style(&self) -> Appearance { + *self } } From 3e190b9ee0d95d73008dab23b18117e0a21223d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Tue, 12 Mar 2024 15:47:37 +0100 Subject: [PATCH 15/17] Use closures for `TextEditor::style` --- widget/src/helpers.rs | 8 ++++---- widget/src/text_editor.rs | 25 ++++++++++++++----------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/widget/src/helpers.rs b/widget/src/helpers.rs index b23e3cb9c9..4863e55066 100644 --- a/widget/src/helpers.rs +++ b/widget/src/helpers.rs @@ -218,12 +218,12 @@ where /// Creates a new [`TextEditor`]. /// /// [`TextEditor`]: crate::TextEditor -pub fn text_editor( - content: &text_editor::Content, -) -> TextEditor<'_, core::text::highlighter::PlainText, Message, Theme, Renderer> +pub fn text_editor<'a, Message, Theme, Renderer>( + content: &'a text_editor::Content, +) -> TextEditor<'a, core::text::highlighter::PlainText, Message, Theme, Renderer> where Message: Clone, - Theme: text_editor::DefaultStyle, + Theme: text_editor::DefaultStyle + 'a, Renderer: core::text::Renderer, { TextEditor::new(content) diff --git a/widget/src/text_editor.rs b/widget/src/text_editor.rs index c7d62d92a5..5b8f6a1b72 100644 --- a/widget/src/text_editor.rs +++ b/widget/src/text_editor.rs @@ -41,7 +41,7 @@ pub struct TextEditor< width: Length, height: Length, padding: Padding, - style: Style, + style: Style<'a, Theme>, on_edit: Option Message + 'a>>, highlighter_settings: Highlighter::Settings, highlighter_format: fn( @@ -58,7 +58,7 @@ where /// Creates new [`TextEditor`] with the given [`Content`]. pub fn new(content: &'a Content) -> Self where - Theme: DefaultStyle, + Theme: DefaultStyle + 'a, { Self { content, @@ -68,7 +68,7 @@ where width: Length::Fill, height: Length::Shrink, padding: Padding::new(5.0), - style: Theme::default_style(), + style: Box::new(Theme::default_style), on_edit: None, highlighter_settings: (), highlighter_format: |_highlight, _theme| { @@ -142,8 +142,11 @@ where } /// Sets the style of the [`TextEditor`]. - pub fn style(mut self, style: fn(&Theme, Status) -> Appearance) -> Self { - self.style = style.into(); + pub fn style( + mut self, + style: impl Fn(&Theme, Status) -> Appearance + 'a, + ) -> Self { + self.style = Box::new(style); self } } @@ -809,23 +812,23 @@ pub struct Appearance { } /// The style of a [`TextEditor`]. -pub type Style = fn(&Theme, Status) -> Appearance; +pub type Style<'a, Theme> = Box Appearance + 'a>; /// The default style of a [`TextEditor`]. pub trait DefaultStyle { /// Returns the default style of a [`TextEditor`]. - fn default_style() -> Style; + fn default_style(&self, status: Status) -> Appearance; } impl DefaultStyle for Theme { - fn default_style() -> Style { - default + fn default_style(&self, status: Status) -> Appearance { + default(self, status) } } impl DefaultStyle for Appearance { - fn default_style() -> Style { - |appearance, _status| *appearance + fn default_style(&self, _status: Status) -> Appearance { + *self } } From b721fd935c6b689b1365e21dfc864e43bf3a5895 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Tue, 12 Mar 2024 16:40:56 +0100 Subject: [PATCH 16/17] Use closures for `PickList::style` --- widget/src/combo_box.rs | 20 +++++----- widget/src/overlay/menu.rs | 75 +++++++++----------------------------- widget/src/pick_list.rs | 41 +++++++-------------- 3 files changed, 41 insertions(+), 95 deletions(-) diff --git a/widget/src/combo_box.rs b/widget/src/combo_box.rs index 956678824f..ee24d7429a 100644 --- a/widget/src/combo_box.rs +++ b/widget/src/combo_box.rs @@ -42,7 +42,7 @@ pub struct ComboBox< on_option_hovered: Option Message>>, on_close: Option, on_input: Option Message>>, - menu_style: menu::Style, + menu_style: menu::Style<'a, Theme>, padding: Padding, size: Option, } @@ -125,7 +125,7 @@ where } /// Sets the style of the [`ComboBox`]. - pub fn style(mut self, style: impl Into>) -> Self + pub fn style(mut self, style: impl Into>) -> Self where Theme: 'a, { @@ -672,7 +672,7 @@ where self.state.sync_filtered_options(filtered_options); - let mut menu = menu::Menu::with_style( + let mut menu = menu::Menu::new( menu, &filtered_options.options, hovered_option, @@ -686,7 +686,7 @@ where (self.on_selected)(x) }, self.on_option_hovered.as_deref(), - self.menu_style, + &self.menu_style, ) .width(bounds.width) .padding(self.padding); @@ -765,27 +765,27 @@ where /// The style of a [`ComboBox`]. #[allow(missing_debug_implementations)] -pub struct Style { +pub struct Style<'a, Theme> { /// The style of the [`TextInput`] of the [`ComboBox`]. - pub text_input: text_input::Style<'static, Theme>, + pub text_input: text_input::Style<'a, Theme>, /// The style of the [`Menu`] of the [`ComboBox`]. /// /// [`Menu`]: menu::Menu - pub menu: menu::Style, + pub menu: menu::Style<'a, Theme>, } /// The default style of a [`ComboBox`]. pub trait DefaultStyle: Sized { /// Returns the default style of a [`ComboBox`]. - fn default_style() -> Style; + fn default_style() -> Style<'static, Self>; } impl DefaultStyle for Theme { - fn default_style() -> Style { + fn default_style() -> Style<'static, Self> { Style { text_input: Box::new(text_input::default), - menu: menu::Style::DEFAULT, + menu: menu::DefaultStyle::default_style(), } } } diff --git a/widget/src/overlay/menu.rs b/widget/src/overlay/menu.rs index 746407c645..0364f980d4 100644 --- a/widget/src/overlay/menu.rs +++ b/widget/src/overlay/menu.rs @@ -38,7 +38,7 @@ pub struct Menu< text_line_height: text::LineHeight, text_shaping: text::Shaping, font: Option, - style: Style, + style: &'a Style<'a, Theme>, } impl<'a, T, Message, Theme, Renderer> Menu<'a, T, Message, Theme, Renderer> @@ -48,37 +48,15 @@ where Theme: 'a, Renderer: text::Renderer + 'a, { - /// Creates a new [`Menu`] with the given [`State`], a list of options, and - /// the message to produced when an option is selected. - pub fn new( - state: &'a mut State, - options: &'a [T], - hovered_option: &'a mut Option, - on_selected: impl FnMut(T) -> Message + 'a, - on_option_hovered: Option<&'a dyn Fn(T) -> Message>, - ) -> Self - where - Theme: DefaultStyle, - { - Self::with_style( - state, - options, - hovered_option, - on_selected, - on_option_hovered, - Theme::default_style(), - ) - } - /// Creates a new [`Menu`] with the given [`State`], a list of options, /// the message to produced when an option is selected, and its [`Style`]. - pub fn with_style( + pub fn new( state: &'a mut State, options: &'a [T], hovered_option: &'a mut Option, on_selected: impl FnMut(T) -> Message + 'a, on_option_hovered: Option<&'a dyn Fn(T) -> Message>, - style: Style, + style: &'a Style<'a, Theme>, ) -> Self { Menu { state, @@ -135,12 +113,6 @@ where self } - /// Sets the style of the [`Menu`]. - pub fn style(mut self, style: impl Into>) -> Self { - self.style = style.into(); - self - } - /// Turns the [`Menu`] into an overlay [`Element`] at the given target /// position. /// @@ -190,7 +162,7 @@ where container: Container<'a, Message, Theme, Renderer>, width: f32, target_height: f32, - style: Style, + style: &'a Style<'a, Theme>, } impl<'a, Message, Theme, Renderer> Overlay<'a, Message, Theme, Renderer> @@ -234,10 +206,10 @@ where text_line_height, text_shaping, padding, - style: style.list, + style: &style.list, }, scrollable::Direction::default(), - style.scrollable, + &style.scrollable, ), container::transparent, ); @@ -356,7 +328,7 @@ where text_line_height: text::LineHeight, text_shaping: text::Shaping, font: Option, - style: fn(&Theme) -> Appearance, + style: &'a dyn Fn(&Theme) -> Appearance, } impl<'a, T, Message, Theme, Renderer> Widget @@ -599,39 +571,26 @@ pub struct Appearance { } /// The style of the different parts of a [`Menu`]. -#[derive(Debug, PartialEq, Eq)] -pub struct Style { +#[allow(missing_debug_implementations)] +pub struct Style<'a, Theme> { /// The style of the list of the [`Menu`]. - pub list: fn(&Theme) -> Appearance, + pub list: Box Appearance + 'a>, /// The style of the [`Scrollable`] of the [`Menu`]. - pub scrollable: fn(&Theme, scrollable::Status) -> scrollable::Appearance, + pub scrollable: scrollable::Style<'a, Theme>, } -impl Style { - /// The default style of a [`Menu`] with the built-in [`Theme`]. - pub const DEFAULT: Self = Self { - list: default, - scrollable: scrollable::default, - }; -} - -impl Clone for Style { - fn clone(&self) -> Self { - *self - } -} - -impl Copy for Style {} - /// The default style of a [`Menu`]. pub trait DefaultStyle: Sized { /// Returns the default style of a [`Menu`]. - fn default_style() -> Style; + fn default_style() -> Style<'static, Self>; } impl DefaultStyle for Theme { - fn default_style() -> Style { - Style::::DEFAULT + fn default_style() -> Style<'static, Self> { + Style { + list: Box::new(default), + scrollable: Box::new(scrollable::default), + } } } diff --git a/widget/src/pick_list.rs b/widget/src/pick_list.rs index beb4e0c1f2..52d5439705 100644 --- a/widget/src/pick_list.rs +++ b/widget/src/pick_list.rs @@ -47,7 +47,7 @@ pub struct PickList< text_shaping: text::Shaping, font: Option, handle: Handle, - style: Style, + style: Style<'a, Theme>, } impl<'a, T, L, V, Message, Theme, Renderer> @@ -151,7 +151,7 @@ where } /// Sets the style of the [`PickList`]. - pub fn style(mut self, style: impl Into>) -> Self { + pub fn style(mut self, style: impl Into>) -> Self { self.style = style.into(); self } @@ -529,7 +529,7 @@ where let on_select = &self.on_select; - let mut menu = Menu::with_style( + let mut menu = Menu::new( &mut state.menu, self.options.borrow(), &mut state.hovered_option, @@ -539,7 +539,7 @@ where (on_select)(option) }, None, - self.style.menu, + &self.style.menu, ) .width(bounds.width) .padding(self.padding) @@ -676,40 +676,27 @@ pub struct Appearance { } /// The styles of the different parts of a [`PickList`]. -#[derive(Debug, PartialEq, Eq)] -pub struct Style { +#[allow(missing_debug_implementations)] +pub struct Style<'a, Theme> { /// The style of the [`PickList`] itself. - pub field: fn(&Theme, Status) -> Appearance, + pub field: Box Appearance + 'a>, /// The style of the [`Menu`] of the pick list. - pub menu: menu::Style, + pub menu: menu::Style<'a, Theme>, } -impl Style { - /// The default style of a [`PickList`] with the built-in [`Theme`]. - pub const DEFAULT: Self = Self { - field: default, - menu: menu::Style::::DEFAULT, - }; -} - -impl Clone for Style { - fn clone(&self) -> Self { - *self - } -} - -impl Copy for Style {} - /// The default style of a [`PickList`]. pub trait DefaultStyle: Sized { /// Returns the default style of a [`PickList`]. - fn default_style() -> Style; + fn default_style() -> Style<'static, Self>; } impl DefaultStyle for Theme { - fn default_style() -> Style { - Style::::DEFAULT + fn default_style() -> Style<'static, Self> { + Style { + field: Box::new(default), + menu: menu::DefaultStyle::default_style(), + } } } From 98621aa344a7a0e1b23f320d21a4687af559998e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Tue, 12 Mar 2024 16:52:53 +0100 Subject: [PATCH 17/17] Remove `themer` use from `gradient` example :tada: --- examples/gradient/src/main.rs | 20 ++++++++++---------- widget/src/container.rs | 24 +++++++++++++++++++++--- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/examples/gradient/src/main.rs b/examples/gradient/src/main.rs index 4a8b2fa54e..8ed4c830cc 100644 --- a/examples/gradient/src/main.rs +++ b/examples/gradient/src/main.rs @@ -1,6 +1,6 @@ use iced::application; use iced::widget::{ - checkbox, column, container, horizontal_space, row, slider, text, themer, + checkbox, column, container, horizontal_space, row, slider, text, }; use iced::{gradient, window}; use iced::{ @@ -70,16 +70,16 @@ impl Sandbox for Gradient { transparent, } = *self; - let gradient = gradient::Linear::new(angle) - .add_stop(0.0, start) - .add_stop(1.0, end); + let gradient_box = container(horizontal_space()) + .style(move |_theme, _status| { + let gradient = gradient::Linear::new(angle) + .add_stop(0.0, start) + .add_stop(1.0, end); - let gradient_box = themer( - gradient, - container(horizontal_space()) - .width(Length::Fill) - .height(Length::Fill), - ); + gradient.into() + }) + .width(Length::Fill) + .height(Length::Fill); let angle_picker = row![ text("Angle").width(64), diff --git a/widget/src/container.rs b/widget/src/container.rs index f51ff8789d..7c133588ed 100644 --- a/widget/src/container.rs +++ b/widget/src/container.rs @@ -539,6 +539,24 @@ impl Appearance { } } +impl From for Appearance { + fn from(color: Color) -> Self { + Self::default().with_background(color) + } +} + +impl From for Appearance { + fn from(gradient: Gradient) -> Self { + Self::default().with_background(gradient) + } +} + +impl From for Appearance { + fn from(gradient: gradient::Linear) -> Self { + Self::default().with_background(gradient) + } +} + /// The possible status of a [`Container`]. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Status { @@ -571,19 +589,19 @@ impl DefaultStyle for Appearance { impl DefaultStyle for Color { fn default_style(&self, _status: Status) -> Appearance { - Appearance::default().with_background(*self) + Appearance::from(*self) } } impl DefaultStyle for Gradient { fn default_style(&self, _status: Status) -> Appearance { - Appearance::default().with_background(*self) + Appearance::from(*self) } } impl DefaultStyle for gradient::Linear { fn default_style(&self, _status: Status) -> Appearance { - Appearance::default().with_background(*self) + Appearance::from(*self) } }