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//! mod imp {
58//!     use super::*;
59//!
60//!     // This is the struct containing all state carried with
61//!     // the new type. Generally this has to make use of
62//!     // interior mutability.
63//!     // If it implements the `Default` trait, then `Self::default()`
64//!     // will be called every time a new instance is created.
65//!     #[derive(Default)]
66//!     pub struct SimpleObject {
67//!         name: RefCell<Option<String>>,
68//!         animal: Cell<Animal>,
69//!         flags: Cell<MyFlags>,
70//!         variant: RefCell<Option<Variant>>,
71//!     }
72//!
73//!     // ObjectSubclass is the trait that defines the new type and
74//!     // contains all information needed by the GObject type system,
75//!     // including the new type's name, parent type, etc.
76//!     // If you do not want to implement `Default`, you can provide
77//!     // a `new()` method.
78//!     #[glib::object_subclass]
79//!     impl ObjectSubclass for SimpleObject {
80//!         // This type name must be unique per process.
81//!         const NAME: &'static str = "SimpleObject";
82//!
83//!         type Type = super::SimpleObject;
84//!
85//!         // The parent type this one is inheriting from.
86//!         // Optional, if not specified it defaults to `glib::Object`
87//!         type ParentType = glib::Object;
88//!
89//!         // Interfaces this type implements.
90//!         // Optional, if not specified it defaults to `()`
91//!         type Interfaces = ();
92//!     }
93//!
94//!     // Trait that is used to override virtual methods of glib::Object.
95//!     impl ObjectImpl for SimpleObject {
96//!         // Called once in the very beginning to list all properties of this class.
97//!         fn properties() -> &'static [glib::ParamSpec] {
98//!             use std::sync::OnceLock;
99//!             static PROPERTIES: OnceLock<Vec<glib::ParamSpec>> = OnceLock::new();
100//!             PROPERTIES.get_or_init(|| {
101//!                 vec![
102//!                     glib::ParamSpecString::builder("name")
103//!                         .build(),
104//!                     glib::ParamSpecEnum::builder::<Animal>("animal")
105//!                         .build(),
106//!                     glib::ParamSpecFlags::builder::<MyFlags>("flags")
107//!                         .build(),
108//!                     glib::ParamSpecVariant::builder("variant", glib::VariantTy::ANY)
109//!                         .build(),
110//!                 ]
111//!             })
112//!         }
113//!
114//!         // Called whenever a property is set on this instance. The id
115//!         // is the same as the index of the property in the PROPERTIES array.
116//!         fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
117//!             match pspec.name() {
118//!                 "name" => {
119//!                     let name = value
120//!                         .get()
121//!                         .expect("type conformity checked by `Object::set_property`");
122//!                     self.name.replace(name);
123//!                 },
124//!                 "animal" => {
125//!                     let animal = value
126//!                         .get()
127//!                         .expect("type conformity checked by `Object::set_property`");
128//!                     self.animal.replace(animal);
129//!                 },
130//!                 "flags" => {
131//!                     let flags = value
132//!                         .get()
133//!                         .expect("type conformity checked by `Object::set_property`");
134//!                     self.flags.replace(flags);
135//!                 },
136//!                 "variant" => {
137//!                     let variant = value
138//!                         .get()
139//!                         .expect("type conformity checked by `Object::set_property`");
140//!                     self.variant.replace(variant);
141//!                 },
142//!                 _ => unimplemented!(),
143//!             }
144//!         }
145//!
146//!         // Called whenever a property is retrieved from this instance. The id
147//!         // is the same as the index of the property in the PROPERTIES array.
148//!         fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
149//!             match pspec.name() {
150//!                 "name" => self.name.borrow().to_value(),
151//!                 "animal" => self.animal.get().to_value(),
152//!                 "flags" => self.flags.get().to_value(),
153//!                 "variant" => self.variant.borrow().to_value(),
154//!                 _ => unimplemented!(),
155//!             }
156//!         }
157//!
158//!         // Called right after construction of the instance.
159//!         fn constructed(&self) {
160//!             // Chain up to the parent type's implementation of this virtual
161//!             // method.
162//!             self.parent_constructed();
163//!
164//!             // And here we could do our own initialization.
165//!         }
166//!     }
167//! }
168//!
169//! // Optionally, define a wrapper type to make it more ergonomic to use from Rust
170//! glib::wrapper! {
171//!     pub struct SimpleObject(ObjectSubclass<imp::SimpleObject>);
172//! }
173//!
174//! impl SimpleObject {
175//!     // Create an object instance of the new type.
176//!     pub fn new() -> Self {
177//!         glib::Object::new()
178//!     }
179//! }
180//!
181//! pub fn main() {
182//!     let obj = SimpleObject::new();
183//!
184//!     // Get the name property and change its value.
185//!     assert_eq!(obj.property::<Option<String>>("name"), None);
186//!     obj.set_property("name", "test");
187//!     assert_eq!(&obj.property::<String>("name"), "test");
188//!
189//!     assert_eq!(obj.property::<Animal>("animal"), Animal::Goat);
190//!     obj.set_property("animal", Animal::Cat);
191//!     assert_eq!(obj.property::<Animal>("animal"), Animal::Cat);
192//!
193//!     assert_eq!(obj.property::<MyFlags>("flags"), MyFlags::A);
194//!     obj.set_property("flags", MyFlags::B);
195//!     assert_eq!(obj.property::<MyFlags>("flags"), MyFlags::B);
196//! }
197//! ```
198//!
199//! # Example for registering a `glib::Object` subclass within a module
200//!
201//! The following code implements a subclass of `glib::Object` and registers it as
202//! a dynamic type.
203//!
204//! ```rust
205//! use glib::prelude::*;
206//! use glib::subclass::prelude::*;
207//!
208//! pub mod imp {
209//!     use super::*;
210//!
211//!     // SimpleModuleObject is a dynamic type.
212//!     #[derive(Default)]
213//!     pub struct SimpleModuleObject;
214//!
215//!     #[glib::object_subclass]
216//!     #[object_subclass_dynamic]
217//!     impl ObjectSubclass for SimpleModuleObject {
218//!         const NAME: &'static str = "SimpleModuleObject";
219//!         type Type = super::SimpleModuleObject;
220//!     }
221//!
222//!     impl ObjectImpl for SimpleModuleObject {}
223//!
224//!     // SimpleTypeModule is the type module within the object subclass is registered as a dynamic type.
225//!     #[derive(Default)]
226//!     pub struct SimpleTypeModule;
227//!
228//!     #[glib::object_subclass]
229//!     impl ObjectSubclass for SimpleTypeModule {
230//!         const NAME: &'static str = "SimpleTypeModule";
231//!         type Type = super::SimpleTypeModule;
232//!         type ParentType = glib::TypeModule;
233//!         type Interfaces = (glib::TypePlugin,);
234//!     }
235//!
236//!     impl ObjectImpl for SimpleTypeModule {}
237//!
238//!     impl TypeModuleImpl for SimpleTypeModule {
239//!         /// Loads the module and registers the object subclass as a dynamic type.
240//!         fn load(&self) -> bool {
241//!             SimpleModuleObject::on_implementation_load(self.obj().upcast_ref::<glib::TypeModule>())
242//!         }
243//!
244//!         /// Unloads the module.
245//!         fn unload(&self) {
246//!             SimpleModuleObject::on_implementation_unload(self.obj().upcast_ref::<glib::TypeModule>());
247//!         }
248//!     }
249//!
250//!     impl TypePluginImpl for SimpleTypeModule {}
251//! }
252//!
253//! // Optionally, defines a wrapper type to make SimpleModuleObject more ergonomic to use from Rust.
254//! glib::wrapper! {
255//!     pub struct SimpleModuleObject(ObjectSubclass<imp::SimpleModuleObject>);
256//! }
257//!
258//! // Optionally, defines a wrapper type to make SimpleTypeModule more ergonomic to use from Rust.
259//! glib::wrapper! {
260//!     pub struct SimpleTypeModule(ObjectSubclass<imp::SimpleTypeModule>)
261//!     @extends glib::TypeModule, @implements glib::TypePlugin;
262//! }
263//!
264//! impl SimpleTypeModule {
265//!     // Creates an object instance of the new type.
266//!     pub fn new() -> Self {
267//!         glib::Object::new()
268//!     }
269//! }
270//!
271//! pub fn main() {
272//!     let simple_type_module = SimpleTypeModule::new();
273//!     // at this step, SimpleTypeModule has not been loaded therefore
274//!     // SimpleModuleObject must not be registered yet.
275//!     let simple_module_object_type = imp::SimpleModuleObject::type_();
276//!     assert!(!simple_module_object_type.is_valid());
277//!
278//!     // simulates the GLib type system to load the module.
279//!     TypeModuleExt::use_(&simple_type_module);
280//!
281//!     // at this step, SimpleModuleObject must have been registered.
282//!     let simple_module_object_type = imp::SimpleModuleObject::type_();
283//!     assert!(simple_module_object_type.is_valid());
284//! }
285//! ```
286//!
287//! # Example for registering a `glib::Object` subclass within a plugin
288//!
289//! The following code implements a subclass of `glib::Object` and registers it as
290//! a dynamic type.
291//!
292//! ```rust
293//! use glib::prelude::*;
294//! use glib::subclass::prelude::*;
295//!
296//! pub mod imp {
297//!     use super::*;
298//!
299//!     // SimplePluginObject is a dynamic type.
300//!     #[derive(Default)]
301//!     pub struct SimplePluginObject;
302//!
303//!     #[glib::object_subclass]
304//!     #[object_subclass_dynamic(plugin_type = super::SimpleTypePlugin)]
305//!     impl ObjectSubclass for SimplePluginObject {
306//!         const NAME: &'static str = "SimplePluginObject";
307//!         type Type = super::SimplePluginObject;
308//!     }
309//!
310//!     impl ObjectImpl for SimplePluginObject {}
311//!
312//!     // SimpleTypePlugin is the type plugin within the object subclass is registered as a dynamic type.
313//!     #[derive(Default)]
314//!     pub struct SimpleTypePlugin {
315//!         type_info: std::cell::Cell<Option<glib::TypeInfo>>
316//!     }
317//!
318//!     #[glib::object_subclass]
319//!     impl ObjectSubclass for SimpleTypePlugin {
320//!         const NAME: &'static str = "SimpleTypePlugin";
321//!         type Type = super::SimpleTypePlugin;
322//!         type Interfaces = (glib::TypePlugin,);
323//!     }
324//!
325//!     impl ObjectImpl for SimpleTypePlugin {}
326//!
327//!     impl TypePluginImpl for SimpleTypePlugin {
328//!         /// Uses the plugin and registers the object subclass as a dynamic type.
329//!         fn use_plugin(&self) {
330//!             SimplePluginObject::on_implementation_load(self.obj().as_ref());
331//!         }
332//!
333//!         /// Unuses the plugin.
334//!         fn unuse_plugin(&self) {
335//!             SimplePluginObject::on_implementation_unload(self.obj().as_ref());
336//!         }
337//!
338//!         /// Returns type information about the object subclass registered as a dynamic type.
339//!         fn complete_type_info(&self, _type_: glib::Type) -> (glib::TypeInfo, glib::TypeValueTable) {
340//!             assert!(self.type_info.get().is_some());
341//!             // returns type info.
342//!             (self.type_info.get().unwrap(), glib::TypeValueTable::default())
343//!         }
344//!     }
345//!
346//!     impl TypePluginRegisterImpl for SimpleTypePlugin {
347//!         fn register_dynamic_type(&self, parent_type: glib::Type, type_name: &str, type_info: &glib::TypeInfo, flags: glib::TypeFlags) -> glib::Type {
348//!             let type_ = glib::Type::from_name(type_name).unwrap_or_else(|| {
349//!                 glib::Type::register_dynamic(parent_type, type_name, self.obj().upcast_ref::<glib::TypePlugin>(), flags)
350//!             });
351//!             if type_.is_valid() {
352//!                 // saves type info.
353//!                 self.type_info.set(Some(*type_info));
354//!             }
355//!             type_
356//!         }
357//!     }
358//! }
359//!
360//! // Optionally, defines a wrapper type to make SimplePluginObject more ergonomic to use from Rust.
361//! glib::wrapper! {
362//!     pub struct SimplePluginObject(ObjectSubclass<imp::SimplePluginObject>);
363//! }
364//!
365//! // Optionally, defines a wrapper type to make SimpleTypePlugin more ergonomic to use from Rust.
366//! glib::wrapper! {
367//!     pub struct SimpleTypePlugin(ObjectSubclass<imp::SimpleTypePlugin>)
368//!     @implements glib::TypePlugin;
369//! }
370//!
371//! impl SimpleTypePlugin {
372//!     // Creates an object instance of the new type.
373//!     pub fn new() -> Self {
374//!         glib::Object::new()
375//!     }
376//! }
377//!
378//! pub fn main() {
379//!     let simple_type_plugin = SimpleTypePlugin::new();
380//!     // at this step, SimpleTypePlugin has not been used therefore
381//!     // SimplePluginObject must not be registered yet.
382//!     let simple_plugin_object_type = imp::SimplePluginObject::type_();
383//!     assert!(!simple_plugin_object_type.is_valid());
384//!
385//!     // simulates the GLib type system to use the plugin.
386//!     TypePluginExt::use_(&simple_type_plugin);
387//!
388//!     // at this step, SimplePluginObject must have been registered.
389//!     let simple_plugin_object_type = imp::SimplePluginObject::type_();
390//!     assert!(simple_plugin_object_type.is_valid());
391//! }
392//! ```
393//!
394//!//! # Example for registering a boxed type for a Rust struct
395//!
396//! The following code boxed type for a tuple struct around `String` and uses it in combination
397//! with `glib::Value`.
398//!
399//! ```rust
400//! use glib::prelude::*;
401//! use glib::subclass;
402//! use glib::subclass::prelude::*;
403//!
404//! #[derive(Clone, Debug, PartialEq, Eq, glib::Boxed)]
405//! #[boxed_type(name = "MyBoxed")]
406//! struct MyBoxed(String);
407//!
408//! pub fn main() {
409//!     assert!(MyBoxed::static_type().is_valid());
410//!
411//!     let b = MyBoxed(String::from("abc"));
412//!     let v = b.to_value();
413//!     let b2 = v.get::<&MyBoxed>().unwrap();
414//!     assert_eq!(&b, b2);
415//! }
416//! ```
417
418pub mod basic;
419#[macro_use]
420pub mod types;
421
422#[macro_use]
423pub mod interface;
424
425#[macro_use]
426pub mod object;
427
428#[macro_use]
429pub mod boxed;
430
431pub mod shared;
432
433pub mod signal;
434
435mod object_impl_ref;
436pub use object_impl_ref::{ObjectImplRef, ObjectImplWeakRef};
437
438pub mod type_module;
439
440pub mod type_plugin;
441
442pub mod prelude {
443    // rustdoc-stripper-ignore-next
444    //! Prelude that re-exports all important traits from this crate.
445    pub use super::{
446        boxed::BoxedType,
447        interface::{ObjectInterface, ObjectInterfaceExt, ObjectInterfaceType},
448        object::{DerivedObjectProperties, ObjectClassSubclassExt, ObjectImpl, ObjectImplExt},
449        shared::{RefCounted, SharedType},
450        type_module::{TypeModuleImpl, TypeModuleImplExt},
451        type_plugin::{TypePluginImpl, TypePluginImplExt, TypePluginRegisterImpl},
452        types::{
453            ClassStruct, InstanceStruct, InstanceStructExt, InterfaceStruct, IsImplementable,
454            IsSubclassable, IsSubclassableExt, ObjectSubclass, ObjectSubclassExt,
455            ObjectSubclassIsExt, ObjectSubclassType,
456        },
457    };
458}
459
460pub use self::{
461    boxed::register_boxed_type,
462    interface::{register_dynamic_interface, register_interface},
463    signal::{
464        Signal, SignalClassHandlerToken, SignalId, SignalInvocationHint, SignalQuery, SignalType,
465    },
466    types::{register_dynamic_type, register_type, InitializingObject, InitializingType, TypeData},
467};