From e7e5b05ca8c11c2ba329d0b6daffe9a218aee9a1 Mon Sep 17 00:00:00 2001 From: pml68 Date: Tue, 15 Apr 2025 01:34:09 +0200 Subject: refactor!: move backdrop_color into `Style` struct --- .gitignore | 1 + README.md | 2 + example/src/main.rs | 13 +++---- src/dialog.rs | 104 +++++++++++++++++++++++++++++++++++++++++++++------- src/lib.rs | 2 + 5 files changed, 102 insertions(+), 20 deletions(-) diff --git a/.gitignore b/.gitignore index 2c96eb1..2fd7392 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ target/ Cargo.lock +rustc-ice-*.txt diff --git a/README.md b/README.md index 18d0e0a..0f1c11c 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ Custom dialog for [`iced`](https://iced.rs) +It's mostly the dialog from @frgp42's [Fluent Iced Gallery](https://github.com/frgp42/fluent_iced_gallery), but made into a "widget" + ## Example See the [/example](/example) directory. diff --git a/example/src/main.rs b/example/src/main.rs index 6b0a363..8d2fcc3 100644 --- a/example/src/main.rs +++ b/example/src/main.rs @@ -1,8 +1,8 @@ use iced::{ - Element, Length, Task, - widget::{center, column, text}, + Element, Length, Task, color, + widget::{button, center, column, text}, }; -use iced_dialog::{button, dialog}; +use iced_dialog::dialog; #[derive(Default)] struct State { @@ -41,8 +41,7 @@ impl State { let base = center( column![ text(&self.action_text), - iced::widget::button("Open Dialog") - .on_press(Message::OpenDialog) + button("Open Dialog").on_press(Message::OpenDialog) ] .spacing(14.0), ) @@ -53,8 +52,8 @@ impl State { dialog(self.is_open, base, dialog_content) .title("Save") - .push_button(button("Save").on_press(Message::Saved)) - .push_button(button("Cancel").on_press(Message::Cancelled)) + .push_button(iced_dialog::button("Save", Message::Saved)) + .push_button(iced_dialog::button("Cancel", Message::Cancelled)) .width(350) .height(234) .into() diff --git a/src/dialog.rs b/src/dialog.rs index dba27f7..5df75ae 100644 --- a/src/dialog.rs +++ b/src/dialog.rs @@ -31,7 +31,7 @@ where spacing: f32, padding: Padding, button_alignment: Alignment, - backdrop_color: Box Color + 'a>, + class: ::Class<'a>, title_class: ::Class<'a>, container_class: ::Class<'a>, } @@ -41,8 +41,6 @@ where Renderer: 'a + core::Renderer + core::text::Renderer, Theme: 'a + Catalog, Message: 'a + Clone, - ::Class<'a>: - From>, { /// Creates a new [`Dialog`] with the given base and dialog content. pub fn new( @@ -72,7 +70,7 @@ where spacing: 8.0, padding: 24.into(), button_alignment: Alignment::Start, - backdrop_color: Box::new(|_theme| color!(0x000000, 0.3)), + class: ::default(), title_class: ::default_title(), container_class: ::default_container(), } @@ -151,9 +149,13 @@ where buttons.into_iter().fold(self, Self::push_button) } - /// Sets the coloring method for the [`Dialog`]'s backdrop. - pub fn backdrop(mut self, color: impl Fn(&Theme) -> Color + 'a) -> Self { - self.backdrop_color = Box::new(color); + /// Sets the style of the [`Dialog`]. + #[must_use] + pub fn style(mut self, style: impl Fn(&Theme) -> Style + 'a) -> Self + where + ::Class<'a>: From>, + { + self.class = (Box::new(style) as StyleFn<'a, Theme>).into(); self } @@ -185,7 +187,42 @@ where self } - fn view(self) -> Element<'a, Message, Theme, Renderer> { + /// Sets the style class of the [`Dialog`]. + #[must_use] + pub fn class( + mut self, + class: impl Into<::Class<'a>>, + ) -> Self { + self.class = class.into(); + self + } + + /// Sets the style class of the [`Dialog`]'s title. + #[must_use] + pub fn title_class( + mut self, + class: impl Into<::Class<'a>>, + ) -> Self { + self.title_class = class.into(); + self + } + + /// Sets the style class of the [`Dialog`]'s container. + #[must_use] + pub fn container_class( + mut self, + class: impl Into<::Class<'a>>, + ) -> Self { + self.container_class = class.into(); + self + } + + fn view(self) -> Element<'a, Message, Theme, Renderer> + where + ::Class<'a>: + From>, + ::Class<'a>: Into>, + { if self.is_open { let contents = Container::new( Column::new() @@ -226,7 +263,7 @@ where .class(self.container_class) .clip(true); - modal(self.base, dialog, self.backdrop_color) + modal(self.base, dialog, self.class) } else { self.base } @@ -241,6 +278,7 @@ where Message: 'a + Clone, ::Class<'a>: From>, + ::Class<'a>: Into>, { fn from(dialog: Dialog<'a, Message, Theme, Renderer>) -> Self { dialog.view() @@ -250,17 +288,21 @@ where fn modal<'a, Message, Theme, Renderer>( base: impl Into>, content: impl Into>, - backdrop_color: impl Fn(&Theme) -> Color + 'a, + class: ::Class<'a>, ) -> Element<'a, Message, Theme, Renderer> where Message: 'a + Clone, Renderer: 'a + core::Renderer, - Theme: 'a + container::Catalog, - Theme::Class<'a>: From>, + Theme: 'a + container::Catalog + Catalog, + ::Class<'a>: + From>, + ::Class<'a>: Into>, { + let style = class.into(); + let area = mouse_area(center(opaque(content)).style(move |theme| { container::Style { - background: Some(backdrop_color(theme).into()), + background: Some(style(theme).backdrop_color.into()), ..Default::default() } })); @@ -268,8 +310,21 @@ where stack![base.into(), opaque(area)].into() } +/// The style of a [`Dialog`]. +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct Style { + /// The [`Dialog`]'s backdrop. + pub backdrop_color: Color, +} + /// The theme catalog of a [`Dialog`]. pub trait Catalog: text::Catalog + container::Catalog { + /// The item class of the [`Catalog`]. + type Class<'a>; + + /// The default class produced by the [`Catalog`]. + fn default<'a>() -> ::Class<'a>; + /// The default class for the [`Dialog`]'s title. fn default_title<'a>() -> ::Class<'a> { ::default() @@ -279,9 +334,21 @@ pub trait Catalog: text::Catalog + container::Catalog { fn default_container<'a>() -> ::Class<'a> { ::default() } + + /// The [`Style`] of a class. + fn style(&self, class: ::Class<'_>) -> Style; } +/// A styling function for a [`Dialog`]. +pub type StyleFn<'a, Theme> = Box Style + 'a>; + impl Catalog for Theme { + type Class<'a> = StyleFn<'a, Self>; + + fn default<'a>() -> ::Class<'a> { + Box::new(default) + } + fn default_container<'a>() -> ::Class<'a> { Box::new(|theme| { container::background( @@ -289,4 +356,15 @@ impl Catalog for Theme { ) }) } + + fn style(&self, class: ::Class<'_>) -> Style { + class(self) + } +} + +/// The default style of a [`Dialog`]. +pub fn default(_theme: &Theme) -> Style { + Style { + backdrop_color: color!(0x000000, 0.3), + } } diff --git a/src/lib.rs b/src/lib.rs index 856a45c..718f1ce 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,6 +30,7 @@ where /// [`Button`]: https://docs.iced.rs/iced/widget/struct.Button.html pub fn button<'a, Message, Theme, Renderer>( content: &'a str, + message: Message, ) -> Button<'a, Message, Theme, Renderer> where Theme: 'a + iced_widget::button::Catalog + text::Catalog, @@ -41,6 +42,7 @@ where .line_height(text::LineHeight::Absolute(core::Pixels(20.0))) .align_x(Horizontal::Center), ) + .on_press(message) .height(32) .width(core::Length::Fill) } -- cgit v1.2.3