gtk4/subclass/
font_chooser.rs
1use std::sync::OnceLock;
6
7use glib::{translate::*, GString, Quark};
8use pango::{FontFace, FontFamily, FontMap};
9
10use super::PtrHolder;
11use crate::{ffi, prelude::*, subclass::prelude::*, FontChooser};
12
13#[derive(Debug)]
14pub struct FilterCallback {
15 filter_func: ffi::GtkFontFilterFunc,
16 user_data: glib::ffi::gpointer,
17 destroy_notify: glib::ffi::GDestroyNotify,
18}
19
20impl FilterCallback {
21 pub fn call(&self, font_family: &FontFamily, font_face: &FontFace) -> bool {
23 unsafe {
24 if let Some(filter_func) = self.filter_func {
25 from_glib(filter_func(
26 font_family.to_glib_none().0,
27 font_face.to_glib_none().0,
28 self.user_data,
29 ))
30 } else {
31 true
33 }
34 }
35 }
36}
37
38impl Drop for FilterCallback {
39 #[inline]
40 fn drop(&mut self) {
41 unsafe {
42 if let Some(destroy_notify) = self.destroy_notify {
43 destroy_notify(self.user_data)
44 }
45 }
46 }
47}
48
49#[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
50#[allow(deprecated)]
51pub trait FontChooserImpl: ObjectImpl + ObjectSubclass<Type: IsA<FontChooser>> {
52 fn font_family(&self) -> Option<FontFamily> {
53 self.parent_font_family()
54 }
55
56 fn font_face(&self) -> Option<FontFace> {
57 self.parent_font_face()
58 }
59
60 fn font_size(&self) -> i32 {
61 self.parent_font_size()
62 }
63
64 fn set_filter_func(&self, callback: Option<FilterCallback>) {
65 self.parent_set_filter_func(callback)
66 }
67
68 fn set_font_map<P: IsA<FontMap>>(&self, font_map: Option<&P>) {
69 self.parent_set_font_map(font_map)
70 }
71
72 fn font_map(&self) -> Option<FontMap> {
73 self.parent_font_map()
74 }
75
76 fn font_activated(&self, font_name: &str) {
77 self.parent_font_activated(font_name)
78 }
79}
80
81#[cfg_attr(feature = "v4_10", deprecated = "Since 4.10")]
82#[allow(deprecated)]
83pub trait FontChooserImplExt: FontChooserImpl {
84 fn parent_font_family(&self) -> Option<FontFamily> {
85 unsafe {
86 let type_data = Self::type_data();
87 let parent_iface = type_data.as_ref().parent_interface::<FontChooser>()
88 as *const ffi::GtkFontChooserIface;
89 let f = (*parent_iface)
90 .get_font_family
91 .expect("no parent \"get_font_family\" implementation");
92
93 from_glib_none(f(self
94 .obj()
95 .unsafe_cast_ref::<FontChooser>()
96 .to_glib_none()
97 .0))
98 }
99 }
100
101 fn parent_font_face(&self) -> Option<FontFace> {
102 unsafe {
103 let type_data = Self::type_data();
104 let parent_iface = type_data.as_ref().parent_interface::<FontChooser>()
105 as *const ffi::GtkFontChooserIface;
106
107 let f = (*parent_iface)
108 .get_font_face
109 .expect("no parent \"get_font_face\" implementation");
110
111 from_glib_none(f(self
112 .obj()
113 .unsafe_cast_ref::<FontChooser>()
114 .to_glib_none()
115 .0))
116 }
117 }
118
119 fn parent_font_size(&self) -> i32 {
120 unsafe {
121 let type_data = Self::type_data();
122 let parent_iface = type_data.as_ref().parent_interface::<FontChooser>()
123 as *const ffi::GtkFontChooserIface;
124
125 if let Some(f) = (*parent_iface).get_font_size {
126 f(self.obj().unsafe_cast_ref::<FontChooser>().to_glib_none().0)
127 } else {
128 -1
130 }
131 }
132 }
133
134 fn parent_set_filter_func(&self, callback: Option<FilterCallback>) {
135 unsafe {
136 let type_data = Self::type_data();
137 let parent_iface = type_data.as_ref().parent_interface::<FontChooser>()
138 as *const ffi::GtkFontChooserIface;
139
140 if let Some(f) = (*parent_iface).set_filter_func {
141 if let Some(filter_callback) = callback {
142 f(
143 self.obj().unsafe_cast_ref::<FontChooser>().to_glib_none().0,
144 filter_callback.filter_func,
145 filter_callback.user_data,
146 filter_callback.destroy_notify,
147 )
148 } else {
149 f(
150 self.obj().unsafe_cast_ref::<FontChooser>().to_glib_none().0,
151 None,
152 std::ptr::null_mut(),
153 None,
154 )
155 }
156 }
157 }
158 }
159
160 fn parent_set_font_map<P: IsA<FontMap>>(&self, font_map: Option<&P>) {
161 unsafe {
162 let type_data = Self::type_data();
163 let parent_iface = type_data.as_ref().parent_interface::<FontChooser>()
164 as *const ffi::GtkFontChooserIface;
165
166 let f = (*parent_iface)
167 .set_font_map
168 .expect("no parent \"set_font_map\" implementation");
169 f(
170 self.obj().unsafe_cast_ref::<FontChooser>().to_glib_none().0,
171 font_map.map(|fm| fm.as_ref()).to_glib_none().0,
172 );
173 }
174 }
175
176 fn parent_font_map(&self) -> Option<FontMap> {
177 unsafe {
178 let type_data = Self::type_data();
179 let parent_iface = type_data.as_ref().parent_interface::<FontChooser>()
180 as *const ffi::GtkFontChooserIface;
181
182 let f = (*parent_iface)
183 .get_font_map
184 .expect("no parent \"get_font_map\" implementation");
185
186 from_glib_none(f(self
187 .obj()
188 .unsafe_cast_ref::<FontChooser>()
189 .to_glib_none()
190 .0))
191 }
192 }
193
194 fn parent_font_activated(&self, font_name: &str) {
195 unsafe {
196 let type_data = Self::type_data();
197 let parent_iface = type_data.as_ref().parent_interface::<FontChooser>()
198 as *const ffi::GtkFontChooserIface;
199 if let Some(f) = (*parent_iface).font_activated {
200 f(
201 self.obj().unsafe_cast_ref::<FontChooser>().to_glib_none().0,
202 font_name.to_glib_none().0,
203 );
204 }
205 }
206 }
207}
208
209impl<T: FontChooserImpl> FontChooserImplExt for T {}
210
211unsafe impl<T: FontChooserImpl> IsImplementable<T> for FontChooser {
212 fn interface_init(iface: &mut glib::Interface<Self>) {
213 let iface = iface.as_mut();
214
215 assert_initialized_main_thread!();
216
217 iface.get_font_family = Some(font_chooser_get_font_family::<T>);
218 iface.get_font_face = Some(font_chooser_get_font_face::<T>);
219 iface.get_font_size = Some(font_chooser_get_font_size::<T>);
220 iface.font_activated = Some(font_chooser_font_activated::<T>);
221 iface.set_font_map = Some(font_chooser_set_font_map::<T>);
222 iface.get_font_map = Some(font_chooser_get_font_map::<T>);
223 iface.set_filter_func = Some(font_chooser_set_filter_func::<T>);
224 }
225}
226
227unsafe extern "C" fn font_chooser_get_font_family<T: FontChooserImpl>(
228 font_chooser: *mut ffi::GtkFontChooser,
229) -> *mut pango::ffi::PangoFontFamily {
230 let instance = &*(font_chooser as *mut T::Instance);
231 let imp = instance.imp();
232
233 let ret = imp.font_family();
234 if let Some(font_family) = ret {
235 let font_family = font_family.into_glib_ptr();
236
237 static QUARK: OnceLock<Quark> = OnceLock::new();
238 let quark =
239 *QUARK.get_or_init(|| Quark::from_str("gtk4-rs-subclass-font-chooser-font-family"));
240
241 imp.obj().set_qdata(
242 quark,
243 PtrHolder(font_family, |ptr| {
244 glib::gobject_ffi::g_object_unref(ptr as *mut _)
245 }),
246 );
247 font_family
248 } else {
249 std::ptr::null_mut()
250 }
251}
252
253unsafe extern "C" fn font_chooser_get_font_face<T: FontChooserImpl>(
254 font_chooser: *mut ffi::GtkFontChooser,
255) -> *mut pango::ffi::PangoFontFace {
256 let instance = &*(font_chooser as *mut T::Instance);
257 let imp = instance.imp();
258
259 let ret = imp.font_face();
260 if let Some(font_face) = ret {
261 let font_face = font_face.into_glib_ptr();
262 static QUARK: OnceLock<Quark> = OnceLock::new();
263 let quark =
264 *QUARK.get_or_init(|| Quark::from_str("gtk4-rs-subclass-font-chooser-font-face"));
265 imp.obj().set_qdata(
266 quark,
267 PtrHolder(font_face, |ptr| {
268 glib::gobject_ffi::g_object_unref(ptr as *mut _);
269 }),
270 );
271 font_face
272 } else {
273 std::ptr::null_mut()
274 }
275}
276
277unsafe extern "C" fn font_chooser_get_font_size<T: FontChooserImpl>(
278 font_chooser: *mut ffi::GtkFontChooser,
279) -> i32 {
280 let instance = &*(font_chooser as *mut T::Instance);
281 let imp = instance.imp();
282
283 imp.font_size()
284}
285
286unsafe extern "C" fn font_chooser_font_activated<T: FontChooserImpl>(
287 font_chooser: *mut ffi::GtkFontChooser,
288 font_nameptr: *const libc::c_char,
289) {
290 let instance = &*(font_chooser as *mut T::Instance);
291 let imp = instance.imp();
292 let font_name: Borrowed<GString> = from_glib_borrow(font_nameptr);
293
294 imp.font_activated(&font_name)
295}
296
297unsafe extern "C" fn font_chooser_set_font_map<T: FontChooserImpl>(
298 font_chooser: *mut ffi::GtkFontChooser,
299 font_mapptr: *mut pango::ffi::PangoFontMap,
300) {
301 let instance = &*(font_chooser as *mut T::Instance);
302 let imp = instance.imp();
303 let font_map: Borrowed<Option<FontMap>> = from_glib_borrow(font_mapptr);
304
305 imp.set_font_map(font_map.as_ref().as_ref())
306}
307
308unsafe extern "C" fn font_chooser_get_font_map<T: FontChooserImpl>(
309 font_chooser: *mut ffi::GtkFontChooser,
310) -> *mut pango::ffi::PangoFontMap {
311 let instance = &*(font_chooser as *mut T::Instance);
312 let imp = instance.imp();
313
314 imp.font_map().into_glib_ptr()
315}
316
317unsafe extern "C" fn font_chooser_set_filter_func<T: FontChooserImpl>(
318 font_chooser: *mut ffi::GtkFontChooser,
319 filter_func: ffi::GtkFontFilterFunc,
320 user_data: glib::ffi::gpointer,
321 destroy_notify: glib::ffi::GDestroyNotify,
322) {
323 let instance = &*(font_chooser as *mut T::Instance);
324 let imp = instance.imp();
325
326 let callback = if filter_func.is_some() {
327 None
328 } else {
329 Some(FilterCallback {
330 filter_func,
331 user_data,
332 destroy_notify,
333 })
334 };
335
336 imp.set_filter_func(callback);
337}