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