Skip to content

Commit a70ccad

Browse files
committed
Add support for child events in relm widgets
1 parent ab55ca3 commit a70ccad

3 files changed

Lines changed: 63 additions & 9 deletions

File tree

examples/child-event.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,39 @@ use relm_attributes::widget;
4444

4545
use self::Msg::*;
4646

47+
#[widget]
48+
impl Widget for TreeView {
49+
fn init_view(&mut self) {
50+
let columns = vec![Type::String];
51+
let model = ListStore::new(&columns);
52+
let row = model.append();
53+
model.set_value(&row, 0, &"String".to_value());
54+
let row = model.append();
55+
model.set_value(&row, 0, &"Text".to_value());
56+
57+
let view_column = TreeViewColumn::new();
58+
let cell = CellRendererText::new();
59+
view_column.pack_start(&cell, true);
60+
view_column.add_attribute(&cell, "text", 0);
61+
self.tree_view.append_column(&view_column);
62+
63+
self.tree_view.set_model(Some(&model));
64+
}
65+
66+
fn model() -> () {
67+
}
68+
69+
fn update(&mut self, event: Msg) {
70+
}
71+
72+
view! {
73+
#[name="tree_view"]
74+
gtk::TreeView {
75+
selection.changed(selection) => SelectionChanged(selection.clone()),
76+
}
77+
}
78+
}
79+
4780
#[derive(Msg)]
4881
pub enum Msg {
4982
SelectionChanged(TreeSelection),
@@ -86,6 +119,9 @@ impl Widget for Win {
86119
gtk::TreeView {
87120
selection.changed(selection) => SelectionChanged(selection.clone()),
88121
},
122+
TreeView {
123+
selection.changed(selection) => SelectionChanged(selection.clone()),
124+
},
89125
},
90126
delete_event(_, _) => (Quit, Inhibit(false)),
91127
}

relm-gen-widget/src/gen.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ impl<'a> Generator<'a> {
251251
for (name, event) in &gtk_widget.events {
252252
self.collect_event(widget_name, gtk_widget.save, name, event);
253253
}
254-
for (&(ref child_name, ref name), event) in &gtk_widget.child_events {
254+
for (&(ref child_name, ref name), event) in &widget.child_events {
255255
let widget_name = Ident::new(format!("{}.get_{}()", widget_name, child_name));
256256
self.collect_event(&widget_name, false, &name, event);
257257
}
@@ -293,10 +293,14 @@ impl<'a> Generator<'a> {
293293
self.events.push(connect);
294294
}
295295
}
296+
let ident = Ident::new(format!("{}.widget().root()", widget_name));
296297
for (name, event) in &relm_widget.gtk_events {
297-
let ident = Ident::new(format!("{}.widget().root()", widget_name));
298298
self.collect_event(&ident, true, name, event);
299299
}
300+
for (&(ref child_name, ref name), event) in &widget.child_events {
301+
let ident = Ident::new(format!("{}.get_{}()", ident, child_name));
302+
self.collect_event(&ident, false, &name, event);
303+
}
300304
}
301305

302306
fn gtk_widget(&mut self, widget: &Widget, gtk_widget: &GtkWidget, parent: Option<&Ident>,

relm-gen-widget/src/parser.rs

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ lazy_static! {
4848
static ref NAMES_INDEX: Mutex<HashMap<String, u32>> = Mutex::new(HashMap::new());
4949
}
5050

51+
type ChildEvents = HashMap<(String, String), Event>;
52+
5153
#[derive(Clone, Copy, PartialEq)]
5254
enum DefaultParam {
5355
DefaultNoParam,
@@ -91,6 +93,7 @@ enum IsEventOrNot {
9193
}
9294

9395
pub struct Widget {
96+
pub child_events: ChildEvents,
9497
pub child_properties: HashMap<String, Expr>,
9598
pub children: Vec<Widget>,
9699
pub container_type: Option<Option<String>>,
@@ -104,10 +107,11 @@ pub struct Widget {
104107

105108
impl Widget {
106109
fn new_gtk(widget: GtkWidget, typ: Path, init_parameters: Vec<Expr>, children: Vec<Widget>,
107-
properties: HashMap<String, Expr>, child_properties: HashMap<String, Expr>) -> Self
110+
properties: HashMap<String, Expr>, child_properties: HashMap<String, Expr>, child_events: ChildEvents) -> Self
108111
{
109112
let name = gen_widget_name(&typ);
110113
Widget {
114+
child_events,
111115
child_properties,
112116
children,
113117
container_type: None,
@@ -121,14 +125,15 @@ impl Widget {
121125
}
122126

123127
fn new_relm(widget: RelmWidget, typ: Path, init_parameters: Vec<Expr>, children: Vec<Widget>,
124-
properties: HashMap<String, Expr>, child_properties: HashMap<String, Expr>) -> Self
128+
properties: HashMap<String, Expr>, child_properties: HashMap<String, Expr>, child_events: ChildEvents) -> Self
125129
{
126130
let mut name = gen_widget_name(&typ);
127131
// Relm widgets are not used in the update() method; they are only saved to avoid dropping
128132
// their channel too soon.
129133
// So prepend an underscore to hide a warning.
130134
name.insert(0, '_');
131135
Widget {
136+
child_events,
132137
child_properties,
133138
children,
134139
container_type: None,
@@ -150,7 +155,6 @@ pub enum EitherWidget {
150155

151156
#[derive(Debug)]
152157
pub struct GtkWidget {
153-
pub child_events: HashMap<(String, String), Event>,
154158
pub construct_properties: HashMap<syn::Ident, Expr>,
155159
pub events: HashMap<String, Event>,
156160
pub relm_name: Option<Ty>,
@@ -160,7 +164,6 @@ pub struct GtkWidget {
160164
impl GtkWidget {
161165
fn new() -> Self {
162166
GtkWidget {
163-
child_events: HashMap::new(),
164167
construct_properties: HashMap::new(),
165168
events: HashMap::new(),
166169
relm_name: None,
@@ -231,6 +234,7 @@ fn parse_widget(tokens: &[TokenTree], save: bool) -> (Widget, &[TokenTree]) {
231234
let mut children = vec![];
232235
let mut properties = HashMap::new();
233236
let mut child_properties = HashMap::new();
237+
let mut child_events = HashMap::new();
234238
gtk_widget.save = save;
235239
if let TokenTree::Delimited(Delimited { delim: Paren, ref tts }) = tokens[0] {
236240
if let TokenTree::Delimited(Delimited { delim: Brace, ref tts }) = tts[0] {
@@ -261,7 +265,7 @@ fn parse_widget(tokens: &[TokenTree], save: bool) -> (Widget, &[TokenTree]) {
261265
let child_name = ident;
262266
let (ident, new_tts) = parse_ident(&tts[1..]);
263267
let (event, new_tts) = parse_event(new_tts, DefaultOneParam);
264-
gtk_widget.child_events.insert((child_name, ident), event);
268+
child_events.insert((child_name, ident), event);
265269
tts = new_tts;
266270
},
267271
TokenTree::Delimited(Delimited { delim: Paren, .. }) | Token(FatArrow) => {
@@ -281,7 +285,8 @@ fn parse_widget(tokens: &[TokenTree], save: bool) -> (Widget, &[TokenTree]) {
281285
else {
282286
panic!("Expected {{ but found `{:?}` in view! macro", tokens[0]);
283287
}
284-
let widget = Widget::new_gtk(gtk_widget, gtk_type, init_parameters, children, properties, child_properties);
288+
let widget = Widget::new_gtk(gtk_widget, gtk_type, init_parameters, children, properties, child_properties,
289+
child_events);
285290
(widget, &tokens[1..])
286291
}
287292

@@ -609,6 +614,7 @@ fn parse_relm_widget(tokens: &[TokenTree]) -> (Widget, &[TokenTree]) {
609614
let mut children = vec![];
610615
let mut properties = HashMap::new();
611616
let mut child_properties = HashMap::new();
617+
let mut child_events = HashMap::new();
612618
if let TokenTree::Delimited(Delimited { delim: Paren, ref tts }) = tokens[0] {
613619
let parameters = parse_comma_list(tts);
614620
init_parameters = parameters;
@@ -642,6 +648,13 @@ fn parse_relm_widget(tokens: &[TokenTree]) -> (Widget, &[TokenTree]) {
642648
Token(Colon) => {
643649
tts = parse_value_or_child_properties(tts, ident, &mut child_properties, &mut properties);
644650
},
651+
Token(Dot) => {
652+
let child_name = ident;
653+
let (ident, new_tts) = parse_ident(&tts[1..]);
654+
let (event, new_tts) = parse_event(new_tts, DefaultOneParam);
655+
child_events.insert((child_name, ident), event);
656+
tts = new_tts;
657+
},
645658
TokenTree::Delimited(Delimited { delim: Paren, .. }) | Token(FatArrow) => {
646659
if ident.chars().next().map(|char| char.is_lowercase()) == Some(false) {
647660
// Uppercase is a msg.
@@ -666,7 +679,8 @@ fn parse_relm_widget(tokens: &[TokenTree]) -> (Widget, &[TokenTree]) {
666679
}
667680
}
668681
}
669-
let widget = Widget::new_relm(relm_widget, relm_type, init_parameters, children, properties, child_properties);
682+
let widget = Widget::new_relm(relm_widget, relm_type, init_parameters, children, properties, child_properties,
683+
child_events);
670684
(widget, &tokens[1..])
671685
}
672686

0 commit comments

Comments
 (0)