glib/subclass/
type_module.rs1use crate::{Object, TypeModule, ffi, gobject_ffi, prelude::*, subclass::prelude::*, translate::*};
4
5pub trait TypeModuleImpl: ObjectImpl + ObjectSubclass<Type: IsA<Object> + IsA<TypeModule>> {
6 fn load(&self) -> bool;
15
16 fn unload(&self);
22}
23
24pub trait TypeModuleImplExt: TypeModuleImpl {
25 fn parent_load(&self) -> bool;
26 fn parent_unload(&self);
27}
28
29impl<T: TypeModuleImpl> TypeModuleImplExt for T {
30 fn parent_load(&self) -> bool {
31 unsafe {
32 let data = T::type_data();
33 let parent_class = data.as_ref().parent_class() as *const gobject_ffi::GTypeModuleClass;
34
35 let f = (*parent_class)
36 .load
37 .expect("No parent class implementation for \"load\"");
38
39 from_glib(f(self
40 .obj()
41 .unsafe_cast_ref::<TypeModule>()
42 .to_glib_none()
43 .0))
44 }
45 }
46
47 fn parent_unload(&self) {
48 unsafe {
49 let data = T::type_data();
50 let parent_class = data.as_ref().parent_class() as *const gobject_ffi::GTypeModuleClass;
51
52 let f = (*parent_class)
53 .unload
54 .expect("No parent class implementation for \"unload\"");
55
56 f(self.obj().unsafe_cast_ref::<TypeModule>().to_glib_none().0);
57 }
58 }
59}
60
61unsafe impl<T: TypeModuleImpl> IsSubclassable<T> for TypeModule {
62 fn class_init(class: &mut crate::Class<Self>) {
63 Self::parent_class_init::<T>(class);
64
65 let klass = class.as_mut();
66 klass.load = Some(load::<T>);
67 klass.unload = Some(unload::<T>);
68 }
69}
70
71unsafe extern "C" fn load<T: TypeModuleImpl>(
72 type_module: *mut gobject_ffi::GTypeModule,
73) -> ffi::gboolean {
74 unsafe {
75 let instance = &*(type_module as *mut T::Instance);
76 let imp = instance.imp();
77
78 let res = imp.load();
79 if res && (*(type_module as *const gobject_ffi::GObject)).ref_count == 1 {
86 gobject_ffi::g_object_ref(type_module as _);
87 }
88
89 res.into_glib()
90 }
91}
92
93unsafe extern "C" fn unload<T: TypeModuleImpl>(type_module: *mut gobject_ffi::GTypeModule) {
94 unsafe {
95 let instance = &*(type_module as *mut T::Instance);
96 let imp = instance.imp();
97
98 imp.unload();
99 }
100}
101
102#[cfg(test)]
103mod tests {
104 use crate as glib;
105
106 use super::*;
107
108 mod imp {
109 use super::*;
110
111 #[derive(Default)]
112 pub struct SimpleModule;
113
114 #[crate::object_subclass]
115 impl ObjectSubclass for SimpleModule {
116 const NAME: &'static str = "SimpleModule";
117 type Type = super::SimpleModule;
118 type ParentType = TypeModule;
119 type Interfaces = (crate::TypePlugin,);
120 }
121
122 impl ObjectImpl for SimpleModule {}
123
124 impl TypePluginImpl for SimpleModule {}
125
126 impl TypeModuleImpl for SimpleModule {
127 fn load(&self) -> bool {
128 SimpleModuleType::on_implementation_load(self.obj().upcast_ref::<TypeModule>())
130 }
131
132 fn unload(&self) {
133 SimpleModuleType::on_implementation_unload(self.obj().upcast_ref::<TypeModule>());
135 }
136 }
137
138 #[derive(Default)]
139 pub struct SimpleModuleType;
140
141 #[crate::object_subclass]
142 #[object_subclass_dynamic]
143 impl ObjectSubclass for SimpleModuleType {
144 const NAME: &'static str = "SimpleModuleType";
145 type Type = super::SimpleModuleType;
146 }
147
148 impl ObjectImpl for SimpleModuleType {}
149 }
150
151 crate::wrapper! {
152 pub struct SimpleModule(ObjectSubclass<imp::SimpleModule>)
153 @extends TypeModule, @implements crate::TypePlugin;
154 }
155
156 crate::wrapper! {
157 pub struct SimpleModuleType(ObjectSubclass<imp::SimpleModuleType>);
158 }
159
160 #[test]
161 fn test_module() {
162 assert!(!imp::SimpleModuleType::type_().is_valid());
163 let simple_module = glib::Object::new::<SimpleModule>();
164 assert!(TypeModuleExt::use_(&simple_module));
166 assert!(imp::SimpleModuleType::type_().is_valid());
167 TypeModuleExt::unuse(&simple_module);
168 }
169}