1use crate::{Action, App, ForegroundPlatform, MutableAppContext};
2
3pub struct Menu<'a> {
4 pub name: &'a str,
5 pub items: Vec<MenuItem<'a>>,
6}
7
8pub enum MenuItem<'a> {
9 Separator,
10 Submenu(Menu<'a>),
11 Action {
12 name: &'a str,
13 action: Box<dyn Action>,
14 },
15}
16
17impl MutableAppContext {
18 pub fn set_menus(&mut self, menus: Vec<Menu>) {
19 self.foreground_platform
20 .set_menus(menus, &self.keystroke_matcher);
21 }
22}
23
24pub(crate) fn setup_menu_handlers(foreground_platform: &dyn ForegroundPlatform, app: &App) {
25 foreground_platform.on_will_open_menu(Box::new({
26 let cx = app.0.clone();
27 move || {
28 let mut cx = cx.borrow_mut();
29 cx.keystroke_matcher.clear_pending();
30 }
31 }));
32 foreground_platform.on_validate_menu_command(Box::new({
33 let cx = app.0.clone();
34 move |action| {
35 let cx = cx.borrow_mut();
36 !cx.keystroke_matcher.has_pending_keystrokes() && cx.is_action_available(action)
37 }
38 }));
39 foreground_platform.on_menu_command(Box::new({
40 let cx = app.0.clone();
41 move |action| {
42 let mut cx = cx.borrow_mut();
43 if let Some(key_window_id) = cx.cx.platform.key_window_id() {
44 if let Some(view_id) = cx.focused_view_id(key_window_id) {
45 cx.handle_dispatch_action_from_effect(key_window_id, Some(view_id), action);
46 return;
47 }
48 }
49 cx.dispatch_global_action_any(action);
50 }
51 }));
52}