libadwaita/alert_dialog.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
use glib::object::IsA;
use glib::translate::*;
use crate::prelude::*;
use crate::AlertDialog;
use std::boxed::Box as Box_;
use std::pin::Pin;
mod sealed {
pub trait Sealed {}
impl<T: super::IsA<super::AlertDialog>> Sealed for T {}
}
pub trait AlertDialogExtManual: sealed::Sealed + IsA<AlertDialog> + 'static {
/// Gets the label of @response.
///
/// See [`AlertDialogExt::set_response_label()`][crate::prelude::AlertDialogExt::set_response_label()].
/// ## `response`
/// a response ID
///
/// # Returns
///
/// the label of @response
#[doc(alias = "adw_alert_dialog_get_response_label")]
#[doc(alias = "get_response_label")]
fn response_label(&self, response: &str) -> glib::GString {
assert!(self.as_ref().has_response(response));
unsafe {
from_glib_none(ffi::adw_alert_dialog_get_response_label(
self.as_ref().to_glib_none().0,
response.to_glib_none().0,
))
}
}
/// Adds multiple responses to @self.
///
/// This is the same as calling [`AlertDialogExt::add_response()`][crate::prelude::AlertDialogExt::add_response()] repeatedly. The
/// variable argument list should be `NULL`-terminated list of response IDs and
/// labels.
///
/// Example:
///
/// **⚠️ The following code is in c ⚠️**
///
/// ```c
/// adw_alert_dialog_add_responses (dialog,
/// "cancel", _("_Cancel"),
/// "discard", _("_Discard"),
/// "save", _("_Save"),
/// NULL);
/// ```
/// ## `first_id`
/// response id
#[doc(alias = "adw_alert_dialog_add_responses")]
fn add_responses(&self, ids_and_labels: &[(&str, &str)]) {
ids_and_labels.iter().for_each(|(id, label)| {
self.add_response(id, label);
});
}
/// This function shows @self to the user.
///
/// If the window is an [`Window`][crate::Window] or [`ApplicationWindow`][crate::ApplicationWindow], the dialog
/// will be shown within it. Otherwise, it will be a separate window.
/// ## `parent`
/// the parent widget
/// ## `cancellable`
/// a `GCancellable` to cancel the operation
/// ## `callback`
/// a callback to call when the operation is complete
#[doc(alias = "adw_alert_dialog_choose")]
fn choose<P: FnOnce(glib::GString) + 'static>(
self,
parent: &impl IsA<gtk::Widget>,
cancellable: Option<&impl IsA<gio::Cancellable>>,
callback: P,
) {
let main_context = glib::MainContext::ref_thread_default();
let is_main_context_owner = main_context.is_owner();
let has_acquired_main_context = (!is_main_context_owner)
.then(|| main_context.acquire().ok())
.flatten();
assert!(
is_main_context_owner || has_acquired_main_context.is_some(),
"Async operations only allowed if the thread is owning the MainContext"
);
let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
Box_::new(glib::thread_guard::ThreadGuard::new(callback));
unsafe extern "C" fn choose_trampoline<P: FnOnce(glib::GString) + 'static>(
_source_object: *mut glib::gobject_ffi::GObject,
res: *mut gio::ffi::GAsyncResult,
user_data: glib::ffi::gpointer,
) {
let result = from_glib_none(ffi::adw_alert_dialog_choose_finish(
_source_object as *mut _,
res,
));
let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
Box_::from_raw(user_data as *mut _);
let callback: P = callback.into_inner();
callback(result);
}
let callback = choose_trampoline::<P>;
unsafe {
ffi::adw_alert_dialog_choose(
self.upcast().into_glib_ptr(),
parent.as_ref().to_glib_none().0,
cancellable.map(|p| p.as_ref()).to_glib_none().0,
Some(callback),
Box_::into_raw(user_data) as *mut _,
);
}
}
fn choose_future(
self,
parent: &impl IsA<gtk::Widget>,
) -> Pin<Box_<dyn std::future::Future<Output = glib::GString> + 'static>> {
let parent = parent.clone();
Box_::pin(gio::GioFuture::new(
&self,
move |obj: &Self, cancellable, send| {
obj.clone().choose(&parent, Some(cancellable), move |res| {
send.resolve(res);
});
},
))
}
}
impl<O: IsA<AlertDialog>> AlertDialogExtManual for O {}