Skip to content

Commit

Permalink
Merge pull request #169 from lucatrv/extend-modal-for-multiple-overlays
Browse files Browse the repository at this point in the history
Extend modal to support multiple overlays
  • Loading branch information
Andrew Wheeler(Genusis) authored Aug 16, 2023
2 parents eceab41 + 935dd5e commit dd08aaa
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 62 deletions.
71 changes: 38 additions & 33 deletions examples/modal/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ impl Application for ModalExample {
.center_x()
.into(),
ModalExample::Loaded(state) => {
let content = Container::new(
let underlay = Container::new(
Row::new()
.spacing(10)
.align_items(Alignment::Center)
Expand All @@ -113,41 +113,46 @@ impl Application for ModalExample {
))),
);

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.")
)
.foot(
Row::new()
.spacing(10)
.padding(5)
.width(Length::Fill)
.push(
Button::new(
Text::new("Cancel").horizontal_alignment(Horizontal::Center),
)
let overlay = if state.show_modal {
Some(
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.")
)
.foot(
Row::new()
.spacing(10)
.padding(5)
.width(Length::Fill)
.on_press(Message::CancelButtonPressed),
)
.push(
Button::new(
Text::new("Ok").horizontal_alignment(Horizontal::Center),
.push(
Button::new(
Text::new("Cancel")
.horizontal_alignment(Horizontal::Center),
)
.width(Length::Fill)
.on_press(Message::CancelButtonPressed),
)
.width(Length::Fill)
.on_press(Message::OkButtonPressed),
),
.push(
Button::new(
Text::new("Ok").horizontal_alignment(Horizontal::Center),
)
.width(Length::Fill)
.on_press(Message::OkButtonPressed),
),
)
.max_width(300.0)
//.width(Length::Shrink)
.on_close(Message::CloseModal),
)
.max_width(300.0)
//.width(Length::Shrink)
.on_close(Message::CloseModal),
)
.backdrop(Message::CloseModal)
.on_esc(Message::CloseModal)
.align_y(alignment::Vertical::Top)
.into()
} else {
None
};

modal(underlay, overlay)
.backdrop(Message::CloseModal)
.on_esc(Message::CloseModal)
.align_y(alignment::Vertical::Top)
.into()
}
}
}
Expand Down
20 changes: 11 additions & 9 deletions examples/modal_component/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ impl Application for ModalExample {
.center_x()
.into(),
ModalExample::Loaded(state) => {
let content = Container::new(
let underlay = Container::new(
Row::new()
.spacing(10)
.align_items(Alignment::Center)
Expand All @@ -105,14 +105,16 @@ impl Application for ModalExample {
))),
);

Modal::new(
state.show_modal,
content,
container(my_component::MyComponent),
)
.backdrop(Message::CloseModal)
.on_esc(Message::CloseModal)
.into()
let overlay = if state.show_modal {
Some(container(my_component::MyComponent))
} else {
None
};

Modal::new(underlay, overlay)
.backdrop(Message::CloseModal)
.on_esc(Message::CloseModal)
.into()
}
}
}
Expand Down
5 changes: 2 additions & 3 deletions src/native/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,16 +256,15 @@ where
/// [`Modal`]: crate::Modal
#[must_use]
pub fn modal<'a, Message, Renderer>(
show_modal: bool,
underlay: impl Into<Element<'a, Message, Renderer>>,
content: impl Into<Element<'a, Message, Renderer>>,
overlay: Option<impl Into<Element<'a, Message, Renderer>>>,
) -> crate::Modal<'a, Message, Renderer>
where
Message: Clone,
Renderer: core::Renderer,
Renderer::Theme: crate::style::modal::StyleSheet,
{
crate::Modal::new(show_modal, underlay, content)
crate::Modal::new(underlay, overlay)
}

#[cfg(feature = "number_input")]
Expand Down
38 changes: 21 additions & 17 deletions src/native/modal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,10 @@ where
Renderer: core::Renderer,
Renderer::Theme: StyleSheet,
{
/// Show the modal.
show_modal: bool,
/// The underlying element.
underlay: Element<'a, Message, Renderer>,
/// The content of the [`ModalOverlay`](ModalOverlay).
content: Element<'a, Message, Renderer>,
overlay: Option<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 Down Expand Up @@ -77,14 +75,12 @@ where
/// will be wrapped around.
/// * the content [`Element`] of the [`Modal`](Modal).
pub fn new(
show_modal: bool,
underlay: impl Into<Element<'a, Message, Renderer>>,
content: impl Into<Element<'a, Message, Renderer>>,
overlay: Option<impl Into<Element<'a, Message, Renderer>>>,
) -> Self {
Modal {
show_modal,
underlay: underlay.into(),
content: content.into(),
overlay: overlay.map(Into::into),
backdrop: None,
esc: None,
style: <Renderer::Theme as StyleSheet>::Style::default(),
Expand Down Expand Up @@ -140,11 +136,19 @@ where
Renderer::Theme: StyleSheet,
{
fn children(&self) -> Vec<Tree> {
vec![Tree::new(&self.underlay), Tree::new(&self.content)]
if let Some(overlay) = &self.overlay {

Check failure on line 139 in src/native/modal.rs

View workflow job for this annotation

GitHub Actions / all

use Option::map_or_else instead of an if let/else
vec![Tree::new(&self.underlay), Tree::new(overlay)]
} else {
vec![Tree::new(&self.underlay)]
}
}

fn diff(&self, tree: &mut Tree) {
tree.diff_children(&[&self.underlay, &self.content]);
if let Some(overlay) = &self.overlay {
tree.diff_children(&[&self.underlay, overlay]);
} else {
tree.diff_children(&[&self.underlay]);
}
}

fn width(&self) -> Length {
Expand All @@ -170,7 +174,7 @@ where
shell: &mut Shell<'_, Message>,
viewport: &Rectangle,
) -> event::Status {
if !self.show_modal {
if self.overlay.is_none() {
return self.underlay.as_widget_mut().on_event(
&mut state.children[0],
event,
Expand All @@ -194,7 +198,7 @@ where
viewport: &Rectangle,
renderer: &Renderer,
) -> mouse::Interaction {
if !self.show_modal {
if self.overlay.is_none() {
return self.underlay.as_widget().mouse_interaction(
&state.children[0],
layout,
Expand Down Expand Up @@ -234,16 +238,16 @@ where
layout: Layout<'_>,
renderer: &Renderer,
) -> Option<overlay::Element<'b, Message, Renderer>> {
if self.show_modal {
if let Some(overlay) = &mut self.overlay {
let bounds = layout.bounds();
let position = Point::new(bounds.x, bounds.y);
self.content.as_widget().diff(&mut state.children[1]);
overlay.as_widget().diff(&mut state.children[1]);

Some(overlay::Element::new(
position,
Box::new(ModalOverlay::new(
&mut state.children[1],
&mut self.content,
overlay,
self.backdrop.clone(),
self.esc.clone(),
self.style.clone(),
Expand All @@ -265,10 +269,10 @@ where
renderer: &Renderer,
operation: &mut dyn Operation<Message>,
) {
if self.show_modal {
self.content.as_widget().diff(&mut state.children[1]);
if let Some(overlay) = &self.overlay {
overlay.as_widget().diff(&mut state.children[1]);

self.content
overlay
.as_widget()
.operate(&mut state.children[1], layout, renderer, operation);
} else {
Expand Down

0 comments on commit dd08aaa

Please sign in to comment.