This repository has been archived by the owner on Mar 4, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 90
/
main.rs
140 lines (117 loc) · 5.16 KB
/
main.rs
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
use gtk::prelude::*;
use gtk::AboutDialog;
use gtk::{gio, glib};
fn main() {
let application = gtk::Application::new(
Some("com.github.gtk-rs.examples.menu_bar_system"),
Default::default(),
);
application.connect_startup(|app| {
add_accelerators(app);
});
application.connect_activate(build_ui);
application.run();
}
fn add_accelerators(application: >k::Application) {
application.set_accels_for_action("app.about", &["F1"]);
// `Primary` is a platform-agnostic accelerator modifier.
// On Windows and Linux, `Primary` maps to the `Ctrl` key,
// and on macOS it maps to the `command` key.
application.set_accels_for_action("app.quit", &["<Primary>Q"]);
}
fn build_ui(application: >k::Application) {
let window = gtk::ApplicationWindow::new(application);
window.set_title("System menu bar");
window.set_border_width(10);
window.set_position(gtk::WindowPosition::Center);
window.set_default_size(350, 70);
let v_box = gtk::Box::new(gtk::Orientation::Vertical, 10);
let label = gtk::Label::new(Some("Nothing happened yet"));
let switch = gtk::Switch::new();
v_box.pack_start(&label, false, false, 0);
v_box.pack_start(&switch, true, true, 0);
window.add(&v_box);
build_system_menu(application);
add_actions(application, &switch, &label, &window);
window.show_all();
}
fn build_system_menu(application: >k::Application) {
let menu = gio::Menu::new();
let menu_bar = gio::Menu::new();
let more_menu = gio::Menu::new();
let switch_menu = gio::Menu::new();
let settings_menu = gio::Menu::new();
let submenu = gio::Menu::new();
// The first argument is the label of the menu item whereas the second is the action name. It'll
// makes more sense when you'll be reading the "add_actions" function.
menu.append(Some("Quit"), Some("app.quit"));
switch_menu.append(Some("Switch"), Some("app.switch"));
menu_bar.append_submenu(Some("_Switch"), &switch_menu);
settings_menu.append(Some("Sub another"), Some("app.sub_another"));
submenu.append(Some("Sub sub another"), Some("app.sub_sub_another"));
submenu.append(Some("Sub sub another2"), Some("app.sub_sub_another2"));
settings_menu.append_submenu(Some("Sub menu"), &submenu);
menu_bar.append_submenu(Some("_Another"), &settings_menu);
more_menu.append(Some("About"), Some("app.about"));
menu_bar.append_submenu(Some("?"), &more_menu);
application.set_app_menu(Some(&menu));
application.set_menubar(Some(&menu_bar));
}
/// This function creates "actions" which connect on the declared actions from the menu items.
fn add_actions(
application: >k::Application,
switch: >k::Switch,
label: >k::Label,
window: >k::ApplicationWindow,
) {
// Thanks to this method, we can say that this item is actually a checkbox.
let switch_action = gio::SimpleAction::new_stateful("switch", None, &false.to_variant());
switch_action.connect_activate(glib::clone!(@weak switch => move |g, _| {
let mut is_active = false;
if let Some(g) = g.state() {
is_active = g.get().expect("couldn't get bool");
// We update the state of the toggle.
switch.set_active(!is_active);
}
// We need to change the toggle state ourselves. `gio` dark magic.
g.change_state(&(!is_active).to_variant());
}));
// The same goes the around way: if we update the switch state, we need to update the menu
// item's state.
switch.connect_active_notify(glib::clone!(@weak switch_action => move |s| {
switch_action.change_state(&s.is_active().to_variant());
}));
let sub_another = gio::SimpleAction::new("sub_another", None);
sub_another.connect_activate(glib::clone!(@weak label => move |_, _| {
label.set_text("sub another menu item clicked");
}));
let sub_sub_another = gio::SimpleAction::new("sub_sub_another", None);
sub_sub_another.connect_activate(glib::clone!(@weak label => move |_, _| {
label.set_text("sub sub another menu item clicked");
}));
let sub_sub_another2 = gio::SimpleAction::new("sub_sub_another2", None);
sub_sub_another2.connect_activate(glib::clone!(@weak label => move |_, _| {
label.set_text("sub sub another2 menu item clicked");
}));
let quit = gio::SimpleAction::new("quit", None);
quit.connect_activate(glib::clone!(@weak window => move |_, _| {
window.close();
}));
let about = gio::SimpleAction::new("about", None);
about.connect_activate(glib::clone!(@weak window => move |_, _| {
let p = AboutDialog::new();
p.set_website_label(Some("gtk-rs"));
p.set_website(Some("http://gtk-rs.org"));
p.set_authors(&["gtk-rs developers"]);
p.set_title("About!");
p.set_transient_for(Some(&window));
p.show_all();
}));
// We need to add all the actions to the application so they can be taken into account.
application.add_action(&about);
application.add_action(&quit);
application.add_action(&sub_another);
application.add_action(&sub_sub_another);
application.add_action(&sub_sub_another2);
application.add_action(&switch_action);
}