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