diff --git a/examples/cosmic/src/window.rs b/examples/cosmic/src/window.rs index a0219e7..50b5490 100644 --- a/examples/cosmic/src/window.rs +++ b/examples/cosmic/src/window.rs @@ -277,7 +277,7 @@ impl Window { .spacing(16), ) .padding([20, 24]) - .style(theme::Container::Custom(list::column::style)), + .style(theme::Container::custom(list::column::style)), ) .padding(0) .style(theme::Button::Transparent) diff --git a/src/applet/mod.rs b/src/applet/mod.rs index ed4cc7a..60e4fc1 100644 --- a/src/applet/mod.rs +++ b/src/applet/mod.rs @@ -19,16 +19,18 @@ pub use cosmic_panel_config; const APPLET_PADDING: u32 = 8; -pub const APPLET_BUTTON_THEME: Button = Button::Custom { - active: |t| iced_style::button::Appearance { - border_radius: BorderRadius::from(0.0), - ..t.active(&Button::Text) - }, - hover: |t| iced_style::button::Appearance { - border_radius: BorderRadius::from(0.0), - ..t.hovered(&Button::Text) - }, -}; +pub fn applet_button_theme() -> Button { + Button::Custom { + active: Box::new(|t| iced_style::button::Appearance { + border_radius: BorderRadius::from(0.0), + ..t.active(&Button::Text) + }), + hover: Box::new(|t| iced_style::button::Appearance { + border_radius: BorderRadius::from(0.0), + ..t.hovered(&Button::Text) + }), + } +} #[derive(Debug, Clone)] pub struct CosmicAppletHelper { @@ -130,7 +132,7 @@ impl CosmicAppletHelper { }; Container::::new(Container::::new(content).style( - crate::theme::Container::Custom(|theme| Appearance { + crate::theme::Container::custom(|theme| Appearance { text_color: Some(theme.cosmic().background.on.into()), background: Some(Color::from(theme.cosmic().background.base).into()), border_radius: 12.0, diff --git a/src/theme/expander.rs b/src/theme/expander.rs index b2b736e..5210ba9 100644 --- a/src/theme/expander.rs +++ b/src/theme/expander.rs @@ -52,7 +52,7 @@ impl std::default::Default for Appearance { /// A set of rules that dictate the [`Appearance`] of a container. pub trait StyleSheet { - type Style: Default + Copy; + type Style: Default; /// Produces the [`Appearance`] of a container. fn appearance(&self, style: Self::Style) -> Appearance; diff --git a/src/theme/mod.rs b/src/theme/mod.rs index 1533b4d..51462d6 100644 --- a/src/theme/mod.rs +++ b/src/theme/mod.rs @@ -6,6 +6,7 @@ mod segmented_button; use std::hash::Hash; use std::hash::Hasher; +use std::rc::Rc; pub use self::segmented_button::SegmentedButton; @@ -132,15 +133,16 @@ impl LayeredTheme for Theme { } } -#[derive(Clone, Copy)] +#[derive(Default)] pub enum Application { + #[default] Default, - Custom(fn(&Theme) -> application::Appearance), + Custom(Box application::Appearance>), } -impl Default for Application { - fn default() -> Self { - Self::Default +impl Application { + pub fn custom application::Appearance + 'static>(f: F) -> Self { + Self::Custom(Box::new(f)) } } @@ -163,7 +165,6 @@ impl application::StyleSheet for Theme { /* * TODO: Button */ -#[derive(Clone, Copy)] pub enum Button { Deactivated, Destructive, @@ -175,8 +176,8 @@ pub enum Button { LinkActive, Transparent, Custom { - active: fn(&Theme) -> button::Appearance, - hover: fn(&Theme) -> button::Appearance, + active: Box button::Appearance>, + hover: Box button::Appearance>, }, } @@ -439,21 +440,16 @@ impl checkbox::StyleSheet for Theme { } } -#[derive(Clone, Copy)] +#[derive(Default)] pub enum Expander { + #[default] Default, - Custom(fn(&Theme) -> expander::Appearance), + Custom(Box expander::Appearance>), } -impl Default for Expander { - fn default() -> Self { - Self::Default - } -} - -impl From expander::Appearance> for Expander { - fn from(f: fn(&Theme) -> expander::Appearance) -> Self { - Self::Custom(f) +impl Expander { + pub fn custom expander::Appearance + 'static>(f: F) -> Self { + Self::Custom(Box::new(f)) } } @@ -471,24 +467,19 @@ impl expander::StyleSheet for Theme { /* * TODO: Container */ -#[derive(Clone, Copy)] +#[derive(Default)] pub enum Container { Background, Primary, Secondary, + #[default] Transparent, - Custom(fn(&Theme) -> container::Appearance), + Custom(Box container::Appearance>), } -impl Default for Container { - fn default() -> Self { - Self::Transparent - } -} - -impl From container::Appearance> for Container { - fn from(_: fn(&Theme) -> container::Appearance) -> Self { - Self::default() +impl Container { + pub fn custom container::Appearance + 'static>(f: F) -> Self { + Self::Custom(Box::new(f)) } } @@ -754,17 +745,18 @@ impl pane_grid::StyleSheet for Theme { /* * TODO: Progress Bar */ -#[derive(Clone, Copy)] +#[derive(Default)] pub enum ProgressBar { + #[default] Primary, Success, Danger, - Custom(fn(&Theme) -> progress_bar::Appearance), + Custom(Box progress_bar::Appearance>), } -impl Default for ProgressBar { - fn default() -> Self { - Self::Primary +impl ProgressBar { + pub fn custom progress_bar::Appearance + 'static>(f: F) -> Self { + Self::Custom(Box::new(f)) } } @@ -798,17 +790,18 @@ impl progress_bar::StyleSheet for Theme { /* * TODO: Rule */ -#[derive(Clone, Copy)] +#[derive(Default)] pub enum Rule { + #[default] Default, LightDivider, HeavyDivider, - Custom(fn(&Theme) -> rule::Appearance), + Custom(Box rule::Appearance>), } -impl Default for Rule { - fn default() -> Self { - Self::Default +impl Rule { + pub fn custom rule::Appearance + 'static>(f: F) -> Self { + Self::Custom(Box::new(f)) } } @@ -883,10 +876,10 @@ impl scrollable::StyleSheet for Theme { } } -#[derive(Default, Clone, Copy)] +#[derive(Clone, Default)] pub enum Svg { /// Apply a custom appearance filter - Custom(fn(&Theme) -> svg::Appearance), + Custom(Rc svg::Appearance>), /// No filtering is applied #[default] Default, @@ -915,6 +908,12 @@ impl Hash for Svg { } } +impl Svg { + pub fn custom svg::Appearance + 'static>(f: F) -> Self { + Self::Custom(Rc::new(f)) + } +} + impl svg::StyleSheet for Theme { type Style = Svg; @@ -948,6 +947,7 @@ pub enum Text { #[default] Default, Color(Color), + // TODO: Can't use dyn Fn since this must be copy Custom(fn(&Theme) -> text::Appearance), } diff --git a/src/theme/segmented_button.rs b/src/theme/segmented_button.rs index 6041cbf..1e1f53c 100644 --- a/src/theme/segmented_button.rs +++ b/src/theme/segmented_button.rs @@ -6,7 +6,7 @@ use crate::{theme::Theme, widget::segmented_button::ItemStatusAppearance}; use iced_core::{Background, BorderRadius}; use palette::{rgb::Rgb, Alpha}; -#[derive(Clone, Copy, Default)] +#[derive(Default)] pub enum SegmentedButton { /// A tabbed widget for switching between views in an interface. #[default] @@ -14,7 +14,7 @@ pub enum SegmentedButton { /// A widget for multiple choice selection. Selection, /// Or implement any custom theme of your liking. - Custom(fn(&Theme) -> Appearance), + Custom(Box Appearance>), } impl StyleSheet for Theme { diff --git a/src/widget/icon.rs b/src/widget/icon.rs index 28f0cb3..3810be7 100644 --- a/src/widget/icon.rs +++ b/src/widget/icon.rs @@ -207,7 +207,7 @@ impl<'a> Icon<'a> { fn svg_element(&self, handle: svg::Handle) -> Element<'static, Message> { svg::Svg::::new(handle) - .style(self.style) + .style(self.style.clone()) .width(self.width.unwrap_or(Length::Units(self.size))) .height(self.height.unwrap_or(Length::Units(self.size))) .content_fit(self.content_fit) diff --git a/src/widget/list/column.rs b/src/widget/list/column.rs index 9a6e814..0a1f5c3 100644 --- a/src/widget/list/column.rs +++ b/src/widget/list/column.rs @@ -45,7 +45,7 @@ impl<'a, Message: 'static> ListColumn<'a, Message> { .spacing(12) .apply(iced::widget::container) .padding([16, 6]) - .style(theme::Container::Custom(style)) + .style(theme::Container::custom(style)) .into() } } diff --git a/src/widget/nav_bar.rs b/src/widget/nav_bar.rs index 3057b30..3ee2263 100644 --- a/src/widget/nav_bar.rs +++ b/src/widget/nav_bar.rs @@ -36,7 +36,7 @@ where .apply(container) .height(Length::Fill) .padding(11) - .style(theme::Container::Custom(nav_bar_style)) + .style(theme::Container::custom(nav_bar_style)) } #[must_use] diff --git a/src/widget/search/field.rs b/src/widget/search/field.rs index 3a2ae64..89aa61d 100644 --- a/src/widget/search/field.rs +++ b/src/widget/search/field.rs @@ -58,7 +58,7 @@ impl<'a, Message: 'static + Clone> Field<'a, Message> { .spacing(8) .align_items(iced::Alignment::Center) .apply(container) - .style(crate::theme::Container::Custom(active_style)) + .style(crate::theme::Container::custom(active_style)) .into() } } diff --git a/src/widget/spin_button/mod.rs b/src/widget/spin_button/mod.rs index eb2f73d..d994ee8 100644 --- a/src/widget/spin_button/mod.rs +++ b/src/widget/spin_button/mod.rs @@ -83,7 +83,7 @@ impl<'a, Message: 'static> SpinButton<'a, Message> { .align_y(Vertical::Center) .width(Length::Units(95)) .height(Length::Units(32)) - .style(theme::Container::Custom(container_style)) + .style(theme::Container::custom(container_style)) .apply(Element::from) .map(on_change) } diff --git a/src/widget/warning.rs b/src/widget/warning.rs index 0cf2241..b64315f 100644 --- a/src/widget/warning.rs +++ b/src/widget/warning.rs @@ -51,7 +51,7 @@ impl<'a, Message: 'static + Clone> Warning<'a, Message> { ]) .align_items(Alignment::Center), ) - .style(theme::Container::Custom(warning_container)) + .style(theme::Container::custom(warning_container)) .padding(10) .align_y(alignment::Vertical::Center) .width(Length::Fill)