Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nested overlays #1719

Merged
merged 13 commits into from
Jun 14, 2023
16 changes: 15 additions & 1 deletion core/src/overlay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,23 @@ where
///
/// By default, it returns true if the bounds of the `layout` contain
/// the `cursor_position`.
fn is_over(&self, layout: Layout<'_>, cursor_position: Point) -> bool {
fn is_over(
&self,
layout: Layout<'_>,
_renderer: &Renderer,
cursor_position: Point,
) -> bool {
layout.bounds().contains(cursor_position)
}

/// Returns the nested overlay of the [`Overlay`], if there is any.
fn overlay<'a>(
&'a mut self,
_layout: Layout<'_>,
_renderer: &Renderer,
) -> Option<Element<'a, Message, Renderer>> {
None
}
}

/// Returns a [`Group`] of overlay [`Element`] children.
Expand Down
37 changes: 33 additions & 4 deletions core/src/overlay/element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,22 @@ where
}

/// Returns true if the cursor is over the [`Element`].
pub fn is_over(&self, layout: Layout<'_>, cursor_position: Point) -> bool {
self.overlay.is_over(layout, cursor_position)
pub fn is_over(
&self,
layout: Layout<'_>,
renderer: &Renderer,
cursor_position: Point,
) -> bool {
self.overlay.is_over(layout, renderer, cursor_position)
}

/// Returns the nested overlay of the [`Element`], if there is any.
pub fn overlay<'b>(
&'b mut self,
layout: Layout<'_>,
renderer: &Renderer,
) -> Option<Element<'b, Message, Renderer>> {
self.overlay.overlay(layout, renderer)
}
}

Expand Down Expand Up @@ -248,7 +262,22 @@ where
self.content.draw(renderer, theme, style, layout, cursor)
}

fn is_over(&self, layout: Layout<'_>, cursor_position: Point) -> bool {
self.content.is_over(layout, cursor_position)
fn is_over(
&self,
layout: Layout<'_>,
renderer: &Renderer,
cursor_position: Point,
) -> bool {
self.content.is_over(layout, renderer, cursor_position)
}

fn overlay<'b>(
&'b mut self,
layout: Layout<'_>,
renderer: &Renderer,
) -> Option<Element<'b, B, Renderer>> {
self.content
.overlay(layout, renderer)
.map(|overlay| overlay.map(self.mapper))
}
}
26 changes: 24 additions & 2 deletions core/src/overlay/group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,11 +147,33 @@ where
});
}

fn is_over(&self, layout: Layout<'_>, cursor_position: Point) -> bool {
fn is_over(
&self,
layout: Layout<'_>,
renderer: &Renderer,
cursor_position: Point,
) -> bool {
self.children
.iter()
.zip(layout.children())
.any(|(child, layout)| child.is_over(layout, cursor_position))
.any(|(child, layout)| {
child.is_over(layout, renderer, cursor_position)
})
}

fn overlay<'b>(
&'b mut self,
layout: Layout<'_>,
renderer: &Renderer,
) -> Option<overlay::Element<'b, Message, Renderer>> {
let children = self
.children
.iter_mut()
.zip(layout.children())
.filter_map(|(child, layout)| child.overlay(layout, renderer))
.collect::<Vec<_>>();

(!children.is_empty()).then(|| Group::with_children(children).overlay())
}
}

Expand Down
57 changes: 55 additions & 2 deletions examples/modal/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ use iced::keyboard;
use iced::subscription::{self, Subscription};
use iced::theme;
use iced::widget::{
self, button, column, container, horizontal_space, row, text, text_input,
self, button, column, container, horizontal_space, pick_list, row, text,
text_input,
};
use iced::{Alignment, Application, Command, Element, Event, Length, Settings};

use self::modal::Modal;
use modal::Modal;
use std::fmt;

pub fn main() -> iced::Result {
App::run(Settings::default())
Expand All @@ -18,6 +20,7 @@ struct App {
show_modal: bool,
email: String,
password: String,
plan: Plan,
}

#[derive(Debug, Clone)]
Expand All @@ -26,6 +29,7 @@ enum Message {
HideModal,
Email(String),
Password(String),
Plan(Plan),
Submit,
Event(Event),
}
Expand Down Expand Up @@ -66,6 +70,10 @@ impl Application for App {
self.password = password;
Command::none()
}
Message::Plan(plan) => {
self.plan = plan;
Command::none()
}
Message::Submit => {
if !self.email.is_empty() && !self.password.is_empty() {
self.hide_modal();
Expand Down Expand Up @@ -149,6 +157,16 @@ impl Application for App {
.padding(5),
]
.spacing(5),
column![
text("Plan").size(12),
pick_list(
Plan::ALL,
Some(self.plan),
Message::Plan
)
.padding(5),
]
.spacing(5),
button(text("Submit")).on_press(Message::HideModal),
]
.spacing(10)
Expand Down Expand Up @@ -176,6 +194,29 @@ impl App {
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
enum Plan {
#[default]
Basic,
Pro,
Enterprise,
}

impl Plan {
pub const ALL: &[Self] = &[Self::Basic, Self::Pro, Self::Enterprise];
}

impl fmt::Display for Plan {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Plan::Basic => "Basic",
Plan::Pro => "Pro",
Plan::Enterprise => "Enterprise",
}
.fmt(f)
}
}

mod modal {
use iced::advanced::layout::{self, Layout};
use iced::advanced::overlay;
Expand Down Expand Up @@ -469,6 +510,18 @@ mod modal {
renderer,
)
}

fn overlay<'c>(
&'c mut self,
layout: Layout<'_>,
renderer: &Renderer,
) -> Option<overlay::Element<'c, Message, Renderer>> {
self.content.as_widget_mut().overlay(
self.tree,
layout.children().next().unwrap(),
renderer,
)
}
}

impl<'a, Message, Renderer> From<Modal<'a, Message, Renderer>>
Expand Down
7 changes: 6 additions & 1 deletion examples/toast/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,12 @@ mod toast {
.unwrap_or_default()
}

fn is_over(&self, layout: Layout<'_>, cursor_position: Point) -> bool {
fn is_over(
&self,
layout: Layout<'_>,
_renderer: &Renderer,
cursor_position: Point,
) -> bool {
layout
.children()
.any(|layout| layout.bounds().contains(cursor_position))
Expand Down
1 change: 1 addition & 0 deletions runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ pub mod clipboard;
pub mod command;
pub mod font;
pub mod keyboard;
pub mod overlay;
pub mod program;
pub mod system;
pub mod user_interface;
Expand Down
4 changes: 4 additions & 0 deletions runtime/src/overlay.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
//! Overlays for user interfaces.
mod nested;

pub use nested::Nested;
Loading