simple_manual/
simple_manual.rs

1use gtk::glib::clone;
2use gtk::prelude::{BoxExt, ButtonExt, GtkWindowExt};
3use relm4::{ComponentParts, ComponentSender, RelmApp, RelmWidgetExt, SimpleComponent};
4
5struct AppModel {
6    counter: u8,
7}
8
9#[derive(Debug)]
10enum AppMsg {
11    Increment,
12    Decrement,
13}
14
15struct AppWidgets {
16    // window: gtk::Window,
17    // vbox: gtk::Box,
18    // inc_button: gtk::Button,
19    // dec_button: gtk::Button,
20    label: gtk::Label,
21}
22
23impl SimpleComponent for AppModel {
24    type Init = u8;
25    type Input = AppMsg;
26    type Output = ();
27    type Widgets = AppWidgets;
28    type Root = gtk::Window;
29
30    fn init_root() -> Self::Root {
31        gtk::Window::builder()
32            .title("Simple app")
33            .default_width(300)
34            .default_height(100)
35            .build()
36    }
37
38    // Initialize the component.
39    fn init(
40        counter: Self::Init,
41        window: Self::Root,
42        sender: ComponentSender<Self>,
43    ) -> ComponentParts<Self> {
44        let model = AppModel { counter };
45
46        let vbox = gtk::Box::builder()
47            .orientation(gtk::Orientation::Vertical)
48            .spacing(5)
49            .build();
50
51        let inc_button = gtk::Button::with_label("Increment");
52        let dec_button = gtk::Button::with_label("Decrement");
53
54        let label = gtk::Label::new(Some(&format!("Counter: {}", model.counter)));
55        label.set_margin_all(5);
56
57        window.set_child(Some(&vbox));
58        vbox.set_margin_all(5);
59        vbox.append(&inc_button);
60        vbox.append(&dec_button);
61        vbox.append(&label);
62
63        inc_button.connect_clicked(clone!(
64            #[strong]
65            sender,
66            move |_| {
67                sender.input(AppMsg::Increment);
68            }
69        ));
70
71        dec_button.connect_clicked(clone!(
72            #[strong]
73            sender,
74            move |_| {
75                sender.input(AppMsg::Decrement);
76            }
77        ));
78
79        let widgets = AppWidgets { label };
80
81        ComponentParts { model, widgets }
82    }
83
84    fn update(&mut self, msg: Self::Input, _sender: ComponentSender<Self>) {
85        match msg {
86            AppMsg::Increment => {
87                self.counter = self.counter.wrapping_add(1);
88            }
89            AppMsg::Decrement => {
90                self.counter = self.counter.wrapping_sub(1);
91            }
92        }
93    }
94
95    // Update the view to represent the updated model.
96    fn update_view(&self, widgets: &mut Self::Widgets, _sender: ComponentSender<Self>) {
97        widgets
98            .label
99            .set_label(&format!("Counter: {}", self.counter));
100    }
101}
102
103fn main() {
104    let app = RelmApp::new("relm4.example.simple_manual");
105    app.run::<AppModel>(0);
106}