gtk4/native_dialog.rs
1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{
4 cell::{Cell, RefCell},
5 future::Future,
6 pin::Pin,
7 rc::Rc,
8};
9
10use crate::{prelude::*, NativeDialog, ResponseType};
11
12// rustdoc-stripper-ignore-next
13/// Trait containing manually implemented methods of
14/// [`NativeDialog`](crate::NativeDialog).
15#[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
16#[allow(deprecated)]
17pub trait NativeDialogExtManual: IsA<NativeDialog> {
18 // rustdoc-stripper-ignore-next
19 /// Shows the dialog and returns a `Future` that resolves to the
20 /// `ResponseType` on response.
21 ///
22 /// ```no_run
23 /// # use gtk4 as gtk;
24 /// use gtk::prelude::*;
25 ///
26 /// # async fn run() {
27 /// let dialog = gtk::FileChooserNative::builder()
28 /// .title("Select a File")
29 /// .build();
30 ///
31 /// dialog.run_future().await;
32 /// println!("Selected file: {:?}", dialog.file());
33 /// dialog.destroy();
34 /// # }
35 /// ```
36 fn run_future<'a>(&'a self) -> Pin<Box<dyn Future<Output = ResponseType> + 'a>> {
37 Box::pin(async move {
38 let (sender, receiver) = futures_channel::oneshot::channel();
39
40 let sender = Cell::new(Some(sender));
41
42 let response_handler = self.connect_response(move |_, response_type| {
43 if let Some(m) = sender.replace(None) {
44 let _result = m.send(response_type);
45 }
46 });
47
48 self.show();
49
50 if let Ok(response) = receiver.await {
51 self.disconnect(response_handler);
52 response
53 } else {
54 ResponseType::None
55 }
56 })
57 }
58
59 // rustdoc-stripper-ignore-next
60 /// Shows the dialog and calls the callback when a response has been
61 /// received.
62 ///
63 /// **Important**: this function isn't blocking.
64 ///
65 /// ```no_run
66 /// # use gtk4 as gtk;
67 /// use gtk::prelude::*;
68 ///
69 /// let dialog = gtk::FileChooserNative::builder()
70 /// .title("Select a File")
71 /// .build();
72 ///
73 /// dialog.run_async(move |obj, answer| {
74 /// obj.destroy();
75 /// println!("Selected file: {:?}", obj.file());
76 /// });
77 /// ```
78 fn run_async<F: FnOnce(&Self, ResponseType) + 'static>(&self, f: F) {
79 let response_handler = Rc::new(RefCell::new(None));
80 let response_handler_clone = response_handler.clone();
81 let f = RefCell::new(Some(f));
82 *response_handler.borrow_mut() = Some(self.connect_response(move |s, response_type| {
83 if let Some(handler) = response_handler_clone.borrow_mut().take() {
84 s.disconnect(handler);
85 }
86 (*f.borrow_mut()).take().expect("cannot get callback")(s, response_type);
87 }));
88 self.show();
89 }
90}
91
92impl<O: IsA<NativeDialog>> NativeDialogExtManual for O {}