gtk/native_dialog.rs
1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use crate::NativeDialog;
4use crate::ResponseType;
5use crate::prelude::*;
6use std::cell::Cell;
7use std::future::Future;
8use std::pin::Pin;
9
10pub trait NativeDialogExtManual: IsA<NativeDialog> {
11 // rustdoc-stripper-ignore-next
12 /// Shows the dialog and returns a `Future` that resolves to the
13 /// `ResponseType` on response.
14 ///
15 /// ```no_run
16 /// use gtk::prelude::*;
17 ///
18 /// # async fn run() {
19 /// let dialog = gtk::FileChooserNative::builder()
20 /// .title("Select a File")
21 /// .build();
22 ///
23 /// dialog.run_future().await;
24 /// println!("Selected file: {:?}", dialog.file());
25 /// dialog.destroy();
26 /// # }
27 /// ```
28 fn run_future<'a>(&'a self) -> Pin<Box<dyn Future<Output = ResponseType> + 'a>> {
29 Box::pin(async move {
30 let (sender, receiver) = futures_channel::oneshot::channel();
31
32 let sender = Cell::new(Some(sender));
33
34 let response_handler = self.connect_response(move |_, response_type| {
35 if let Some(m) = sender.replace(None) {
36 let _result = m.send(response_type);
37 }
38 });
39
40 self.show();
41
42 if let Ok(response) = receiver.await {
43 if response != ResponseType::DeleteEvent {
44 self.disconnect(response_handler);
45 }
46 response
47 } else {
48 ResponseType::None
49 }
50 })
51 }
52}
53
54impl<O: IsA<NativeDialog>> NativeDialogExtManual for O {}