1 // Copyright 2017-2018, The Gtk-rs Project Developers.
2 // See the COPYRIGHT file at the top-level directory of this distribution.
3 // Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>
4 
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 //! #[macro_use]
14 //! extern crate glib;
15 //! use glib::prelude::*;
16 //! use glib::subclass;
17 //! use glib::subclass::prelude::*;
18 //!
19 //! use std::cell::RefCell;
20 //!
21 //! // Static array for defining the properties of the new type.
22 //! static PROPERTIES: [subclass::Property; 1] = [subclass::Property("name", |name| {
23 //!     glib::ParamSpec::string(
24 //!         name,
25 //!         "Name",
26 //!         "Name of this object",
27 //!         None,
28 //!         glib::ParamFlags::READWRITE,
29 //!     )
30 //! })];
31 //!
32 //! // This is the struct containing all state carried with
33 //! // the new type. Generally this has to make use of
34 //! // interior mutability.
35 //! pub struct SimpleObject {
36 //!     name: RefCell<Option<String>>,
37 //! }
38 //!
39 //! // ObjectSubclass is the trait that defines the new type and
40 //! // contains all information needed by the GObject type system,
41 //! // including the new type's name, parent type, etc.
42 //! impl ObjectSubclass for SimpleObject {
43 //!     // This type name must be unique per process.
44 //!     const NAME: &'static str = "SimpleObject";
45 //!
46 //!     // The parent type this one is inheriting from.
47 //!     type ParentType = glib::Object;
48 //!
49 //!     // The C/FFI instance and class structs. The simple ones
50 //!     // are enough in most cases and more is only needed to
51 //!     // expose public instance fields to C APIs or to provide
52 //!     // new virtual methods for subclasses of this type.
53 //!     type Instance = subclass::simple::InstanceStruct<Self>;
54 //!     type Class = subclass::simple::ClassStruct<Self>;
55 //!
56 //!     // This macro defines some boilerplate.
57 //!     glib_object_subclass!();
58 //!
59 //!     // Called right before the first time an instance of the new
60 //!     // type is created. Here class specific settings can be performed,
61 //!     // including installation of properties and registration of signals
62 //!     // for the new type.
63 //!     fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) {
64 //!         klass.install_properties(&PROPERTIES);
65 //!     }
66 //!
67 //!     // Called every time a new instance is created. This should return
68 //!     // a new instance of our type with its basic values.
69 //!     fn new() -> Self {
70 //!         Self {
71 //!             name: RefCell::new(None),
72 //!         }
73 //!     }
74 //! }
75 //!
76 //! // Trait that is used to override virtual methods of glib::Object.
77 //! impl ObjectImpl for SimpleObject {
78 //!     // This macro defines some boilerplate.
79 //!     glib_object_impl!();
80 //!
81 //!     // Called whenever a property is set on this instance. The id
82 //!     // is the same as the index of the property in the PROPERTIES array.
83 //!     fn set_property(&self, _obj: &glib::Object, id: usize, value: &glib::Value) {
84 //!         let prop = &PROPERTIES[id];
85 //!
86 //!         match *prop {
87 //!             subclass::Property("name", ..) => {
88 //!                 let name = value.get();
89 //!                 self.name.replace(name);
90 //!             }
91 //!             _ => unimplemented!(),
92 //!         }
93 //!     }
94 //!
95 //!     // Called whenever a property is retrieved from this instance. The id
96 //!     // is the same as the index of the property in the PROPERTIES array.
97 //!     fn get_property(&self, _obj: &glib::Object, id: usize) -> Result<glib::Value, ()> {
98 //!         let prop = &PROPERTIES[id];
99 //!
100 //!         match *prop {
101 //!             subclass::Property("name", ..) => Ok(self.name.borrow().to_value()),
102 //!             _ => unimplemented!(),
103 //!         }
104 //!     }
105 //!
106 //!     // Called right after construction of the instance.
107 //!     fn constructed(&self, obj: &glib::Object) {
108 //!         // Chain up to the parent type's implementation of this virtual
109 //!         // method.
110 //!         self.parent_constructed(obj);
111 //!
112 //!         // And here we could do our own initialization.
113 //!     }
114 //! }
115 //!
116 //! pub fn main() {
117 //!     // Create an object instance of the new type.
118 //!     let obj = glib::Object::new(SimpleObject::get_type(), &[]).unwrap();
119 //!
120 //!     // Get the name property and change its value.
121 //!     assert_eq!(obj.get_property("name").unwrap().get::<&str>(), None);
122 //!     obj.set_property("name", &"test").unwrap();
123 //!     assert_eq!(
124 //!         obj.get_property("name").unwrap().get::<&str>(),
125 //!         Some("test")
126 //!     );
127 //! }
128 //! ```
129 //!
130 //! # Example for registering a boxed type for a Rust struct
131 //!
132 //! The following code boxed type for a tuple struct around `String` and uses it in combination
133 //! with `glib::Value`.
134 //!
135 //! ```rust
136 //! #[macro_use]
137 //! extern crate glib;
138 //! use glib::prelude::*;
139 //! use glib::subclass;
140 //! use glib::subclass::prelude::*;
141 //!
142 //! #[derive(Clone, Debug, PartialEq, Eq)]
143 //! struct MyBoxed(String);
144 //!
145 //! impl BoxedType for MyBoxed {
146 //!     // This type name must be unique per process.
147 //!     const NAME: &'static str = "MyBoxed";
148 //!
149 //!     // This macro defines a
150 //!     //   fn get_type() -> glib::Type
151 //!     // function
152 //!     glib_boxed_type!();
153 //! }
154 //!
155 //! // This macro derives some traits on the struct
156 //! glib_boxed_derive_traits!(MyBoxed);
157 //!
158 //! pub fn main() {
159 //!     assert_ne!(glib::Type::Invalid, MyBoxed::get_type());
160 //!
161 //!     let b = MyBoxed(String::from("abc"));
162 //!     let v = b.to_value();
163 //!     let b2 = v.get::<&MyBoxed>().unwrap();
164 //!     assert_eq!(&b, b2);
165 //! }
166 //! ```
167 
168 #[macro_use]
169 #[doc(hidden)]
170 pub mod guard;
171 
172 pub mod simple;
173 #[macro_use]
174 pub mod types;
175 
176 #[macro_use]
177 pub mod interface;
178 
179 #[macro_use]
180 pub mod object;
181 
182 #[macro_use]
183 pub mod boxed;
184 
185 pub mod prelude {
186     //! Prelude that re-exports all important traits from this crate.
187     pub use super::boxed::BoxedType;
188     pub use super::interface::{ObjectInterface, ObjectInterfaceExt};
189     pub use super::object::{ObjectClassSubclassExt, ObjectImpl, ObjectImplExt};
190     pub use super::types::{
191         ClassStruct, InstanceStruct, IsImplementable, IsSubclassable, ObjectSubclass,
192     };
193 }
194 
195 pub use self::boxed::register_boxed_type;
196 pub use self::interface::register_interface;
197 pub use self::object::Property;
198 pub use self::types::{
199     register_type, InitializingType, SignalClassHandlerToken, SignalInvocationHint, TypeData,
200 };
201