libadwaita/
alert_dialog.rs

1use glib::object::IsA;
2use glib::translate::*;
3
4use crate::prelude::*;
5use crate::AlertDialog;
6
7use std::boxed::Box as Box_;
8use std::pin::Pin;
9
10mod sealed {
11    pub trait Sealed {}
12    impl<T: super::IsA<super::AlertDialog>> Sealed for T {}
13}
14
15pub trait AlertDialogExtManual: sealed::Sealed + IsA<AlertDialog> + 'static {
16    #[doc(alias = "adw_alert_dialog_get_response_label")]
17    #[doc(alias = "get_response_label")]
18    fn response_label(&self, response: &str) -> glib::GString {
19        assert!(self.as_ref().has_response(response));
20
21        unsafe {
22            from_glib_none(ffi::adw_alert_dialog_get_response_label(
23                self.as_ref().to_glib_none().0,
24                response.to_glib_none().0,
25            ))
26        }
27    }
28
29    #[doc(alias = "adw_alert_dialog_add_responses")]
30    fn add_responses(&self, ids_and_labels: &[(&str, &str)]) {
31        ids_and_labels.iter().for_each(|(id, label)| {
32            self.add_response(id, label);
33        });
34    }
35
36    #[doc(alias = "adw_alert_dialog_choose")]
37    fn choose<P: FnOnce(glib::GString) + 'static>(
38        self,
39        parent: Option<&impl IsA<gtk::Widget>>,
40        cancellable: Option<&impl IsA<gio::Cancellable>>,
41        callback: P,
42    ) {
43        let main_context = glib::MainContext::ref_thread_default();
44        let is_main_context_owner = main_context.is_owner();
45        let has_acquired_main_context = (!is_main_context_owner)
46            .then(|| main_context.acquire().ok())
47            .flatten();
48        assert!(
49            is_main_context_owner || has_acquired_main_context.is_some(),
50            "Async operations only allowed if the thread is owning the MainContext"
51        );
52
53        let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
54            Box_::new(glib::thread_guard::ThreadGuard::new(callback));
55        unsafe extern "C" fn choose_trampoline<P: FnOnce(glib::GString) + 'static>(
56            _source_object: *mut glib::gobject_ffi::GObject,
57            res: *mut gio::ffi::GAsyncResult,
58            user_data: glib::ffi::gpointer,
59        ) {
60            unsafe {
61                let result = from_glib_none(ffi::adw_alert_dialog_choose_finish(
62                    _source_object as *mut _,
63                    res,
64                ));
65                let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
66                    Box_::from_raw(user_data as *mut _);
67                let callback: P = callback.into_inner();
68                callback(result);
69            }
70        }
71        let callback = choose_trampoline::<P>;
72        unsafe {
73            ffi::adw_alert_dialog_choose(
74                self.upcast().into_glib_ptr(),
75                parent.map(|p| p.as_ref()).to_glib_none().0,
76                cancellable.map(|p| p.as_ref()).to_glib_none().0,
77                Some(callback),
78                Box_::into_raw(user_data) as *mut _,
79            );
80        }
81    }
82
83    fn choose_future(
84        self,
85        parent: Option<&impl IsA<gtk::Widget>>,
86    ) -> Pin<Box_<dyn std::future::Future<Output = glib::GString> + 'static>> {
87        let parent = parent.map(ToOwned::to_owned);
88        Box_::pin(gio::GioFuture::new(
89            &self,
90            move |obj: &Self, cancellable, send| {
91                obj.clone().choose(
92                    parent.as_ref().map(::std::borrow::Borrow::borrow),
93                    Some(cancellable),
94                    move |res| {
95                        send.resolve(res);
96                    },
97                );
98            },
99        ))
100    }
101}
102
103impl<O: IsA<AlertDialog>> AlertDialogExtManual for O {}