gtk4/subclass/
builder_scope.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3// rustdoc-stripper-ignore-next
4//! Traits intended for implementing the [`BuilderScope`](crate::BuilderScope)
5//! interface.
6
7use glib::{translate::*, GString};
8
9use crate::{
10    ffi, prelude::*, subclass::prelude::*, Builder, BuilderCScope, BuilderClosureFlags,
11    BuilderScope,
12};
13
14pub trait BuilderCScopeImpl: BuilderScopeImpl {}
15
16unsafe impl<T: BuilderCScopeImpl> IsSubclassable<T> for BuilderCScope {}
17
18pub trait BuilderScopeImpl: ObjectImpl {
19    #[doc(alias = "get_type_from_name")]
20    fn type_from_name(&self, builder: &Builder, type_name: &str) -> glib::Type {
21        self.parent_type_from_name(builder, type_name)
22    }
23
24    #[doc(alias = "get_type_from_function")]
25    fn type_from_function(&self, builder: &Builder, function_name: &str) -> glib::Type {
26        self.parent_type_from_function(builder, function_name)
27    }
28
29    fn create_closure(
30        &self,
31        builder: &Builder,
32        function_name: &str,
33        flags: BuilderClosureFlags,
34        object: Option<&glib::Object>,
35    ) -> Result<glib::Closure, glib::Error>;
36}
37
38mod sealed {
39    pub trait Sealed {}
40    impl<T: super::BuilderScopeImplExt> Sealed for T {}
41}
42
43pub trait BuilderScopeImplExt: sealed::Sealed + ObjectSubclass {
44    fn parent_type_from_name(&self, builder: &Builder, type_name: &str) -> glib::Type {
45        unsafe {
46            let type_data = Self::type_data();
47            let parent_iface = type_data.as_ref().parent_interface::<BuilderScope>()
48                as *const ffi::GtkBuilderScopeInterface;
49
50            let func = (*parent_iface)
51                .get_type_from_name
52                .expect("no parent \"get_type_from_name\" implementation");
53
54            from_glib(func(
55                self.obj()
56                    .unsafe_cast_ref::<BuilderScope>()
57                    .to_glib_none()
58                    .0,
59                builder.to_glib_none().0,
60                type_name.to_glib_none().0,
61            ))
62        }
63    }
64
65    fn parent_type_from_function(&self, builder: &Builder, function_name: &str) -> glib::Type {
66        unsafe {
67            let type_data = Self::type_data();
68            let parent_iface = type_data.as_ref().parent_interface::<BuilderScope>()
69                as *const ffi::GtkBuilderScopeInterface;
70
71            let func = (*parent_iface)
72                .get_type_from_function
73                .expect("no parent \"get_type_from_function\" implementation");
74
75            from_glib(func(
76                self.obj()
77                    .unsafe_cast_ref::<BuilderScope>()
78                    .to_glib_none()
79                    .0,
80                builder.to_glib_none().0,
81                function_name.to_glib_none().0,
82            ))
83        }
84    }
85
86    fn parent_create_closure(
87        &self,
88        builder: &Builder,
89        function_name: &str,
90        flags: BuilderClosureFlags,
91        object: Option<&glib::Object>,
92    ) -> Result<glib::Closure, glib::Error> {
93        unsafe {
94            let type_data = Self::type_data();
95            let parent_iface = type_data.as_ref().parent_interface::<BuilderScope>()
96                as *const ffi::GtkBuilderScopeInterface;
97
98            let func = (*parent_iface)
99                .create_closure
100                .expect("no parent \"create_closure\" implementation");
101
102            let mut error = std::ptr::null_mut();
103            let closure = func(
104                self.obj()
105                    .unsafe_cast_ref::<BuilderScope>()
106                    .to_glib_none()
107                    .0,
108                builder.to_glib_none().0,
109                function_name.to_glib_none().0,
110                flags.into_glib(),
111                object.to_glib_none().0,
112                &mut error,
113            );
114            if error.is_null() {
115                Ok(from_glib_none(closure))
116            } else {
117                Err(from_glib_full(error))
118            }
119        }
120    }
121}
122
123impl<T: BuilderScopeImpl> BuilderScopeImplExt for T {}
124
125unsafe impl<T: BuilderScopeImpl> IsImplementable<T> for BuilderScope {
126    fn interface_init(iface: &mut glib::Interface<Self>) {
127        let iface = iface.as_mut();
128
129        assert_initialized_main_thread!();
130
131        iface.get_type_from_name = Some(builder_scope_get_type_from_name::<T>);
132        iface.get_type_from_function = Some(builder_scope_get_type_from_function::<T>);
133        iface.create_closure = Some(builder_scope_create_closure::<T>);
134    }
135}
136
137unsafe extern "C" fn builder_scope_get_type_from_name<T: BuilderScopeImpl>(
138    builder_scope: *mut ffi::GtkBuilderScope,
139    builderptr: *mut ffi::GtkBuilder,
140    type_nameptr: *const libc::c_char,
141) -> glib::ffi::GType {
142    let instance = &*(builder_scope as *mut T::Instance);
143    let imp = instance.imp();
144    let builder: Borrowed<Builder> = from_glib_borrow(builderptr);
145    let type_name: Borrowed<GString> = from_glib_borrow(type_nameptr);
146
147    imp.type_from_name(&builder, &type_name).into_glib()
148}
149
150unsafe extern "C" fn builder_scope_get_type_from_function<T: BuilderScopeImpl>(
151    builder_scope: *mut ffi::GtkBuilderScope,
152    builderptr: *mut ffi::GtkBuilder,
153    func_nameptr: *const libc::c_char,
154) -> glib::ffi::GType {
155    let instance = &*(builder_scope as *mut T::Instance);
156    let imp = instance.imp();
157    let builder: Borrowed<Builder> = from_glib_borrow(builderptr);
158    let func_name: Borrowed<GString> = from_glib_borrow(func_nameptr);
159
160    imp.type_from_function(&builder, &func_name).into_glib()
161}
162
163unsafe extern "C" fn builder_scope_create_closure<T: BuilderScopeImpl>(
164    builder_scope: *mut ffi::GtkBuilderScope,
165    builderptr: *mut ffi::GtkBuilder,
166    func_nameptr: *const libc::c_char,
167    flags: ffi::GtkBuilderClosureFlags,
168    objectptr: *mut glib::gobject_ffi::GObject,
169    errorptr: *mut *mut glib::ffi::GError,
170) -> *mut glib::gobject_ffi::GClosure {
171    let instance = &*(builder_scope as *mut T::Instance);
172    let imp = instance.imp();
173    let builder: Borrowed<Builder> = from_glib_borrow(builderptr);
174    let func_name: Borrowed<GString> = from_glib_borrow(func_nameptr);
175    let object: Borrowed<Option<glib::Object>> = from_glib_borrow(objectptr);
176
177    let ret = imp.create_closure(
178        &builder,
179        &func_name,
180        from_glib(flags),
181        object.as_ref().as_ref(),
182    );
183
184    match ret {
185        Ok(closure) => closure.into_glib_ptr(),
186        Err(e) => {
187            if !errorptr.is_null() {
188                *errorptr = e.into_glib_ptr();
189            }
190            std::ptr::null_mut()
191        }
192    }
193}