egui_file_dialog/modals/
overwrite_file_modal.rs

1use std::path::PathBuf;
2
3use super::{FileDialogModal, ModalAction, ModalState};
4use crate::config::{FileDialogConfig, FileDialogKeyBindings};
5
6/// The modal that is used to ask the user if the selected path should be
7/// overwritten.
8pub struct OverwriteFileModal {
9    /// The current state of the modal.
10    state: ModalState,
11    /// The path selected for overwriting.
12    path: PathBuf,
13}
14
15impl OverwriteFileModal {
16    /// Creates a new modal object.
17    ///
18    /// # Arguments
19    ///
20    /// * `path` - The path selected for overwriting.
21    pub const fn new(path: PathBuf) -> Self {
22        Self {
23            state: ModalState::Pending,
24            path,
25        }
26    }
27}
28
29impl OverwriteFileModal {
30    /// Submits the modal and triggers the action to save the file.
31    fn submit(&mut self) {
32        self.state = ModalState::Close(ModalAction::SaveFile(self.path.clone()));
33    }
34
35    /// Closes the modal without overwriting the file.
36    fn cancel(&mut self) {
37        self.state = ModalState::Close(ModalAction::None);
38    }
39}
40
41impl FileDialogModal for OverwriteFileModal {
42    fn update(&mut self, config: &FileDialogConfig, ui: &mut egui::Ui) -> ModalState {
43        const SECTION_SPACING: f32 = 15.0;
44        const BUTTON_SIZE: egui::Vec2 = egui::Vec2::new(90.0, 20.0);
45
46        ui.vertical_centered(|ui| {
47            let warn_icon = egui::RichText::new(&config.warn_icon)
48                .color(ui.visuals().warn_fg_color)
49                .heading();
50
51            ui.add_space(SECTION_SPACING);
52
53            ui.label(warn_icon);
54
55            ui.add_space(SECTION_SPACING);
56
57            // Used to wrap the path on a single line.
58            let mut job = egui::text::LayoutJob::single_section(
59                format!("'{}'", self.path.to_str().unwrap_or_default()),
60                egui::TextFormat::default(),
61            );
62
63            job.wrap = egui::text::TextWrapping {
64                max_rows: 1,
65                ..Default::default()
66            };
67
68            ui.label(job);
69            ui.label(&config.labels.overwrite_file_modal_text);
70
71            ui.add_space(SECTION_SPACING);
72
73            ui.horizontal(|ui| {
74                let required_width = BUTTON_SIZE
75                    .x
76                    .mul_add(2.0, ui.style().spacing.item_spacing.x);
77                let padding = (ui.available_width() - required_width) / 2.0;
78
79                ui.add_space(padding);
80
81                if ui
82                    .add_sized(BUTTON_SIZE, egui::Button::new(&config.labels.cancel))
83                    .clicked()
84                {
85                    self.cancel();
86                }
87
88                ui.add_space(ui.style().spacing.item_spacing.x);
89
90                if ui
91                    .add_sized(BUTTON_SIZE, egui::Button::new(&config.labels.overwrite))
92                    .clicked()
93                {
94                    self.submit();
95                }
96            });
97        });
98
99        self.state.clone()
100    }
101
102    fn update_keybindings(&mut self, config: &FileDialogConfig, ctx: &egui::Context) {
103        if FileDialogKeyBindings::any_pressed(ctx, &config.keybindings.submit, true) {
104            self.submit();
105        }
106
107        if FileDialogKeyBindings::any_pressed(ctx, &config.keybindings.cancel, true) {
108            self.cancel();
109        }
110    }
111}