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
#[macro_export]
macro_rules! state {
(
$(
$widget:ident[$field:expr]: $t:ty = $init:expr;
)*
) => {
$(
let widget_name = stringify!($widget);
let widget = &$widget;
unsafe {widget.set_data::<$t>($field, $init);}
let (sender, receiver) = glib::MainContext::channel::<$t>(glib::PRIORITY_DEFAULT);
unsafe {
widget.set_data::<glib::Sender<$t>>(&format!("{}.sender", $field), sender);
widget.set_data::<Vec<glib::Sender<$t>>>(&format!("{}.delegators", $field), Vec::new());
}
receiver.attach(None, glib::clone!(@weak widget => @default-return glib::Continue(true), move |value| {
if let Some(delegators) = unsafe {widget
.data::<Vec<glib::Sender<$t>>>(&format!("{}.delegators", $field))
.map(|p| p.as_ptr() as *const Vec<glib::Sender<$t>>)
.map(|p| p.as_ref())
.flatten()}
{
for sender in delegators {
sender.send(value.clone())
.expect(&format!("Could not send local state update of state {}[\"{}.delegators\"].", widget_name, $field));
}
} else {
error!("Could not read {}[\"{}.delegators\"]", widget_name, $field);
}
glib::Continue(true)
}));
)*
}
}
#[macro_export]
macro_rules! update_state {
(
$view:ident[$field:expr] => $variable:ident: $t:ty => $handler:expr
) => {
unsafe {
if let (Some($variable), Some(_sender)) = (
$view
.data::<$t>($field)
.map(|p| p.as_ptr() as *mut $t)
.map(|p| p.as_mut())
.flatten(),
$view
.data::<glib::Sender<$t>>(&format!("{}.sender", $field))
.map(|p| p.as_ptr() as *const glib::Sender<$t>)
.map(|p| p.as_ref())
.flatten(),
) {
$handler;
_sender
.send($variable.clone())
.expect("Could not send update of local state.");
}
}
};
}
#[macro_export]
macro_rules! get_state {
(
$view:ident[$field:expr]: $t:ty
) => {
unsafe {
if let Some(v) = $view
.data($field)
.map(|p| p.as_ptr() as *const $t)
.map(|p| p.as_ref())
.flatten()
{
Some(v)
} else {
None
}
}
};
}
#[macro_export]
macro_rules! on_state_update {
(
$view:ident[$field:expr]: $t:ty => $callback:expr
) => {
unsafe {
let (sender, receiver) = glib::MainContext::channel::<$t>(glib::PRIORITY_DEFAULT);
if let Some(delegators) = $view
.data::<Vec<glib::Sender<$t>>>(&format!("{}.delegators", $field))
.map(|p| p.as_ptr() as *mut Vec<glib::Sender<$t>>)
.map(|p| p.as_mut())
.flatten()
{
delegators.push(sender);
receiver.attach(None, $callback);
} else {
error!(
"Could not attach on_state_update for {0}[\"{1}\"]. No delegators on widget {0}.",
stringify!($view),
$field
);
}
}
};
}