Skip to content

Commit

Permalink
Custom quick access sections (#95)
Browse files Browse the repository at this point in the history
* Implement custom quick access

* Update CHANGELOG.md
  • Loading branch information
fluxxcode authored Mar 7, 2024
1 parent c61a70d commit 69fd7a2
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 3 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# egui-file-dialog changelog

## [Unreleased] - v0.5.0 - [TODO]
### ✨ Features
- Added `FileDialog::add_quick_access` and `FileDialogConfig::add_quick_access` to add your own quick access sections to the left sidebar [#95](https://github.com/fluxxcode/egui-file-dialog/pull/95)

### 🔧 Changes
- Automatically edit filter string when user is typing [#93](https://github.com/fluxxcode/egui-file-dialog/pull/93) (thanks [@crumblingstatue](https://github.com/crumblingstatue) and [@aymey](https://github.com/aymey)!)

Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,12 @@ FileDialog::new()
.show_new_folder_button(false)
.show_search(false)
.show_path_edit_button(false)
// Add a new quick access section to the left sidebar
.add_quick_access("Project", |s| {
s.add_path("☆ Examples", "examples");
s.add_path("📷 Media", "media");
s.add_path("📂 Source", "src");
})
// Markdown and text files should use the "document with text (U+1F5B9)" icon
.set_file_icon(
"🖹",
Expand Down
8 changes: 7 additions & 1 deletion examples/sandbox/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@ struct MyApp {
impl MyApp {
pub fn new(_cc: &eframe::CreationContext) -> Self {
Self {
file_dialog: FileDialog::new().id("egui_file_dialog"),
file_dialog: FileDialog::new()
.add_quick_access("Project", |s| {
s.add_path("☆ Examples", "examples");
s.add_path("📷 Media", "media");
s.add_path("📂 Source", "src");
})
.id("egui_file_dialog"),

selected_directory: None,
selected_file: None,
Expand Down
Binary file modified media/customization_demo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
73 changes: 73 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::fs;
use std::path::{Path, PathBuf};
use std::sync::Arc;

Expand All @@ -21,6 +22,43 @@ impl std::fmt::Debug for IconFilter {
}
}

/// Stores the display name and the actual path of a quick access link.
#[derive(Debug, Clone)]
pub struct QuickAccessPath {
pub display_name: String,
pub path: PathBuf,
}

/// Stores a custom quick access section of the file dialog.
#[derive(Debug, Clone)]
pub struct QuickAccess {
pub canonicalize_paths: bool,
pub heading: String,
pub paths: Vec<QuickAccessPath>,
}

impl QuickAccess {
/// Adds a new path to the quick access.
///
/// Since `fs::canonicalize` is used, both absolute paths and relative paths are allowed.
/// See `FileDialog::canonicalize_paths` for more information.
///
/// See `FileDialogConfig::add_quick_access` for an example.
pub fn add_path(&mut self, display_name: &str, path: impl Into<PathBuf>) {
let path = path.into();

let canonicalized_path = match self.canonicalize_paths {
true => fs::canonicalize(&path).unwrap_or(path),
false => path,
};

self.paths.push(QuickAccessPath {
display_name: display_name.to_string(),
path: canonicalized_path,
});
}
}

/// Contains configuration values of a file dialog.
///
/// The configuration of a file dialog can be set using
Expand Down Expand Up @@ -82,6 +120,10 @@ pub struct FileDialogConfig {
/// Use `FileDialogConfig::set_file_icon` to add a new icon to this list.
pub file_icon_filters: Vec<IconFilter>,

/// Custom sections added to the left sidebar for quick access.
/// Use `FileDialogConfig::add_quick_access` to add a new section to this list.
pub quick_accesses: Vec<QuickAccess>,

// ------------------------------------------------------------------------
// Window options:
/// If set, the window title will be overwritten and set to the fixed value instead
Expand Down Expand Up @@ -159,6 +201,8 @@ impl Default for FileDialogConfig {

file_icon_filters: Vec::new(),

quick_accesses: Vec::new(),

title: None,
id: None,
default_pos: None,
Expand Down Expand Up @@ -218,6 +262,35 @@ impl FileDialogConfig {

self
}

/// Adds a new custom quick access section to the left panel of the file dialog.
///
/// # Examples
///
/// ```
/// use egui_file_dialog::FileDialogConfig;
///
/// FileDialogConfig::default()
/// .add_quick_access("My App", |s| {
/// s.add_path("Config", "/app/config");
/// s.add_path("Themes", "/app/themes");
/// s.add_path("Languages", "/app/languages");
/// });
/// ```
pub fn add_quick_access(
mut self,
heading: &str,
builder: impl FnOnce(&mut QuickAccess),
) -> Self {
let mut obj = QuickAccess {
canonicalize_paths: self.canonicalize_paths,
heading: heading.to_string(),
paths: Vec::new(),
};
builder(&mut obj);
self.quick_accesses.push(obj);
self
}
}

/// Contains the text labels that the file dialog uses.
Expand Down
57 changes: 55 additions & 2 deletions src/file_dialog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::{fs, io};

use egui::text::{CCursor, CCursorRange};

use crate::config::{FileDialogConfig, FileDialogLabels, Filter};
use crate::config::{FileDialogConfig, FileDialogLabels, Filter, QuickAccess};
use crate::create_directory_dialog::CreateDirectoryDialog;
use crate::data::{DirectoryContent, DirectoryEntry, Disk, Disks, UserDirectories};

Expand Down Expand Up @@ -478,7 +478,7 @@ impl FileDialog {
/// use std::sync::Arc;
/// use egui_file_dialog::FileDialog;
///
/// let config = FileDialog::new()
/// FileDialog::new()
/// // .png files should use the "document with picture (U+1F5BB)" icon.
/// .set_file_icon("🖻", Arc::new(|path| path.extension().unwrap_or_default() == "png"))
/// // .git directories should use the "web-github (U+E624)" icon.
Expand All @@ -489,6 +489,30 @@ impl FileDialog {
self
}

/// Adds a new custom quick access section to the left panel.
///
/// # Examples
///
/// ```
/// use egui_file_dialog::FileDialog;
///
/// FileDialog::new()
/// .add_quick_access("My App", |s| {
/// s.add_path("Config", "/app/config");
/// s.add_path("Themes", "/app/themes");
/// s.add_path("Languages", "/app/languages");
/// });
/// ```
// pub fn add_quick_access(mut self, heading: &str, builder: &fn(&mut QuickAccess)) -> Self {
pub fn add_quick_access(
mut self,
heading: &str,
builder: impl FnOnce(&mut QuickAccess),
) -> Self {
self.config = self.config.add_quick_access(heading, builder);
self
}

/// Overwrites the window title.
///
/// By default, the title is set dynamically, based on the `DialogMode`
Expand Down Expand Up @@ -1093,6 +1117,18 @@ impl FileDialog {
.show(ui, |ui| {
let mut spacing = ui.ctx().style().spacing.item_spacing.y * 2.0;

// Update custom quick access sections
let quick_accesses = std::mem::take(&mut self.config.quick_accesses);

for quick_access in &quick_accesses {
ui.add_space(spacing);
self.ui_update_quick_access(ui, quick_access);
spacing = ui.ctx().style().spacing.item_spacing.y * 4.0;
}

self.config.quick_accesses = quick_accesses;

// Update native quick access sections
if self.config.show_places && self.ui_update_user_directories(ui, spacing) {
spacing = ui.ctx().style().spacing.item_spacing.y * 4.0;
}
Expand All @@ -1115,6 +1151,23 @@ impl FileDialog {
});
}

/// Updates a custom quick access section added to the left panel.
fn ui_update_quick_access(&mut self, ui: &mut egui::Ui, quick_access: &QuickAccess) {
ui.label(&quick_access.heading);

for entry in &quick_access.paths {
if ui
.selectable_label(
self.current_directory() == Some(&entry.path),
&entry.display_name,
)
.clicked()
{
let _ = self.load_directory(&entry.path);
}
}
}

/// Updates the list of the user directories (Places).
///
/// Returns true if at least one directory was included in the list and the
Expand Down

0 comments on commit 69fd7a2

Please sign in to comment.