... and also make `center_x` and `center_y` set `width` and `height` to `Length::Fill`, respectively. This targets the most common use case when centering things and removes a bunch of boilerplate as a result.
220 lines
6.1 KiB
Rust
220 lines
6.1 KiB
Rust
use iced::event::{self, Event};
|
|
use iced::keyboard;
|
|
use iced::keyboard::key;
|
|
use iced::widget::{
|
|
self, button, center, column, container, horizontal_space, mouse_area,
|
|
opaque, pick_list, row, stack, text, text_input,
|
|
};
|
|
use iced::{Alignment, Color, Command, Element, Length, Subscription};
|
|
|
|
use std::fmt;
|
|
|
|
pub fn main() -> iced::Result {
|
|
iced::program("Modal - Iced", App::update, App::view)
|
|
.subscription(App::subscription)
|
|
.run()
|
|
}
|
|
|
|
#[derive(Default)]
|
|
struct App {
|
|
show_modal: bool,
|
|
email: String,
|
|
password: String,
|
|
plan: Plan,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
enum Message {
|
|
ShowModal,
|
|
HideModal,
|
|
Email(String),
|
|
Password(String),
|
|
Plan(Plan),
|
|
Submit,
|
|
Event(Event),
|
|
}
|
|
|
|
impl App {
|
|
fn subscription(&self) -> Subscription<Message> {
|
|
event::listen().map(Message::Event)
|
|
}
|
|
|
|
fn update(&mut self, message: Message) -> Command<Message> {
|
|
match message {
|
|
Message::ShowModal => {
|
|
self.show_modal = true;
|
|
widget::focus_next()
|
|
}
|
|
Message::HideModal => {
|
|
self.hide_modal();
|
|
Command::none()
|
|
}
|
|
Message::Email(email) => {
|
|
self.email = email;
|
|
Command::none()
|
|
}
|
|
Message::Password(password) => {
|
|
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();
|
|
}
|
|
|
|
Command::none()
|
|
}
|
|
Message::Event(event) => match event {
|
|
Event::Keyboard(keyboard::Event::KeyPressed {
|
|
key: keyboard::Key::Named(key::Named::Tab),
|
|
modifiers,
|
|
..
|
|
}) => {
|
|
if modifiers.shift() {
|
|
widget::focus_previous()
|
|
} else {
|
|
widget::focus_next()
|
|
}
|
|
}
|
|
Event::Keyboard(keyboard::Event::KeyPressed {
|
|
key: keyboard::Key::Named(key::Named::Escape),
|
|
..
|
|
}) => {
|
|
self.hide_modal();
|
|
Command::none()
|
|
}
|
|
_ => Command::none(),
|
|
},
|
|
}
|
|
}
|
|
|
|
fn view(&self) -> Element<Message> {
|
|
let content = container(
|
|
column![
|
|
row![text("Top Left"), horizontal_space(), text("Top Right")]
|
|
.align_items(Alignment::Start)
|
|
.height(Length::Fill),
|
|
center(button(text("Show Modal")).on_press(Message::ShowModal)),
|
|
row![
|
|
text("Bottom Left"),
|
|
horizontal_space(),
|
|
text("Bottom Right")
|
|
]
|
|
.align_items(Alignment::End)
|
|
.height(Length::Fill),
|
|
]
|
|
.height(Length::Fill),
|
|
)
|
|
.padding(10);
|
|
|
|
if self.show_modal {
|
|
let signup = container(
|
|
column![
|
|
text("Sign Up").size(24),
|
|
column![
|
|
column![
|
|
text("Email").size(12),
|
|
text_input("abc@123.com", &self.email,)
|
|
.on_input(Message::Email)
|
|
.on_submit(Message::Submit)
|
|
.padding(5),
|
|
]
|
|
.spacing(5),
|
|
column![
|
|
text("Password").size(12),
|
|
text_input("", &self.password)
|
|
.on_input(Message::Password)
|
|
.on_submit(Message::Submit)
|
|
.secure(true)
|
|
.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)
|
|
]
|
|
.spacing(20),
|
|
)
|
|
.width(300)
|
|
.padding(10)
|
|
.style(container::rounded_box);
|
|
|
|
modal(content, signup, Message::HideModal)
|
|
} else {
|
|
content.into()
|
|
}
|
|
}
|
|
}
|
|
|
|
impl App {
|
|
fn hide_modal(&mut self) {
|
|
self.show_modal = false;
|
|
self.email.clear();
|
|
self.password.clear();
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
|
enum Plan {
|
|
#[default]
|
|
Basic,
|
|
Pro,
|
|
Enterprise,
|
|
}
|
|
|
|
impl Plan {
|
|
pub const ALL: &'static [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)
|
|
}
|
|
}
|
|
|
|
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()
|
|
}
|
|
}))
|
|
.on_press(on_blur)
|
|
]
|
|
.into()
|
|
}
|