1use crate::{
2 command::Command,
3 menus::{ActionItem, MenuItem, SeparatorItem, SubMenuItem},
4};
5
6#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct Menu {
12 pub title: String,
14
15 pub items: Vec<super::MenuItem>,
17
18 pub enabled: bool,
20
21 pub hotkey: Option<char>,
23
24 pub focused_item: Option<usize>,
26}
27
28impl Menu {
30 pub fn new(title: impl Into<String>) -> Self {
32 Self {
33 title: title.into(),
34 items: Vec::new(),
35 enabled: true,
36 hotkey: None,
37 focused_item: None,
38 }
39 }
40
41 pub fn with_hotkey(title: impl Into<String>, hotkey: char) -> Self {
43 Self {
44 title: title.into(),
45 items: Vec::new(),
46 enabled: true,
47 hotkey: Some(hotkey),
48 focused_item: None,
49 }
50 }
51
52 pub fn with_items<S: Into<String>>(
65 title: S,
66 hotkey: Option<char>,
67 items: Vec<MenuItem>,
68 ) -> Self {
69 Self {
70 title: title.into(),
71 items,
72 enabled: true,
73 hotkey,
74 focused_item: None,
75 }
76 }
77
78 pub fn hotkey(mut self, hotkey: char) -> Self {
80 self.hotkey = Some(hotkey);
81 self
82 }
83
84 pub fn item(mut self, item: MenuItem) -> Self {
86 self.items.push(item);
87 self
88 }
89
90 pub fn items(mut self, items: Vec<MenuItem>) -> Self {
92 self.items.extend(items);
93 self
94 }
95
96 pub fn add_action<S: Into<String>, C: Into<Command>>(
98 &mut self,
99 label: S,
100 command: C,
101 hotkey: Option<char>,
102 ) -> &mut Self {
103 let action = ActionItem::new(label, command);
104 let action = if let Some(hk) = hotkey {
105 action.hotkey(hk)
106 } else {
107 action
108 };
109 self.items.push(MenuItem::Action(action));
110 self
111 }
112
113 pub fn add_separator(&mut self) -> &mut Self {
115 self.items.push(MenuItem::Separator(SeparatorItem::new()));
116 self
117 }
118
119 pub fn add_submenu<S: Into<String>>(&mut self, label: S, hotkey: Option<char>) -> &mut Self {
121 self.items.push(MenuItem::SubMenu(SubMenuItem::with_items(
122 label,
123 hotkey,
124 vec![],
125 )));
126 self
127 }
128
129 pub fn add_item(&mut self, item: MenuItem) {
131 self.items.push(item);
132 }
133}