diff options
| author | pml68 <contact@pml68.dev> | 2025-04-15 01:34:09 +0200 |
|---|---|---|
| committer | pml68 <contact@pml68.dev> | 2025-04-15 01:34:09 +0200 |
| commit | e7e5b05ca8c11c2ba329d0b6daffe9a218aee9a1 (patch) | |
| tree | 2d86d51c1d9ab46258f7f626ace6645c19582bf8 | |
| parent | fix: example package name (diff) | |
| download | iced_dialog-e7e5b05ca8c11c2ba329d0b6daffe9a218aee9a1.tar.gz | |
refactor!: move backdrop_color into `Style` struct
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | example/src/main.rs | 13 | ||||
| -rw-r--r-- | src/dialog.rs | 104 | ||||
| -rw-r--r-- | src/lib.rs | 2 |
5 files changed, 102 insertions, 20 deletions
@@ -1,2 +1,3 @@ target/ Cargo.lock +rustc-ice-*.txt @@ -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<dyn Fn(&Theme) -> Color + 'a>, + class: <Theme as Catalog>::Class<'a>, title_class: <Theme as text::Catalog>::Class<'a>, container_class: <Theme as container::Catalog>::Class<'a>, } @@ -41,8 +41,6 @@ where Renderer: 'a + core::Renderer + core::text::Renderer, Theme: 'a + Catalog, Message: 'a + Clone, - <Theme as container::Catalog>::Class<'a>: - From<container::StyleFn<'a, Theme>>, { /// 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: <Theme as Catalog>::default(), title_class: <Theme as Catalog>::default_title(), container_class: <Theme as Catalog>::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 + <Theme as Catalog>::Class<'a>: From<StyleFn<'a, Theme>>, + { + 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<<Theme as Catalog>::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<<Theme as text::Catalog>::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<<Theme as container::Catalog>::Class<'a>>, + ) -> Self { + self.container_class = class.into(); + self + } + + fn view(self) -> Element<'a, Message, Theme, Renderer> + where + <Theme as container::Catalog>::Class<'a>: + From<container::StyleFn<'a, Theme>>, + <Theme as Catalog>::Class<'a>: Into<StyleFn<'a, Theme>>, + { 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, <Theme as container::Catalog>::Class<'a>: From<container::StyleFn<'a, Theme>>, + <Theme as Catalog>::Class<'a>: Into<StyleFn<'a, Theme>>, { 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<Element<'a, Message, Theme, Renderer>>, content: impl Into<Element<'a, Message, Theme, Renderer>>, - backdrop_color: impl Fn(&Theme) -> Color + 'a, + class: <Theme as Catalog>::Class<'a>, ) -> Element<'a, Message, Theme, Renderer> where Message: 'a + Clone, Renderer: 'a + core::Renderer, - Theme: 'a + container::Catalog, - Theme::Class<'a>: From<container::StyleFn<'a, Theme>>, + Theme: 'a + container::Catalog + Catalog, + <Theme as container::Catalog>::Class<'a>: + From<container::StyleFn<'a, Theme>>, + <Theme as Catalog>::Class<'a>: Into<StyleFn<'a, Theme>>, { + 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>() -> <Self as Catalog>::Class<'a>; + /// The default class for the [`Dialog`]'s title. fn default_title<'a>() -> <Self as text::Catalog>::Class<'a> { <Self as text::Catalog>::default() @@ -279,9 +334,21 @@ pub trait Catalog: text::Catalog + container::Catalog { fn default_container<'a>() -> <Self as container::Catalog>::Class<'a> { <Self as container::Catalog>::default() } + + /// The [`Style`] of a class. + fn style(&self, class: <Self as Catalog>::Class<'_>) -> Style; } +/// A styling function for a [`Dialog`]. +pub type StyleFn<'a, Theme> = Box<dyn Fn(&Theme) -> Style + 'a>; + impl Catalog for Theme { + type Class<'a> = StyleFn<'a, Self>; + + fn default<'a>() -> <Self as Catalog>::Class<'a> { + Box::new(default) + } + fn default_container<'a>() -> <Self as container::Catalog>::Class<'a> { Box::new(|theme| { container::background( @@ -289,4 +356,15 @@ impl Catalog for Theme { ) }) } + + fn style(&self, class: <Self as Catalog>::Class<'_>) -> Style { + class(self) + } +} + +/// The default style of a [`Dialog`]. +pub fn default(_theme: &Theme) -> Style { + Style { + backdrop_color: color!(0x000000, 0.3), + } } @@ -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) } |
