Skip to content

Commit

Permalink
made Modal block all underlay events when visible
Browse files Browse the repository at this point in the history
  • Loading branch information
genusistimelord committed Jul 24, 2023
1 parent 686f815 commit 9955bc6
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 98 deletions.
9 changes: 5 additions & 4 deletions examples/modal/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,9 @@ impl Application for ModalExample {
))),
);

modal(state.show_modal, content, || {
modal(
state.show_modal,
content,
Card::new(
Text::new("My modal"),
Text::new("This is a modal!"), //Text::new("Zombie ipsum reversus ab viral inferno, nam rick grimes malum cerebro. De carne lumbering animata corpora quaeritis. Summus brains sit​​, morbo vel maleficia? De apocalypsi gorger omero undead survivor dictum mauris. Hi mindless mortuis soulless creaturas, imo evil stalking monstra adventus resi dentevil vultus comedat cerebella viventium. Qui animated corpse, cricket bat max brucks terribilem incessu zomby. The voodoo sacerdos flesh eater, suscitat mortuos comedere carnem virus. Zonbi tattered for solum oculi eorum defunctis go lum cerebro. Nescio brains an Undead zombies. Sicut malus putrid voodoo horror. Nigh tofth eliv ingdead.")
Expand All @@ -140,9 +142,8 @@ impl Application for ModalExample {
)
.max_width(300.0)
//.width(Length::Shrink)
.on_close(Message::CloseModal)
.into()
})
.on_close(Message::CloseModal),
)
.backdrop(Message::CloseModal)
.on_esc(Message::CloseModal)
.into()
Expand Down
4 changes: 1 addition & 3 deletions examples/modal_component/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,7 @@ impl Application for ModalExample {
))),

Check failure on line 105 in examples/modal_component/src/main.rs

View workflow job for this annotation

GitHub Actions / all

Diff in /home/runner/work/iced_aw/iced_aw/examples/modal_component/src/main.rs
);

Modal::new(state.show_modal, content, || {
container(my_component::MyComponent).into()
})
Modal::new(state.show_modal, content, container(my_component::MyComponent))
.backdrop(Message::CloseModal)
.on_esc(Message::CloseModal)
.into()
Expand Down
7 changes: 3 additions & 4 deletions src/native/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,13 +179,12 @@ where
#[cfg(feature = "modal")]
/// Shortcut helper to create a Card Widget.
#[must_use]
pub fn modal<'a, Content, Message, Renderer>(
pub fn modal<'a, Message, Renderer>(
show_modal: bool,
underlay: impl Into<Element<'a, Message, Renderer>>,
content: Content,
) -> crate::Modal<'a, Content, Message, Renderer>
content: impl Into<Element<'a, Message, Renderer>>,
) -> crate::Modal<'a, Message, Renderer>
where
Content: Fn() -> Element<'a, Message, Renderer>,
Message: Clone,
Renderer: core::Renderer,
Renderer::Theme: crate::style::modal::StyleSheet,
Expand Down
2 changes: 1 addition & 1 deletion src/native/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ pub type IconText<Renderer> = crate::native::icon_text::IconText<Renderer>;
pub mod modal;
#[cfg(feature = "modal")]
/// A modal content as an overlay.
pub type Modal<'a, Content, Message, Renderer> = modal::Modal<'a, Content, Message, Renderer>;
pub type Modal<'a, Message, Renderer> = modal::Modal<'a, Message, Renderer>;

#[cfg(feature = "split")]
pub mod split;
Expand Down
125 changes: 63 additions & 62 deletions src/native/modal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,25 @@ pub use crate::style::modal::StyleSheet;
/// ```
/// # use core::Renderer::Null;
/// # use iced_native::widget::Text;
/// # use iced_aw::native::modal;
/// # use iced_aw::native::{ modal};
/// #
/// # pub type Modal<'a, Content, Message>
/// # = modal::Modal<'a, Message, Content, Null>;
/// # pub type Modal<'a, Message>
/// # = modal::Modal<'a, Message, Null>;
/// #[derive(Debug, Clone)]
/// enum Message {
/// CloseModal,
/// }
///
/// let modal = Modal::new(
/// true,
/// false,
/// Text::new("Underlay"),
/// || Text::new("Overlay").into()
/// )
/// .backdrop(Message::CloseModal);
/// ```
#[allow(missing_debug_implementations)]
pub struct Modal<'a, Content, Message, Renderer = crate::Renderer>
pub struct Modal<'a, Message, Renderer = crate::Renderer>
where
Content: Fn() -> Element<'a, Message, Renderer>,
Message: Clone,
Renderer: core::Renderer,
Renderer::Theme: StyleSheet,
Expand All @@ -51,7 +50,7 @@ where
/// The underlying element.
underlay: Element<'a, Message, Renderer>,
/// The content of teh [`ModalOverlay`](ModalOverlay).
content: Content,
content: Element<'a, Message, Renderer>,
/// The optional message that will be send when the user clicked on the backdrop.
backdrop: Option<Message>,
/// The optional message that will be send when the ESC key was pressed.
Expand All @@ -60,9 +59,8 @@ where
style: <Renderer::Theme as StyleSheet>::Style,
}

impl<'a, Content, Message, Renderer> Modal<'a, Content, Message, Renderer>
impl<'a, Message, Renderer> Modal<'a, Message, Renderer>
where
Content: Fn() -> Element<'a, Message, Renderer>,
Message: Clone,
Renderer: core::Renderer,
Renderer::Theme: StyleSheet,
Expand All @@ -78,14 +76,15 @@ where
/// * the underlay [`Element`](iced_native::Element) on which this [`Modal`](Modal)
/// will be wrapped around.
/// * the content [`Element`](iced_native::Element) of the [`Modal`](Modal).
pub fn new<U>(show_modal: bool, underlay: U, content: Content) -> Self
pub fn new<U, C>(show_modal: bool, underlay: U, content: C) -> Self
where
U: Into<Element<'a, Message, Renderer>>,
C: Into<Element<'a, Message, Renderer>>,
{
Modal {
show_modal,
underlay: underlay.into(),
content,
content: content.into(),
backdrop: None,
esc: None,
style: <Renderer::Theme as StyleSheet>::Style::default(),
Expand Down Expand Up @@ -118,20 +117,18 @@ where
}
}

impl<'a, Content, Message, Renderer> Widget<Message, Renderer>
for Modal<'a, Content, Message, Renderer>
impl<'a, Message, Renderer> Widget<Message, Renderer> for Modal<'a, Message, Renderer>
where
Content: 'a + Fn() -> Element<'a, Message, Renderer>,
Message: 'a + Clone,
Renderer: 'a + core::Renderer,
Message: Clone,
Renderer: core::Renderer,
Renderer::Theme: StyleSheet,
{
fn children(&self) -> Vec<Tree> {
vec![Tree::new(&self.underlay), Tree::new(&(self.content)())]
vec![Tree::new(&self.underlay), Tree::new(&self.content)]
}

fn diff(&self, tree: &mut Tree) {
tree.diff_children(&[&self.underlay, &(self.content)()]);
tree.diff_children(&[&self.underlay, &self.content]);
}

fn width(&self) -> Length {
Expand All @@ -157,16 +154,20 @@ where
shell: &mut Shell<'_, Message>,
viewport: &Rectangle,
) -> event::Status {
self.underlay.as_widget_mut().on_event(
&mut state.children[0],
event,
layout,
cursor,
renderer,
clipboard,
shell,
viewport,
)
if !self.show_modal {
return self.underlay.as_widget_mut().on_event(
&mut state.children[0],
event,
layout,
cursor,
renderer,
clipboard,
shell,
viewport,
);
}

event::Status::Ignored
}

fn mouse_interaction(
Expand All @@ -177,13 +178,17 @@ where
viewport: &Rectangle,
renderer: &Renderer,
) -> mouse::Interaction {
self.underlay.as_widget().mouse_interaction(
&state.children[0],
layout,
cursor,
viewport,
renderer,
)
if !self.show_modal {
return self.underlay.as_widget().mouse_interaction(
&state.children[0],
layout,
cursor,
viewport,
renderer,
);
}

mouse::Interaction::default()
}

fn draw(
Expand Down Expand Up @@ -213,28 +218,26 @@ where
layout: Layout<'_>,
renderer: &Renderer,
) -> Option<overlay::Element<'b, Message, Renderer>> {
if !self.show_modal {
return self
.underlay
if self.show_modal {
let bounds = layout.bounds();
let position = Point::new(bounds.x, bounds.y);
self.content.as_widget().diff(&mut state.children[1]);

Some(overlay::Element::new(
position,
Box::new(ModalOverlay::new(
&mut state.children[1],
&mut self.content,
self.backdrop.clone(),
self.esc.clone(),
self.style,
)),
))
} else {
self.underlay
.as_widget_mut()
.overlay(&mut state.children[0], layout, renderer);
.overlay(&mut state.children[0], layout, renderer)
}

let bounds = layout.bounds();
let position = Point::new(bounds.x, bounds.y);
let content = (self.content)();
content.as_widget().diff(&mut state.children[1]);

Some(
ModalOverlay::new(
&mut state.children[1],
content,
self.backdrop.clone(),
self.esc.clone(),
self.style,
)
.overlay(position),
)
}

fn operate<'b>(
Expand All @@ -245,10 +248,9 @@ where
operation: &mut dyn Operation<Message>,
) {
if self.show_modal {
let content = (self.content)();
content.as_widget().diff(&mut state.children[1]);
self.content.as_widget().diff(&mut state.children[1]);

content
self.content
.as_widget()
.operate(&mut state.children[1], layout, renderer, operation);
} else {
Expand All @@ -259,18 +261,17 @@ where
}
}

impl<'a, Content, Message, Renderer> From<Modal<'a, Content, Message, Renderer>>
for Element<'a, Message, Renderer>
impl<'a, Message, Renderer> From<Modal<'a, Message, Renderer>> for Element<'a, Message, Renderer>
where
Content: 'a + Fn() -> Element<'a, Message, Renderer>,
Message: 'a + Clone,
Renderer: 'a + core::Renderer,
Renderer::Theme: StyleSheet,
{
fn from(modal: Modal<'a, Content, Message, Renderer>) -> Self {
fn from(modal: Modal<'a, Message, Renderer>) -> Self {
Element::new(modal)
}
}

/// The state of the modal.
#[derive(Debug, Default)]
pub struct State<S> {
Expand Down
40 changes: 16 additions & 24 deletions src/native/overlay/modal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use iced_widget::core::{
self, event, keyboard, layout,
mouse::{self, Cursor},
overlay, renderer, touch,
renderer, touch,
widget::Tree,
Clipboard, Color, Element, Event, Layout, Overlay, Point, Rectangle, Shell, Size, Vector,
};
Expand All @@ -13,16 +13,16 @@ use crate::style::modal::StyleSheet;

/// The overlay of the modal.
#[allow(missing_debug_implementations)]
pub struct ModalOverlay<'a, Message, Renderer>
pub struct ModalOverlay<'a, 'b, Message, Renderer>
where
Message: 'a + Clone,
Renderer: 'a + core::Renderer,
Message: Clone,
Renderer: core::Renderer,
Renderer::Theme: StyleSheet,
{
/// The state of the [`ModalOverlay`](ModalOverlay).
state: &'a mut Tree,
state: &'b mut Tree,
/// The content of the [`ModalOverlay`](ModalOverlay).
content: Element<'a, Message, Renderer>,
content: &'b mut Element<'a, Message, Renderer>,
/// The optional message that will be send when the user clicks on the backdrop.
backdrop: Option<Message>,
/// The optional message that will be send when the ESC key was pressed.
Expand All @@ -31,43 +31,35 @@ where
style: <Renderer::Theme as StyleSheet>::Style,
}

impl<'a, Message, Renderer> ModalOverlay<'a, Message, Renderer>
impl<'a, 'b, Message, Renderer> ModalOverlay<'a, 'b, Message, Renderer>
where
Message: Clone,
Renderer: core::Renderer,
Renderer::Theme: StyleSheet,
{
/// Creates a new [`ModalOverlay`](ModalOverlay).
pub fn new<C>(
state: &'a mut Tree,
content: C,
pub fn new(
state: &'b mut Tree,
content: &'b mut Element<'a, Message, Renderer>,
backdrop: Option<Message>,
esc: Option<Message>,
style: <Renderer::Theme as StyleSheet>::Style,
) -> Self
where
C: Into<Element<'a, Message, Renderer>>,
{
) -> Self {
ModalOverlay {
state,
content: content.into(),
content,
backdrop,
esc,
style,
}
}

/// Turn this [`ModalOverlay`] into an overlay
/// [`Element`](iced_native::overlay::Element).
pub fn overlay(self, position: Point) -> overlay::Element<'a, Message, Renderer> {
overlay::Element::new(position, Box::new(self))
}
}

impl<'a, Message, Renderer> Overlay<Message, Renderer> for ModalOverlay<'a, Message, Renderer>
impl<'a, 'b, Message, Renderer> Overlay<Message, Renderer>
for ModalOverlay<'a, 'b, Message, Renderer>
where
Message: 'a + Clone,
Renderer: 'a + core::Renderer,
Message: Clone,
Renderer: core::Renderer,
Renderer::Theme: StyleSheet,
{
fn layout(&self, renderer: &Renderer, bounds: Size, position: Point) -> layout::Node {
Expand Down

0 comments on commit 9955bc6

Please sign in to comment.