actions/
actions.rs

1use gtk::prelude::*;
2use relm4::actions::*;
3use relm4::prelude::*;
4
5#[derive(Default)]
6struct App {
7    counter: u8,
8}
9
10#[derive(Debug)]
11enum Msg {
12    Increment,
13    Decrement,
14}
15
16#[relm4::component]
17impl SimpleComponent for App {
18    type Init = ();
19    type Input = Msg;
20    type Output = ();
21
22    view! {
23        main_window = gtk::ApplicationWindow {
24            set_title: Some("Action example"),
25            set_default_size: (300, 100),
26
27            gtk::Box {
28                set_orientation: gtk::Orientation::Vertical,
29                set_margin_all: 5,
30                set_spacing: 5,
31
32                gtk::Button {
33                    set_label: "Increment",
34                    connect_clicked => Msg::Increment,
35                    ActionablePlus::set_action::<ExampleU8Action>: 1,
36                },
37
38                gtk::Button::with_label("Decrement") {
39                    connect_clicked => Msg::Decrement,
40                },
41
42                gtk::Label {
43                    set_margin_all: 5,
44                    #[watch]
45                    set_label: &format!("Counter: {}", model.counter),
46                },
47
48                gtk::MenuButton {
49                    set_menu_model: Some(&menu_model),
50                }
51            },
52        }
53    }
54
55    fn init(
56        _init: Self::Init,
57        root: Self::Root,
58        sender: ComponentSender<Self>,
59    ) -> ComponentParts<Self> {
60        let menu_model = gtk::gio::Menu::new();
61        menu_model.append(Some("Stateless"), Some(&ExampleAction::action_name()));
62
63        let model = Self { counter: 0 };
64
65        let widgets = view_output!();
66
67        let app = relm4::main_application();
68        app.set_accelerators_for_action::<ExampleAction>(&["<primary>W"]);
69
70        let action: RelmAction<ExampleAction> = RelmAction::new_stateless(move |_| {
71            println!("Statelesss action!");
72            sender.input(Msg::Increment);
73        });
74
75        let action2: RelmAction<ExampleU8Action> =
76            RelmAction::new_stateful_with_target_value(&0, |_, state, value| {
77                println!("Stateful action -> state: {state}, value: {value}");
78                *state += value;
79            });
80
81        let mut group = RelmActionGroup::<WindowActionGroup>::new();
82        group.add_action(action);
83        group.add_action(action2);
84        group.register_for_widget(&widgets.main_window);
85
86        ComponentParts { model, widgets }
87    }
88
89    fn update(&mut self, message: Self::Input, _sender: ComponentSender<Self>) {
90        match message {
91            Msg::Increment => {
92                self.counter = self.counter.wrapping_add(1);
93            }
94            Msg::Decrement => {
95                self.counter = self.counter.wrapping_sub(1);
96            }
97        }
98    }
99}
100
101relm4::new_action_group!(WindowActionGroup, "win");
102relm4::new_stateless_action!(ExampleAction, WindowActionGroup, "example");
103relm4::new_stateful_action!(ExampleU8Action, WindowActionGroup, "example2", u8, u8);
104
105fn main() {
106    let app = RelmApp::new("relm4.example.actions");
107    app.run::<App>(());
108}