1use crate::{
4 platform::{MenuApi, MenuItemApi, Wrapper},
5 platform_impl::{MenuImpl, MenuItemImpl},
6 ContextOwner,
7 Icon,
8};
9
10#[derive(Debug)]
12pub enum Action {
13 Event(String),
19
20 Callback(fn()),
22}
23
24impl Action {
25 pub fn new_event<S>(name: S) -> Self
30 where
31 S: Into<String>,
32 {
33 Self::Event(name.into())
34 }
35
36 pub fn new_callback(callback: fn()) -> Self { Self::Callback(callback) }
41}
42
43#[derive(Debug, Default)]
46pub struct ShortCode {
47 pub(crate) macos: Option<String>,
48}
49
50impl ShortCode {
51 pub fn macos_code(&self) -> Option<&String> { self.macos.as_ref() }
53}
54
55#[derive(Debug)]
57pub struct MenuItem(MenuItemImpl);
58
59impl MenuItem {
60 pub fn builder() -> MenuItemBuilder { MenuItemBuilder::new() }
62
63 fn new(ctx: &impl ContextOwner) -> Self { Self(MenuItemImpl::new(ctx, false)) }
64
65 pub fn separator(ctx: &impl ContextOwner) -> Self { Self(MenuItemImpl::new(ctx, true)) }
70}
71
72impl MenuItem {
73 pub fn set_title<S>(&mut self, title: S)
78 where
79 S: Into<String>,
80 {
81 self.0.set_title(title.into());
82 }
83
84 pub fn title(&self) -> String { self.0.title() }
86
87 pub fn set_action(&mut self, action: Option<Action>) { self.0.set_action(action); }
92
93 pub fn set_submenu(&mut self, submenu: Option<Menu>) { self.0.set_submenu(submenu); }
98
99 pub fn submenu(&self) -> Option<&Menu> { self.0.submenu() }
101
102 pub fn submenu_mut(&mut self) -> Option<&mut Menu> { self.0.submenu_mut() }
104
105 pub fn has_submenu(&self) -> bool { self.0.has_submenu() }
107
108 pub fn set_short_code(&mut self, short_code: ShortCode) { self.0.set_short_code(short_code); }
113
114 pub fn short_code(&self) -> &ShortCode { self.0.short_code() }
116
117 pub fn set_enabled(&mut self, enabled: bool) { self.0.set_enabled(enabled); }
122
123 pub fn enabled(&self) -> bool { self.0.enabled() }
125
126 pub fn set_tooltip(&mut self, tooltip: Option<String>) { self.0.set_tooltip(tooltip); }
131
132 pub fn tooltip(&self) -> Option<String> { self.0.tooltip() }
134
135 pub fn set_icon(&mut self, icon: Option<Icon>) { self.0.set_icon(icon); }
140
141 pub fn icon(&self) -> Option<&Icon> { self.0.icon() }
143}
144
145impl Wrapper<MenuItemImpl> for MenuItem {
146 #[inline]
147 fn get_impl(&self) -> &MenuItemImpl { &self.0 }
148
149 #[inline]
150 fn get_impl_mut(&mut self) -> &mut MenuItemImpl { &mut self.0 }
151}
152
153#[derive(Debug, Default)]
155pub struct MenuItemBuilder {
156 title: Option<String>,
157 action: Option<Action>,
158 submenu: Option<Menu>,
159 short_code: ShortCode,
160 enabled: Option<bool>,
161 icon: Option<Icon>,
162}
163
164impl MenuItemBuilder {
165 fn new() -> Self {
166 Self {
167 ..Default::default()
168 }
169 }
170
171 pub fn with_title<S>(mut self, title: S) -> MenuItemBuilder
176 where
177 S: Into<String>,
178 {
179 self.title = Some(title.into());
180 self
181 }
182
183 pub fn with_action(mut self, action: Action) -> MenuItemBuilder {
188 self.action = Some(action);
189 self
190 }
191
192 pub fn with_submenu(mut self, submenu: Menu) -> MenuItemBuilder {
197 self.submenu = Some(submenu);
198 self
199 }
200
201 pub fn with_macos_short_code<S>(mut self, short_code: S) -> MenuItemBuilder
206 where
207 S: Into<String>,
208 {
209 self.short_code.macos = Some(short_code.into());
210 self
211 }
212
213 pub fn with_enabled(mut self, enabled: bool) -> MenuItemBuilder {
218 self.enabled = Some(enabled);
219 self
220 }
221
222 pub fn with_icon(mut self, icon: Icon) -> MenuItemBuilder {
227 self.icon = Some(icon);
228 self
229 }
230
231 pub fn build(self, ctx: &impl ContextOwner) -> MenuItem {
236 let mut item = MenuItem::new(ctx);
237
238 if let Some(title) = self.title {
239 item.set_title(title);
240 }
241
242 if self.action.is_some() {
243 item.set_action(self.action);
244 }
245
246 if self.submenu.is_some() {
247 item.set_submenu(self.submenu);
248 }
249
250 item.set_short_code(self.short_code);
251
252 if let Some(enabled) = self.enabled {
253 item.set_enabled(enabled);
254 }
255
256 if self.icon.is_some() {
257 item.set_icon(self.icon);
258 }
259
260 item
261 }
262}
263
264#[derive(Debug)]
266pub struct Menu(MenuImpl);
267
268impl Menu {
269 pub fn builder() -> MenuBuilder { MenuBuilder::new() }
271
272 fn new(ctx: &impl ContextOwner, items: Vec<MenuItem>) -> Self {
273 Self(MenuImpl::new(ctx, items))
274 }
275}
276
277impl Wrapper<MenuImpl> for Menu {
278 #[inline]
279 fn get_impl(&self) -> &MenuImpl { &self.0 }
280
281 #[inline]
282 fn get_impl_mut(&mut self) -> &mut MenuImpl { &mut self.0 }
283}
284
285#[derive(Debug)]
287pub struct MenuBuilder {
288 items: Vec<MenuItem>,
289}
290
291impl MenuBuilder {
292 #[inline]
293 fn new() -> Self {
294 Self {
295 items: Vec::new()
296 }
297 }
298
299 pub fn with_item(mut self, item: MenuItem) -> MenuBuilder {
304 self.items.push(item);
305 self
306 }
307
308 pub fn build(self, ctx: &impl ContextOwner) -> Menu { Menu::new(ctx, self.items) }
313}