Skip to content

Commit 2d2a50b

Browse files
committed
Added channel example
Also added missing for_each_subsequent variants.
1 parent af1c026 commit 2d2a50b

File tree

2 files changed

+85
-0
lines changed

2 files changed

+85
-0
lines changed

examples/channels.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
use std::time::{Duration, Instant};
2+
3+
use cushy::value::{Destination, Dynamic, Source};
4+
use cushy::widget::MakeWidget;
5+
use cushy::widgets::label::Displayable;
6+
use cushy::Run;
7+
8+
fn main() -> cushy::Result {
9+
let channel_counter = Dynamic::new(0_usize);
10+
let channel_counter_label = channel_counter.to_label();
11+
let sender = cushy::channel::build()
12+
.on_receive({
13+
move |_| {
14+
std::thread::sleep(Duration::from_secs(1));
15+
*channel_counter.lock() += 1;
16+
}
17+
})
18+
.finish();
19+
20+
let dynamic_counter = Dynamic::new(0_usize);
21+
let dynamic_counter_label = dynamic_counter.to_label();
22+
let dynamic_value = Dynamic::new(Instant::now());
23+
// We use a `for_each_subsequent_cloned` to only execute the callback after
24+
// the current value changes, and the `cloned` version ensures the dynamic
25+
// isn't locked while the callback is being executed.
26+
dynamic_value
27+
.for_each_subsequent_cloned(move |_| {
28+
std::thread::sleep(Duration::from_secs(1));
29+
*dynamic_counter.lock() += 1;
30+
})
31+
.persist();
32+
33+
"Channels ensure every value sent is received. Try \
34+
clicking the button quickly and seeing how the \
35+
channel version increments for every click while \
36+
the dynamic version increments at most once every \
37+
500 milliseconds."
38+
.and(
39+
"Click Me"
40+
.into_button()
41+
.on_click(move |_| {
42+
let now = Instant::now();
43+
sender.send(now).expect("value to be received");
44+
dynamic_value.set(now);
45+
})
46+
.centered(),
47+
)
48+
.and(
49+
"Channel Counter"
50+
.and(channel_counter_label)
51+
.into_rows()
52+
.and("Dynamic Counter".and(dynamic_counter_label).into_rows())
53+
.into_columns()
54+
.centered(),
55+
)
56+
.into_rows()
57+
.run()
58+
}

src/reactive/value.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,9 @@ pub trait Source<T> {
299299

300300
/// Invokes `for_each` with the current contents and each time this source's
301301
/// contents are updated.
302+
///
303+
/// Returning `Err(CallbackDisconnected)` will prevent the callback from
304+
/// being invoked again.
302305
fn for_each_cloned_try<F>(&self, mut for_each: F) -> CallbackHandle
303306
where
304307
T: Clone + Send + 'static,
@@ -307,6 +310,30 @@ pub trait Source<T> {
307310
self.for_each_generational_cloned_try(move |gen| for_each(gen.value))
308311
}
309312

313+
/// Invokes `for_each` each time this source's contents are updated.
314+
///
315+
/// Returning `Err(CallbackDisconnected)` will prevent the callback from
316+
/// being invoked again.
317+
fn for_each_subsequent_cloned_try<F>(&self, mut for_each: F) -> CallbackHandle
318+
where
319+
T: Clone + Send + 'static,
320+
F: FnMut(T) -> Result<(), CallbackDisconnected> + Send + 'static,
321+
{
322+
self.for_each_subsequent_generational_cloned_try(move |gen| for_each(gen.value))
323+
}
324+
325+
/// Invokes `for_each` each time this source's contents are updated.
326+
fn for_each_subsequent_cloned<F>(&self, mut for_each: F) -> CallbackHandle
327+
where
328+
T: Clone + Send + 'static,
329+
F: FnMut(T) + Send + 'static,
330+
{
331+
self.for_each_subsequent_cloned_try(move |value| {
332+
for_each(value);
333+
Ok(())
334+
})
335+
}
336+
310337
/// Invokes `for_each` with the current contents and each time this source's
311338
/// contents are updated.
312339
fn for_each_cloned<F>(&self, mut for_each: F) -> CallbackHandle

0 commit comments

Comments
 (0)