glib/subclass/
type_module.rs1use crate::{ffi, gobject_ffi, prelude::*, subclass::prelude::*, translate::*, TypeModule};
4
5pub trait TypeModuleImpl: ObjectImpl + TypeModuleImplExt {
6 fn load(&self) -> bool;
15
16 fn unload(&self);
22}
23
24pub trait TypeModuleImplExt: ObjectSubclass {
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 let instance = &*(type_module as *mut T::Instance);
75 let imp = instance.imp();
76
77 let res = imp.load();
78 if res && (*(type_module as *const gobject_ffi::GObject)).ref_count == 1 {
85 unsafe {
86 gobject_ffi::g_object_ref(type_module as _);
87 }
88 }
89
90 res.into_glib()
91}
92
93unsafe extern "C" fn unload<T: TypeModuleImpl>(type_module: *mut gobject_ffi::GTypeModule) {
94 let instance = &*(type_module as *mut T::Instance);
95 let imp = instance.imp();
96
97 imp.unload();
98}
99
100#[cfg(test)]
101mod tests {
102 use crate as glib;
103
104 use super::*;
105
106 mod imp {
107 use super::*;
108
109 #[derive(Default)]
110 pub struct SimpleModule;
111
112 #[crate::object_subclass]
113 impl ObjectSubclass for SimpleModule {
114 const NAME: &'static str = "SimpleModule";
115 type Type = super::SimpleModule;
116 type ParentType = TypeModule;
117 type Interfaces = (crate::TypePlugin,);
118 }
119
120 impl ObjectImpl for SimpleModule {}
121
122 impl TypePluginImpl for SimpleModule {}
123
124 impl TypeModuleImpl for SimpleModule {
125 fn load(&self) -> bool {
126 SimpleModuleType::on_implementation_load(self.obj().upcast_ref::<TypeModule>())
128 }
129
130 fn unload(&self) {
131 SimpleModuleType::on_implementation_unload(self.obj().upcast_ref::<TypeModule>());
133 }
134 }
135
136 #[derive(Default)]
137 pub struct SimpleModuleType;
138
139 #[crate::object_subclass]
140 #[object_subclass_dynamic]
141 impl ObjectSubclass for SimpleModuleType {
142 const NAME: &'static str = "SimpleModuleType";
143 type Type = super::SimpleModuleType;
144 }
145
146 impl ObjectImpl for SimpleModuleType {}
147 }
148
149 crate::wrapper! {
150 pub struct SimpleModule(ObjectSubclass<imp::SimpleModule>)
151 @extends TypeModule, @implements crate::TypePlugin;
152 }
153
154 crate::wrapper! {
155 pub struct SimpleModuleType(ObjectSubclass<imp::SimpleModuleType>);
156 }
157
158 #[test]
159 fn test_module() {
160 assert!(!imp::SimpleModuleType::type_().is_valid());
161 let simple_module = glib::Object::new::<SimpleModule>();
162 assert!(TypeModuleExt::use_(&simple_module));
164 assert!(imp::SimpleModuleType::type_().is_valid());
165 TypeModuleExt::unuse(&simple_module);
166 }
167}