glib/subclass/
type_plugin.rs1use crate::enums::{EnumValues, FlagsValues};
4use crate::{
5 Interface, InterfaceInfo, Object, Type, TypeFlags, TypeInfo, TypePlugin, TypeValueTable, ffi,
6 gobject_ffi, prelude::*, subclass::prelude::*, translate::*,
7};
8
9pub trait TypePluginImpl: ObjectImpl + ObjectSubclass<Type: IsA<Object> + IsA<TypePlugin>> {
10 fn use_plugin(&self) {
11 self.parent_use_plugin();
12 }
13
14 fn unuse_plugin(&self) {
15 self.parent_unuse_plugin();
16 }
17
18 fn complete_type_info(&self, type_: Type) -> (TypeInfo, TypeValueTable) {
19 self.parent_complete_type_info(type_)
20 }
21
22 fn complete_interface_info(&self, instance_type: Type, interface_type: Type) -> InterfaceInfo {
23 self.parent_complete_interface_info(instance_type, interface_type)
24 }
25}
26
27pub trait TypePluginImplExt: TypePluginImpl {
28 fn parent_use_plugin(&self);
29 fn parent_unuse_plugin(&self);
30 fn parent_complete_type_info(&self, type_: Type) -> (TypeInfo, TypeValueTable);
31 fn parent_complete_interface_info(
32 &self,
33 instance_type: Type,
34 interface_type: Type,
35 ) -> InterfaceInfo;
36}
37
38impl<T: TypePluginImpl> TypePluginImplExt for T {
39 fn parent_use_plugin(&self) {
40 unsafe {
41 let type_data = Self::type_data();
42 let parent_iface = type_data.as_ref().parent_interface::<TypePlugin>()
43 as *const gobject_ffi::GTypePluginClass;
44
45 let f = (*parent_iface)
46 .use_plugin
47 .expect("no parent \"use_plugin\" implementation");
48
49 f(self.obj().unsafe_cast_ref::<TypePlugin>().to_glib_none().0)
50 }
51 }
52
53 fn parent_unuse_plugin(&self) {
54 unsafe {
55 let type_data = Self::type_data();
56 let parent_iface = type_data.as_ref().parent_interface::<TypePlugin>()
57 as *const gobject_ffi::GTypePluginClass;
58
59 let f = (*parent_iface)
60 .unuse_plugin
61 .expect("no parent \"unuse_plugin\" implementation");
62
63 f(self.obj().unsafe_cast_ref::<TypePlugin>().to_glib_none().0)
64 }
65 }
66
67 fn parent_complete_type_info(&self, type_: Type) -> (TypeInfo, TypeValueTable) {
68 unsafe {
69 let type_data = Self::type_data();
70 let parent_iface = type_data.as_ref().parent_interface::<TypePlugin>()
71 as *const gobject_ffi::GTypePluginClass;
72
73 let f = (*parent_iface)
74 .complete_type_info
75 .expect("no parent \"complete_type_info\" implementation");
76
77 let info = TypeInfo::default();
78 let value_table = TypeValueTable::default();
79 f(
80 self.obj().unsafe_cast_ref::<TypePlugin>().to_glib_none().0,
81 type_.into_glib(),
82 info.as_ptr(),
83 value_table.as_ptr(),
84 );
85
86 (info, value_table)
87 }
88 }
89
90 fn parent_complete_interface_info(
91 &self,
92 instance_type: Type,
93 interface_type: Type,
94 ) -> InterfaceInfo {
95 let info = InterfaceInfo::default();
96 unsafe {
97 let type_data = Self::type_data();
98 let parent_iface = type_data.as_ref().parent_interface::<TypePlugin>()
99 as *const gobject_ffi::GTypePluginClass;
100
101 let f = (*parent_iface)
102 .complete_interface_info
103 .expect("no parent \"complete_interface_info\" implementation");
104
105 f(
106 self.obj().unsafe_cast_ref::<TypePlugin>().to_glib_none().0,
107 instance_type.into_glib(),
108 interface_type.into_glib(),
109 info.as_ptr(),
110 )
111 }
112 info
113 }
114}
115
116unsafe impl<T: TypePluginImpl> IsImplementable<T> for TypePlugin {
117 fn interface_init(iface: &mut Interface<Self>) {
118 let iface = iface.as_mut();
119
120 iface.use_plugin = Some(use_plugin::<T>);
121 iface.unuse_plugin = Some(unuse_plugin::<T>);
122 iface.complete_type_info = Some(complete_type_info::<T>);
123 iface.complete_interface_info = Some(complete_interface_info::<T>);
124 }
125}
126
127unsafe extern "C" fn use_plugin<T: TypePluginImpl>(type_plugin: *mut gobject_ffi::GTypePlugin) {
128 unsafe {
129 let instance = &*(type_plugin as *mut T::Instance);
130 let imp = instance.imp();
131
132 imp.use_plugin();
133 }
134}
135
136unsafe extern "C" fn unuse_plugin<T: TypePluginImpl>(type_plugin: *mut gobject_ffi::GTypePlugin) {
137 unsafe {
138 let instance = &*(type_plugin as *mut T::Instance);
139 let imp = instance.imp();
140
141 imp.unuse_plugin();
142 }
143}
144
145unsafe extern "C" fn complete_type_info<T: TypePluginImpl>(
146 type_plugin: *mut gobject_ffi::GTypePlugin,
147 gtype: ffi::GType,
148 info_ptr: *mut gobject_ffi::GTypeInfo,
149 value_table_ptr: *mut gobject_ffi::GTypeValueTable,
150) {
151 unsafe {
152 assert!(!info_ptr.is_null());
153 assert!(!value_table_ptr.is_null());
154 let instance = &*(type_plugin as *mut T::Instance);
155 let imp = instance.imp();
156 let type_ = Type::from_glib(gtype);
157 let info = TypeInfo::from_glib_ptr_borrow_mut(info_ptr);
158 let value_table = TypeValueTable::from_glib_ptr_borrow_mut(value_table_ptr);
159
160 let (info_, value_table_) = imp.complete_type_info(type_);
161
162 *info = info_;
163 *value_table = value_table_;
164 }
165}
166
167unsafe extern "C" fn complete_interface_info<T: TypePluginImpl>(
168 type_plugin: *mut gobject_ffi::GTypePlugin,
169 instance_gtype: ffi::GType,
170 interface_gtype: ffi::GType,
171 info_ptr: *mut gobject_ffi::GInterfaceInfo,
172) {
173 unsafe {
174 assert!(!info_ptr.is_null());
175 let instance = &*(type_plugin as *mut T::Instance);
176 let imp = instance.imp();
177 let instance_type = Type::from_glib(instance_gtype);
178 let interface_type = Type::from_glib(interface_gtype);
179 let info = InterfaceInfo::from_glib_ptr_borrow_mut(info_ptr);
180
181 let info_ = imp.complete_interface_info(instance_type, interface_type);
182 *info = info_;
183 }
184}
185
186pub trait TypePluginRegisterImpl:
187 TypePluginImpl + ObjectSubclass<Type: IsA<Object> + IsA<TypePlugin>>
188{
189 fn add_dynamic_interface(
190 &self,
191 _instance_type: Type,
192 _interface_type: Type,
193 _interface_info: &InterfaceInfo,
194 ) {
195 unimplemented!()
196 }
197 fn register_dynamic_enum(
198 &self,
199 _name: &str,
200 _const_static_values: &'static EnumValues,
201 ) -> Type {
202 unimplemented!()
203 }
204 fn register_dynamic_flags(
205 &self,
206 _name: &str,
207 _const_static_values: &'static FlagsValues,
208 ) -> Type {
209 unimplemented!()
210 }
211 fn register_dynamic_type(
212 &self,
213 _parent_type: Type,
214 _type_name: &str,
215 _type_info: &TypeInfo,
216 _flags: TypeFlags,
217 ) -> Type {
218 unimplemented!()
219 }
220}
221
222#[cfg(test)]
223mod tests {
224 use crate::{self as glib, prelude::TypePluginExt};
225
226 use super::*;
227
228 mod imp {
229 use super::*;
230
231 #[derive(Default)]
232 pub struct SimplePlugin {
233 type_info: std::cell::Cell<Option<TypeInfo>>,
234 }
235
236 #[crate::object_subclass]
237 impl ObjectSubclass for SimplePlugin {
238 const NAME: &'static str = "SimplePlugin";
239 type Type = super::SimplePlugin;
240 type Interfaces = (TypePlugin,);
241 }
242
243 impl ObjectImpl for SimplePlugin {}
244
245 impl TypePluginImpl for SimplePlugin {
246 fn use_plugin(&self) {
247 SimplePluginType::on_implementation_load(self.obj().as_ref());
249 }
250
251 fn unuse_plugin(&self) {
252 SimplePluginType::on_implementation_unload(self.obj().as_ref());
254 }
255
256 fn complete_type_info(&self, _type_: Type) -> (TypeInfo, TypeValueTable) {
257 assert!(self.type_info.get().is_some());
258 (self.type_info.get().unwrap(), TypeValueTable::default())
260 }
261 }
262
263 impl TypePluginRegisterImpl for SimplePlugin {
264 fn register_dynamic_type(
265 &self,
266 parent_type: Type,
267 type_name: &str,
268 type_info: &TypeInfo,
269 flags: TypeFlags,
270 ) -> Type {
271 let type_ = Type::from_name(type_name).unwrap_or_else(|| {
272 Type::register_dynamic(
273 parent_type,
274 type_name,
275 self.obj().upcast_ref::<TypePlugin>(),
276 flags,
277 )
278 });
279 if type_.is_valid() {
280 self.type_info.set(Some(*type_info));
282 }
283 type_
284 }
285 }
286
287 #[derive(Default)]
288 pub struct SimplePluginType;
289
290 #[crate::object_subclass]
291 #[object_subclass_dynamic(plugin_type = super::SimplePlugin)]
292 impl ObjectSubclass for SimplePluginType {
293 const NAME: &'static str = "SimplePluginType";
294 type Type = super::SimplePluginType;
295 }
296
297 impl ObjectImpl for SimplePluginType {}
298 }
299
300 crate::wrapper! {
301 pub struct SimplePlugin(ObjectSubclass<imp::SimplePlugin>)
302 @implements TypePlugin;
303 }
304
305 crate::wrapper! {
306 pub struct SimplePluginType(ObjectSubclass<imp::SimplePluginType>);
307 }
308
309 #[test]
310 fn test_plugin() {
311 assert!(!imp::SimplePluginType::type_().is_valid());
312 let simple_plugin = crate::Object::new::<SimplePlugin>();
313 TypePluginExt::use_(&simple_plugin);
315 assert!(imp::SimplePluginType::type_().is_valid());
316 TypePluginExt::unuse(&simple_plugin);
317 }
318}