use crate::{prelude::*, subclass::prelude::*, translate::*, TypeModule};
pub trait TypeModuleImpl: ObjectImpl + TypeModuleImplExt {
fn load(&self) -> bool;
fn unload(&self);
}
pub trait TypeModuleImplExt: ObjectSubclass {
fn parent_load(&self) -> bool;
fn parent_unload(&self);
}
impl<T: TypeModuleImpl> TypeModuleImplExt for T {
fn parent_load(&self) -> bool {
unsafe {
let data = T::type_data();
let parent_class = data.as_ref().parent_class() as *const gobject_ffi::GTypeModuleClass;
let f = (*parent_class)
.load
.expect("No parent class implementation for \"load\"");
from_glib(f(self
.obj()
.unsafe_cast_ref::<TypeModule>()
.to_glib_none()
.0))
}
}
fn parent_unload(&self) {
unsafe {
let data = T::type_data();
let parent_class = data.as_ref().parent_class() as *const gobject_ffi::GTypeModuleClass;
let f = (*parent_class)
.unload
.expect("No parent class implementation for \"unload\"");
f(self.obj().unsafe_cast_ref::<TypeModule>().to_glib_none().0);
}
}
}
unsafe impl<T: TypeModuleImpl> IsSubclassable<T> for TypeModule {
fn class_init(class: &mut crate::Class<Self>) {
Self::parent_class_init::<T>(class);
let klass = class.as_mut();
klass.load = Some(load::<T>);
klass.unload = Some(unload::<T>);
}
}
unsafe extern "C" fn load<T: TypeModuleImpl>(
type_module: *mut gobject_ffi::GTypeModule,
) -> ffi::gboolean {
let instance = &*(type_module as *mut T::Instance);
let imp = instance.imp();
let res = imp.load();
if res && (*(type_module as *const gobject_ffi::GObject)).ref_count == 1 {
unsafe {
gobject_ffi::g_object_ref(type_module as _);
}
}
res.into_glib()
}
unsafe extern "C" fn unload<T: TypeModuleImpl>(type_module: *mut gobject_ffi::GTypeModule) {
let instance = &*(type_module as *mut T::Instance);
let imp = instance.imp();
imp.unload();
}
#[cfg(test)]
mod tests {
use crate as glib;
use super::*;
mod imp {
use super::*;
#[derive(Default)]
pub struct SimpleModule;
#[crate::object_subclass]
impl ObjectSubclass for SimpleModule {
const NAME: &'static str = "SimpleModule";
type Type = super::SimpleModule;
type ParentType = TypeModule;
type Interfaces = (crate::TypePlugin,);
}
impl ObjectImpl for SimpleModule {}
impl TypePluginImpl for SimpleModule {}
impl TypeModuleImpl for SimpleModule {
fn load(&self) -> bool {
SimpleModuleType::on_implementation_load(self.obj().upcast_ref::<TypeModule>())
}
fn unload(&self) {
SimpleModuleType::on_implementation_unload(self.obj().upcast_ref::<TypeModule>());
}
}
#[derive(Default)]
pub struct SimpleModuleType;
#[crate::object_subclass]
#[object_subclass_dynamic]
impl ObjectSubclass for SimpleModuleType {
const NAME: &'static str = "SimpleModuleType";
type Type = super::SimpleModuleType;
}
impl ObjectImpl for SimpleModuleType {}
}
crate::wrapper! {
pub struct SimpleModule(ObjectSubclass<imp::SimpleModule>)
@extends TypeModule, @implements crate::TypePlugin;
}
crate::wrapper! {
pub struct SimpleModuleType(ObjectSubclass<imp::SimpleModuleType>);
}
#[test]
fn test_module() {
assert!(!imp::SimpleModuleType::type_().is_valid());
let simple_module = glib::Object::new::<SimpleModule>();
assert!(TypeModuleExt::use_(&simple_module));
assert!(imp::SimpleModuleType::type_().is_valid());
TypeModuleExt::unuse(&simple_module);
}
}