Permalink
Browse files

Allow multiple values in message variants

Fix #29
  • Loading branch information...
antoyo committed May 20, 2017
1 parent 32aec08 commit aeebe4e8c09affe1f00354a2c2e7fe78828c2edd
Showing with 52 additions and 35 deletions.
  1. +10 −6 examples/text-fields-attribute.rs
  2. +39 −29 relm-derive/src/lib.rs
  3. +3 −0 src/lib.rs
@@ -47,7 +47,7 @@ pub struct Model {
#[derive(Msg)]
pub enum Msg {
Change(String),
Change(String, usize),
Quit,
}
@@ -61,7 +61,10 @@ impl Widget for Win {
fn update(&mut self, event: Msg) {
match event {
Change(text) => self.model.content = text,
Change(text, len) => {
self.model.content = text.chars().rev().collect();
self.model.content += &format!(" ({})", len);
},
Quit => gtk::main_quit(),
}
}
@@ -71,10 +74,11 @@ impl Widget for Win {
gtk::Box {
orientation: Vertical,
gtk::Entry {
changed(entry) => Change(
entry.get_text().unwrap()
.chars().rev().collect()
),
changed(entry) => {
let text = entry.get_text().unwrap();
let len = text.len();
Change(text, len)
},
placeholder_text: "Text to reverse",
},
gtk::Label {
View
@@ -119,20 +119,12 @@ fn derive_clone(ast: &MacroInput) -> Tokens {
}
fn derive_clone_enum(name: &Ident, typ: Tokens, mut generics: Generics, variants: &[Variant]) -> Tokens {
let variant_idents_values: Vec<_> = variants.iter().map(|variant| {
let has_value =
if let VariantData::Tuple(_) = variant.data {
true
}
else {
false
};
(&variant.ident, has_value)
}).collect();
let variant_patterns = variant_idents_values.iter().map(|&(ref ident, has_value)| {
if has_value {
let variant_idents_values = gen_idents_count(variants);
let variant_patterns = variant_idents_values.iter().map(|&(ref ident, value_count)| {
if value_count > 0 {
let value_idents = gen_idents(value_count);
quote! {
#name::#ident(ref value)
#name::#ident(#(ref #value_idents),*)
}
}
else {
@@ -141,10 +133,11 @@ fn derive_clone_enum(name: &Ident, typ: Tokens, mut generics: Generics, variants
}
}
});
let variant_values = variant_idents_values.iter().map(|&(ref ident, has_value)| {
if has_value {
let variant_values = variant_idents_values.iter().map(|&(ref ident, value_count)| {
if value_count > 0 {
let value_idents = gen_idents(value_count);
quote! {
#name::#ident(value.clone())
#name::#ident(#(#value_idents.clone()),*)
}
}
else {
@@ -222,20 +215,12 @@ fn derive_display_variant(ast: &MacroInput) -> Tokens {
};
if let Body::Enum(ref variants) = ast.body {
let variant_idents_values: Vec<_> = variants.iter().map(|variant| {
let has_value =
if let VariantData::Tuple(_) = variant.data {
true
}
else {
false
};
(&variant.ident, has_value)
}).collect();
let variant_patterns = variant_idents_values.iter().map(|&(ref ident, has_value)| {
if has_value {
let variant_idents_values = gen_idents_count(variants);
let variant_patterns = variant_idents_values.iter().map(|&(ref ident, value_count)| {
let value_idents = gen_ignored_idents(value_count);
if value_count > 0 {
quote! {
#name::#ident(_)
#name::#ident(#(#value_idents),*)
}
}
else {
@@ -297,3 +282,28 @@ fn remove_generic_bounds(generics: &Generics) -> Generics {
}
generics.clone()
}
fn gen_ignored_idents(count: usize) -> Vec<Ident> {
(0..count)
.map(|count| Ident::new("_"))
.collect()
}
fn gen_idents(count: usize) -> Vec<Ident> {
(0..count)
.map(|count| Ident::new(format!("value{}", count)))
.collect()
}
fn gen_idents_count(variants: &[Variant]) -> Vec<(&Ident, usize)> {
variants.iter().map(|variant| {
let value_count =
if let VariantData::Tuple(ref tuple) = variant.data {
tuple.len()
}
else {
0
};
(&variant.ident, value_count)
}).collect()
}
View
@@ -44,6 +44,9 @@
* TODO: add construct-only properties for relm widget (to replace initial parameters) to allow
* setting them by name (or with default value).
* TODO: find a way to do two-step initialization (to avoid using unitialized in model()).
* TODO: consider using GBinding instead of manually adding calls to set_property().
* TODO: consider using a nested event loop to transform synchronous callback into asynchronous
* (allowing to set Inhibit(true) in the update() method).
*
* TODO: show a warning when components are destroyed after the end of call to Widget::view().
* TODO: warn in the attribute when an event cycle is found.

0 comments on commit aeebe4e

Please sign in to comment.