Skip to main content

gtk4/
font_dialog.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{boxed::Box as Box_, pin::Pin, ptr};
4
5use glib::translate::*;
6
7use crate::{FontDialog, Window, ffi, prelude::*};
8
9impl FontDialog {
10    /// Presents a font chooser dialog to the user.
11    ///
12    /// The font chooser dialog will be set up for selecting a font
13    /// and specify features for the selected font.
14    ///
15    /// Font features affect how the font is rendered, for example
16    /// enabling glyph variants or ligatures.
17    /// ## `parent`
18    /// the parent window
19    /// ## `initial_value`
20    /// the font to select initially
21    /// ## `cancellable`
22    /// a cancellable to cancel the operation
23    /// ## `callback`
24    /// a callback to call when the
25    ///   operation is complete
26    #[doc(alias = "gtk_font_dialog_choose_font_and_features")]
27    #[doc(alias = "gtk_font_dialog_choose_font_and_features_finish")]
28    pub fn choose_font_and_features<
29        P: FnOnce(
30                Result<
31                    (
32                        Option<pango::FontDescription>,
33                        glib::GString,
34                        pango::Language,
35                    ),
36                    glib::Error,
37                >,
38            ) + 'static,
39    >(
40        &self,
41        parent: Option<&impl IsA<Window>>,
42        initial_value: Option<&pango::FontDescription>,
43        cancellable: Option<&impl IsA<gio::Cancellable>>,
44        callback: P,
45    ) {
46        let main_context = glib::MainContext::ref_thread_default();
47        let is_main_context_owner = main_context.is_owner();
48        let has_acquired_main_context = (!is_main_context_owner)
49            .then(|| main_context.acquire().ok())
50            .flatten();
51        assert!(
52            is_main_context_owner || has_acquired_main_context.is_some(),
53            "Async operations only allowed if the thread is owning the MainContext"
54        );
55
56        let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
57            Box_::new(glib::thread_guard::ThreadGuard::new(callback));
58        unsafe extern "C" fn choose_font_and_features_trampoline<
59            P: FnOnce(
60                    Result<
61                        (
62                            Option<pango::FontDescription>,
63                            glib::GString,
64                            pango::Language,
65                        ),
66                        glib::Error,
67                    >,
68                ) + 'static,
69        >(
70            _source_object: *mut glib::gobject_ffi::GObject,
71            res: *mut gio::ffi::GAsyncResult,
72            user_data: glib::ffi::gpointer,
73        ) {
74            unsafe {
75                let mut error = ptr::null_mut();
76                let mut font_desc = ptr::null_mut();
77                let mut font_features = ptr::null_mut();
78                let mut language = ptr::null_mut();
79                let _ = ffi::gtk_font_dialog_choose_font_and_features_finish(
80                    _source_object as *mut _,
81                    res,
82                    &mut font_desc,
83                    &mut font_features,
84                    &mut language,
85                    &mut error,
86                );
87                let result = if error.is_null() {
88                    Ok((
89                        from_glib_full(font_desc),
90                        from_glib_full(font_features),
91                        from_glib_full(language),
92                    ))
93                } else {
94                    Err(from_glib_full(error))
95                };
96                let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
97                    Box_::from_raw(user_data as *mut _);
98                let callback: P = callback.into_inner();
99                callback(result);
100            }
101        }
102        let callback = choose_font_and_features_trampoline::<P>;
103        unsafe {
104            ffi::gtk_font_dialog_choose_font_and_features(
105                self.to_glib_none().0,
106                parent.map(|p| p.as_ref()).to_glib_none().0,
107                mut_override(initial_value.to_glib_none().0),
108                cancellable.map(|p| p.as_ref()).to_glib_none().0,
109                Some(callback),
110                Box_::into_raw(user_data) as *mut _,
111            );
112        }
113    }
114
115    #[allow(clippy::type_complexity)]
116    pub fn choose_font_and_features_future(
117        &self,
118        parent: Option<&(impl IsA<Window> + Clone + 'static)>,
119        initial_value: Option<&pango::FontDescription>,
120    ) -> Pin<
121        Box_<
122            dyn std::future::Future<
123                    Output = Result<
124                        (
125                            Option<pango::FontDescription>,
126                            glib::GString,
127                            pango::Language,
128                        ),
129                        glib::Error,
130                    >,
131                > + 'static,
132        >,
133    > {
134        let parent = parent.map(ToOwned::to_owned);
135        let initial_value = initial_value.map(ToOwned::to_owned);
136        Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
137            obj.choose_font_and_features(
138                parent.as_ref().map(::std::borrow::Borrow::borrow),
139                initial_value.as_ref().map(::std::borrow::Borrow::borrow),
140                Some(cancellable),
141                move |res| {
142                    send.resolve(res);
143                },
144            );
145        }))
146    }
147}