Skip to content

Commit f8dc3b1

Browse files
ranfdevbilelmoussaoui
authored andcommitted
glib: Add a Properties derive macro
The macro would simplify the creation of properties and generate traits that can be used in ObjectImpl for now until further integration with signals & the rest of GObject creation is figured out.
1 parent f3374ed commit f8dc3b1

File tree

16 files changed

+1661
-7
lines changed

16 files changed

+1661
-7
lines changed

glib-macros/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ proc-macro = true
2626
[dev-dependencies]
2727
glib = { path = "../glib" }
2828
trybuild2 = "1.0"
29+
once_cell = "1.9.0"

glib-macros/src/boxed_derive.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,5 +243,15 @@ pub fn impl_boxed(input: &syn::DeriveInput) -> TokenStream {
243243
::std::boxed::Box::into_raw(::std::boxed::Box::new(self.clone())) as *mut _
244244
}
245245
}
246+
247+
impl #crate_ident::HasParamSpec for #name {
248+
type ParamSpec = #crate_ident::ParamSpecBoxed;
249+
type SetValue = Self;
250+
type BuilderFn = fn(&str) -> #crate_ident::ParamSpecBoxedBuilder<Self>;
251+
252+
fn param_spec_builder() -> Self::BuilderFn {
253+
|name| Self::ParamSpec::builder(name)
254+
}
255+
}
246256
}
247257
}

glib-macros/src/enum_derive.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,5 +189,15 @@ pub fn impl_enum(input: &syn::DeriveInput) -> TokenStream {
189189
}
190190
}
191191
}
192+
193+
impl #crate_ident::HasParamSpec for #name {
194+
type ParamSpec = #crate_ident::ParamSpecEnum;
195+
type SetValue = Self;
196+
type BuilderFn = fn(&str, Self) -> #crate_ident::ParamSpecEnumBuilder<Self>;
197+
198+
fn param_spec_builder() -> Self::BuilderFn {
199+
|name, default_value| Self::ParamSpec::builder_with_default(name, default_value)
200+
}
201+
}
192202
}
193203
}

glib-macros/src/lib.rs

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ mod error_domain_derive;
99
mod flags_attribute;
1010
mod object_interface_attribute;
1111
mod object_subclass_attribute;
12+
mod properties;
1213
mod shared_boxed_derive;
1314
mod variant_derive;
1415

@@ -819,7 +820,6 @@ pub fn variant_derive(input: TokenStream) -> TokenStream {
819820
let input = parse_macro_input!(input as DeriveInput);
820821
variant_derive::impl_variant(input)
821822
}
822-
823823
#[proc_macro]
824824
pub fn cstr_bytes(item: TokenStream) -> TokenStream {
825825
syn::parse::Parser::parse2(
@@ -836,3 +836,92 @@ pub fn cstr_bytes(item: TokenStream) -> TokenStream {
836836
)
837837
.unwrap_or_else(|e| e.into_compile_error().into())
838838
}
839+
840+
/// # Example
841+
/// ```
842+
/// use std::cell::RefCell;
843+
/// use std::marker::PhantomData;
844+
/// use std::sync::Mutex;
845+
/// use glib::prelude::*;
846+
/// use glib::subclass::prelude::*;
847+
/// use glib_macros::Properties;
848+
///
849+
/// #[derive(Default, Clone)]
850+
/// struct Author {
851+
/// name: String,
852+
/// nick: String,
853+
/// }
854+
///
855+
/// pub mod imp {
856+
/// use glib::{ParamSpec, Value};
857+
/// use std::rc::Rc;
858+
///
859+
/// use super::*;
860+
///
861+
/// #[derive(Properties, Default)]
862+
/// #[properties(wrapper_type = super::Foo)]
863+
/// pub struct Foo {
864+
/// #[property(get, set = Self::set_fizz)]
865+
/// fizz: RefCell<String>,
866+
/// #[property(name = "author-name", get, set, type = String, member = name)]
867+
/// #[property(name = "author-nick", get, set, type = String, member = nick)]
868+
/// author: RefCell<Author>,
869+
/// #[property(get, set, user_1, user_2, lax_validation)]
870+
/// custom_flags: RefCell<String>,
871+
/// #[property(get, set, builder().minimum(0).maximum(5))]
872+
/// numeric_builder: RefCell<u32>,
873+
/// #[property(get, set, builder('c'))]
874+
/// builder_with_required_param: RefCell<char>,
875+
/// #[property(get, set)]
876+
/// optional: RefCell<Option<String>>,
877+
/// #[property(get, set)]
878+
/// smart_pointer: Rc<RefCell<String>>,
879+
/// }
880+
///
881+
/// impl ObjectImpl for Foo {
882+
/// fn properties() -> &'static [ParamSpec] {
883+
/// Self::derived_properties()
884+
/// }
885+
/// fn set_property(
886+
/// &self,
887+
/// _id: usize,
888+
/// _value: &Value,
889+
/// _pspec: &ParamSpec,
890+
/// ) {
891+
/// Self::derived_set_property(self, _id, _value, _pspec).unwrap()
892+
/// }
893+
/// fn property(&self, _id: usize, _pspec: &ParamSpec) -> Value {
894+
/// Self::derived_property(self, _id, _pspec).unwrap()
895+
/// }
896+
/// }
897+
///
898+
/// #[glib::object_subclass]
899+
/// impl ObjectSubclass for Foo {
900+
/// const NAME: &'static str = "MyFoo";
901+
/// type Type = super::Foo;
902+
/// }
903+
///
904+
/// impl Foo {
905+
/// fn set_fizz(&self, value: String) {
906+
/// *self.fizz.borrow_mut() = format!("custom set: {}", value);
907+
/// }
908+
/// }
909+
/// }
910+
///
911+
/// glib::wrapper! {
912+
/// pub struct Foo(ObjectSubclass<imp::Foo>);
913+
/// }
914+
///
915+
/// fn main() {
916+
/// let myfoo: Foo = glib::object::Object::new(&[]);
917+
///
918+
/// myfoo.set_fizz("test value");
919+
/// assert_eq!(myfoo.fizz(), "custom set: test value".to_string());
920+
/// }
921+
/// ```
922+
#[allow(clippy::needless_doctest_main)]
923+
#[proc_macro_derive(Properties, attributes(properties, property))]
924+
pub fn derive_props(input: TokenStream) -> TokenStream {
925+
let input = parse_macro_input!(input as properties::PropsMacroInput);
926+
properties::impl_derive_props(input)
927+
}

0 commit comments

Comments
 (0)