ced/src/app/state/lifecycle.rs

125 lines
4.6 KiB
Rust
Raw Normal View History

2025-07-05 14:42:45 -04:00
use super::editor::{TextEditor, UnsavedAction};
use eframe::egui;
impl TextEditor {
pub fn has_unsaved_changes(&self) -> bool {
self.tabs.iter().any(|tab| tab.is_modified)
}
pub fn get_unsaved_files(&self) -> Vec<String> {
self.tabs
.iter()
.filter(|tab| tab.is_modified)
.map(|tab| tab.title.clone())
.collect()
}
pub fn request_quit(&mut self, ctx: &egui::Context) {
if self.has_unsaved_changes() {
self.pending_unsaved_action = Some(UnsavedAction::Quit);
} else {
self.clean_quit_requested = true;
ctx.send_viewport_cmd(egui::ViewportCommand::Close);
}
}
pub fn force_quit(&mut self, ctx: &egui::Context) {
self.force_quit_confirmed = true;
ctx.send_viewport_cmd(egui::ViewportCommand::Close);
}
pub(crate) fn show_unsaved_changes_dialog(&mut self, ctx: &egui::Context) {
let mut close_action_now = None;
let mut cancel_action = false;
let (files_to_list, title, confirmation_text, button_text, action) =
if let Some(action) = &self.pending_unsaved_action {
match action {
UnsavedAction::Quit => (
self.get_unsaved_files(),
"Unsaved Changes".to_string(),
"You have unsaved changes.".to_string(),
"Quit Without Saving".to_string(),
action.clone(),
),
UnsavedAction::CloseTab(tab_index) => {
let file_name = self
.tabs
.get(*tab_index)
.map_or_else(|| "unknown file".to_string(), |tab| tab.title.clone());
(
vec![file_name],
"Unsaved Changes".to_string(),
"The file has unsaved changes.".to_string(),
"Close Without Saving".to_string(),
action.clone(),
)
}
}
} else {
return;
2025-07-05 14:42:45 -04:00
};
let visuals = &ctx.style().visuals;
egui::Window::new(title)
.collapsible(false)
.resizable(false)
.anchor(egui::Align2::CENTER_CENTER, egui::Vec2::ZERO)
.frame(egui::Frame {
fill: visuals.window_fill,
stroke: visuals.window_stroke,
corner_radius: egui::CornerRadius::same(8),
shadow: visuals.window_shadow,
inner_margin: egui::Margin::same(16),
outer_margin: egui::Margin::same(0),
})
.show(ctx, |ui| {
ui.vertical(|ui| {
ui.label(egui::RichText::new(&confirmation_text).size(14.0));
ui.add_space(8.0);
for file in &files_to_list {
2025-07-15 00:42:01 -04:00
ui.label(egui::RichText::new(format!("{file}")).size(18.0).weak());
2025-07-05 14:42:45 -04:00
}
ui.add_space(12.0);
ui.horizontal(|ui| {
let cancel_fill = ui.visuals().widgets.inactive.bg_fill;
let cancel_stroke = ui.visuals().widgets.inactive.bg_stroke;
let cancel_button = egui::Button::new("Cancel")
.fill(cancel_fill)
.stroke(cancel_stroke);
if ui.add(cancel_button).clicked() {
cancel_action = true;
}
ui.add_space(8.0);
let destructive_color = ui.visuals().error_fg_color;
let confirm_button = egui::Button::new(&button_text)
.fill(destructive_color)
.stroke(egui::Stroke::new(1.0, destructive_color));
if ui.add(confirm_button).clicked() {
close_action_now = Some(action);
}
});
});
});
if cancel_action {
self.pending_unsaved_action = None;
}
if let Some(action) = close_action_now {
match action {
UnsavedAction::Quit => self.force_quit(ctx),
UnsavedAction::CloseTab(tab_index) => {
self.close_tab(tab_index);
}
}
self.pending_unsaved_action = None;
}
}
}