Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: opening mode #239

Merged
merged 4 commits into from
Feb 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,17 @@
- Renamed `DialogState`'s: `Selected` -> `Picked`, `SelectedMultiple` -> `PickedMultiple` [#229](https://github.com/fluxxcode/egui-file-dialog/pull/229)
- Renamed `active_entry` -> `selected_entry` [#229](https://github.com/fluxxcode/egui-file-dialog/pull/229)
- Renamed `active_selected_entries` -> `selected_entries` [#229](https://github.com/fluxxcode/egui-file-dialog/pull/229)
- Added `file_system` attribute to `FileDialogConfig` [#227](https://github.com/fluxxcode/egui-file-dialog/pull/227)

#### Breaking changes due to new features and updated configuration
- Added `file_system` to `FileDialogConfig` [#227](https://github.com/fluxxcode/egui-file-dialog/pull/227)
- Added `file_system` parameter to `DirectoryEntry::from_path` [#227](https://github.com/fluxxcode/egui-file-dialog/pull/227)
- Added `opening_mode` to `FileDialogConfig` [#239](https://github.com/fluxxcode/egui-file-dialog/pull/239)
- Added `last_visited_dir` and `last_picked_dir` to `FileDialogStorage` [#239](https://github.com/fluxxcode/egui-file-dialog/pull/239)

### ✨ Features

- Implement file system abstraction so that the file dialog can be used with virtual file systems [#227](https://github.com/fluxxcode/egui-file-dialog/pull/227) (thanks [@Masterchef365](https://github.com/Masterchef365)!)
- Added new configuration option `FileDialog::opening_mode` which allows to further specify which directory is loaded when the file dialog is opened [#239](https://github.com/fluxxcode/egui-file-dialog/pull/239)

### 🐛 Bug Fixes

Expand Down
21 changes: 21 additions & 0 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ pub struct FileDialogStorage {
pub show_hidden: bool,
/// If system files should be listed inside the directory view.
pub show_system_files: bool,
/// The last directory the user visited.
pub last_visited_dir: Option<PathBuf>,
/// The last directory from which the user picked an item.
pub last_picked_dir: Option<PathBuf>,
}

impl Default for FileDialogStorage {
Expand All @@ -29,10 +33,24 @@ impl Default for FileDialogStorage {
pinned_folders: Vec::new(),
show_hidden: false,
show_system_files: false,
last_visited_dir: None,
last_picked_dir: None,
}
}
}

/// Sets which directory is loaded when opening the file dialog.
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum OpeningMode {
/// The configured initial directory (`FileDialog::initial_directory`) should always be opened.
AlwaysInitialDir,
/// The directory most recently visited by the user should be opened regardless of
/// whether anything was picked.
LastVisitedDir,
/// The last directory from which the user picked an item should be opened.
LastPickedDir,
}

/// Contains configuration values of a file dialog.
///
/// The configuration of a file dialog can be set using `FileDialog::with_config`.
Expand Down Expand Up @@ -77,6 +95,8 @@ pub struct FileDialogConfig {

// ------------------------------------------------------------------------
// General options:
/// Sets which directory is loaded when opening the file dialog.
pub opening_mode: OpeningMode,
/// If the file dialog should be visible as a modal window.
/// This means that the input outside the window is not registered.
pub as_modal: bool,
Expand Down Expand Up @@ -222,6 +242,7 @@ impl FileDialogConfig {
labels: FileDialogLabels::default(),
keybindings: FileDialogKeyBindings::default(),

opening_mode: OpeningMode::LastPickedDir,
as_modal: true,
modal_overlay_color: egui::Color32::from_rgba_premultiplied(0, 0, 0, 120),
initial_directory: file_system.current_dir().unwrap_or_default(),
Expand Down
33 changes: 30 additions & 3 deletions src/file_dialog.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::config::{
FileDialogConfig, FileDialogKeyBindings, FileDialogLabels, FileDialogStorage, FileFilter,
Filter, QuickAccess,
Filter, OpeningMode, QuickAccess,
};
use crate::create_directory_dialog::CreateDirectoryDialog;
use crate::data::{
Expand Down Expand Up @@ -347,7 +347,7 @@ impl FileDialog {
.id
.map_or_else(|| egui::Id::new(self.get_window_title()), |id| id);

self.load_directory(&self.gen_initial_directory(&self.config.initial_directory));
self.load_directory(&self.get_initial_directory());

// TODO: Dont return a result from this method
Ok(())
Expand Down Expand Up @@ -484,6 +484,12 @@ impl FileDialog {
&mut self.config.labels
}

/// Sets which directory is loaded when opening the file dialog.
pub const fn opening_mode(mut self, opening_mode: OpeningMode) -> Self {
self.config.opening_mode = opening_mode;
self
}

/// If the file dialog window should be displayed as a modal.
///
/// If the window is displayed as modal, the area outside the dialog can no longer be
Expand Down Expand Up @@ -2752,6 +2758,8 @@ impl FileDialog {
return;
}

self.config.storage.last_picked_dir = self.current_directory().map(PathBuf::from);

match &self.mode {
DialogMode::PickDirectory | DialogMode::PickFile => {
// Should always contain a value since `is_selection_valid` is used to
Expand Down Expand Up @@ -2798,9 +2806,26 @@ impl FileDialog {

/// This function generates the initial directory based on the configuration.
/// The function does the following things:
/// - Get the path to open based on the opening mode
/// - Canonicalize the path if enabled
/// - Attempts to use the parent directory if the path is a file
fn gen_initial_directory(&self, path: &Path) -> PathBuf {
fn get_initial_directory(&self) -> PathBuf {
let path = match self.config.opening_mode {
OpeningMode::AlwaysInitialDir => &self.config.initial_directory,
OpeningMode::LastVisitedDir => self
.config
.storage
.last_visited_dir
.as_deref()
.unwrap_or(&self.config.initial_directory),
OpeningMode::LastPickedDir => self
.config
.storage
.last_picked_dir
.as_deref()
.unwrap_or(&self.config.initial_directory),
};

let mut path = self.canonicalize_path(path);

if self.config.file_system.is_file(&path) {
Expand Down Expand Up @@ -3117,6 +3142,8 @@ impl FileDialog {

/// Loads the directory content of the given path.
fn load_directory_content(&mut self, path: &Path) {
self.config.storage.last_visited_dir = Some(path.to_path_buf());

self.directory_content = DirectoryContent::from_path(
&self.config,
path,
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ mod modals;

pub use config::{
FileDialogConfig, FileDialogKeyBindings, FileDialogLabels, FileDialogStorage, IconFilter,
KeyBinding, QuickAccess, QuickAccessPath,
KeyBinding, OpeningMode, QuickAccess, QuickAccessPath,
};
pub use data::{DirectoryEntry, Disk, Disks, Metadata, UserDirectories};
pub use file_dialog::{DialogMode, DialogState, FileDialog};
Expand Down