Skip to content

Commit 9fc8980

Browse files
committed
glib-macros: add a default attribute to #[property]
When naked (rather than `default = 1`), this specifies that we should use the param spec builder defined via `HasParamSpecDefaulted` as the default value. This is particularly relevant for enums, for which we did a blanket implementation in a previous commit.
1 parent a97c3ff commit 9fc8980

File tree

2 files changed

+56
-4
lines changed

2 files changed

+56
-4
lines changed

glib-macros/src/properties.rs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ enum PropAttr {
138138

139139
// ident = "literal"
140140
Name(syn::LitStr),
141+
142+
// ident
143+
Default,
141144
}
142145

143146
impl Parse for PropAttr {
@@ -194,6 +197,7 @@ impl Parse for PropAttr {
194197
),
195198
))
196199
}
200+
"default" => PropAttr::Default,
197201
_ => PropAttr::BuilderField((name, None)),
198202
}
199203
};
@@ -213,6 +217,7 @@ struct ReceivedAttrs {
213217
name: Option<syn::LitStr>,
214218
builder: Option<(Punctuated<syn::Expr, Token![,]>, TokenStream2)>,
215219
builder_fields: HashMap<syn::Ident, Option<syn::Expr>>,
220+
use_default: bool,
216221
}
217222

218223
impl Parse for ReceivedAttrs {
@@ -244,6 +249,9 @@ impl ReceivedAttrs {
244249
PropAttr::BuilderField((ident, expr)) => {
245250
self.builder_fields.insert(ident, expr);
246251
}
252+
PropAttr::Default => {
253+
self.use_default = true;
254+
}
247255
}
248256
}
249257
}
@@ -265,6 +273,7 @@ struct PropDesc {
265273
builder: Option<(Punctuated<syn::Expr, Token![,]>, TokenStream2)>,
266274
builder_fields: HashMap<syn::Ident, Option<syn::Expr>>,
267275
is_construct_only: bool,
276+
use_default: bool,
268277
}
269278

270279
impl PropDesc {
@@ -286,6 +295,7 @@ impl PropDesc {
286295
name,
287296
builder,
288297
builder_fields,
298+
use_default,
289299
} = attrs;
290300

291301
let is_construct_only = builder_fields.iter().any(|(k, _)| *k == "construct_only");
@@ -333,6 +343,7 @@ impl PropDesc {
333343
builder,
334344
builder_fields,
335345
is_construct_only,
346+
use_default,
336347
})
337348
}
338349
fn is_overriding(&self) -> bool {
@@ -343,7 +354,11 @@ impl PropDesc {
343354
fn expand_param_spec(prop: &PropDesc) -> TokenStream2 {
344355
let crate_ident = crate_ident_new();
345356
let PropDesc {
346-
ty, name, builder, ..
357+
ty,
358+
name,
359+
builder,
360+
use_default,
361+
..
347362
} = prop;
348363
let stripped_name = strip_raw_prefix_from_name(name);
349364

@@ -385,9 +400,20 @@ fn expand_param_spec(prop: &PropDesc) -> TokenStream2 {
385400
let builder_fields = prop.builder_fields.iter().map(|(k, v)| quote!(.#k(#v)));
386401

387402
let span = prop.attrs_span;
403+
404+
// Figure out if we should use the default version or the one that explicitly sets the `Default` value.
405+
let (trait_name, fn_name) = if *use_default {
406+
(
407+
quote!(HasParamSpecDefaulted),
408+
quote!(param_spec_builder_defaulted),
409+
)
410+
} else {
411+
(quote!(HasParamSpec), quote!(param_spec_builder))
412+
};
413+
388414
quote_spanned! {span=>
389-
<<#ty as #crate_ident::property::Property>::Value as #crate_ident::prelude::HasParamSpec>
390-
::param_spec_builder() #builder_call
415+
<<#ty as #crate_ident::property::Property>::Value as #crate_ident::#trait_name>
416+
::#fn_name() #builder_call
391417
#rw_flags
392418
#(#builder_fields)*
393419
.build()

glib-macros/tests/properties.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ mod foo {
6969
pub enum SimpleEnum {
7070
#[default]
7171
One,
72+
Two,
7273
}
7374

7475
#[derive(Default, Clone)]
@@ -129,10 +130,14 @@ mod foo {
129130
builder_fields_without_builder: RefCell<u32>,
130131
#[property(get, set, builder('c'))]
131132
builder_with_required_param: RefCell<char>,
133+
#[property(get, set, default)]
134+
char_default: RefCell<char>,
132135
#[property(get, set)]
133136
boxed: RefCell<SimpleBoxedString>,
134-
#[property(get, set, builder(SimpleEnum::One))]
137+
#[property(get, set, builder(SimpleEnum::Two))]
135138
fenum: RefCell<SimpleEnum>,
139+
#[property(get, set, default)]
140+
fenum_default: RefCell<SimpleEnum>,
136141
#[property(get, set, nullable)]
137142
object: RefCell<Option<glib::Object>>,
138143
#[property(get, set, nullable)]
@@ -206,6 +211,8 @@ mod foo {
206211

207212
#[test]
208213
fn props() {
214+
use crate::foo::SimpleEnum;
215+
209216
let myfoo: foo::Foo = glib::object::Object::new();
210217

211218
// Read values
@@ -274,6 +281,25 @@ fn props() {
274281
"hello".to_string()
275282
);
276283

284+
assert_eq!(
285+
myfoo
286+
.find_property("fenum")
287+
.unwrap()
288+
.default_value()
289+
.get::<SimpleEnum>()
290+
.unwrap(),
291+
SimpleEnum::Two
292+
);
293+
assert_eq!(
294+
myfoo
295+
.find_property("fenum_default")
296+
.unwrap()
297+
.default_value()
298+
.get::<SimpleEnum>()
299+
.unwrap(),
300+
SimpleEnum::One
301+
);
302+
277303
// numeric builder
278304
assert_eq!(
279305
myfoo

0 commit comments

Comments
 (0)