summaryrefslogtreecommitdiffstats
path: root/examples/modal/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'examples/modal/src/main.rs')
-rw-r--r--examples/modal/src/main.rs368
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()
}