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 {
|
2025-07-16 13:27:31 -04:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|