Skip to content

Commit f4c4a48

Browse files
committed
Add IntoOption trait to allow returning () from an event handler
1 parent 04cb3ab commit f4c4a48

File tree

5 files changed

+77
-9
lines changed

5 files changed

+77
-9
lines changed

examples/communication-attribute.rs

+6
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ impl Widget for Win {
166166
#[name="counter1"]
167167
Counter {
168168
Increment => counter2@Decrement,
169+
Increment => log_increment(),
169170
},
170171
#[name="counter2"]
171172
Counter,
@@ -182,6 +183,11 @@ impl Widget for Win {
182183
}
183184
}
184185

186+
fn log_increment() {
187+
println!("Increment");
188+
}
189+
190+
185191
impl Win {
186192
fn inc(&mut self) -> Option<CounterMsg> {
187193
Some(Increment)

relm-derive/src/lib.rs

+22
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ fn impl_simple_msg(ast: &MacroInput) -> Tokens {
4747

4848
let clone = derive_clone(ast);
4949
let display = derive_display_variant(ast);
50+
let into_option = derive_into_option(ast);
5051

5152
let generics = &ast.generics;
5253
let generics_without_bound = remove_generic_bounds(generics);
@@ -58,6 +59,7 @@ fn impl_simple_msg(ast: &MacroInput) -> Tokens {
5859
quote! {
5960
#clone
6061
#display
62+
#into_option
6163

6264
impl #generics FnOnce<((),)> for #typ #where_clause {
6365
type Output = #typ;
@@ -92,10 +94,12 @@ pub fn msg(input: TokenStream) -> TokenStream {
9294
fn impl_msg(ast: &MacroInput) -> Tokens {
9395
let clone = derive_clone(ast);
9496
let display = derive_display_variant(ast);
97+
let into_option = derive_into_option(ast);
9598

9699
quote! {
97100
#clone
98101
#display
102+
#into_option
99103
}
100104
}
101105

@@ -175,6 +179,24 @@ fn derive_clone_enum(name: &Ident, typ: Tokens, mut generics: Generics, variants
175179
}
176180
}
177181

182+
fn derive_into_option(ast: &MacroInput) -> Tokens {
183+
let generics = &ast.generics;
184+
let name = &ast.ident;
185+
let generics_without_bound = remove_generic_bounds(generics);
186+
let typ = quote! {
187+
#name #generics_without_bound
188+
};
189+
let where_clause = gen_where_clause(&generics);
190+
191+
quote! {
192+
impl #generics ::relm::IntoOption<#typ> for #typ #where_clause {
193+
fn into_option(self) -> Option<#typ> {
194+
Some(self)
195+
}
196+
}
197+
}
198+
}
199+
178200
fn derive_clone_struct(name: &Ident, typ: Tokens, generics: &Generics, fields: &[Field]) -> Tokens {
179201
let idents: Vec<_> = fields.iter().map(|field| field.ident.clone().unwrap()).collect();
180202
let idents1 = &idents;

src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ extern crate relm_core;
8585
mod component;
8686
mod container;
8787
mod macros;
88+
mod option;
8889
mod stream;
8990
mod widget;
9091

@@ -109,6 +110,7 @@ pub use relm_core::EventStream;
109110

110111
pub use container::{Container, ContainerWidget, RelmContainer};
111112
pub use component::Component;
113+
pub use option::IntoOption;
112114
use stream::ToStream;
113115
pub use widget::Widget;
114116

src/macros.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ macro_rules! check_recursion {
2929
to the same widget.\nInspect the stack trace to determine which call it is.\nThen you can either \
3030
refactor your code to avoid a cyclic event dependency or block events from being emitted by doing \
3131
the following:\n{\n let _lock = self.model.relm.stream().lock();\n // Your panicking call.\n}\
32-
\nSee this example:\
33-
https://github.com/antoyo/relm/blob/feature/futures-glib/examples/checkboxes.rs#L88\n
32+
\nSee this example: \
33+
https://github.com/antoyo/relm/blob/feature/futures-glib/examples/checkboxes.rs#L88\
3434
This issue can also happen when emitting a signal to the same widget, in which case you need to\
3535
refactor your code to avoid this cyclic event dependency.");
3636
}
@@ -60,7 +60,7 @@ macro_rules! connect {
6060
($widget:expr, $event:ident($($args:pat),*), $other_component:expr, $msg:expr) => {
6161
let stream = $other_component.stream().clone();
6262
$widget.$event(move |$($args),*| {
63-
let msg: Option<_> = $msg.into();
63+
let msg: Option<_> = ::relm::IntoOption::into_option($msg);
6464
if let Some(msg) = msg {
6565
stream.emit(msg);
6666
}
@@ -75,7 +75,7 @@ macro_rules! connect {
7575
let stream = $relm.stream().clone();
7676
$widget.$event(move |$($args),*| {
7777
let (msg, return_value) = $msg;
78-
let msg: Option<_> = msg.into();
78+
let msg: Option<_> = ::relm::IntoOption::into_option(msg);
7979
if let Some(msg) = msg {
8080
stream.emit(msg);
8181
}
@@ -97,7 +97,7 @@ macro_rules! connect {
9797
check_recursion!($widget_clone);
9898
let mut $widget_clone = $widget_clone.borrow_mut();
9999
let (msg, return_value) = $msg;
100-
let msg: Option<_> = msg.into();
100+
let msg: Option<_> = ::relm::IntoOption::into_option(msg);
101101
if let Some(msg) = msg {
102102
stream.emit(msg);
103103
}
@@ -117,7 +117,7 @@ macro_rules! connect {
117117
let $widget_clone = $widget_clone.upgrade().expect("upgrade should always work");
118118
check_recursion!($widget_clone);
119119
let mut $widget_clone = $widget_clone.borrow_mut();
120-
let msg: Option<_> = $msg.into();
120+
let msg: Option<_> = ::relm::IntoOption::into_option($msg);
121121
if let Some(msg) = msg {
122122
stream.emit(msg);
123123
}
@@ -136,7 +136,7 @@ macro_rules! connect {
136136
let $widget = $widget.upgrade().expect("upgrade should always work");
137137
check_recursion!($widget);
138138
let mut $widget = $widget.borrow_mut();
139-
let msg: Option<_> = $msg.into();
139+
let msg: Option<_> = ::relm::IntoOption::into_option($msg);
140140
if let Some(msg) = msg {
141141
stream.emit(msg);
142142
}
@@ -150,7 +150,7 @@ macro_rules! connect {
150150
($relm:expr, $widget:expr, $event:ident($($args:pat),*), $msg:expr) => {{
151151
let stream = $relm.stream().clone();
152152
$widget.$event(move |$($args),*| {
153-
let msg: Option<_> = $msg.into();
153+
let msg: Option<_> = ::relm::IntoOption::into_option($msg);
154154
if let Some(msg) = msg {
155155
stream.emit(msg);
156156
}
@@ -165,7 +165,7 @@ macro_rules! connect {
165165
#[allow(unreachable_patterns)]
166166
match msg {
167167
$message => {
168-
let msg: Option<_> = $msg.into();
168+
let msg: Option<_> = ::relm::IntoOption::into_option($msg);
169169
if let Some(msg) = msg {
170170
stream.emit(msg);
171171
}

src/option.rs

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright (c) 2017 Boucher, Antoni <bouanto@zoho.com>
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy of
5+
* this software and associated documentation files (the "Software"), to deal in
6+
* the Software without restriction, including without limitation the rights to
7+
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8+
* the Software, and to permit persons to whom the Software is furnished to do so,
9+
* subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in all
12+
* copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16+
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17+
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18+
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20+
*/
21+
22+
#[doc(hidden)]
23+
pub trait IntoOption<T> {
24+
#[doc(hidden)]
25+
fn into_option(self) -> Option<T>;
26+
}
27+
28+
impl<T> IntoOption<T> for Option<T> {
29+
fn into_option(self) -> Option<T> {
30+
self
31+
}
32+
}
33+
34+
impl<T> IntoOption<T> for () {
35+
fn into_option(self) -> Option<T> {
36+
None
37+
}
38+
}

0 commit comments

Comments
 (0)