use crate::FileHandle;
use std::path::Path;
use std::path::PathBuf;
use raw_window_handle::{HasDisplayHandle, HasWindowHandle, RawDisplayHandle, RawWindowHandle};
#[derive(Debug, Clone)]
pub(crate) struct Filter {
#[allow(dead_code)]
pub name: String,
pub extensions: Vec<String>,
}
#[derive(Default, Debug, Clone)]
pub struct FileDialog {
pub(crate) filters: Vec<Filter>,
pub(crate) starting_directory: Option<PathBuf>,
pub(crate) file_name: Option<String>,
pub(crate) title: Option<String>,
pub(crate) parent: Option<RawWindowHandle>,
pub(crate) parent_display: Option<RawDisplayHandle>,
pub(crate) can_create_directories: Option<bool>,
}
unsafe impl Send for FileDialog {}
unsafe impl Sync for FileDialog {}
impl FileDialog {
#[cfg(not(target_arch = "wasm32"))]
pub fn new() -> Self {
Default::default()
}
pub fn add_filter(mut self, name: impl Into<String>, extensions: &[impl ToString]) -> Self {
self.filters.push(Filter {
name: name.into(),
extensions: extensions.iter().map(|e| e.to_string()).collect(),
});
self
}
pub fn set_directory<P: AsRef<Path>>(mut self, path: P) -> Self {
let path = path.as_ref();
if path.to_str().map(|p| p.is_empty()).unwrap_or(false) {
self.starting_directory = None;
} else {
self.starting_directory = Some(path.into());
}
self
}
pub fn set_file_name(mut self, file_name: impl Into<String>) -> Self {
self.file_name = Some(file_name.into());
self
}
pub fn set_title(mut self, title: impl Into<String>) -> Self {
self.title = Some(title.into());
self
}
pub fn set_parent<W: HasWindowHandle + HasDisplayHandle>(mut self, parent: &W) -> Self {
self.parent = parent.window_handle().ok().map(|x| x.as_raw());
self.parent_display = parent.display_handle().ok().map(|x| x.as_raw());
self
}
pub fn set_can_create_directories(mut self, can: bool) -> Self {
self.can_create_directories.replace(can);
self
}
}
#[cfg(not(target_arch = "wasm32"))]
use crate::backend::{FilePickerDialogImpl, FileSaveDialogImpl, FolderPickerDialogImpl};
#[cfg(not(target_arch = "wasm32"))]
impl FileDialog {
pub fn pick_file(self) -> Option<PathBuf> {
FilePickerDialogImpl::pick_file(self)
}
pub fn pick_files(self) -> Option<Vec<PathBuf>> {
FilePickerDialogImpl::pick_files(self)
}
pub fn pick_folder(self) -> Option<PathBuf> {
FolderPickerDialogImpl::pick_folder(self)
}
pub fn pick_folders(self) -> Option<Vec<PathBuf>> {
FolderPickerDialogImpl::pick_folders(self)
}
pub fn save_file(self) -> Option<PathBuf> {
FileSaveDialogImpl::save_file(self)
}
}
#[derive(Default, Debug, Clone)]
pub struct AsyncFileDialog {
file_dialog: FileDialog,
}
impl AsyncFileDialog {
pub fn new() -> Self {
Default::default()
}
pub fn add_filter(mut self, name: impl Into<String>, extensions: &[impl ToString]) -> Self {
self.file_dialog = self.file_dialog.add_filter(name, extensions);
self
}
pub fn set_directory<P: AsRef<Path>>(mut self, path: P) -> Self {
self.file_dialog = self.file_dialog.set_directory(path);
self
}
pub fn set_file_name(mut self, file_name: impl Into<String>) -> Self {
self.file_dialog = self.file_dialog.set_file_name(file_name);
self
}
pub fn set_title(mut self, title: impl Into<String>) -> Self {
self.file_dialog = self.file_dialog.set_title(title);
self
}
pub fn set_parent<W: HasWindowHandle + HasDisplayHandle>(mut self, parent: &W) -> Self {
self.file_dialog = self.file_dialog.set_parent(parent);
self
}
pub fn set_can_create_directories(mut self, can: bool) -> Self {
self.file_dialog = self.file_dialog.set_can_create_directories(can);
self
}
}
use crate::backend::AsyncFilePickerDialogImpl;
use crate::backend::AsyncFileSaveDialogImpl;
#[cfg(not(target_arch = "wasm32"))]
use crate::backend::AsyncFolderPickerDialogImpl;
use std::future::Future;
impl AsyncFileDialog {
pub fn pick_file(self) -> impl Future<Output = Option<FileHandle>> {
AsyncFilePickerDialogImpl::pick_file_async(self.file_dialog)
}
pub fn pick_files(self) -> impl Future<Output = Option<Vec<FileHandle>>> {
AsyncFilePickerDialogImpl::pick_files_async(self.file_dialog)
}
#[cfg(not(target_arch = "wasm32"))]
pub fn pick_folder(self) -> impl Future<Output = Option<FileHandle>> {
AsyncFolderPickerDialogImpl::pick_folder_async(self.file_dialog)
}
#[cfg(not(target_arch = "wasm32"))]
pub fn pick_folders(self) -> impl Future<Output = Option<Vec<FileHandle>>> {
AsyncFolderPickerDialogImpl::pick_folders_async(self.file_dialog)
}
pub fn save_file(self) -> impl Future<Output = Option<FileHandle>> {
AsyncFileSaveDialogImpl::save_file_async(self.file_dialog)
}
}