use glib::{prelude::*, subclass::prelude::*};
mod static_ {
use super::*;
pub mod imp {
use super::*;
#[derive(Clone, Copy)]
#[repr(C)]
pub struct MyStaticInterface {
parent: glib::gobject_ffi::GTypeInterface,
}
#[glib::object_interface]
unsafe impl ObjectInterface for MyStaticInterface {
const NAME: &'static str = "MyStaticInterface";
}
pub trait MyStaticInterfaceImpl: ObjectImpl + ObjectSubclass {}
#[derive(Default)]
pub struct MyStaticType;
#[glib::object_subclass]
impl ObjectSubclass for MyStaticType {
const NAME: &'static str = "MyStaticType";
type Type = super::MyStaticType;
type Interfaces = (super::MyStaticInterface,);
}
impl ObjectImpl for MyStaticType {}
impl MyStaticInterfaceImpl for MyStaticType {}
pub trait MyStaticTypeImpl: ObjectImpl + ObjectSubclass {}
}
glib::wrapper! {
pub struct MyStaticInterface(ObjectInterface<imp::MyStaticInterface>);
}
unsafe impl<T: imp::MyStaticInterfaceImpl> IsImplementable<T> for MyStaticInterface {}
glib::wrapper! {
pub struct MyStaticType(ObjectSubclass<imp::MyStaticType>) @implements MyStaticInterface;
}
unsafe impl<T: imp::MyStaticTypeImpl> IsSubclassable<T> for MyStaticType {}
}
use static_::{
imp::{MyStaticInterfaceImpl, MyStaticTypeImpl},
*,
};
mod module {
use super::*;
mod imp {
use super::*;
#[derive(Clone, Copy)]
#[repr(C)]
pub struct MyModuleInterface {
parent: glib::gobject_ffi::GTypeInterface,
}
#[glib::object_interface]
#[object_interface_dynamic]
unsafe impl ObjectInterface for MyModuleInterface {
const NAME: &'static str = "MyModuleInterface";
type Prerequisites = (MyStaticInterface,);
}
pub trait MyModuleInterfaceImpl: ObjectImpl + ObjectSubclass {}
#[derive(Default)]
pub struct MyModuleType;
#[glib::object_subclass]
#[object_subclass_dynamic]
impl ObjectSubclass for MyModuleType {
const NAME: &'static str = "MyModuleType";
type Type = super::MyModuleType;
type ParentType = MyStaticType;
type Interfaces = (MyStaticInterface, super::MyModuleInterface);
}
impl ObjectImpl for MyModuleType {}
impl MyStaticTypeImpl for MyModuleType {}
impl MyStaticInterfaceImpl for MyModuleType {}
impl MyModuleInterfaceImpl for MyModuleType {}
#[derive(Clone, Copy)]
#[repr(C)]
pub struct MyModuleInterfaceLazy {
parent: glib::gobject_ffi::GTypeInterface,
}
#[glib::object_interface]
#[object_interface_dynamic(lazy_registration = true)]
unsafe impl ObjectInterface for MyModuleInterfaceLazy {
const NAME: &'static str = "MyModuleInterfaceLazy";
type Prerequisites = (MyStaticInterface,);
}
pub trait MyModuleInterfaceLazyImpl: ObjectImpl + ObjectSubclass {}
#[derive(Default)]
pub struct MyModuleTypeLazy;
#[glib::object_subclass]
#[object_subclass_dynamic(lazy_registration = true)]
impl ObjectSubclass for MyModuleTypeLazy {
const NAME: &'static str = "MyModuleTypeLazy";
type Type = super::MyModuleTypeLazy;
type ParentType = MyStaticType;
type Interfaces = (MyStaticInterface, super::MyModuleInterfaceLazy);
}
impl ObjectImpl for MyModuleTypeLazy {}
impl MyStaticTypeImpl for MyModuleTypeLazy {}
impl MyStaticInterfaceImpl for MyModuleTypeLazy {}
impl MyModuleInterfaceLazyImpl for MyModuleTypeLazy {}
#[derive(Default)]
pub struct MyModule;
#[glib::object_subclass]
impl ObjectSubclass for MyModule {
const NAME: &'static str = "MyModule";
type Type = super::MyModule;
type ParentType = glib::TypeModule;
type Interfaces = (glib::TypePlugin,);
}
impl ObjectImpl for MyModule {}
impl TypePluginImpl for MyModule {}
impl TypeModuleImpl for MyModule {
fn load(&self) -> bool {
let my_module = self.obj();
let type_module: &glib::TypeModule = my_module.upcast_ref();
MyModuleInterface::on_implementation_load(type_module)
&& MyModuleType::on_implementation_load(type_module)
&& MyModuleInterfaceLazy::on_implementation_load(type_module)
&& MyModuleTypeLazy::on_implementation_load(type_module)
}
fn unload(&self) {
let my_module = self.obj();
let type_module: &glib::TypeModule = my_module.upcast_ref();
MyModuleTypeLazy::on_implementation_unload(type_module);
MyModuleInterfaceLazy::on_implementation_unload(type_module);
MyModuleType::on_implementation_unload(type_module);
MyModuleInterface::on_implementation_unload(type_module);
}
}
}
glib::wrapper! {
pub struct MyModuleInterface(ObjectInterface<imp::MyModuleInterface>) @requires MyStaticInterface;
}
unsafe impl<T: imp::MyModuleInterfaceImpl> IsImplementable<T> for MyModuleInterface {}
glib::wrapper! {
pub struct MyModuleType(ObjectSubclass<imp::MyModuleType>) @extends MyStaticType, @implements MyStaticInterface, MyModuleInterface;
}
glib::wrapper! {
pub struct MyModuleInterfaceLazy(ObjectInterface<imp::MyModuleInterfaceLazy>) @requires MyStaticInterface;
}
unsafe impl<T: imp::MyModuleInterfaceLazyImpl> IsImplementable<T> for MyModuleInterfaceLazy {}
glib::wrapper! {
pub struct MyModuleTypeLazy(ObjectSubclass<imp::MyModuleTypeLazy>) @extends MyStaticType, @implements MyStaticInterface, MyModuleInterfaceLazy;
}
glib::wrapper! {
pub struct MyModule(ObjectSubclass<imp::MyModule>)
@extends glib::TypeModule, @implements glib::TypePlugin;
}
#[test]
fn dynamic_object_subclasses() {
use glib::prelude::TypeModuleExt;
assert!(!imp::MyModuleInterface::type_().is_valid());
assert!(!imp::MyModuleType::type_().is_valid());
assert!(!imp::MyModuleInterfaceLazy::type_().is_valid());
assert!(!imp::MyModuleTypeLazy::type_().is_valid());
let module = glib::Object::new::<MyModule>();
TypeModuleExt::use_(&module);
TypeModuleExt::unuse(&module);
assert!(imp::MyModuleInterface::type_().is_valid());
assert!(imp::MyModuleType::type_().is_valid());
assert!(!imp::MyModuleInterfaceLazy::type_().is_valid());
assert!(!imp::MyModuleTypeLazy::type_().is_valid());
TypeModuleExt::use_(&module);
let iface_type = imp::MyModuleInterface::type_();
assert!(iface_type.is_valid());
let obj_type = imp::MyModuleType::type_();
assert!(obj_type.is_valid());
let iface_lazy_type = imp::MyModuleInterfaceLazy::type_();
assert!(iface_lazy_type.is_valid());
let obj_lazy_type = imp::MyModuleTypeLazy::type_();
assert!(obj_lazy_type.is_valid());
assert_eq!(
iface_type.plugin().as_ref(),
Some(module.upcast_ref::<glib::TypePlugin>())
);
assert_eq!(
obj_type.plugin().as_ref(),
Some(module.upcast_ref::<glib::TypePlugin>())
);
assert_eq!(
iface_lazy_type.plugin().as_ref(),
Some(module.upcast_ref::<glib::TypePlugin>())
);
assert_eq!(
obj_lazy_type.plugin().as_ref(),
Some(module.upcast_ref::<glib::TypePlugin>())
);
TypeModuleExt::unuse(&module);
assert!(imp::MyModuleInterface::type_().is_valid());
assert!(imp::MyModuleType::type_().is_valid());
assert!(imp::MyModuleInterfaceLazy::type_().is_valid());
assert!(imp::MyModuleTypeLazy::type_().is_valid());
TypeModuleExt::use_(&module);
assert!(imp::MyModuleInterface::type_().is_valid());
assert!(imp::MyModuleType::type_().is_valid());
assert!(imp::MyModuleInterfaceLazy::type_().is_valid());
assert!(imp::MyModuleTypeLazy::type_().is_valid());
TypeModuleExt::unuse(&module);
}
}
pub mod plugin {
use super::*;
pub mod imp {
use super::*;
use std::cell::Cell;
#[derive(Clone, Copy)]
#[repr(C)]
pub struct MyPluginInterface {
parent: glib::gobject_ffi::GTypeInterface,
}
#[glib::object_interface]
#[object_interface_dynamic(plugin_type = super::MyPlugin)]
unsafe impl ObjectInterface for MyPluginInterface {
const NAME: &'static str = "MyPluginInterface";
type Prerequisites = (MyStaticInterface,);
}
pub trait MyPluginInterfaceImpl: ObjectImpl + ObjectSubclass {}
#[derive(Default)]
pub struct MyPluginType;
#[glib::object_subclass]
#[object_subclass_dynamic(plugin_type = super::MyPlugin)]
impl ObjectSubclass for MyPluginType {
const NAME: &'static str = "MyPluginType";
type Type = super::MyPluginType;
type ParentType = MyStaticType;
type Interfaces = (MyStaticInterface, super::MyPluginInterface);
}
impl ObjectImpl for MyPluginType {}
impl MyStaticTypeImpl for MyPluginType {}
impl MyStaticInterfaceImpl for MyPluginType {}
impl MyPluginInterfaceImpl for MyPluginType {}
#[derive(Clone, Copy)]
#[repr(C)]
pub struct MyPluginInterfaceLazy {
parent: glib::gobject_ffi::GTypeInterface,
}
#[glib::object_interface]
#[object_interface_dynamic(plugin_type = super::MyPlugin, lazy_registration = true)]
unsafe impl ObjectInterface for MyPluginInterfaceLazy {
const NAME: &'static str = "MyPluginInterfaceLazy";
type Prerequisites = (MyStaticInterface,);
}
pub trait MyPluginInterfaceLazyImpl: ObjectImpl + ObjectSubclass {}
#[derive(Default)]
pub struct MyPluginTypeLazy;
#[glib::object_subclass]
#[object_subclass_dynamic(plugin_type = super::MyPlugin, lazy_registration = true)]
impl ObjectSubclass for MyPluginTypeLazy {
const NAME: &'static str = "MyPluginTypeLazy";
type Type = super::MyPluginTypeLazy;
type ParentType = MyStaticType;
type Interfaces = (MyStaticInterface, super::MyPluginInterfaceLazy);
}
impl ObjectImpl for MyPluginTypeLazy {}
impl MyStaticTypeImpl for MyPluginTypeLazy {}
impl MyStaticInterfaceImpl for MyPluginTypeLazy {}
impl MyPluginInterfaceLazyImpl for MyPluginTypeLazy {}
#[derive(Default)]
pub struct MyPlugin {
my_interface_type_info: Cell<Option<glib::TypeInfo>>,
my_interface_iface_info: Cell<Option<glib::InterfaceInfo>>,
my_type_type_info: Cell<Option<glib::TypeInfo>>,
my_interface_lazy_type_info: Cell<Option<glib::TypeInfo>>,
my_interface_lazy_iface_info: Cell<Option<glib::InterfaceInfo>>,
my_type_lazy_type_info: Cell<Option<glib::TypeInfo>>,
}
#[glib::object_subclass]
impl ObjectSubclass for MyPlugin {
const NAME: &'static str = "MyPlugin";
type Type = super::MyPlugin;
type Interfaces = (glib::TypePlugin,);
}
impl ObjectImpl for MyPlugin {}
impl TypePluginImpl for MyPlugin {
fn use_plugin(&self) {
let my_plugin = self.obj();
MyPluginInterface::on_implementation_load(my_plugin.as_ref());
MyPluginType::on_implementation_load(my_plugin.as_ref());
MyPluginInterfaceLazy::on_implementation_load(my_plugin.as_ref());
MyPluginTypeLazy::on_implementation_load(my_plugin.as_ref());
}
fn unuse_plugin(&self) {
let my_plugin = self.obj();
MyPluginTypeLazy::on_implementation_unload(my_plugin.as_ref());
MyPluginInterfaceLazy::on_implementation_unload(my_plugin.as_ref());
MyPluginType::on_implementation_unload(my_plugin.as_ref());
MyPluginInterface::on_implementation_unload(my_plugin.as_ref());
}
fn complete_type_info(
&self,
type_: glib::Type,
) -> (glib::TypeInfo, glib::TypeValueTable) {
let info = match type_ {
type_ if type_ == MyPluginType::type_() => self.my_type_type_info.get(),
type_ if type_ == MyPluginInterface::type_() => {
self.my_interface_type_info.get()
}
type_ if type_ == MyPluginTypeLazy::type_() => {
self.my_type_lazy_type_info.get()
}
type_ if type_ == MyPluginInterfaceLazy::type_() => {
self.my_interface_lazy_type_info.get()
}
_ => panic!("unexpected"),
};
match info {
Some(info) => (info, glib::TypeValueTable::default()),
_ => panic!("unexpected"),
}
}
fn complete_interface_info(
&self,
_instance_type: glib::Type,
interface_type: glib::Type,
) -> glib::InterfaceInfo {
let info = match interface_type {
type_ if type_ == MyPluginInterface::type_() => {
self.my_interface_iface_info.get()
}
type_ if type_ == MyPluginInterfaceLazy::type_() => {
self.my_interface_lazy_iface_info.get()
}
_ => panic!("unexpected"),
};
match info {
Some(info) => info,
_ => panic!("unexpected"),
}
}
}
impl TypePluginRegisterImpl for MyPlugin {
fn add_dynamic_interface(
&self,
instance_type: glib::Type,
interface_type: glib::Type,
interface_info: &glib::InterfaceInfo,
) {
if !instance_type.is_a(interface_type) {
instance_type.add_interface_dynamic(
interface_type,
self.obj().upcast_ref::<glib::TypePlugin>(),
);
}
match interface_type {
type_ if type_ == imp::MyPluginInterface::type_() => {
self.my_interface_iface_info.set(Some(*interface_info))
}
type_ if type_ == imp::MyPluginInterfaceLazy::type_() => {
self.my_interface_lazy_iface_info.set(Some(*interface_info))
}
_ => panic!("unexpected"),
};
}
fn register_dynamic_type(
&self,
parent_type: glib::Type,
type_name: &str,
type_info: &glib::TypeInfo,
flags: glib::TypeFlags,
) -> glib::Type {
let type_ = glib::Type::from_name(type_name).unwrap_or_else(|| {
glib::Type::register_dynamic(
parent_type,
type_name,
self.obj().upcast_ref::<glib::TypePlugin>(),
flags,
)
});
if type_.is_valid() {
match type_name {
imp::MyPluginType::NAME => self.my_type_type_info.set(Some(*type_info)),
imp::MyPluginInterface::NAME => {
self.my_interface_type_info.set(Some(*type_info))
}
imp::MyPluginTypeLazy::NAME => {
self.my_type_lazy_type_info.set(Some(*type_info))
}
imp::MyPluginInterfaceLazy::NAME => {
self.my_interface_lazy_type_info.set(Some(*type_info))
}
_ => panic!("unexpected"),
};
}
type_
}
}
}
glib::wrapper! {
pub struct MyPluginInterface(ObjectInterface<imp::MyPluginInterface>) @requires MyStaticInterface;
}
unsafe impl<T: imp::MyPluginInterfaceImpl> IsImplementable<T> for MyPluginInterface {}
glib::wrapper! {
pub struct MyPluginType(ObjectSubclass<imp::MyPluginType>) @implements MyPluginInterface;
}
glib::wrapper! {
pub struct MyPluginInterfaceLazy(ObjectInterface<imp::MyPluginInterfaceLazy>) @requires MyStaticInterface;
}
unsafe impl<T: imp::MyPluginInterfaceLazyImpl> IsImplementable<T> for MyPluginInterfaceLazy {}
glib::wrapper! {
pub struct MyPluginTypeLazy(ObjectSubclass<imp::MyPluginTypeLazy>) @implements MyPluginInterfaceLazy;
}
glib::wrapper! {
pub struct MyPlugin(ObjectSubclass<imp::MyPlugin>) @implements glib::TypePlugin;
}
#[test]
fn dynamic_object_subclasses() {
use glib::prelude::TypePluginExt;
assert!(!imp::MyPluginInterface::type_().is_valid());
assert!(!imp::MyPluginType::type_().is_valid());
assert!(!imp::MyPluginInterfaceLazy::type_().is_valid());
assert!(!imp::MyPluginTypeLazy::type_().is_valid());
let plugin = glib::Object::new::<MyPlugin>();
TypePluginExt::use_(&plugin);
TypePluginExt::unuse(&plugin);
assert!(imp::MyPluginInterface::type_().is_valid());
assert!(imp::MyPluginType::type_().is_valid());
assert!(!imp::MyPluginInterfaceLazy::type_().is_valid());
assert!(!imp::MyPluginTypeLazy::type_().is_valid());
TypePluginExt::use_(&plugin);
let iface_type = imp::MyPluginInterface::type_();
assert!(iface_type.is_valid());
let obj_type = imp::MyPluginType::type_();
assert!(obj_type.is_valid());
let iface_lazy_type = imp::MyPluginInterfaceLazy::type_();
assert!(iface_lazy_type.is_valid());
let obj_lazy_type = imp::MyPluginTypeLazy::type_();
assert!(obj_lazy_type.is_valid());
assert_eq!(
iface_type.plugin().as_ref(),
Some(plugin.upcast_ref::<glib::TypePlugin>())
);
assert_eq!(
obj_type.plugin().as_ref(),
Some(plugin.upcast_ref::<glib::TypePlugin>())
);
assert_eq!(
iface_lazy_type.plugin().as_ref(),
Some(plugin.upcast_ref::<glib::TypePlugin>())
);
assert_eq!(
obj_lazy_type.plugin().as_ref(),
Some(plugin.upcast_ref::<glib::TypePlugin>())
);
TypePluginExt::unuse(&plugin);
assert!(imp::MyPluginInterface::type_().is_valid());
assert!(imp::MyPluginType::type_().is_valid());
assert!(imp::MyPluginInterfaceLazy::type_().is_valid());
assert!(imp::MyPluginTypeLazy::type_().is_valid());
TypePluginExt::use_(&plugin);
assert!(imp::MyPluginInterface::type_().is_valid());
assert!(imp::MyPluginType::type_().is_valid());
assert!(imp::MyPluginInterfaceLazy::type_().is_valid());
assert!(imp::MyPluginTypeLazy::type_().is_valid());
TypePluginExt::unuse(&plugin);
}
}