use std::path::PathBuf;
#[derive(Clone, Debug)]
pub struct FileFilter {
pub name: String,
pub extensions: Vec<String>,
}
impl FileFilter {
pub fn new(name: impl Into<String>) -> Self {
Self {
name: name.into(),
extensions: Vec::new(),
}
}
pub fn ext(mut self, extension: impl Into<String>) -> Self {
self.extensions.push(extension.into());
self
}
}
pub struct OpenFileDialog {
title: Option<String>,
directory: Option<PathBuf>,
filters: Vec<FileFilter>,
}
pub fn open_file() -> OpenFileDialog {
OpenFileDialog {
title: None,
directory: None,
filters: Vec::new(),
}
}
impl OpenFileDialog {
pub fn title(mut self, title: impl Into<String>) -> Self {
self.title = Some(title.into());
self
}
pub fn directory(mut self, dir: impl Into<PathBuf>) -> Self {
self.directory = Some(dir.into());
self
}
pub fn filter(mut self, filter: FileFilter) -> Self {
self.filters.push(filter);
self
}
pub fn pick(self) -> Option<PathBuf> {
let mut d = rfd::FileDialog::new();
if let Some(title) = &self.title {
d = d.set_title(title);
}
if let Some(dir) = &self.directory {
d = d.set_directory(dir);
}
for f in &self.filters {
let exts: Vec<&str> = f.extensions.iter().map(|s| s.as_str()).collect();
d = d.add_filter(&f.name, &exts);
}
d.pick_file()
}
pub fn pick_many(self) -> Vec<PathBuf> {
let mut d = rfd::FileDialog::new();
if let Some(title) = &self.title {
d = d.set_title(title);
}
if let Some(dir) = &self.directory {
d = d.set_directory(dir);
}
for f in &self.filters {
let exts: Vec<&str> = f.extensions.iter().map(|s| s.as_str()).collect();
d = d.add_filter(&f.name, &exts);
}
d.pick_files().unwrap_or_default()
}
}
pub struct SaveFileDialog {
title: Option<String>,
directory: Option<PathBuf>,
file_name: Option<String>,
filters: Vec<FileFilter>,
}
pub fn save_file() -> SaveFileDialog {
SaveFileDialog {
title: None,
directory: None,
file_name: None,
filters: Vec::new(),
}
}
impl SaveFileDialog {
pub fn title(mut self, title: impl Into<String>) -> Self {
self.title = Some(title.into());
self
}
pub fn directory(mut self, dir: impl Into<PathBuf>) -> Self {
self.directory = Some(dir.into());
self
}
pub fn file_name(mut self, name: impl Into<String>) -> Self {
self.file_name = Some(name.into());
self
}
pub fn filter(mut self, filter: FileFilter) -> Self {
self.filters.push(filter);
self
}
pub fn save(self) -> Option<PathBuf> {
let mut d = rfd::FileDialog::new();
if let Some(title) = &self.title {
d = d.set_title(title);
}
if let Some(dir) = &self.directory {
d = d.set_directory(dir);
}
if let Some(name) = &self.file_name {
d = d.set_file_name(name);
}
for f in &self.filters {
let exts: Vec<&str> = f.extensions.iter().map(|s| s.as_str()).collect();
d = d.add_filter(&f.name, &exts);
}
d.save_file()
}
}
pub struct FolderPickerDialog {
title: Option<String>,
directory: Option<PathBuf>,
}
pub fn pick_folder() -> FolderPickerDialog {
FolderPickerDialog {
title: None,
directory: None,
}
}
impl FolderPickerDialog {
pub fn title(mut self, title: impl Into<String>) -> Self {
self.title = Some(title.into());
self
}
pub fn directory(mut self, dir: impl Into<PathBuf>) -> Self {
self.directory = Some(dir.into());
self
}
pub fn pick(self) -> Option<PathBuf> {
let mut d = rfd::FileDialog::new();
if let Some(title) = &self.title {
d = d.set_title(title);
}
if let Some(dir) = &self.directory {
d = d.set_directory(dir);
}
d.pick_folder()
}
}