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