1use gtk::prelude::{BoxExt, ButtonExt, GtkWindowExt, OrientableExt};
2use relm4::actions::{AccelsPlus, ActionablePlus, RelmAction, RelmActionGroup};
3use relm4::{ComponentParts, ComponentSender, RelmApp, RelmWidgetExt, SimpleComponent};
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 = u8;
19 type Input = Msg;
20 type Output = ();
21
22 view! {
23 #[root]
24 main_window = gtk::ApplicationWindow {
25 set_title: Some("Menu example"),
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 => Msg::Increment,
36 ActionablePlus::set_action::<ExampleU8Action>: 1,
37 },
38 gtk::Button {
39 set_label: "Decrement",
40 connect_clicked => Msg::Decrement,
41 },
42 gtk::Label {
43 set_margin_all: 5,
44 #[watch]
45 set_label: &format!("Counter: {}", model.counter),
46 },
47 gtk::MenuButton {
48 #[wrap(Some)]
49 set_popover = >k::PopoverMenu::from_model(Some(&main_menu)) {
50 add_child: (&popover_child, "my_widget"),
51 }
52 }
53 },
54 },
55 popover_child = gtk::Spinner {
56 set_spinning: true,
57 }
58 }
59
60 menu! {
61 main_menu: {
62 custom: "my_widget",
63 "Example" => ExampleAction,
64 "Example2" => ExampleAction,
65 "Example toggle" => ExampleU8Action(1_u8),
66 section! {
67 "Section example" => ExampleAction,
68 "Example toggle" => ExampleU8Action(1_u8),
69 },
70 section! {
71 "Example" => ExampleAction,
72 "Example2" => ExampleAction,
73 "Example Value" => ExampleU8Action(1_u8),
74 },
75 "submenu1" {
76 "Example" => ExampleAction,
77 "Example2" => ExampleAction,
78 "Example toggle" => ExampleU8Action(1_u8),
79 "submenu2" {
80 "Example" => ExampleAction,
81 "Example2" => ExampleAction,
82 "Example toggle" => ExampleU8Action(1_u8),
83 "submenu3" {
84 "Example" => ExampleAction,
85 "Example2" => ExampleAction,
86 "Example toggle" => ExampleU8Action(1_u8),
87 }
88 }
89 }
90 }
91 }
92
93 fn init(
94 counter: Self::Init,
95 root: Self::Root,
96 sender: ComponentSender<Self>,
97 ) -> ComponentParts<Self> {
98 let model = Self { counter };
124 let widgets = view_output!();
125
126 let app = relm4::main_application();
127 app.set_accelerators_for_action::<ExampleAction>(&["<primary>W"]);
128
129 let action: RelmAction<ExampleAction> = {
130 RelmAction::new_stateless(move |_| {
131 println!("Statelesss action!");
132 sender.input(Msg::Increment);
133 })
134 };
135
136 let action2: RelmAction<ExampleU8Action> =
137 RelmAction::new_stateful_with_target_value(&0, |_, state, _value| {
138 *state ^= 1;
139 dbg!(state);
140 });
141
142 let mut group = RelmActionGroup::<WindowActionGroup>::new();
143 group.add_action(action);
144 group.add_action(action2);
145 group.register_for_widget(&widgets.main_window);
146
147 ComponentParts { model, widgets }
148 }
149
150 fn update(&mut self, msg: Self::Input, _sender: ComponentSender<Self>) {
151 match msg {
152 Msg::Increment => {
153 self.counter = self.counter.wrapping_add(1);
154 }
155 Msg::Decrement => {
156 self.counter = self.counter.wrapping_sub(1);
157 }
158 }
159 }
160}
161
162relm4::new_action_group!(WindowActionGroup, "win");
163
164relm4::new_stateless_action!(ExampleAction, WindowActionGroup, "example");
165relm4::new_stateful_action!(ExampleU8Action, WindowActionGroup, "example2", u8, u8);
166
167fn main() {
168 let app = RelmApp::new("relm4.example.menu");
169 app.run::<App>(0);
170}