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
extern crate cursive_async_view;
use std::sync::mpsc::channel;
use std::sync::mpsc::TryRecvError;
use std::thread;
use std::time::Duration;
use cursive::views::{Dialog, LinearLayout, RadioGroup};
use cursive::{Cursive, CursiveExt};
use cursive_async_view::{AsyncState, AsyncView};
fn main() {
let mut siv = Cursive::default();
// We can quit by pressing `q`
siv.add_global_callback('q', Cursive::quit);
// create channel to send radio buttons text over it
let (tx, rx) = channel();
// calculate the radio button contents in a different thread
thread::spawn(move || {
// Figuring out the radio button texts takes veeeeery long!
// Glad we have the async view, entertaining the user until
// all our figuring out is done!
tx.send("πΆπ Ding dong, you are wrong...").unwrap();
thread::sleep(Duration::from_secs(1));
tx.send("π¦π¦ Splish splash, your opinion is trash!")
.unwrap();
thread::sleep(Duration::from_secs(1));
tx.send("π¦π Flippity flop, you need to stop").unwrap();
thread::sleep(Duration::from_secs(1));
tx.send("π«πΈ Hippity hoppity, this view is now my property")
.unwrap();
thread::sleep(Duration::from_secs(1));
tx.send("π¦π¬ Miss me").unwrap();
thread::sleep(Duration::from_secs(1));
});
let mut group = RadioGroup::new(); // !Send struct
// We can't use a LinearLayout here, 'cause it's not `Copy`. Further
// explanation below.
let mut buttons = Vec::new();
let async_view = AsyncView::new(&mut siv, move || {
// be quick or be dead
match rx.try_recv() {
// ooooooh, another radio button for me
Ok(msg) => {
buttons.push(group.button_str(msg));
// there are more buttons to be excited about!
AsyncState::Pending
}
// no button today, but maybe next time
Err(TryRecvError::Empty) => AsyncState::Pending,
// channel got closed, so looks like these are all my buttons...
Err(TryRecvError::Disconnected) => {
// If the channel has disconnected, we have received all radio
// buttons, so lets resolve the async view.
match buttons.len() {
0 => AsyncState::Error("Buttons could not be loaded".to_string()),
1 => AsyncState::Error("There is no choice!".to_string()),
_ => {
// ==> EXPLANATION <==
// We have to create the linear layout here, as it does
// not implement the copy trait. As we cannot move a
// captured variable out of an FnMut and cannot copy the
// linear layout, we have to create it inside the
// closure from the buttons vector.
let mut layout = LinearLayout::vertical();
for button in buttons.drain(..) {
layout.add_child(button);
}
AsyncState::Available(layout)
}
}
}
}
});
// dialogs are cool, so let's use one!
let dialog = Dialog::around(async_view.with_width(40)).button("Ok", |s| s.quit());
siv.add_layer(dialog);
// fox on the run!
siv.run();
}