1use std::{boxed::Box as Box_, pin::Pin, ptr};
4
5use glib::translate::*;
6
7use crate::{ffi, prelude::*, FontDialog, Window};
8
9impl FontDialog {
10 #[doc(alias = "gtk_font_dialog_choose_font_and_features")]
11 #[doc(alias = "gtk_font_dialog_choose_font_and_features_finish")]
12 pub fn choose_font_and_features<
13 P: FnOnce(
14 Result<
15 (
16 Option<pango::FontDescription>,
17 glib::GString,
18 pango::Language,
19 ),
20 glib::Error,
21 >,
22 ) + 'static,
23 >(
24 &self,
25 parent: Option<&impl IsA<Window>>,
26 initial_value: Option<&pango::FontDescription>,
27 cancellable: Option<&impl IsA<gio::Cancellable>>,
28 callback: P,
29 ) {
30 let main_context = glib::MainContext::ref_thread_default();
31 let is_main_context_owner = main_context.is_owner();
32 let has_acquired_main_context = (!is_main_context_owner)
33 .then(|| main_context.acquire().ok())
34 .flatten();
35 assert!(
36 is_main_context_owner || has_acquired_main_context.is_some(),
37 "Async operations only allowed if the thread is owning the MainContext"
38 );
39
40 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
41 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
42 unsafe extern "C" fn choose_font_and_features_trampoline<
43 P: FnOnce(
44 Result<
45 (
46 Option<pango::FontDescription>,
47 glib::GString,
48 pango::Language,
49 ),
50 glib::Error,
51 >,
52 ) + 'static,
53 >(
54 _source_object: *mut glib::gobject_ffi::GObject,
55 res: *mut gio::ffi::GAsyncResult,
56 user_data: glib::ffi::gpointer,
57 ) {
58 let mut error = ptr::null_mut();
59 let mut font_desc = ptr::null_mut();
60 let mut font_features = ptr::null_mut();
61 let mut language = ptr::null_mut();
62 let _ = ffi::gtk_font_dialog_choose_font_and_features_finish(
63 _source_object as *mut _,
64 res,
65 &mut font_desc,
66 &mut font_features,
67 &mut language,
68 &mut error,
69 );
70 let result = if error.is_null() {
71 Ok((
72 from_glib_full(font_desc),
73 from_glib_full(font_features),
74 from_glib_full(language),
75 ))
76 } else {
77 Err(from_glib_full(error))
78 };
79 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
80 Box_::from_raw(user_data as *mut _);
81 let callback: P = callback.into_inner();
82 callback(result);
83 }
84 let callback = choose_font_and_features_trampoline::<P>;
85 unsafe {
86 ffi::gtk_font_dialog_choose_font_and_features(
87 self.to_glib_none().0,
88 parent.map(|p| p.as_ref()).to_glib_none().0,
89 mut_override(initial_value.to_glib_none().0),
90 cancellable.map(|p| p.as_ref()).to_glib_none().0,
91 Some(callback),
92 Box_::into_raw(user_data) as *mut _,
93 );
94 }
95 }
96
97 #[allow(clippy::type_complexity)]
98 pub fn choose_font_and_features_future(
99 &self,
100 parent: Option<&(impl IsA<Window> + Clone + 'static)>,
101 initial_value: Option<&pango::FontDescription>,
102 ) -> Pin<
103 Box_<
104 dyn std::future::Future<
105 Output = Result<
106 (
107 Option<pango::FontDescription>,
108 glib::GString,
109 pango::Language,
110 ),
111 glib::Error,
112 >,
113 > + 'static,
114 >,
115 > {
116 let parent = parent.map(ToOwned::to_owned);
117 let initial_value = initial_value.map(ToOwned::to_owned);
118 Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
119 obj.choose_font_and_features(
120 parent.as_ref().map(::std::borrow::Borrow::borrow),
121 initial_value.as_ref().map(::std::borrow::Borrow::borrow),
122 Some(cancellable),
123 move |res| {
124 send.resolve(res);
125 },
126 );
127 }))
128 }
129}