par_term/
close_confirmation_ui.rs1use crate::tab::TabId;
8
9#[derive(Debug, Clone, PartialEq, Eq)]
11pub enum CloseConfirmAction {
12 Close {
14 tab_id: TabId,
15 pane_id: Option<crate::pane::PaneId>,
16 },
17 Cancel,
19 None,
21}
22
23pub struct CloseConfirmationUI {
25 visible: bool,
27 pending_tab_id: Option<TabId>,
29 pending_pane_id: Option<crate::pane::PaneId>,
31 command_name: String,
33 tab_title: String,
35}
36
37impl Default for CloseConfirmationUI {
38 fn default() -> Self {
39 Self::new()
40 }
41}
42
43impl CloseConfirmationUI {
44 pub fn new() -> Self {
46 Self {
47 visible: false,
48 pending_tab_id: None,
49 pending_pane_id: None,
50 command_name: String::new(),
51 tab_title: String::new(),
52 }
53 }
54
55 pub fn is_visible(&self) -> bool {
57 self.visible
58 }
59
60 pub fn show_for_tab(&mut self, tab_id: TabId, tab_title: &str, command_name: &str) {
62 self.visible = true;
63 self.pending_tab_id = Some(tab_id);
64 self.pending_pane_id = None;
65 self.command_name = command_name.to_string();
66 self.tab_title = tab_title.to_string();
67 }
68
69 pub fn show_for_pane(
71 &mut self,
72 tab_id: TabId,
73 pane_id: crate::pane::PaneId,
74 tab_title: &str,
75 command_name: &str,
76 ) {
77 self.visible = true;
78 self.pending_tab_id = Some(tab_id);
79 self.pending_pane_id = Some(pane_id);
80 self.command_name = command_name.to_string();
81 self.tab_title = tab_title.to_string();
82 }
83
84 fn hide(&mut self) {
86 self.visible = false;
87 self.pending_tab_id = None;
88 self.pending_pane_id = None;
89 self.command_name.clear();
90 self.tab_title.clear();
91 }
92
93 pub fn show(&mut self, ctx: &egui::Context) -> CloseConfirmAction {
95 if !self.visible {
96 return CloseConfirmAction::None;
97 }
98
99 let mut action = CloseConfirmAction::None;
100
101 egui::Window::new("Close Tab?")
102 .collapsible(false)
103 .resizable(false)
104 .order(egui::Order::Foreground)
105 .anchor(egui::Align2::CENTER_CENTER, [0.0, 0.0])
106 .show(ctx, |ui| {
107 ui.vertical_centered(|ui| {
108 ui.add_space(10.0);
109
110 ui.label(
112 egui::RichText::new("⚠ Running Job Detected")
113 .color(egui::Color32::YELLOW)
114 .size(18.0)
115 .strong(),
116 );
117 ui.add_space(10.0);
118
119 let target = if self.pending_pane_id.is_some() {
121 "pane"
122 } else {
123 "tab"
124 };
125 ui.label(format!(
126 "The {} \"{}\" has a running command:",
127 target, self.tab_title
128 ));
129 ui.add_space(5.0);
130
131 ui.horizontal(|ui| {
133 ui.add_space(20.0);
134 egui::Frame::new()
135 .fill(egui::Color32::from_rgba_unmultiplied(60, 60, 60, 200))
136 .inner_margin(egui::Margin::symmetric(12, 6))
137 .corner_radius(4.0)
138 .show(ui, |ui| {
139 ui.label(
140 egui::RichText::new(&self.command_name)
141 .color(egui::Color32::LIGHT_GREEN)
142 .monospace()
143 .size(14.0),
144 );
145 });
146 });
147
148 ui.add_space(10.0);
149 ui.label(
150 egui::RichText::new("Closing will terminate this process.")
151 .color(egui::Color32::GRAY),
152 );
153 ui.add_space(15.0);
154
155 ui.horizontal(|ui| {
157 let close_button = egui::Button::new(
159 egui::RichText::new("Close Anyway").color(egui::Color32::WHITE),
160 )
161 .fill(egui::Color32::from_rgb(180, 50, 50));
162
163 if ui.add(close_button).clicked() {
164 if let Some(tab_id) = self.pending_tab_id {
166 action = CloseConfirmAction::Close {
167 tab_id,
168 pane_id: self.pending_pane_id,
169 };
170 }
171 }
172
173 ui.add_space(10.0);
174
175 if ui.button("Cancel").clicked() {
176 action = CloseConfirmAction::Cancel;
177 }
178 });
179 ui.add_space(10.0);
180 });
181 });
182
183 if ctx.input(|i| i.key_pressed(egui::Key::Escape)) {
185 action = CloseConfirmAction::Cancel;
186 }
187
188 if !matches!(action, CloseConfirmAction::None) {
190 self.hide();
191 }
192
193 action
194 }
195}