diff options
Diffstat (limited to 'examples/modal/src/main.rs')
-rw-r--r-- | examples/modal/src/main.rs | 368 |
1 files changed, 30 insertions, 338 deletions
diff --git a/examples/modal/src/main.rs b/examples/modal/src/main.rs index 398728e0..a012c310 100644 --- a/examples/modal/src/main.rs +++ b/examples/modal/src/main.rs @@ -2,12 +2,11 @@ use iced::event::{self, Event}; use iced::keyboard; use iced::keyboard::key; use iced::widget::{ - self, button, column, container, horizontal_space, pick_list, row, text, - text_input, + self, button, center, column, container, horizontal_space, mouse_area, + opaque, pick_list, row, stack, text, text_input, }; -use iced::{Alignment, Command, Element, Length, Subscription}; +use iced::{Alignment, Color, Command, Element, Length, Subscription}; -use modal::Modal; use std::fmt; pub fn main() -> iced::Result { @@ -99,13 +98,7 @@ impl App { row![text("Top Left"), horizontal_space(), text("Top Right")] .align_items(Alignment::Start) .height(Length::Fill), - container( - button(text("Show Modal")).on_press(Message::ShowModal) - ) - .center_x() - .center_y() - .width(Length::Fill) - .height(Length::Fill), + center(button(text("Show Modal")).on_press(Message::ShowModal)), row![ text("Bottom Left"), horizontal_space(), @@ -116,12 +109,10 @@ impl App { ] .height(Length::Fill), ) - .padding(10) - .width(Length::Fill) - .height(Length::Fill); + .padding(10); if self.show_modal { - let modal = container( + let signup = container( column![ text("Sign Up").size(24), column![ @@ -162,9 +153,7 @@ impl App { .padding(10) .style(container::rounded_box); - Modal::new(content, modal) - .on_blur(Message::HideModal) - .into() + modal(content, signup, Message::HideModal) } else { content.into() } @@ -203,326 +192,29 @@ impl fmt::Display for Plan { } } -mod modal { - use iced::advanced::layout::{self, Layout}; - use iced::advanced::overlay; - use iced::advanced::renderer; - use iced::advanced::widget::{self, Widget}; - use iced::advanced::{self, Clipboard, Shell}; - use iced::alignment::Alignment; - use iced::event; - use iced::mouse; - use iced::{Color, Element, Event, Length, Point, Rectangle, Size, Vector}; - - /// A widget that centers a modal element over some base element - pub struct Modal<'a, Message, Theme, Renderer> { - base: Element<'a, Message, Theme, Renderer>, - modal: Element<'a, Message, Theme, Renderer>, - on_blur: Option<Message>, - } - - impl<'a, Message, Theme, Renderer> Modal<'a, Message, Theme, Renderer> { - /// Returns a new [`Modal`] - pub fn new( - base: impl Into<Element<'a, Message, Theme, Renderer>>, - modal: impl Into<Element<'a, Message, Theme, Renderer>>, - ) -> Self { - Self { - base: base.into(), - modal: modal.into(), - on_blur: None, - } - } - - /// Sets the message that will be produces when the background - /// of the [`Modal`] is pressed - pub fn on_blur(self, on_blur: Message) -> Self { - Self { - on_blur: Some(on_blur), - ..self - } - } - } - - impl<'a, Message, Theme, Renderer> Widget<Message, Theme, Renderer> - for Modal<'a, Message, Theme, Renderer> - where - Renderer: advanced::Renderer, - Message: Clone, - { - fn children(&self) -> Vec<widget::Tree> { - vec![ - widget::Tree::new(&self.base), - widget::Tree::new(&self.modal), - ] - } - - fn diff(&self, tree: &mut widget::Tree) { - tree.diff_children(&[&self.base, &self.modal]); - } - - fn size(&self) -> Size<Length> { - self.base.as_widget().size() - } - - fn layout( - &self, - tree: &mut widget::Tree, - renderer: &Renderer, - limits: &layout::Limits, - ) -> layout::Node { - self.base.as_widget().layout( - &mut tree.children[0], - renderer, - limits, - ) - } - - fn on_event( - &mut self, - state: &mut widget::Tree, - event: Event, - layout: Layout<'_>, - cursor: mouse::Cursor, - renderer: &Renderer, - clipboard: &mut dyn Clipboard, - shell: &mut Shell<'_, Message>, - viewport: &Rectangle, - ) -> event::Status { - self.base.as_widget_mut().on_event( - &mut state.children[0], - event, - layout, - cursor, - renderer, - clipboard, - shell, - viewport, - ) - } - - fn draw( - &self, - state: &widget::Tree, - renderer: &mut Renderer, - theme: &Theme, - style: &renderer::Style, - layout: Layout<'_>, - cursor: mouse::Cursor, - viewport: &Rectangle, - ) { - self.base.as_widget().draw( - &state.children[0], - renderer, - theme, - style, - layout, - cursor, - viewport, - ); - } - - fn overlay<'b>( - &'b mut self, - state: &'b mut widget::Tree, - layout: Layout<'_>, - _renderer: &Renderer, - translation: Vector, - ) -> Option<overlay::Element<'b, Message, Theme, Renderer>> { - Some(overlay::Element::new(Box::new(Overlay { - position: layout.position() + translation, - content: &mut self.modal, - tree: &mut state.children[1], - size: layout.bounds().size(), - on_blur: self.on_blur.clone(), - }))) - } - - fn mouse_interaction( - &self, - state: &widget::Tree, - layout: Layout<'_>, - cursor: mouse::Cursor, - viewport: &Rectangle, - renderer: &Renderer, - ) -> mouse::Interaction { - self.base.as_widget().mouse_interaction( - &state.children[0], - layout, - cursor, - viewport, - renderer, - ) - } - - fn operate( - &self, - state: &mut widget::Tree, - layout: Layout<'_>, - renderer: &Renderer, - operation: &mut dyn widget::Operation<Message>, - ) { - self.base.as_widget().operate( - &mut state.children[0], - layout, - renderer, - operation, - ); - } - } - - struct Overlay<'a, 'b, Message, Theme, Renderer> { - position: Point, - content: &'b mut Element<'a, Message, Theme, Renderer>, - tree: &'b mut widget::Tree, - size: Size, - on_blur: Option<Message>, - } - - impl<'a, 'b, Message, Theme, Renderer> - overlay::Overlay<Message, Theme, Renderer> - for Overlay<'a, 'b, Message, Theme, Renderer> - where - Renderer: advanced::Renderer, - Message: Clone, - { - fn layout( - &mut self, - renderer: &Renderer, - _bounds: Size, - ) -> layout::Node { - let limits = layout::Limits::new(Size::ZERO, self.size) - .width(Length::Fill) - .height(Length::Fill); - - let child = self - .content - .as_widget() - .layout(self.tree, renderer, &limits) - .align(Alignment::Center, Alignment::Center, limits.max()); - - layout::Node::with_children(self.size, vec![child]) - .move_to(self.position) - } - - fn on_event( - &mut self, - event: Event, - layout: Layout<'_>, - cursor: mouse::Cursor, - renderer: &Renderer, - clipboard: &mut dyn Clipboard, - shell: &mut Shell<'_, Message>, - ) -> event::Status { - let content_bounds = layout.children().next().unwrap().bounds(); - - if let Some(message) = self.on_blur.as_ref() { - if let Event::Mouse(mouse::Event::ButtonPressed( - mouse::Button::Left, - )) = &event - { - if !cursor.is_over(content_bounds) { - shell.publish(message.clone()); - return event::Status::Captured; +fn modal<'a, Message>( + base: impl Into<Element<'a, Message>>, + content: impl Into<Element<'a, Message>>, + on_blur: Message, +) -> Element<'a, Message> +where + Message: Clone + 'a, +{ + stack![ + base.into(), + mouse_area(center(opaque(content)).style(|_theme| { + container::Style { + background: Some( + Color { + a: 0.8, + ..Color::BLACK } - } + .into(), + ), + ..container::Style::default() } - - self.content.as_widget_mut().on_event( - self.tree, - event, - layout.children().next().unwrap(), - cursor, - renderer, - clipboard, - shell, - &layout.bounds(), - ) - } - - fn draw( - &self, - renderer: &mut Renderer, - theme: &Theme, - style: &renderer::Style, - layout: Layout<'_>, - cursor: mouse::Cursor, - ) { - renderer.fill_quad( - renderer::Quad { - bounds: layout.bounds(), - ..renderer::Quad::default() - }, - Color { - a: 0.80, - ..Color::BLACK - }, - ); - - self.content.as_widget().draw( - self.tree, - renderer, - theme, - style, - layout.children().next().unwrap(), - cursor, - &layout.bounds(), - ); - } - - fn operate( - &mut self, - layout: Layout<'_>, - renderer: &Renderer, - operation: &mut dyn widget::Operation<Message>, - ) { - self.content.as_widget().operate( - self.tree, - layout.children().next().unwrap(), - renderer, - operation, - ); - } - - fn mouse_interaction( - &self, - layout: Layout<'_>, - cursor: mouse::Cursor, - viewport: &Rectangle, - renderer: &Renderer, - ) -> mouse::Interaction { - self.content.as_widget().mouse_interaction( - self.tree, - layout.children().next().unwrap(), - cursor, - viewport, - renderer, - ) - } - - fn overlay<'c>( - &'c mut self, - layout: Layout<'_>, - renderer: &Renderer, - ) -> Option<overlay::Element<'c, Message, Theme, Renderer>> { - self.content.as_widget_mut().overlay( - self.tree, - layout.children().next().unwrap(), - renderer, - Vector::ZERO, - ) - } - } - - impl<'a, Message, Theme, Renderer> From<Modal<'a, Message, Theme, Renderer>> - for Element<'a, Message, Theme, Renderer> - where - Theme: 'a, - Message: 'a + Clone, - Renderer: 'a + advanced::Renderer, - { - fn from(modal: Modal<'a, Message, Theme, Renderer>) -> Self { - Element::new(modal) - } - } + })) + .on_press(on_blur) + ] + .into() } |