Skip to content

Commit aa525e2

Browse files
authored
Merge pull request #958 from pbor/prop-default
Support `default = ...` in the properties macro
2 parents c6cb449 + 5119b61 commit aa525e2

File tree

2 files changed

+130
-111
lines changed

2 files changed

+130
-111
lines changed

glib-macros/src/properties.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ impl Parse for PropAttr {
114114
"set" => PropAttr::Set(Some(input.parse()?)),
115115
"type" => PropAttr::Type(input.parse()?),
116116
"member" => PropAttr::Member(input.parse()?),
117+
// Special case "default = ..." and map it to .default_value(...)
118+
"default" => PropAttr::BuilderField((
119+
syn::Ident::new("default_value", name.span()),
120+
Some(input.parse()?),
121+
)),
117122
_ => PropAttr::BuilderField((name, Some(input.parse()?))),
118123
}
119124
} else if input.peek(syn::token::Paren) {

glib-macros/tests/properties.rs

Lines changed: 125 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -2,129 +2,132 @@
22

33
use glib::prelude::*;
44
use glib::ParamFlags;
5-
#[test]
6-
fn props() {
7-
mod foo {
8-
use glib::prelude::*;
9-
use glib::subclass::prelude::*;
10-
use glib_macros::Properties;
11-
use std::cell::Cell;
12-
use std::cell::RefCell;
13-
use std::marker::PhantomData;
14-
use std::sync::Mutex;
15-
16-
use once_cell::sync::OnceCell;
17-
18-
#[derive(Clone, Default, Debug, PartialEq, Eq, glib::Boxed)]
19-
#[boxed_type(name = "SimpleBoxedString")]
20-
pub struct SimpleBoxedString(pub String);
21-
22-
#[derive(Copy, Default, Clone, Debug, PartialEq, Eq, glib::Enum)]
23-
#[enum_type(name = "SimpleEnum")]
24-
pub enum SimpleEnum {
25-
#[default]
26-
One,
27-
}
285

29-
#[derive(Default, Clone)]
30-
struct Author {
31-
name: String,
32-
nick: String,
6+
#[cfg(test)]
7+
mod foo {
8+
use glib::prelude::*;
9+
use glib::subclass::prelude::*;
10+
use glib_macros::Properties;
11+
use once_cell::sync::OnceCell;
12+
use std::cell::Cell;
13+
use std::cell::RefCell;
14+
use std::marker::PhantomData;
15+
use std::sync::Mutex;
16+
17+
#[derive(Clone, Default, Debug, PartialEq, Eq, glib::Boxed)]
18+
#[boxed_type(name = "SimpleBoxedString")]
19+
pub struct SimpleBoxedString(pub String);
20+
21+
#[derive(Copy, Default, Clone, Debug, PartialEq, Eq, glib::Enum)]
22+
#[enum_type(name = "SimpleEnum")]
23+
pub enum SimpleEnum {
24+
#[default]
25+
One,
26+
}
27+
28+
#[derive(Default, Clone)]
29+
struct Author {
30+
name: String,
31+
nick: String,
32+
}
33+
34+
pub mod imp {
35+
use glib::{ParamSpec, Value};
36+
use std::rc::Rc;
37+
38+
use super::*;
39+
40+
#[derive(Properties, Default)]
41+
#[properties(wrapper_type = super::Foo)]
42+
pub struct Foo {
43+
#[property(get, set)]
44+
bar: Mutex<String>,
45+
#[property(get, set)]
46+
double: RefCell<f64>,
47+
#[property(get = |_| 42.0, set)]
48+
infer_inline_type: RefCell<f64>,
49+
// The following property doesn't store any data. The value of the property is calculated
50+
// when the value is accessed.
51+
#[property(get = Self::hello_world)]
52+
_buzz: PhantomData<String>,
53+
#[property(get, set = Self::set_fizz, name = "fizz", nick = "fizz-nick",
54+
blurb = "short description stored in the GLib type system"
55+
)]
56+
fizz: RefCell<String>,
57+
#[property(name = "author-name", get, set, type = String, member = name)]
58+
#[property(name = "author-nick", get, set, type = String, member = nick)]
59+
author: RefCell<Author>,
60+
#[property(
61+
type = String,
62+
get = |t: &Self| t.author.borrow().name.to_owned(),
63+
set = Self::set_author_name)]
64+
fake_field: PhantomData<String>,
65+
#[property(get, set, explicit_notify, lax_validation)]
66+
custom_flags: RefCell<String>,
67+
#[property(get, set, default = "hello")]
68+
with_default: RefCell<String>,
69+
#[property(get, set, builder())]
70+
simple_builder: RefCell<u32>,
71+
#[property(get, set, builder().minimum(0).maximum(5))]
72+
numeric_builder: RefCell<u32>,
73+
#[property(get, set, minimum = 0, maximum = 5)]
74+
builder_fields_without_builder: RefCell<u32>,
75+
#[property(get, set, builder('c'))]
76+
builder_with_required_param: RefCell<char>,
77+
#[property(get, set)]
78+
boxed: RefCell<SimpleBoxedString>,
79+
#[property(get, set, builder(SimpleEnum::One))]
80+
fenum: RefCell<SimpleEnum>,
81+
#[property(get, set)]
82+
object: RefCell<Option<glib::Object>>,
83+
#[property(get, set)]
84+
optional: RefCell<Option<String>>,
85+
#[property(get, set)]
86+
smart_pointer: Rc<RefCell<String>>,
87+
#[property(get, set)]
88+
once_cell: OnceCell<u8>,
89+
#[property(get, set)]
90+
cell: Cell<u8>,
3391
}
3492

35-
pub mod imp {
36-
use glib::{ParamSpec, Value};
37-
use std::rc::Rc;
38-
39-
use super::*;
40-
41-
#[derive(Properties, Default)]
42-
#[properties(wrapper_type = super::Foo)]
43-
pub struct Foo {
44-
#[property(get, set)]
45-
bar: Mutex<String>,
46-
#[property(get, set)]
47-
double: RefCell<f64>,
48-
#[property(get = |_| 42.0, set)]
49-
infer_inline_type: RefCell<f64>,
50-
// The following property doesn't store any data. The value of the property is calculated
51-
// when the value is accessed.
52-
#[property(get = Self::hello_world)]
53-
_buzz: PhantomData<String>,
54-
#[property(get, set = Self::set_fizz, name = "fizz", nick = "fizz-nick",
55-
blurb = "short description stored in the GLib type system"
56-
)]
57-
fizz: RefCell<String>,
58-
#[property(name = "author-name", get, set, type = String, member = name)]
59-
#[property(name = "author-nick", get, set, type = String, member = nick)]
60-
author: RefCell<Author>,
61-
#[property(
62-
type = String,
63-
get = |t: &Self| t.author.borrow().name.to_owned(),
64-
set = Self::set_author_name)]
65-
fake_field: PhantomData<String>,
66-
#[property(get, set, explicit_notify, lax_validation)]
67-
custom_flags: RefCell<String>,
68-
#[property(get, set, builder())]
69-
simple_builder: RefCell<u32>,
70-
#[property(get, set, builder().minimum(0).maximum(5))]
71-
numeric_builder: RefCell<u32>,
72-
#[property(get, set, minimum = 0, maximum = 5)]
73-
builder_fields_without_builder: RefCell<u32>,
74-
#[property(get, set, builder('c'))]
75-
builder_with_required_param: RefCell<char>,
76-
#[property(get, set)]
77-
boxed: RefCell<SimpleBoxedString>,
78-
#[property(get, set, builder(SimpleEnum::One))]
79-
fenum: RefCell<SimpleEnum>,
80-
#[property(get, set)]
81-
object: RefCell<Option<glib::Object>>,
82-
#[property(get, set)]
83-
optional: RefCell<Option<String>>,
84-
#[property(get, set)]
85-
smart_pointer: Rc<RefCell<String>>,
86-
#[property(get, set)]
87-
once_cell: OnceCell<u8>,
88-
#[property(get, set)]
89-
cell: Cell<u8>,
93+
impl ObjectImpl for Foo {
94+
fn properties() -> &'static [ParamSpec] {
95+
Self::derived_properties()
9096
}
91-
92-
impl ObjectImpl for Foo {
93-
fn properties() -> &'static [ParamSpec] {
94-
Self::derived_properties()
95-
}
96-
fn set_property(&self, _id: usize, _value: &Value, _pspec: &ParamSpec) {
97-
Self::derived_set_property(self, _id, _value, _pspec)
98-
}
99-
fn property(&self, id: usize, _pspec: &ParamSpec) -> Value {
100-
Self::derived_property(self, id, _pspec)
101-
}
97+
fn set_property(&self, _id: usize, _value: &Value, _pspec: &ParamSpec) {
98+
Self::derived_set_property(self, _id, _value, _pspec)
10299
}
103-
104-
#[glib::object_subclass]
105-
impl ObjectSubclass for Foo {
106-
const NAME: &'static str = "MyFoo";
107-
type Type = super::Foo;
100+
fn property(&self, id: usize, _pspec: &ParamSpec) -> Value {
101+
Self::derived_property(self, id, _pspec)
108102
}
103+
}
109104

110-
impl Foo {
111-
fn set_author_name(&self, value: String) {
112-
self.author.borrow_mut().name = value;
113-
}
114-
fn hello_world(&self) -> String {
115-
String::from("Hello world!")
116-
}
117-
fn set_fizz(&self, value: String) {
118-
*self.fizz.borrow_mut() = format!("custom set: {}", value);
119-
}
120-
}
105+
#[glib::object_subclass]
106+
impl ObjectSubclass for Foo {
107+
const NAME: &'static str = "MyFoo";
108+
type Type = super::Foo;
121109
}
122110

123-
glib::wrapper! {
124-
pub struct Foo(ObjectSubclass<imp::Foo>);
111+
impl Foo {
112+
fn set_author_name(&self, value: String) {
113+
self.author.borrow_mut().name = value;
114+
}
115+
fn hello_world(&self) -> String {
116+
String::from("Hello world!")
117+
}
118+
fn set_fizz(&self, value: String) {
119+
*self.fizz.borrow_mut() = format!("custom set: {}", value);
120+
}
125121
}
126122
}
127123

124+
glib::wrapper! {
125+
pub struct Foo(ObjectSubclass<imp::Foo>);
126+
}
127+
}
128+
129+
#[test]
130+
fn props() {
128131
let myfoo: foo::Foo = glib::object::Object::new();
129132

130133
// Read bar
@@ -160,6 +163,17 @@ fn props() {
160163
ParamFlags::EXPLICIT_NOTIFY | ParamFlags::READWRITE | ParamFlags::LAX_VALIDATION
161164
);
162165

166+
// default value
167+
assert_eq!(
168+
myfoo
169+
.find_property("with_default")
170+
.unwrap()
171+
.default_value()
172+
.get::<String>()
173+
.unwrap(),
174+
"hello".to_string()
175+
);
176+
163177
// numeric builder
164178
assert_eq!(
165179
myfoo

0 commit comments

Comments
 (0)