|
5 | 5 | #[cfg(any(dialog_open, dialog_save))] |
6 | 6 | use std::path::{Path, PathBuf}; |
7 | 7 |
|
| 8 | +#[cfg(not(target_os = "linux"))] |
| 9 | +macro_rules! run_dialog { |
| 10 | + ($e:expr, $h: ident) => {{ |
| 11 | + std::thread::spawn(move || { |
| 12 | + let response = $e; |
| 13 | + $h(response); |
| 14 | + }); |
| 15 | + }}; |
| 16 | +} |
| 17 | + |
| 18 | +#[cfg(target_os = "linux")] |
| 19 | +macro_rules! run_dialog { |
| 20 | + ($e:expr, $h: ident) => {{ |
| 21 | + std::thread::spawn(move || { |
| 22 | + let context = glib::MainContext::default(); |
| 23 | + context.invoke_with_priority(glib::PRIORITY_HIGH, move || { |
| 24 | + let response = $e; |
| 25 | + $h(response); |
| 26 | + }); |
| 27 | + }); |
| 28 | + }}; |
| 29 | +} |
| 30 | + |
8 | 31 | /// The file dialog builder. |
9 | 32 | /// Constructs file picker dialogs that can select single/multiple files or directories. |
10 | 33 | #[cfg(any(dialog_open, dialog_save))] |
@@ -44,55 +67,57 @@ impl FileDialogBuilder { |
44 | 67 | } |
45 | 68 |
|
46 | 69 | /// Pick one file. |
47 | | - pub fn pick_file(self) -> Option<PathBuf> { |
48 | | - self.0.pick_file() |
| 70 | + pub fn pick_file<F: FnOnce(Option<PathBuf>) + Send + 'static>(self, f: F) { |
| 71 | + run_dialog!(self.0.pick_file(), f) |
49 | 72 | } |
50 | 73 |
|
51 | 74 | /// Pick multiple files. |
52 | | - pub fn pick_files(self) -> Option<Vec<PathBuf>> { |
53 | | - self.0.pick_files() |
| 75 | + pub fn pick_files<F: FnOnce(Option<Vec<PathBuf>>) + Send + 'static>(self, f: F) { |
| 76 | + run_dialog!(self.0.pick_files(), f) |
54 | 77 | } |
55 | 78 |
|
56 | 79 | /// Pick one folder. |
57 | | - pub fn pick_folder(self) -> Option<PathBuf> { |
58 | | - self.0.pick_folder() |
| 80 | + pub fn pick_folder<F: FnOnce(Option<PathBuf>) + Send + 'static>(self, f: F) { |
| 81 | + run_dialog!(self.0.pick_folder(), f) |
59 | 82 | } |
60 | 83 |
|
61 | 84 | /// Opens save file dialog. |
62 | | - pub fn save_file(self) -> Option<PathBuf> { |
63 | | - self.0.save_file() |
| 85 | + pub fn save_file<F: FnOnce(Option<PathBuf>) + Send + 'static>(self, f: F) { |
| 86 | + run_dialog!(self.0.save_file(), f) |
64 | 87 | } |
65 | 88 | } |
66 | 89 |
|
67 | | -/// Response for the ask dialog |
68 | | -#[derive(Debug, Clone, PartialEq, Eq)] |
69 | | -pub enum AskResponse { |
70 | | - /// User confirmed. |
71 | | - Yes, |
72 | | - /// User denied. |
73 | | - No, |
74 | | -} |
75 | | - |
76 | | -/// Displays a dialog with a message and an optional title with a "yes" and a "no" button |
77 | | -pub fn ask(title: impl AsRef<str>, message: impl AsRef<str>) -> AskResponse { |
78 | | - match rfd::MessageDialog::new() |
79 | | - .set_title(title.as_ref()) |
80 | | - .set_description(message.as_ref()) |
81 | | - .set_buttons(rfd::MessageButtons::YesNo) |
82 | | - .set_level(rfd::MessageLevel::Info) |
83 | | - .show() |
84 | | - { |
85 | | - true => AskResponse::Yes, |
86 | | - false => AskResponse::No, |
87 | | - } |
| 90 | +/// Displays a dialog with a message and an optional title with a "yes" and a "no" button. |
| 91 | +pub fn ask<F: FnOnce(bool) + Send + 'static>( |
| 92 | + title: impl AsRef<str>, |
| 93 | + message: impl AsRef<str>, |
| 94 | + f: F, |
| 95 | +) { |
| 96 | + let title = title.as_ref().to_string(); |
| 97 | + let message = message.as_ref().to_string(); |
| 98 | + run_dialog!( |
| 99 | + rfd::MessageDialog::new() |
| 100 | + .set_title(&title) |
| 101 | + .set_description(&message) |
| 102 | + .set_buttons(rfd::MessageButtons::YesNo) |
| 103 | + .set_level(rfd::MessageLevel::Info) |
| 104 | + .show(), |
| 105 | + f |
| 106 | + ) |
88 | 107 | } |
89 | 108 |
|
90 | | -/// Displays a message dialog |
| 109 | +/// Displays a message dialog. |
91 | 110 | pub fn message(title: impl AsRef<str>, message: impl AsRef<str>) { |
92 | | - rfd::MessageDialog::new() |
93 | | - .set_title(title.as_ref()) |
94 | | - .set_description(message.as_ref()) |
95 | | - .set_buttons(rfd::MessageButtons::Ok) |
96 | | - .set_level(rfd::MessageLevel::Info) |
97 | | - .show(); |
| 111 | + let title = title.as_ref().to_string(); |
| 112 | + let message = message.as_ref().to_string(); |
| 113 | + let cb = |_| {}; |
| 114 | + run_dialog!( |
| 115 | + rfd::MessageDialog::new() |
| 116 | + .set_title(&title) |
| 117 | + .set_description(&message) |
| 118 | + .set_buttons(rfd::MessageButtons::Ok) |
| 119 | + .set_level(rfd::MessageLevel::Info) |
| 120 | + .show(), |
| 121 | + cb |
| 122 | + ) |
98 | 123 | } |
0 commit comments