1use crate::{ffi, BuilderClosureFlags, BuilderScope};
6use glib::{
7    prelude::*,
8    signal::{connect_raw, SignalHandlerId},
9    translate::*,
10};
11use std::boxed::Box as Box_;
12
13glib::wrapper! {
14    #[doc(alias = "GtkBuilder")]
15    pub struct Builder(Object<ffi::GtkBuilder, ffi::GtkBuilderClass>);
16
17    match fn {
18        type_ => || ffi::gtk_builder_get_type(),
19    }
20}
21
22impl Builder {
23    #[doc(alias = "gtk_builder_new")]
24    pub fn new() -> Builder {
25        assert_initialized_main_thread!();
26        unsafe { from_glib_full(ffi::gtk_builder_new()) }
27    }
28
29    #[doc(alias = "gtk_builder_new_from_resource")]
30    #[doc(alias = "new_from_resource")]
31    pub fn from_resource(resource_path: &str) -> Builder {
32        assert_initialized_main_thread!();
33        unsafe {
34            from_glib_full(ffi::gtk_builder_new_from_resource(
35                resource_path.to_glib_none().0,
36            ))
37        }
38    }
39
40    #[doc(alias = "gtk_builder_new_from_string")]
41    #[doc(alias = "new_from_string")]
42    pub fn from_string(string: &str) -> Builder {
43        assert_initialized_main_thread!();
44        let length = string.len() as _;
45        unsafe {
46            from_glib_full(ffi::gtk_builder_new_from_string(
47                string.to_glib_none().0,
48                length,
49            ))
50        }
51    }
52
53    #[doc(alias = "gtk_builder_add_from_resource")]
54    pub fn add_from_resource(&self, resource_path: &str) -> Result<(), glib::Error> {
55        unsafe {
56            let mut error = std::ptr::null_mut();
57            let is_ok = ffi::gtk_builder_add_from_resource(
58                self.to_glib_none().0,
59                resource_path.to_glib_none().0,
60                &mut error,
61            );
62            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
63            if error.is_null() {
64                Ok(())
65            } else {
66                Err(from_glib_full(error))
67            }
68        }
69    }
70
71    #[doc(alias = "gtk_builder_add_from_string")]
72    pub fn add_from_string(&self, buffer: &str) -> Result<(), glib::Error> {
73        let length = buffer.len() as _;
74        unsafe {
75            let mut error = std::ptr::null_mut();
76            let is_ok = ffi::gtk_builder_add_from_string(
77                self.to_glib_none().0,
78                buffer.to_glib_none().0,
79                length,
80                &mut error,
81            );
82            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
83            if error.is_null() {
84                Ok(())
85            } else {
86                Err(from_glib_full(error))
87            }
88        }
89    }
90
91    #[doc(alias = "gtk_builder_add_objects_from_file")]
92    pub fn add_objects_from_file(
93        &self,
94        filename: impl AsRef<std::path::Path>,
95        object_ids: &[&str],
96    ) -> Result<(), glib::Error> {
97        unsafe {
98            let mut error = std::ptr::null_mut();
99            let is_ok = ffi::gtk_builder_add_objects_from_file(
100                self.to_glib_none().0,
101                filename.as_ref().to_glib_none().0,
102                object_ids.to_glib_none().0,
103                &mut error,
104            );
105            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
106            if error.is_null() {
107                Ok(())
108            } else {
109                Err(from_glib_full(error))
110            }
111        }
112    }
113
114    #[doc(alias = "gtk_builder_add_objects_from_resource")]
115    pub fn add_objects_from_resource(
116        &self,
117        resource_path: &str,
118        object_ids: &[&str],
119    ) -> Result<(), glib::Error> {
120        unsafe {
121            let mut error = std::ptr::null_mut();
122            let is_ok = ffi::gtk_builder_add_objects_from_resource(
123                self.to_glib_none().0,
124                resource_path.to_glib_none().0,
125                object_ids.to_glib_none().0,
126                &mut error,
127            );
128            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
129            if error.is_null() {
130                Ok(())
131            } else {
132                Err(from_glib_full(error))
133            }
134        }
135    }
136
137    #[doc(alias = "gtk_builder_add_objects_from_string")]
138    pub fn add_objects_from_string(
139        &self,
140        buffer: &str,
141        object_ids: &[&str],
142    ) -> Result<(), glib::Error> {
143        let length = buffer.len() as _;
144        unsafe {
145            let mut error = std::ptr::null_mut();
146            let is_ok = ffi::gtk_builder_add_objects_from_string(
147                self.to_glib_none().0,
148                buffer.to_glib_none().0,
149                length,
150                object_ids.to_glib_none().0,
151                &mut error,
152            );
153            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
154            if error.is_null() {
155                Ok(())
156            } else {
157                Err(from_glib_full(error))
158            }
159        }
160    }
161
162    #[doc(alias = "gtk_builder_create_closure")]
163    pub fn create_closure(
164        &self,
165        function_name: &str,
166        flags: BuilderClosureFlags,
167        object: Option<&impl IsA<glib::Object>>,
168    ) -> Result<Option<glib::Closure>, glib::Error> {
169        unsafe {
170            let mut error = std::ptr::null_mut();
171            let ret = ffi::gtk_builder_create_closure(
172                self.to_glib_none().0,
173                function_name.to_glib_none().0,
174                flags.into_glib(),
175                object.map(|p| p.as_ref()).to_glib_none().0,
176                &mut error,
177            );
178            if error.is_null() {
179                Ok(from_glib_full(ret))
180            } else {
181                Err(from_glib_full(error))
182            }
183        }
184    }
185
186    #[doc(alias = "gtk_builder_expose_object")]
187    pub fn expose_object(&self, name: &str, object: &impl IsA<glib::Object>) {
188        unsafe {
189            ffi::gtk_builder_expose_object(
190                self.to_glib_none().0,
191                name.to_glib_none().0,
192                object.as_ref().to_glib_none().0,
193            );
194        }
195    }
196
197    #[doc(alias = "gtk_builder_extend_with_template")]
198    pub fn extend_with_template(
199        &self,
200        object: &impl IsA<glib::Object>,
201        template_type: glib::types::Type,
202        buffer: &str,
203    ) -> Result<(), glib::Error> {
204        let length = buffer.len() as _;
205        unsafe {
206            let mut error = std::ptr::null_mut();
207            let is_ok = ffi::gtk_builder_extend_with_template(
208                self.to_glib_none().0,
209                object.as_ref().to_glib_none().0,
210                template_type.into_glib(),
211                buffer.to_glib_none().0,
212                length,
213                &mut error,
214            );
215            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
216            if error.is_null() {
217                Ok(())
218            } else {
219                Err(from_glib_full(error))
220            }
221        }
222    }
223
224    #[doc(alias = "gtk_builder_get_objects")]
225    #[doc(alias = "get_objects")]
226    pub fn objects(&self) -> Vec<glib::Object> {
227        unsafe {
228            FromGlibPtrContainer::from_glib_container(ffi::gtk_builder_get_objects(
229                self.to_glib_none().0,
230            ))
231        }
232    }
233
234    #[doc(alias = "gtk_builder_get_scope")]
235    #[doc(alias = "get_scope")]
236    pub fn scope(&self) -> BuilderScope {
237        unsafe { from_glib_none(ffi::gtk_builder_get_scope(self.to_glib_none().0)) }
238    }
239
240    #[doc(alias = "gtk_builder_get_translation_domain")]
241    #[doc(alias = "get_translation_domain")]
242    #[doc(alias = "translation-domain")]
243    pub fn translation_domain(&self) -> Option<glib::GString> {
244        unsafe {
245            from_glib_none(ffi::gtk_builder_get_translation_domain(
246                self.to_glib_none().0,
247            ))
248        }
249    }
250
251    #[doc(alias = "gtk_builder_get_type_from_name")]
252    #[doc(alias = "get_type_from_name")]
253    pub fn type_from_name(&self, type_name: &str) -> glib::types::Type {
254        unsafe {
255            from_glib(ffi::gtk_builder_get_type_from_name(
256                self.to_glib_none().0,
257                type_name.to_glib_none().0,
258            ))
259        }
260    }
261
262    #[doc(alias = "gtk_builder_set_current_object")]
263    #[doc(alias = "current-object")]
264    pub fn set_current_object(&self, current_object: Option<&impl IsA<glib::Object>>) {
265        unsafe {
266            ffi::gtk_builder_set_current_object(
267                self.to_glib_none().0,
268                current_object.map(|p| p.as_ref()).to_glib_none().0,
269            );
270        }
271    }
272
273    #[doc(alias = "gtk_builder_set_scope")]
274    #[doc(alias = "scope")]
275    pub fn set_scope(&self, scope: Option<&impl IsA<BuilderScope>>) {
276        unsafe {
277            ffi::gtk_builder_set_scope(
278                self.to_glib_none().0,
279                scope.map(|p| p.as_ref()).to_glib_none().0,
280            );
281        }
282    }
283
284    #[doc(alias = "gtk_builder_set_translation_domain")]
285    #[doc(alias = "translation-domain")]
286    pub fn set_translation_domain(&self, domain: Option<&str>) {
287        unsafe {
288            ffi::gtk_builder_set_translation_domain(self.to_glib_none().0, domain.to_glib_none().0);
289        }
290    }
291
292    #[doc(alias = "gtk_builder_value_from_string")]
293    pub fn value_from_string(
294        &self,
295        pspec: impl AsRef<glib::ParamSpec>,
296        string: &str,
297    ) -> Result<glib::Value, glib::Error> {
298        unsafe {
299            let mut value = glib::Value::uninitialized();
300            let mut error = std::ptr::null_mut();
301            let is_ok = ffi::gtk_builder_value_from_string(
302                self.to_glib_none().0,
303                pspec.as_ref().to_glib_none().0,
304                string.to_glib_none().0,
305                value.to_glib_none_mut().0,
306                &mut error,
307            );
308            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
309            if error.is_null() {
310                Ok(value)
311            } else {
312                Err(from_glib_full(error))
313            }
314        }
315    }
316
317    #[doc(alias = "gtk_builder_value_from_string_type")]
318    pub fn value_from_string_type(
319        &self,
320        type_: glib::types::Type,
321        string: &str,
322    ) -> Result<glib::Value, glib::Error> {
323        unsafe {
324            let mut value = glib::Value::uninitialized();
325            let mut error = std::ptr::null_mut();
326            let is_ok = ffi::gtk_builder_value_from_string_type(
327                self.to_glib_none().0,
328                type_.into_glib(),
329                string.to_glib_none().0,
330                value.to_glib_none_mut().0,
331                &mut error,
332            );
333            debug_assert_eq!(is_ok == glib::ffi::GFALSE, !error.is_null());
334            if error.is_null() {
335                Ok(value)
336            } else {
337                Err(from_glib_full(error))
338            }
339        }
340    }
341
342    #[doc(alias = "current-object")]
343    pub fn connect_current_object_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
344        unsafe extern "C" fn notify_current_object_trampoline<F: Fn(&Builder) + 'static>(
345            this: *mut ffi::GtkBuilder,
346            _param_spec: glib::ffi::gpointer,
347            f: glib::ffi::gpointer,
348        ) {
349            let f: &F = &*(f as *const F);
350            f(&from_glib_borrow(this))
351        }
352        unsafe {
353            let f: Box_<F> = Box_::new(f);
354            connect_raw(
355                self.as_ptr() as *mut _,
356                b"notify::current-object\0".as_ptr() as *const _,
357                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
358                    notify_current_object_trampoline::<F> as *const (),
359                )),
360                Box_::into_raw(f),
361            )
362        }
363    }
364
365    #[doc(alias = "scope")]
366    pub fn connect_scope_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
367        unsafe extern "C" fn notify_scope_trampoline<F: Fn(&Builder) + 'static>(
368            this: *mut ffi::GtkBuilder,
369            _param_spec: glib::ffi::gpointer,
370            f: glib::ffi::gpointer,
371        ) {
372            let f: &F = &*(f as *const F);
373            f(&from_glib_borrow(this))
374        }
375        unsafe {
376            let f: Box_<F> = Box_::new(f);
377            connect_raw(
378                self.as_ptr() as *mut _,
379                b"notify::scope\0".as_ptr() as *const _,
380                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
381                    notify_scope_trampoline::<F> as *const (),
382                )),
383                Box_::into_raw(f),
384            )
385        }
386    }
387
388    #[doc(alias = "translation-domain")]
389    pub fn connect_translation_domain_notify<F: Fn(&Self) + 'static>(
390        &self,
391        f: F,
392    ) -> SignalHandlerId {
393        unsafe extern "C" fn notify_translation_domain_trampoline<F: Fn(&Builder) + 'static>(
394            this: *mut ffi::GtkBuilder,
395            _param_spec: glib::ffi::gpointer,
396            f: glib::ffi::gpointer,
397        ) {
398            let f: &F = &*(f as *const F);
399            f(&from_glib_borrow(this))
400        }
401        unsafe {
402            let f: Box_<F> = Box_::new(f);
403            connect_raw(
404                self.as_ptr() as *mut _,
405                b"notify::translation-domain\0".as_ptr() as *const _,
406                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
407                    notify_translation_domain_trampoline::<F> as *const (),
408                )),
409                Box_::into_raw(f),
410            )
411        }
412    }
413}
414
415impl Default for Builder {
416    fn default() -> Self {
417        Self::new()
418    }
419}