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::{ffi, prelude::*, FontDialog, Window};
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            let mut error = ptr::null_mut();
75            let mut font_desc = ptr::null_mut();
76            let mut font_features = ptr::null_mut();
77            let mut language = ptr::null_mut();
78            let _ = ffi::gtk_font_dialog_choose_font_and_features_finish(
79                _source_object as *mut _,
80                res,
81                &mut font_desc,
82                &mut font_features,
83                &mut language,
84                &mut error,
85            );
86            let result = if error.is_null() {
87                Ok((
88                    from_glib_full(font_desc),
89                    from_glib_full(font_features),
90                    from_glib_full(language),
91                ))
92            } else {
93                Err(from_glib_full(error))
94            };
95            let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
96                Box_::from_raw(user_data as *mut _);
97            let callback: P = callback.into_inner();
98            callback(result);
99        }
100        let callback = choose_font_and_features_trampoline::<P>;
101        unsafe {
102            ffi::gtk_font_dialog_choose_font_and_features(
103                self.to_glib_none().0,
104                parent.map(|p| p.as_ref()).to_glib_none().0,
105                mut_override(initial_value.to_glib_none().0),
106                cancellable.map(|p| p.as_ref()).to_glib_none().0,
107                Some(callback),
108                Box_::into_raw(user_data) as *mut _,
109            );
110        }
111    }
112
113    #[allow(clippy::type_complexity)]
114    pub fn choose_font_and_features_future(
115        &self,
116        parent: Option<&(impl IsA<Window> + Clone + 'static)>,
117        initial_value: Option<&pango::FontDescription>,
118    ) -> Pin<
119        Box_<
120            dyn std::future::Future<
121                    Output = Result<
122                        (
123                            Option<pango::FontDescription>,
124                            glib::GString,
125                            pango::Language,
126                        ),
127                        glib::Error,
128                    >,
129                > + 'static,
130        >,
131    > {
132        let parent = parent.map(ToOwned::to_owned);
133        let initial_value = initial_value.map(ToOwned::to_owned);
134        Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
135            obj.choose_font_and_features(
136                parent.as_ref().map(::std::borrow::Borrow::borrow),
137                initial_value.as_ref().map(::std::borrow::Borrow::borrow),
138                Some(cancellable),
139                move |res| {
140                    send.resolve(res);
141                },
142            );
143        }))
144    }
145}