non_blocking_async/
non_blocking_async.rs1use std::time::Duration;
2
3use gtk::prelude::{BoxExt, ButtonExt, GtkWindowExt, OrientableExt};
4use relm4::{Component, ComponentParts, ComponentSender, RelmApp, RelmWidgetExt};
5
6struct App {
7 counter: u8,
8}
9
10#[derive(Debug)]
11enum Msg {
12 Increment,
13 Decrement,
14}
15
16#[relm4::component]
17impl Component for App {
18 type Init = ();
19 type Input = ();
20 type Output = ();
21 type CommandOutput = Msg;
22
23 view! {
24 gtk::Window {
25 set_title: Some("Async Counter"),
26 set_default_size: (300, 100),
27
28 gtk::Box {
29 set_orientation: gtk::Orientation::Vertical,
30 set_margin_all: 5,
31 set_spacing: 5,
32
33 gtk::Button {
34 set_label: "Increment",
35 connect_clicked[sender] => move |_| {
37 sender.oneshot_command(async move {
38 tokio::time::sleep(Duration::from_secs(1)).await;
39 Msg::Increment
40 })
41 },
42 },
43
44 gtk::Button::with_label("Decrement") {
45 connect_clicked[sender] => move |_| {
46 sender.oneshot_command(async move {
47 tokio::time::sleep(Duration::from_secs(1)).await;
48 Msg::Decrement
49 })
50 },
51 },
52
53 gtk::Label {
54 set_margin_all: 5,
55 #[watch]
56 set_label: &format!("Counter: {}", model.counter),
57 },
58 },
59 }
60 }
61
62 fn init(
63 _: Self::Init,
64 root: Self::Root,
65 sender: ComponentSender<Self>,
66 ) -> ComponentParts<Self> {
67 let model = App { counter: 0 };
68
69 let widgets = view_output!();
70
71 ComponentParts { model, widgets }
72 }
73
74 fn update_cmd(
75 &mut self,
76 msg: Self::CommandOutput,
77 _sender: ComponentSender<Self>,
78 _root: &Self::Root,
79 ) {
80 match msg {
81 Msg::Increment => {
82 self.counter = self.counter.wrapping_add(1);
83 }
84 Msg::Decrement => {
85 self.counter = self.counter.wrapping_sub(1);
86 }
87 }
88 }
89}
90
91fn main() {
92 let app = RelmApp::new("relm4.example.non_blocking_async");
93 app.run::<App>(());
94}