telar_services_core/
dialogs.rs1use std::path::PathBuf;
2use std::sync::{Arc, OnceLock};
3
4#[derive(Clone, Debug, Default)]
6pub struct FileFilter {
7 pub name: String,
8 pub extensions: Vec<String>,
9}
10
11impl FileFilter {
12 pub fn new(name: impl Into<String>, extensions: &[&str]) -> Self {
13 Self {
14 name: name.into(),
15 extensions: extensions.iter().map(|e| (*e).to_string()).collect(),
16 }
17 }
18}
19
20#[derive(Clone, Debug, Default)]
23pub struct FileDialog {
24 pub title: Option<String>,
25 pub directory: Option<PathBuf>,
26 pub file_name: Option<String>,
28 pub filters: Vec<FileFilter>,
29}
30
31impl FileDialog {
32 pub fn new() -> Self {
33 Self::default()
34 }
35
36 pub fn title(mut self, title: impl Into<String>) -> Self {
37 self.title = Some(title.into());
38 self
39 }
40
41 pub fn directory(mut self, dir: impl Into<PathBuf>) -> Self {
42 self.directory = Some(dir.into());
43 self
44 }
45
46 pub fn file_name(mut self, name: impl Into<String>) -> Self {
47 self.file_name = Some(name.into());
48 self
49 }
50
51 pub fn filter(mut self, name: impl Into<String>, extensions: &[&str]) -> Self {
52 self.filters.push(FileFilter::new(name, extensions));
53 self
54 }
55}
56
57pub trait FileDialogs: Send + Sync + 'static {
63 fn open_file(&self, request: FileDialog) -> Option<PathBuf>;
64 fn open_files(&self, request: FileDialog) -> Vec<PathBuf>;
65 fn save_file(&self, request: FileDialog) -> Option<PathBuf>;
66 fn pick_folder(&self, request: FileDialog) -> Option<PathBuf>;
67}
68
69static DIALOGS: OnceLock<Arc<dyn FileDialogs>> = OnceLock::new();
70
71pub fn set_file_dialogs(provider: Arc<dyn FileDialogs>) {
74 let _ = DIALOGS.set(provider);
75}
76
77pub fn file_dialogs() -> Option<Arc<dyn FileDialogs>> {
79 DIALOGS.get().cloned()
80}