use egui::{Context, Id};
use crate::tokens::DESIGN_TOKENS;
use crate::ui_kit::buttons::{Button, ButtonVariant};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ConfirmResult {
None,
Confirmed,
Cancelled,
}
impl ConfirmResult {
pub fn is_confirmed(&self) -> bool {
matches!(self, ConfirmResult::Confirmed)
}
pub fn is_cancelled(&self) -> bool {
matches!(self, ConfirmResult::Cancelled)
}
pub fn is_open(&self) -> bool {
matches!(self, ConfirmResult::None)
}
}
pub struct ConfirmDialog {
id: Id,
title: String,
message: String,
confirm_text: String,
cancel_text: String,
danger: bool,
}
impl ConfirmDialog {
pub fn new(
id: impl std::hash::Hash,
title: impl Into<String>,
message: impl Into<String>,
) -> Self {
Self {
id: Id::new(id),
title: title.into(),
message: message.into(),
confirm_text: "Confirm".to_string(),
cancel_text: "Cancel".to_string(),
danger: false,
}
}
pub fn confirm_text(mut self, text: impl Into<String>) -> Self {
self.confirm_text = text.into();
self
}
pub fn cancel_text(mut self, text: impl Into<String>) -> Self {
self.cancel_text = text.into();
self
}
pub fn danger(mut self) -> Self {
self.danger = true;
self
}
pub fn show(self, ctx: &Context, open: &mut bool) -> ConfirmResult {
if !*open {
return ConfirmResult::None;
}
let mut result = ConfirmResult::None;
egui::Area::new(self.id)
.fixed_pos(egui::pos2(0.0, 0.0))
.order(egui::Order::Foreground)
.show(ctx, |ui| {
let screen_rect = ctx.content_rect();
ui.painter()
.rect_filled(screen_rect, 0.0, egui::Color32::from_black_alpha(180));
if ui.input(|i| i.key_pressed(egui::Key::Escape)) {
result = ConfirmResult::Cancelled;
*open = false;
return;
}
egui::Window::new(&self.title)
.id(self.id.with("_window"))
.fixed_pos(screen_rect.center() - egui::vec2(175.0, 75.0))
.fixed_size(egui::vec2(350.0, 0.0))
.collapsible(false)
.resizable(false)
.title_bar(true)
.show(ctx, |ui| {
ui.add_space(DESIGN_TOKENS.spacing.md);
ui.label(&self.message);
ui.add_space(DESIGN_TOKENS.spacing.xl);
ui.horizontal(|ui| {
ui.with_layout(
egui::Layout::right_to_left(egui::Align::Center),
|ui| {
let confirm_variant = if self.danger {
ButtonVariant::Danger
} else {
ButtonVariant::Primary
};
if ui
.add(
Button::new(&self.confirm_text)
.variant(confirm_variant),
)
.clicked()
{
result = ConfirmResult::Confirmed;
*open = false;
}
ui.add_space(DESIGN_TOKENS.spacing.md);
if ui
.add(
Button::new(&self.cancel_text)
.variant(ButtonVariant::Secondary),
)
.clicked()
{
result = ConfirmResult::Cancelled;
*open = false;
}
},
);
});
ui.add_space(DESIGN_TOKENS.spacing.md);
});
});
result
}
}
pub fn confirm(
ctx: &Context,
id: impl std::hash::Hash,
title: impl Into<String>,
message: impl Into<String>,
open: &mut bool,
) -> ConfirmResult {
ConfirmDialog::new(id, title, message).show(ctx, open)
}
pub fn confirm_danger(
ctx: &Context,
id: impl std::hash::Hash,
title: impl Into<String>,
message: impl Into<String>,
open: &mut bool,
) -> ConfirmResult {
ConfirmDialog::new(id, title, message)
.danger()
.show(ctx, open)
}