Skip to main content

glib/subclass/
mod.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3#![allow(clippy::needless_doctest_main)]
4// rustdoc-stripper-ignore-next
5//! Module containing infrastructure for subclassing `GObject`s and registering boxed types.
6//!
7//! # Example for registering a `glib::Object` subclass
8//!
9//! The following code implements a subclass of `glib::Object` with a
10//! string-typed "name" property.
11//!
12//! ```rust
13//! use glib::prelude::*;
14//! use glib::subclass;
15//! use glib::subclass::prelude::*;
16//! use glib::{Variant, VariantType};
17//!
18//! use std::cell::{Cell, RefCell};
19//!
20//! #[derive(Debug, Eq, PartialEq, Clone, Copy, glib::Enum)]
21//! #[repr(u32)]
22//! // type_name: GType name of the enum (mandatory)
23//! #[enum_type(name = "SimpleObjectAnimal")]
24//! enum Animal {
25//!     Goat = 0,
26//!     #[enum_value(name = "The Dog")]
27//!     Dog = 1,
28//!     // name: the name of the GEnumValue (optional), default to the enum name in CamelCase
29//!     // nick: the nick of the GEnumValue (optional), default to the enum name in kebab-case
30//!     #[enum_value(name = "The Cat", nick = "chat")]
31//!     Cat = 2,
32//! }
33//!
34//! impl Default for Animal {
35//!     fn default() -> Self {
36//!         Animal::Goat
37//!     }
38//! }
39//!
40//! #[glib::flags(name = "MyFlags")]
41//! enum MyFlags {
42//!     #[flags_value(name = "Flag A", nick = "nick-a")]
43//!     A = 0b00000001,
44//!     #[flags_value(name = "Flag B")]
45//!     B = 0b00000010,
46//!     #[flags_value(skip)]
47//!     AB = Self::A.bits() | Self::B.bits(),
48//!     C = 0b00000100,
49//! }
50//!
51//! impl Default for MyFlags {
52//!     fn default() -> Self {
53//!         MyFlags::A
54//!     }
55//! }
56//!
57//!
58//! // Implementing a GObject subclass requires two Rust types
59//! // working closely in tandem.
60//! mod imp {
61//!     use super::*;
62//!
63//!     // This is the struct containing all state carried with
64//!     // the new type. It will be stored in the GType's instance-private data.
65//!     // Generally this has to make use of interior mutability.
66//!     // If it implements the `Default` trait, then `Self::default()`
67//!     // will be called every time a new instance is created.
68//!     #[derive(Default)]
69//!     pub struct SimpleObject {
70//!         name: RefCell<Option<String>>,
71//!         animal: Cell<Animal>,
72//!         flags: Cell<MyFlags>,
73//!         variant: RefCell<Option<Variant>>,
74//!     }
75//!
76//!     // ObjectSubclass is the trait that defines the new type and
77//!     // contains all information needed by the GObject type system,
78//!     // including the new type's name, parent type, etc. The implementation
79//!     // struct is mapped to the type's instance-private data. This information is
80//!     // registered with the Glib runtime in the `register_type()` function.
81//!
82//!     // If you do not want to implement `Default`, you can provide
83//!     // a `new()` method.
84//!     #[glib::object_subclass]
85//!     impl ObjectSubclass for SimpleObject {
86//!         // This type name must be unique per process.
87//!         const NAME: &'static str = "SimpleObject";
88//!
89//!         // The wrapper around the raw GType instance struct
90//!         // (of type `ObjectSubclass::Instance`) providing memory management functionality
91//!         // and defining class relationships in terms of Rust types
92//!         type Type = super::SimpleObject;
93//!
94//!         // The parent type this one is inheriting from.
95//!         // Optional, if not specified it defaults to `glib::Object`
96//!         type ParentType = glib::Object;
97//!
98//!         // Interfaces this type implements.
99//!         // Optional, if not specified it defaults to `()`
100//!         type Interfaces = ();
101//!     }
102//!
103//!     // Trait used to override virtual methods of glib::Object. It requires
104//!     // that the associated `Type` implements the `IsA<Object>` trait declaring that
105//!     // it can be upcasted to glib::Object, ensuring that virtual methods defined by
106//!     // a class can only be overridden by its subclasses.
107//!     //
108//!     // The Rust bindings for GObject generate function wrappers proxying these
109//!     // methods of the private instance struct and initialize the subclass's vtable
110//!     // with those wrappers during object instantiation.
111//!     impl ObjectImpl for SimpleObject {
112//!         // Called once in the very beginning to list all properties of this class.
113//!         fn properties() -> &'static [glib::ParamSpec] {
114//!             use std::sync::OnceLock;
115//!             static PROPERTIES: OnceLock<Vec<glib::ParamSpec>> = OnceLock::new();
116//!             PROPERTIES.get_or_init(|| {
117//!                 vec![
118//!                     glib::ParamSpecString::builder("name")
119//!                         .build(),
120//!                     glib::ParamSpecEnum::builder::<Animal>("animal")
121//!                         .build(),
122//!                     glib::ParamSpecFlags::builder::<MyFlags>("flags")
123//!                         .build(),
124//!                     glib::ParamSpecVariant::builder("variant", glib::VariantTy::ANY)
125//!                         .build(),
126//!                 ]
127//!             })
128//!         }
129//!
130//!         // Called whenever a property is set on this instance. The id
131//!         // is the same as the index of the property in the PROPERTIES array.
132//!         fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
133//!             match pspec.name() {
134//!                 "name" => {
135//!                     let name = value
136//!                         .get()
137//!                         .expect("type conformity checked by `Object::set_property`");
138//!                     self.name.replace(name);
139//!                 },
140//!                 "animal" => {
141//!                     let animal = value
142//!                         .get()
143//!                         .expect("type conformity checked by `Object::set_property`");
144//!                     self.animal.replace(animal);
145//!                 },
146//!                 "flags" => {
147//!                     let flags = value
148//!                         .get()
149//!                         .expect("type conformity checked by `Object::set_property`");
150//!                     self.flags.replace(flags);
151//!                 },
152//!                 "variant" => {
153//!                     let variant = value
154//!                         .get()
155//!                         .expect("type conformity checked by `Object::set_property`");
156//!                     self.variant.replace(variant);
157//!                 },
158//!                 _ => unimplemented!(),
159//!             }
160//!         }
161//!
162//!         // Called whenever a property is retrieved from this instance. The id
163//!         // is the same as the index of the property in the PROPERTIES array.
164//!         fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
165//!             match pspec.name() {
166//!                 "name" => self.name.borrow().to_value(),
167//!                 "animal" => self.animal.get().to_value(),
168//!                 "flags" => self.flags.get().to_value(),
169//!                 "variant" => self.variant.borrow().to_value(),
170//!                 _ => unimplemented!(),
171//!             }
172//!         }
173//!
174//!         // Called right after construction of the instance.
175//!         fn constructed(&self) {
176//!             // Chain up to the parent type's implementation of this virtual
177//!             // method.
178//!             self.parent_constructed();
179//!
180//!             // And here we could do our own initialization.
181//!         }
182//!     }
183//! }
184//!
185//!
186//! // Create a type implementing:
187//! // - the basic traits to support Rust memory management functionality on the
188//! //   raw GType instance pointer defined above
189//! // - the core `IsA<Object>` trait declaring that `SimpleObject` is a subclass of `Object`
190//! // - any public methods on the subclass
191//!
192//! // This type provides the external interface to the `SimpleObject` class. It is
193//! // analogous to an opaque C pointer `SimpleObject*` that would be declared
194//! // in the public header file simpleobject.h if one were to define `SimpleObject`
195//! // in simpleobject.c. The methods defined here correspond to the functions
196//! // declared in simpleobject.h.
197//! //
198//! glib::wrapper! {
199//!     pub struct SimpleObject(ObjectSubclass<imp::SimpleObject>);
200//! }
201//!
202//! impl SimpleObject {
203//!     // Create an object instance of the new type.
204//!     pub fn new() -> Self {
205//!         glib::Object::new()
206//!     }
207//! }
208//!
209//! // This is the Rust analog of a C declaration like
210//! //
211//! // /* simpleobject.h */
212//! // #include <glib-object.h>
213//! // G_DECLARE_FINAL_TYPE (SimpleObject, simple_object, ...)
214//! // SimpleObject* simple_object_new();
215//! //
216//!
217//! // The Rust structs defined above produce roughly the following instance memory layout:
218//! //
219//! //       vtable populated with functions proxying imp::SimpleObject::ObjectImpl
220//! //       during class_init (see `unsafe impl<T: ObjectImpl>IsSubclassable<T> for Object`)
221//! //                                      |
222//! //                                     ffi::GObjectClass
223//! //                                      ^
224//! //                                      |
225//! //                                     ffi::GObject (first member of instance struct)
226//! //                                      |
227//! // |--private data (imp::SimpleObject)--|--instance struct (basic::InstanceStruct)--|
228//! //                                      ^
229//! //                                      |
230//! //                                      |
231//! //                                 SimpleObject
232//!
233//! pub fn main() {
234//!     let obj = SimpleObject::new();
235//!
236//!     // Get the name property and change its value.
237//!     // The `ObjectExt` trait provides implementations of
238//!     // `glib::Object`'s public methods on the (wrappers of)
239//!     // GObject subclasses. These invoke the corresponding GObject
240//!     // virtual methods across the FFI interface, which in turn proxy
241//!     // the `ObjectImpl` methods on the private instance struct above.
242//!     assert_eq!(obj.property::<Option<String>>("name"), None);
243//!     obj.set_property("name", "test");
244//!     assert_eq!(&obj.property::<String>("name"), "test");
245//!
246//!     assert_eq!(obj.property::<Animal>("animal"), Animal::Goat);
247//!     obj.set_property("animal", Animal::Cat);
248//!     assert_eq!(obj.property::<Animal>("animal"), Animal::Cat);
249//!
250//!     assert_eq!(obj.property::<MyFlags>("flags"), MyFlags::A);
251//!     obj.set_property("flags", MyFlags::B);
252//!     assert_eq!(obj.property::<MyFlags>("flags"), MyFlags::B);
253//! }
254//! ```
255//!
256//! # Example for registering a `glib::Object` subclass within a module
257//!
258//! The following code implements a subclass of `glib::Object` and registers it as
259//! a dynamic type.
260//!
261//! ```rust
262//! use glib::prelude::*;
263//! use glib::subclass::prelude::*;
264//!
265//! pub mod imp {
266//!     use super::*;
267//!
268//!     // SimpleModuleObject is a dynamic type.
269//!     #[derive(Default)]
270//!     pub struct SimpleModuleObject;
271//!
272//!     #[glib::object_subclass]
273//!     #[object_subclass_dynamic]
274//!     impl ObjectSubclass for SimpleModuleObject {
275//!         const NAME: &'static str = "SimpleModuleObject";
276//!         type Type = super::SimpleModuleObject;
277//!     }
278//!
279//!     impl ObjectImpl for SimpleModuleObject {}
280//!
281//!     // SimpleTypeModule is the type module within the object subclass is registered as a dynamic type.
282//!     #[derive(Default)]
283//!     pub struct SimpleTypeModule;
284//!
285//!     #[glib::object_subclass]
286//!     impl ObjectSubclass for SimpleTypeModule {
287//!         const NAME: &'static str = "SimpleTypeModule";
288//!         type Type = super::SimpleTypeModule;
289//!         type ParentType = glib::TypeModule;
290//!         type Interfaces = (glib::TypePlugin,);
291//!     }
292//!
293//!     impl ObjectImpl for SimpleTypeModule {}
294//!
295//!     impl TypeModuleImpl for SimpleTypeModule {
296//!         /// Loads the module and registers the object subclass as a dynamic type.
297//!         fn load(&self) -> bool {
298//!             SimpleModuleObject::on_implementation_load(self.obj().upcast_ref::<glib::TypeModule>())
299//!         }
300//!
301//!         /// Unloads the module.
302//!         fn unload(&self) {
303//!             SimpleModuleObject::on_implementation_unload(self.obj().upcast_ref::<glib::TypeModule>());
304//!         }
305//!     }
306//!
307//!     impl TypePluginImpl for SimpleTypeModule {}
308//! }
309//!
310//! // Optionally, defines a wrapper type to make SimpleModuleObject more ergonomic to use from Rust.
311//! glib::wrapper! {
312//!     pub struct SimpleModuleObject(ObjectSubclass<imp::SimpleModuleObject>);
313//! }
314//!
315//! // Optionally, defines a wrapper type to make SimpleTypeModule more ergonomic to use from Rust.
316//! glib::wrapper! {
317//!     pub struct SimpleTypeModule(ObjectSubclass<imp::SimpleTypeModule>)
318//!     @extends glib::TypeModule, @implements glib::TypePlugin;
319//! }
320//!
321//! impl SimpleTypeModule {
322//!     // Creates an object instance of the new type.
323//!     pub fn new() -> Self {
324//!         glib::Object::new()
325//!     }
326//! }
327//!
328//! pub fn main() {
329//!     let simple_type_module = SimpleTypeModule::new();
330//!     // at this step, SimpleTypeModule has not been loaded therefore
331//!     // SimpleModuleObject must not be registered yet.
332//!     let simple_module_object_type = imp::SimpleModuleObject::type_();
333//!     assert!(!simple_module_object_type.is_valid());
334//!
335//!     // simulates the GLib type system to load the module.
336//!     TypeModuleExt::use_(&simple_type_module);
337//!
338//!     // at this step, SimpleModuleObject must have been registered.
339//!     let simple_module_object_type = imp::SimpleModuleObject::type_();
340//!     assert!(simple_module_object_type.is_valid());
341//! }
342//! ```
343//!
344//! # Example for registering a `glib::Object` subclass within a plugin
345//!
346//! The following code implements a subclass of `glib::Object` and registers it as
347//! a dynamic type.
348//!
349//! ```rust
350//! use glib::prelude::*;
351//! use glib::subclass::prelude::*;
352//!
353//! pub mod imp {
354//!     use super::*;
355//!
356//!     // SimplePluginObject is a dynamic type.
357//!     #[derive(Default)]
358//!     pub struct SimplePluginObject;
359//!
360//!     #[glib::object_subclass]
361//!     #[object_subclass_dynamic(plugin_type = super::SimpleTypePlugin)]
362//!     impl ObjectSubclass for SimplePluginObject {
363//!         const NAME: &'static str = "SimplePluginObject";
364//!         type Type = super::SimplePluginObject;
365//!     }
366//!
367//!     impl ObjectImpl for SimplePluginObject {}
368//!
369//!     // SimpleTypePlugin is the type plugin within the object subclass is registered as a dynamic type.
370//!     #[derive(Default)]
371//!     pub struct SimpleTypePlugin {
372//!         type_info: std::cell::Cell<Option<glib::TypeInfo>>
373//!     }
374//!
375//!     #[glib::object_subclass]
376//!     impl ObjectSubclass for SimpleTypePlugin {
377//!         const NAME: &'static str = "SimpleTypePlugin";
378//!         type Type = super::SimpleTypePlugin;
379//!         type Interfaces = (glib::TypePlugin,);
380//!     }
381//!
382//!     impl ObjectImpl for SimpleTypePlugin {}
383//!
384//!     impl TypePluginImpl for SimpleTypePlugin {
385//!         /// Uses the plugin and registers the object subclass as a dynamic type.
386//!         fn use_plugin(&self) {
387//!             SimplePluginObject::on_implementation_load(self.obj().as_ref());
388//!         }
389//!
390//!         /// Unuses the plugin.
391//!         fn unuse_plugin(&self) {
392//!             SimplePluginObject::on_implementation_unload(self.obj().as_ref());
393//!         }
394//!
395//!         /// Returns type information about the object subclass registered as a dynamic type.
396//!         fn complete_type_info(&self, _type_: glib::Type) -> (glib::TypeInfo, glib::TypeValueTable) {
397//!             assert!(self.type_info.get().is_some());
398//!             // returns type info.
399//!             (self.type_info.get().unwrap(), glib::TypeValueTable::default())
400//!         }
401//!     }
402//!
403//!     impl TypePluginRegisterImpl for SimpleTypePlugin {
404//!         fn register_dynamic_type(&self, parent_type: glib::Type, type_name: &str, type_info: &glib::TypeInfo, flags: glib::TypeFlags) -> glib::Type {
405//!             let type_ = glib::Type::from_name(type_name).unwrap_or_else(|| {
406//!                 glib::Type::register_dynamic(parent_type, type_name, self.obj().upcast_ref::<glib::TypePlugin>(), flags)
407//!             });
408//!             if type_.is_valid() {
409//!                 // saves type info.
410//!                 self.type_info.set(Some(*type_info));
411//!             }
412//!             type_
413//!         }
414//!     }
415//! }
416//!
417//! // Optionally, defines a wrapper type to make SimplePluginObject more ergonomic to use from Rust.
418//! glib::wrapper! {
419//!     pub struct SimplePluginObject(ObjectSubclass<imp::SimplePluginObject>);
420//! }
421//!
422//! // Optionally, defines a wrapper type to make SimpleTypePlugin more ergonomic to use from Rust.
423//! glib::wrapper! {
424//!     pub struct SimpleTypePlugin(ObjectSubclass<imp::SimpleTypePlugin>)
425//!     @implements glib::TypePlugin;
426//! }
427//!
428//! impl SimpleTypePlugin {
429//!     // Creates an object instance of the new type.
430//!     pub fn new() -> Self {
431//!         glib::Object::new()
432//!     }
433//! }
434//!
435//! pub fn main() {
436//!     let simple_type_plugin = SimpleTypePlugin::new();
437//!     // at this step, SimpleTypePlugin has not been used therefore
438//!     // SimplePluginObject must not be registered yet.
439//!     let simple_plugin_object_type = imp::SimplePluginObject::type_();
440//!     assert!(!simple_plugin_object_type.is_valid());
441//!
442//!     // simulates the GLib type system to use the plugin.
443//!     TypePluginExt::use_(&simple_type_plugin);
444//!
445//!     // at this step, SimplePluginObject must have been registered.
446//!     let simple_plugin_object_type = imp::SimplePluginObject::type_();
447//!     assert!(simple_plugin_object_type.is_valid());
448//! }
449//! ```
450//!
451//!//! # Example for registering a boxed type for a Rust struct
452//!
453//! The following code boxed type for a tuple struct around `String` and uses it in combination
454//! with `glib::Value`.
455//!
456//! ```rust
457//! use glib::prelude::*;
458//! use glib::subclass;
459//! use glib::subclass::prelude::*;
460//!
461//! #[derive(Clone, Debug, PartialEq, Eq, glib::Boxed)]
462//! #[boxed_type(name = "MyBoxed")]
463//! struct MyBoxed(String);
464//!
465//! pub fn main() {
466//!     assert!(MyBoxed::static_type().is_valid());
467//!
468//!     let b = MyBoxed(String::from("abc"));
469//!     let v = b.to_value();
470//!     let b2 = v.get::<&MyBoxed>().unwrap();
471//!     assert_eq!(&b, b2);
472//! }
473//! ```
474
475pub mod basic;
476#[macro_use]
477pub mod types;
478
479#[macro_use]
480pub mod interface;
481
482#[macro_use]
483pub mod object;
484
485#[macro_use]
486pub mod boxed;
487
488pub mod shared;
489
490pub mod signal;
491
492mod object_impl_ref;
493pub use object_impl_ref::{ObjectImplRef, ObjectImplWeakRef};
494
495pub mod type_module;
496
497pub mod type_plugin;
498
499pub mod prelude {
500    // rustdoc-stripper-ignore-next
501    //! Prelude that re-exports all important traits from this crate.
502    pub use super::{
503        boxed::BoxedType,
504        interface::{ObjectInterface, ObjectInterfaceExt, ObjectInterfaceType},
505        object::{DerivedObjectProperties, ObjectClassSubclassExt, ObjectImpl, ObjectImplExt},
506        shared::{RefCounted, SharedType},
507        type_module::{TypeModuleImpl, TypeModuleImplExt},
508        type_plugin::{TypePluginImpl, TypePluginImplExt, TypePluginRegisterImpl},
509        types::{
510            ClassStruct, InstanceStruct, InstanceStructExt, InterfaceStruct, IsImplementable,
511            IsSubclassable, IsSubclassableExt, ObjectSubclass, ObjectSubclassExt,
512            ObjectSubclassIsExt, ObjectSubclassType,
513        },
514    };
515}
516
517pub use self::{
518    boxed::register_boxed_type,
519    interface::{register_dynamic_interface, register_interface},
520    signal::{
521        Signal, SignalClassHandlerToken, SignalId, SignalInvocationHint, SignalQuery, SignalType,
522    },
523    types::{InitializingObject, InitializingType, TypeData, register_dynamic_type, register_type},
524};