From 82dfab633a028ebf6446ca8ed452811133e5c887 Mon Sep 17 00:00:00 2001 From: Ashley Wulber Date: Fri, 2 Feb 2024 20:28:05 -0500 Subject: [PATCH] refactor: make Theme a generic parameter for the button This makes the button possible to use with custom themes in cosmic-time --- src/widget/button/link.rs | 51 +++++++++++++++++----------------- src/widget/button/mod.rs | 20 ++++++++----- src/widget/button/text.rs | 35 +++++++++++------------ src/widget/button/widget.rs | 45 +++++++++++++++++------------- src/widget/color_picker/mod.rs | 4 +-- 5 files changed, 84 insertions(+), 71 deletions(-) diff --git a/src/widget/button/link.rs b/src/widget/button/link.rs index 960d70a8..6843269c 100644 --- a/src/widget/button/link.rs +++ b/src/widget/button/link.rs @@ -58,32 +58,33 @@ pub fn icon() -> Handle { impl<'a, Message: Clone + 'static> From> for Element<'a, Message> { fn from(mut builder: Button<'a, Message>) -> Element<'a, Message> { - let button: super::Button<'a, Message, crate::Renderer> = row::with_capacity(2) - .push({ - let mut font = crate::font::DEFAULT; - font.weight = builder.font_weight; + let button: super::Button<'a, Message, crate::Theme, crate::Renderer> = + row::with_capacity(2) + .push({ + let mut font = crate::font::DEFAULT; + font.weight = builder.font_weight; - // TODO: Avoid allocation - crate::widget::text(builder.label.to_string()) - .size(builder.font_size) - .line_height(LineHeight::Absolute(builder.line_height.into())) - .font(font) - }) - .push_maybe(if builder.variant.trailing_icon { - Some(icon().icon().size(builder.icon_size)) - } else { - None - }) - .padding(builder.padding) - .width(builder.width) - .height(builder.height) - .spacing(builder.spacing) - .align_items(Alignment::Center) - .apply(button) - .padding(0) - .id(builder.id) - .on_press_maybe(builder.on_press.take()) - .style(builder.style); + // TODO: Avoid allocation + crate::widget::text(builder.label.to_string()) + .size(builder.font_size) + .line_height(LineHeight::Absolute(builder.line_height.into())) + .font(font) + }) + .push_maybe(if builder.variant.trailing_icon { + Some(icon().icon().size(builder.icon_size)) + } else { + None + }) + .padding(builder.padding) + .width(builder.width) + .height(builder.height) + .spacing(builder.spacing) + .align_items(Alignment::Center) + .apply(button) + .padding(0) + .id(builder.id) + .on_press_maybe(builder.on_press.take()) + .style(builder.style); if builder.tooltip.is_empty() { button.into() diff --git a/src/widget/button/mod.rs b/src/widget/button/mod.rs index 32872e0e..b0d1afad 100644 --- a/src/widget/button/mod.rs +++ b/src/widget/button/mod.rs @@ -26,22 +26,28 @@ pub use text::{destructive, standard, suggested, text}; mod widget; pub use widget::{draw, focus, layout, mouse_interaction, Button}; -use crate::Element; +use crate::iced::Element; use iced_core::font::Weight; use iced_core::widget::Id; use iced_core::{Length, Padding}; use std::borrow::Cow; -pub fn button<'a, Message>( - content: impl Into>, -) -> Button<'a, Message, crate::Renderer> { +pub fn button<'a, Message, Theme>( + content: impl Into>, +) -> Button<'a, Message, Theme, crate::Renderer> +where + Theme: style::StyleSheet, +{ Button::new(content) } -pub fn custom_image_button<'a, Message>( - content: impl Into>, +pub fn custom_image_button<'a, Message, Theme>( + content: impl Into>, on_remove: Option, -) -> Button<'a, Message, crate::Renderer> { +) -> Button<'a, Message, Theme, crate::Renderer> +where + Theme: style::StyleSheet, +{ Button::new_image(content, on_remove) } diff --git a/src/widget/button/text.rs b/src/widget/button/text.rs index 4bdb581c..d8f339ff 100644 --- a/src/widget/button/text.rs +++ b/src/widget/button/text.rs @@ -109,23 +109,24 @@ impl<'a, Message: Clone + 'static> From> for Element<'a, Mes .into() }); - let button: super::Button<'a, Message, crate::Renderer> = row::with_capacity(3) - // Optional icon to place before label. - .push_maybe(leading_icon) - // Optional label between icons. - .push_maybe(label) - // Optional icon to place behind the label. - .push_maybe(trailing_icon) - .padding(builder.padding) - .width(builder.width) - .height(builder.height) - .spacing(builder.spacing) - .align_items(Alignment::Center) - .apply(button) - .padding(0) - .id(builder.id) - .on_press_maybe(builder.on_press.take()) - .style(builder.style); + let button: super::Button<'a, Message, crate::Theme, crate::Renderer> = + row::with_capacity(3) + // Optional icon to place before label. + .push_maybe(leading_icon) + // Optional label between icons. + .push_maybe(label) + // Optional icon to place behind the label. + .push_maybe(trailing_icon) + .padding(builder.padding) + .width(builder.width) + .height(builder.height) + .spacing(builder.spacing) + .align_items(Alignment::Center) + .apply(button) + .padding(0) + .id(builder.id) + .on_press_maybe(builder.on_press.take()) + .style(builder.style); if builder.tooltip.is_empty() { button.into() diff --git a/src/widget/button/widget.rs b/src/widget/button/widget.rs index ffc94c3f..f82a6ee3 100644 --- a/src/widget/button/widget.rs +++ b/src/widget/button/widget.rs @@ -40,9 +40,10 @@ enum Variant { /// A generic button which emits a message when pressed. #[allow(missing_debug_implementations)] #[must_use] -pub struct Button<'a, Message, Renderer> +pub struct Button<'a, Message, Theme, Renderer> where Renderer: iced_core::Renderer, + Theme: super::style::StyleSheet, { id: Id, #[cfg(feature = "a11y")] @@ -51,22 +52,23 @@ where description: Option>, #[cfg(feature = "a11y")] label: Option>, - content: Element<'a, Message, crate::Theme, Renderer>, + content: Element<'a, Message, Theme, Renderer>, on_press: Option, width: Length, height: Length, padding: Padding, selected: bool, - style: ::Style, + style: ::Style, variant: Variant, } -impl<'a, Message, Renderer> Button<'a, Message, Renderer> +impl<'a, Message, Theme, Renderer> Button<'a, Message, Theme, Renderer> where Renderer: iced_core::Renderer, + Theme: super::style::StyleSheet, { /// Creates a new [`Button`] with the given content. - pub fn new(content: impl Into>) -> Self { + pub fn new(content: impl Into>) -> Self { Self { id: Id::unique(), #[cfg(feature = "a11y")] @@ -81,13 +83,13 @@ where height: Length::Shrink, padding: Padding::new(5.0), selected: false, - style: ::Style::default(), + style: ::Style::default(), variant: Variant::Normal, } } pub fn new_image( - content: impl Into>, + content: impl Into>, on_remove: Option, ) -> Self { Self { @@ -104,7 +106,7 @@ where height: Length::Shrink, padding: Padding::new(5.0), selected: false, - style: ::Style::default(), + style: ::Style::default(), variant: Variant::Image { on_remove, close_icon: crate::widget::icon::from_name("window-close-symbolic") @@ -178,7 +180,7 @@ where } /// Sets the style variant of this [`Button`]. - pub fn style(mut self, style: ::Style) -> Self { + pub fn style(mut self, style: ::Style) -> Self { self.style = style; self } @@ -214,11 +216,12 @@ where } } -impl<'a, Message, Renderer> Widget - for Button<'a, Message, Renderer> +impl<'a, Message, Theme, Renderer> Widget + for Button<'a, Message, Theme, Renderer> where Message: 'a + Clone, Renderer: 'a + iced_core::Renderer + svg::Renderer, + Theme: super::style::StyleSheet, { fn tag(&self) -> tree::Tag { tree::Tag::of::() @@ -340,7 +343,7 @@ where &self, tree: &Tree, renderer: &mut Renderer, - theme: &crate::Theme, + theme: &Theme, renderer_style: &renderer::Style, layout: Layout<'_>, cursor: mouse::Cursor, @@ -349,7 +352,7 @@ where let bounds = layout.bounds(); let content_layout = layout.children().next().unwrap(); - let styling = draw( + let styling = draw::<_, Theme>( renderer, bounds, cursor, @@ -471,7 +474,7 @@ where tree: &'b mut Tree, layout: Layout<'_>, renderer: &Renderer, - ) -> Option> { + ) -> Option> { self.content.as_widget_mut().overlay( &mut tree.children[0], layout.children().next().unwrap(), @@ -554,13 +557,14 @@ where } } -impl<'a, Message, Renderer> From> - for Element<'a, Message, crate::Theme, Renderer> +impl<'a, Message, Theme, Renderer> From> + for Element<'a, Message, Theme, Renderer> where Message: Clone + 'a, Renderer: iced_core::Renderer + svg::Renderer + 'a, + Theme: super::style::StyleSheet + 'a, { - fn from(button: Button<'a, Message, Renderer>) -> Self { + fn from(button: Button<'a, Message, Theme, Renderer>) -> Self { Self::new(button) } } @@ -680,18 +684,19 @@ pub fn update<'a, Message: Clone>( } #[allow(clippy::too_many_arguments)] -pub fn draw<'a, Renderer: iced_core::Renderer>( +pub fn draw<'a, Renderer: iced_core::Renderer, Theme>( renderer: &mut Renderer, bounds: Rectangle, cursor: mouse::Cursor, is_enabled: bool, is_selected: bool, - style_sheet: &dyn StyleSheet