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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#![windows_subsystem = "windows"]
use std::{thread, time};
use druid::widget::prelude::*;
use druid::widget::{Button, Either, Flex, Label, Spinner};
use druid::{
AppDelegate, AppLauncher, Command, Data, DelegateCtx, ExtEventSink, Handled, Lens,
LocalizedString, Selector, Target, WidgetExt, WindowDesc,
};
const FINISH_SLOW_FUNCTION: Selector<u32> = Selector::new("finish_slow_function");
#[derive(Clone, Default, Data, Lens)]
struct AppState {
processing: bool,
value: u32,
}
fn ui_builder() -> impl Widget<AppState> {
let button = Button::new("Start slow increment")
.on_click(|ctx, data: &mut AppState, _env| {
data.processing = true;
wrapped_slow_function(ctx.get_external_handle(), data.value);
})
.padding(5.0);
let button_placeholder = Flex::column()
.with_child(Label::new(LocalizedString::new("Processing...")).padding(5.0))
.with_child(Spinner::new());
let text = LocalizedString::new("hello-counter")
.with_arg("count", |data: &AppState, _env| (data.value).into());
let label = Label::new(text).padding(5.0).center();
let either = Either::new(|data, _env| data.processing, button_placeholder, button);
Flex::column().with_child(label).with_child(either)
}
fn wrapped_slow_function(sink: ExtEventSink, number: u32) {
thread::spawn(move || {
let number = slow_function(number);
sink.submit_command(FINISH_SLOW_FUNCTION, number, Target::Auto)
.expect("command failed to submit");
});
}
fn slow_function(number: u32) -> u32 {
let a_while = time::Duration::from_millis(2000);
thread::sleep(a_while);
number + 1
}
struct Delegate;
impl AppDelegate<AppState> for Delegate {
fn command(
&mut self,
_ctx: &mut DelegateCtx,
_target: Target,
cmd: &Command,
data: &mut AppState,
_env: &Env,
) -> Handled {
if let Some(number) = cmd.get(FINISH_SLOW_FUNCTION) {
data.processing = false;
data.value = *number;
Handled::Yes
} else {
Handled::No
}
}
}
fn main() {
let main_window =
WindowDesc::new(ui_builder()).title(LocalizedString::new("Blocking functions"));
AppLauncher::with_window(main_window)
.delegate(Delegate {})
.launch(AppState::default())
.expect("launch failed");
}