diff --git a/.changes/predefined-menu-item-with-text-on-menu-builders.md b/.changes/predefined-menu-item-with-text-on-menu-builders.md new file mode 100644 index 000000000000..9c5a6a51b997 --- /dev/null +++ b/.changes/predefined-menu-item-with-text-on-menu-builders.md @@ -0,0 +1,5 @@ +--- +"tauri": "patch:feat" +--- + +Add new methods on `tauri::menu::MenuBuilder` and `tauri::menu::SubmenuBuilder` to create predefined menu item with specific text. diff --git a/crates/tauri/src/menu/builders/menu.rs b/crates/tauri/src/menu/builders/menu.rs index 5d968f9c6ce5..a55d777edc18 100644 --- a/crates/tauri/src/menu/builders/menu.rs +++ b/crates/tauri/src/menu/builders/menu.rs @@ -34,9 +34,9 @@ use crate::{image::Image, menu::*, Manager, Runtime}; /// }); /// ``` pub struct MenuBuilder<'m, R: Runtime, M: Manager> { - id: Option, - manager: &'m M, - items: Vec>>, + pub(crate) id: Option, + pub(crate) manager: &'m M, + pub(crate) items: Vec>>, } impl<'m, R: Runtime, M: Manager> MenuBuilder<'m, R, M> { @@ -58,261 +58,551 @@ impl<'m, R: Runtime, M: Manager> MenuBuilder<'m, R, M> { } } - /// Set the id for this menu. - pub fn id>(mut self, id: I) -> Self { - self.id.replace(id.into()); - self - } - - /// Add this item to the menu. - pub fn item(mut self, item: &dyn IsMenuItem) -> Self { - self.items.push(Ok(item.kind())); - self - } + /// Builds this menu + pub fn build(self) -> crate::Result> { + let menu = if let Some(id) = self.id { + Menu::with_id(self.manager, id)? + } else { + Menu::new(self.manager)? + }; - /// Add these items to the menu. - pub fn items(mut self, items: &[&dyn IsMenuItem]) -> Self { - for item in items { - self = self.item(*item); + for item in self.items { + let item = item?; + menu.append(&item)?; } - self - } - /// Add a [MenuItem] to the menu. - pub fn text, S: AsRef>(mut self, id: I, text: S) -> Self { - self - .items - .push(MenuItem::with_id(self.manager, id, text, true, None::<&str>).map(|i| i.kind())); - self + Ok(menu) } +} - /// Add a [CheckMenuItem] to the menu. - pub fn check, S: AsRef>(mut self, id: I, text: S) -> Self { - self.items.push( - CheckMenuItem::with_id(self.manager, id, text, true, true, None::<&str>).map(|i| i.kind()), - ); - self - } +/// A builder type for [`Submenu`] +/// +/// # Example +/// +/// ```no_run +/// use tauri::menu::*; +/// tauri::Builder::default() +/// .setup(move |app| { +/// let handle = app.handle(); +/// # let icon1 = tauri::image::Image::new(&[], 0, 0); +/// # let icon2 = icon1.clone(); +/// let menu = Menu::new(handle)?; +/// let submenu = SubmenuBuilder::new(handle, "File") +/// .item(&MenuItem::new(handle, "MenuItem 1", true, None::<&str>)?) +/// .items(&[ +/// &CheckMenuItem::new(handle, "CheckMenuItem 1", true, true, None::<&str>)?, +/// &IconMenuItem::new(handle, "IconMenuItem 1", true, Some(icon1), None::<&str>)?, +/// ]) +/// .separator() +/// .cut() +/// .copy() +/// .paste() +/// .separator() +/// .text("item2", "MenuItem 2") +/// .check("checkitem2", "CheckMenuItem 2") +/// .icon("iconitem2", "IconMenuItem 2", app.default_window_icon().cloned().unwrap()) +/// .build()?; +/// menu.append(&submenu)?; +/// app.set_menu(menu); +/// Ok(()) +/// }); +/// ``` +pub struct SubmenuBuilder<'m, R: Runtime, M: Manager> { + pub(crate) id: Option, + pub(crate) manager: &'m M, + pub(crate) text: String, + pub(crate) enabled: bool, + pub(crate) items: Vec>>, +} - /// Add an [IconMenuItem] to the menu. - pub fn icon, S: AsRef>(mut self, id: I, text: S, icon: Image<'_>) -> Self { - self.items.push( - IconMenuItem::with_id(self.manager, id, text, true, Some(icon), None::<&str>) - .map(|i| i.kind()), - ); - self +impl<'m, R: Runtime, M: Manager> SubmenuBuilder<'m, R, M> { + /// Create a new submenu builder. + /// + /// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic + /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. + pub fn new>(manager: &'m M, text: S) -> Self { + Self { + id: None, + items: Vec::new(), + text: text.as_ref().to_string(), + enabled: true, + manager, + } } - /// Add an [IconMenuItem] with a native icon to the menu. - /// - /// ## Platform-specific: + /// Create a new submenu builder with the specified id. /// - /// - **Windows / Linux**: Unsupported. - pub fn native_icon, S: AsRef>( - mut self, - id: I, - text: S, - icon: NativeIcon, - ) -> Self { - self.items.push( - IconMenuItem::with_id_and_native_icon(self.manager, id, text, true, Some(icon), None::<&str>) - .map(|i| i.kind()), - ); - self + /// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic + /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. + pub fn with_id, S: AsRef>(manager: &'m M, id: I, text: S) -> Self { + Self { + id: Some(id.into()), + text: text.as_ref().to_string(), + enabled: true, + items: Vec::new(), + manager, + } } - /// Add Separator menu item to the menu. - pub fn separator(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::separator(self.manager).map(|i| i.kind())); + /// Set the enabled state for the submenu. + pub fn enabled(mut self, enabled: bool) -> Self { + self.enabled = enabled; self } - /// Add Copy menu item to the menu. - pub fn copy(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::copy(self.manager, None).map(|i| i.kind())); - self - } + /// Builds this submenu + pub fn build(self) -> crate::Result> { + let submenu = if let Some(id) = self.id { + Submenu::with_id(self.manager, id, self.text, self.enabled)? + } else { + Submenu::new(self.manager, self.text, self.enabled)? + }; - /// Add Cut menu item to the menu. - pub fn cut(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::cut(self.manager, None).map(|i| i.kind())); - self - } + for item in self.items { + let item = item?; + submenu.append(&item)?; + } - /// Add Paste menu item to the menu. - pub fn paste(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::paste(self.manager, None).map(|i| i.kind())); - self + Ok(submenu) } +} - /// Add SelectAll menu item to the menu. - pub fn select_all(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::select_all(self.manager, None).map(|i| i.kind())); - self - } +macro_rules! shared_menu_builder { + ($menu: ty) => { + impl<'m, R: Runtime, M: Manager> $menu { + /// Set the id for this menu. + pub fn id>(mut self, id: I) -> Self { + self.id.replace(id.into()); + self + } - /// Add Undo menu item to the menu. - /// - /// ## Platform-specific: - /// - /// - **Windows / Linux:** Unsupported. - pub fn undo(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::undo(self.manager, None).map(|i| i.kind())); - self - } - /// Add Redo menu item to the menu. - /// - /// ## Platform-specific: - /// - /// - **Windows / Linux:** Unsupported. - pub fn redo(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::redo(self.manager, None).map(|i| i.kind())); - self - } + /// Add this item to the menu. + pub fn item(mut self, item: &dyn IsMenuItem) -> Self { + self.items.push(Ok(item.kind())); + self + } - /// Add Minimize window menu item to the menu. - /// - /// ## Platform-specific: - /// - /// - **Linux:** Unsupported. - pub fn minimize(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::minimize(self.manager, None).map(|i| i.kind())); - self - } + /// Add these items to the menu. + pub fn items(mut self, items: &[&dyn IsMenuItem]) -> Self { + for item in items { + self = self.item(*item); + } + self + } - /// Add Maximize window menu item to the menu. - /// - /// ## Platform-specific: - /// - /// - **Linux:** Unsupported. - pub fn maximize(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::maximize(self.manager, None).map(|i| i.kind())); - self - } + /// Add a [MenuItem] to the menu. + pub fn text, S: AsRef>(mut self, id: I, text: S) -> Self { + self + .items + .push(MenuItem::with_id(self.manager, id, text, true, None::<&str>).map(|i| i.kind())); + self + } - /// Add Fullscreen menu item to the menu. - /// - /// ## Platform-specific: - /// - /// - **Windows / Linux:** Unsupported. - pub fn fullscreen(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::fullscreen(self.manager, None).map(|i| i.kind())); - self - } + /// Add a [CheckMenuItem] to the menu. + pub fn check, S: AsRef>(mut self, id: I, text: S) -> Self { + self.items.push( + CheckMenuItem::with_id(self.manager, id, text, true, true, None::<&str>) + .map(|i| i.kind()), + ); + self + } - /// Add Hide window menu item to the menu. - /// - /// ## Platform-specific: - /// - /// - **Linux:** Unsupported. - pub fn hide(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::hide(self.manager, None).map(|i| i.kind())); - self - } + /// Add an [IconMenuItem] to the menu. + pub fn icon, S: AsRef>( + mut self, + id: I, + text: S, + icon: Image<'_>, + ) -> Self { + self.items.push( + IconMenuItem::with_id(self.manager, id, text, true, Some(icon), None::<&str>) + .map(|i| i.kind()), + ); + self + } - /// Add Hide other windows menu item to the menu. - /// - /// ## Platform-specific: - /// - /// - **Linux:** Unsupported. - pub fn hide_others(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::hide_others(self.manager, None).map(|i| i.kind())); - self - } + /// Add an [IconMenuItem] with a native icon to the menu. + /// + /// ## Platform-specific: + /// + /// - **Windows / Linux**: Unsupported. + pub fn native_icon, S: AsRef>( + mut self, + id: I, + text: S, + icon: NativeIcon, + ) -> Self { + self.items.push( + IconMenuItem::with_id_and_native_icon( + self.manager, + id, + text, + true, + Some(icon), + None::<&str>, + ) + .map(|i| i.kind()), + ); + self + } - /// Add Show all app windows menu item to the menu. - /// - /// ## Platform-specific: - /// - /// - **Windows / Linux:** Unsupported. - pub fn show_all(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::show_all(self.manager, None).map(|i| i.kind())); - self - } + /// Add Separator menu item to the menu. + pub fn separator(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::separator(self.manager).map(|i| i.kind())); + self + } - /// Add Close window menu item to the menu. - /// - /// ## Platform-specific: - /// - /// - **Linux:** Unsupported. - pub fn close_window(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::close_window(self.manager, None).map(|i| i.kind())); - self - } + /// Add Copy menu item to the menu. + pub fn copy(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::copy(self.manager, None).map(|i| i.kind())); + self + } - /// Add Quit app menu item to the menu. - /// - /// ## Platform-specific: - /// - /// - **Linux:** Unsupported. - pub fn quit(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::quit(self.manager, None).map(|i| i.kind())); - self - } + /// Add Copy menu item with specified text to the menu. + pub fn copy_with_text>(mut self, text: S) -> Self { + self + .items + .push(PredefinedMenuItem::copy(self.manager, Some(text.as_ref())).map(|i| i.kind())); + self + } - /// Add About app menu item to the menu. - pub fn about(mut self, metadata: Option>) -> Self { - self - .items - .push(PredefinedMenuItem::about(self.manager, None, metadata).map(|i| i.kind())); - self - } + /// Add Cut menu item to the menu. + pub fn cut(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::cut(self.manager, None).map(|i| i.kind())); + self + } - /// Add Services menu item to the menu. - /// - /// ## Platform-specific: - /// - /// - **Windows / Linux:** Unsupported. - pub fn services(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::services(self.manager, None).map(|i| i.kind())); - self - } + /// Add Cut menu item with specified text to the menu. + pub fn cut_with_text>(mut self, text: S) -> Self { + self + .items + .push(PredefinedMenuItem::cut(self.manager, Some(text.as_ref())).map(|i| i.kind())); + self + } - /// Builds this menu - pub fn build(self) -> crate::Result> { - let menu = if let Some(id) = self.id { - Menu::with_id(self.manager, id)? - } else { - Menu::new(self.manager)? - }; + /// Add Paste menu item to the menu. + pub fn paste(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::paste(self.manager, None).map(|i| i.kind())); + self + } - for item in self.items { - let item = item?; - menu.append(&item)?; - } + /// Add Paste menu item with specified text to the menu. + pub fn paste_with_text>(mut self, text: S) -> Self { + self + .items + .push(PredefinedMenuItem::paste(self.manager, Some(text.as_ref())).map(|i| i.kind())); + self + } - Ok(menu) - } + /// Add SelectAll menu item to the menu. + pub fn select_all(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::select_all(self.manager, None).map(|i| i.kind())); + self + } + + /// Add SelectAll menu item with specified text to the menu. + pub fn select_all_with_text>(mut self, text: S) -> Self { + self.items.push( + PredefinedMenuItem::select_all(self.manager, Some(text.as_ref())).map(|i| i.kind()), + ); + self + } + + /// Add Undo menu item to the menu. + /// + /// ## Platform-specific: + /// + /// - **Windows / Linux:** Unsupported. + pub fn undo(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::undo(self.manager, None).map(|i| i.kind())); + self + } + + /// Add Undo menu item with specified text to the menu. + /// + /// ## Platform-specific: + /// + /// - **Windows / Linux:** Unsupported. + pub fn undo_with_text>(mut self, text: S) -> Self { + self + .items + .push(PredefinedMenuItem::undo(self.manager, Some(text.as_ref())).map(|i| i.kind())); + self + } + /// Add Redo menu item to the menu. + /// + /// ## Platform-specific: + /// + /// - **Windows / Linux:** Unsupported. + pub fn redo(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::redo(self.manager, None).map(|i| i.kind())); + self + } + + /// Add Redo menu item with specified text to the menu. + /// + /// ## Platform-specific: + /// + /// - **Windows / Linux:** Unsupported. + pub fn redo_with_text>(mut self, text: S) -> Self { + self + .items + .push(PredefinedMenuItem::redo(self.manager, Some(text.as_ref())).map(|i| i.kind())); + self + } + + /// Add Minimize window menu item to the menu. + /// + /// ## Platform-specific: + /// + /// - **Linux:** Unsupported. + pub fn minimize(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::minimize(self.manager, None).map(|i| i.kind())); + self + } + + /// Add Minimize window menu item with specified text to the menu. + /// + /// ## Platform-specific: + /// + /// - **Linux:** Unsupported. + pub fn minimize_with_text>(mut self, text: S) -> Self { + self + .items + .push(PredefinedMenuItem::minimize(self.manager, Some(text.as_ref())).map(|i| i.kind())); + self + } + + /// Add Maximize window menu item to the menu. + /// + /// ## Platform-specific: + /// + /// - **Linux:** Unsupported. + pub fn maximize(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::maximize(self.manager, None).map(|i| i.kind())); + self + } + + /// Add Maximize window menu item with specified text to the menu. + /// + /// ## Platform-specific: + /// + /// - **Linux:** Unsupported. + pub fn maximize_with_text>(mut self, text: S) -> Self { + self + .items + .push(PredefinedMenuItem::maximize(self.manager, Some(text.as_ref())).map(|i| i.kind())); + self + } + + /// Add Fullscreen menu item to the menu. + /// + /// ## Platform-specific: + /// + /// - **Windows / Linux:** Unsupported. + pub fn fullscreen(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::fullscreen(self.manager, None).map(|i| i.kind())); + self + } + + /// Add Fullscreen menu item with specified text to the menu. + /// + /// ## Platform-specific: + /// + /// - **Windows / Linux:** Unsupported. + pub fn fullscreen_with_text>(mut self, text: S) -> Self { + self.items.push( + PredefinedMenuItem::fullscreen(self.manager, Some(text.as_ref())).map(|i| i.kind()), + ); + self + } + + /// Add Hide window menu item to the menu. + /// + /// ## Platform-specific: + /// + /// - **Linux:** Unsupported. + pub fn hide(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::hide(self.manager, None).map(|i| i.kind())); + self + } + + /// Add Hide window menu item with specified text to the menu. + /// + /// ## Platform-specific: + /// + /// - **Linux:** Unsupported. + pub fn hide_with_text>(mut self, text: S) -> Self { + self + .items + .push(PredefinedMenuItem::hide(self.manager, Some(text.as_ref())).map(|i| i.kind())); + self + } + + /// Add Hide other windows menu item to the menu. + /// + /// ## Platform-specific: + /// + /// - **Linux:** Unsupported. + pub fn hide_others(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::hide_others(self.manager, None).map(|i| i.kind())); + self + } + + /// Add Hide other windows menu item with specified text to the menu. + /// + /// ## Platform-specific: + /// + /// - **Linux:** Unsupported. + pub fn hide_others_with_text>(mut self, text: S) -> Self { + self.items.push( + PredefinedMenuItem::hide_others(self.manager, Some(text.as_ref())).map(|i| i.kind()), + ); + self + } + + /// Add Show all app windows menu item to the menu. + /// + /// ## Platform-specific: + /// + /// - **Windows / Linux:** Unsupported. + pub fn show_all(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::show_all(self.manager, None).map(|i| i.kind())); + self + } + + /// Add Show all app windows menu item with specified text to the menu. + /// + /// ## Platform-specific: + /// + /// - **Windows / Linux:** Unsupported. + pub fn show_all_with_text>(mut self, text: S) -> Self { + self + .items + .push(PredefinedMenuItem::show_all(self.manager, Some(text.as_ref())).map(|i| i.kind())); + self + } + + /// Add Close window menu item to the menu. + /// + /// ## Platform-specific: + /// + /// - **Linux:** Unsupported. + pub fn close_window(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::close_window(self.manager, None).map(|i| i.kind())); + self + } + + /// Add Close window menu item with specified text to the menu. + /// + /// ## Platform-specific: + /// + /// - **Linux:** Unsupported. + pub fn close_window_with_text>(mut self, text: S) -> Self { + self.items.push( + PredefinedMenuItem::close_window(self.manager, Some(text.as_ref())).map(|i| i.kind()), + ); + self + } + + /// Add Quit app menu item to the menu. + /// + /// ## Platform-specific: + /// + /// - **Linux:** Unsupported. + pub fn quit(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::quit(self.manager, None).map(|i| i.kind())); + self + } + + /// Add Quit app menu item with specified text to the menu. + /// + /// ## Platform-specific: + /// + /// - **Linux:** Unsupported. + pub fn quit_with_text>(mut self, text: S) -> Self { + self + .items + .push(PredefinedMenuItem::quit(self.manager, Some(text.as_ref())).map(|i| i.kind())); + self + } + + /// Add About app menu item to the menu. + pub fn about(mut self, metadata: Option>) -> Self { + self + .items + .push(PredefinedMenuItem::about(self.manager, None, metadata).map(|i| i.kind())); + self + } + + /// Add About app menu item with specified text to the menu. + pub fn about_with_text>( + mut self, + text: S, + metadata: Option>, + ) -> Self { + self.items.push( + PredefinedMenuItem::about(self.manager, Some(text.as_ref()), metadata).map(|i| i.kind()), + ); + self + } + + /// Add Services menu item to the menu. + /// + /// ## Platform-specific: + /// + /// - **Windows / Linux:** Unsupported. + pub fn services(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::services(self.manager, None).map(|i| i.kind())); + self + } + + /// Add Services menu item with specified text to the menu. + /// + /// ## Platform-specific: + /// + /// - **Windows / Linux:** Unsupported. + pub fn services_with_text>(mut self, text: S) -> Self { + self + .items + .push(PredefinedMenuItem::services(self.manager, Some(text.as_ref())).map(|i| i.kind())); + self + } + } + }; } + +shared_menu_builder!(MenuBuilder<'m, R, M>); +shared_menu_builder!(SubmenuBuilder<'m, R, M>); diff --git a/crates/tauri/src/menu/builders/mod.rs b/crates/tauri/src/menu/builders/mod.rs index ce898c74a0d8..ce816fbd6cea 100644 --- a/crates/tauri/src/menu/builders/mod.rs +++ b/crates/tauri/src/menu/builders/mod.rs @@ -8,10 +8,9 @@ mod menu; pub use menu::MenuBuilder; +pub use menu::SubmenuBuilder; mod normal; pub use normal::MenuItemBuilder; -mod submenu; -pub use submenu::SubmenuBuilder; mod check; pub use check::CheckMenuItemBuilder; mod icon; diff --git a/crates/tauri/src/menu/builders/submenu.rs b/crates/tauri/src/menu/builders/submenu.rs deleted file mode 100644 index c9ef2d5ee2b8..000000000000 --- a/crates/tauri/src/menu/builders/submenu.rs +++ /dev/null @@ -1,339 +0,0 @@ -// Copyright 2019-2024 Tauri Programme within The Commons Conservancy -// SPDX-License-Identifier: Apache-2.0 -// SPDX-License-Identifier: MIT - -use crate::{image::Image, menu::*, Manager, Runtime}; - -/// A builder type for [`Submenu`] -/// -/// # Example -/// -/// ```no_run -/// use tauri::menu::*; -/// tauri::Builder::default() -/// .setup(move |app| { -/// let handle = app.handle(); -/// # let icon1 = tauri::image::Image::new(&[], 0, 0); -/// # let icon2 = icon1.clone(); -/// let menu = Menu::new(handle)?; -/// let submenu = SubmenuBuilder::new(handle, "File") -/// .item(&MenuItem::new(handle, "MenuItem 1", true, None::<&str>)?) -/// .items(&[ -/// &CheckMenuItem::new(handle, "CheckMenuItem 1", true, true, None::<&str>)?, -/// &IconMenuItem::new(handle, "IconMenuItem 1", true, Some(icon1), None::<&str>)?, -/// ]) -/// .separator() -/// .cut() -/// .copy() -/// .paste() -/// .separator() -/// .text("item2", "MenuItem 2") -/// .check("checkitem2", "CheckMenuItem 2") -/// .icon("iconitem2", "IconMenuItem 2", app.default_window_icon().cloned().unwrap()) -/// .build()?; -/// menu.append(&submenu)?; -/// app.set_menu(menu); -/// Ok(()) -/// }); -/// ``` -pub struct SubmenuBuilder<'m, R: Runtime, M: Manager> { - id: Option, - manager: &'m M, - text: String, - enabled: bool, - items: Vec>>, -} - -impl<'m, R: Runtime, M: Manager> SubmenuBuilder<'m, R, M> { - /// Create a new submenu builder. - /// - /// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic - /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. - pub fn new>(manager: &'m M, text: S) -> Self { - Self { - id: None, - items: Vec::new(), - text: text.as_ref().to_string(), - enabled: true, - manager, - } - } - - /// Create a new submenu builder with the specified id. - /// - /// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic - /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`. - pub fn with_id, S: AsRef>(manager: &'m M, id: I, text: S) -> Self { - Self { - id: Some(id.into()), - text: text.as_ref().to_string(), - enabled: true, - items: Vec::new(), - manager, - } - } - - /// Set the id for this submenu. - pub fn id>(mut self, id: I) -> Self { - self.id.replace(id.into()); - self - } - - /// Set the enabled state for the submenu. - pub fn enabled(mut self, enabled: bool) -> Self { - self.enabled = enabled; - self - } - - /// Add this item to the submenu. - pub fn item(mut self, item: &dyn IsMenuItem) -> Self { - self.items.push(Ok(item.kind())); - self - } - - /// Add these items to the submenu. - pub fn items(mut self, items: &[&dyn IsMenuItem]) -> Self { - for item in items { - self = self.item(*item); - } - self - } - - /// Add a [MenuItem] to the submenu. - pub fn text, S: AsRef>(mut self, id: I, text: S) -> Self { - self - .items - .push(MenuItem::with_id(self.manager, id, text, true, None::<&str>).map(|i| i.kind())); - self - } - - /// Add a [CheckMenuItem] to the submenu. - pub fn check, S: AsRef>(mut self, id: I, text: S) -> Self { - self.items.push( - CheckMenuItem::with_id(self.manager, id, text, true, true, None::<&str>).map(|i| i.kind()), - ); - self - } - - /// Add an [IconMenuItem] to the submenu. - pub fn icon, S: AsRef>(mut self, id: I, text: S, icon: Image<'_>) -> Self { - self.items.push( - IconMenuItem::with_id(self.manager, id, text, true, Some(icon), None::<&str>) - .map(|i| i.kind()), - ); - self - } - - /// Add an [IconMenuItem] with a native icon to the submenu. - /// - /// ## Platform-specific: - /// - /// - **Windows / Linux**: Unsupported. - pub fn native_icon, S: AsRef>( - mut self, - id: I, - text: S, - icon: NativeIcon, - ) -> Self { - self.items.push( - IconMenuItem::with_id_and_native_icon(self.manager, id, text, true, Some(icon), None::<&str>) - .map(|i| i.kind()), - ); - self - } - - /// Add Separator menu item to the submenu. - pub fn separator(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::separator(self.manager).map(|i| i.kind())); - self - } - - /// Add Copy menu item to the submenu. - pub fn copy(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::copy(self.manager, None).map(|i| i.kind())); - self - } - - /// Add Cut menu item to the submenu. - pub fn cut(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::cut(self.manager, None).map(|i| i.kind())); - self - } - - /// Add Paste menu item to the submenu. - pub fn paste(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::paste(self.manager, None).map(|i| i.kind())); - self - } - - /// Add SelectAll menu item to the submenu. - pub fn select_all(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::select_all(self.manager, None).map(|i| i.kind())); - self - } - - /// Add Undo menu item to the submenu. - /// - /// ## Platform-specific: - /// - /// - **Windows / Linux:** Unsupported. - pub fn undo(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::undo(self.manager, None).map(|i| i.kind())); - self - } - /// Add Redo menu item to the submenu. - /// - /// ## Platform-specific: - /// - /// - **Windows / Linux:** Unsupported. - pub fn redo(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::redo(self.manager, None).map(|i| i.kind())); - self - } - - /// Add Minimize window menu item to the submenu. - /// - /// ## Platform-specific: - /// - /// - **Linux:** Unsupported. - pub fn minimize(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::minimize(self.manager, None).map(|i| i.kind())); - self - } - - /// Add Maximize window menu item to the submenu. - /// - /// ## Platform-specific: - /// - /// - **Linux:** Unsupported. - pub fn maximize(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::maximize(self.manager, None).map(|i| i.kind())); - self - } - - /// Add Fullscreen menu item to the submenu. - /// - /// ## Platform-specific: - /// - /// - **Windows / Linux:** Unsupported. - pub fn fullscreen(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::fullscreen(self.manager, None).map(|i| i.kind())); - self - } - - /// Add Hide window menu item to the submenu. - /// - /// ## Platform-specific: - /// - /// - **Linux:** Unsupported. - pub fn hide(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::hide(self.manager, None).map(|i| i.kind())); - self - } - - /// Add Hide other windows menu item to the submenu. - /// - /// ## Platform-specific: - /// - /// - **Linux:** Unsupported. - pub fn hide_others(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::hide_others(self.manager, None).map(|i| i.kind())); - self - } - - /// Add Show all app windows menu item to the submenu. - /// - /// ## Platform-specific: - /// - /// - **Windows / Linux:** Unsupported. - pub fn show_all(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::show_all(self.manager, None).map(|i| i.kind())); - self - } - - /// Add Close window menu item to the submenu. - /// - /// ## Platform-specific: - /// - /// - **Linux:** Unsupported. - pub fn close_window(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::close_window(self.manager, None).map(|i| i.kind())); - self - } - - /// Add Quit app menu item to the submenu. - /// - /// ## Platform-specific: - /// - /// - **Linux:** Unsupported. - pub fn quit(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::quit(self.manager, None).map(|i| i.kind())); - self - } - - /// Add About app menu item to the submenu. - pub fn about(mut self, metadata: Option>) -> Self { - self - .items - .push(PredefinedMenuItem::about(self.manager, None, metadata).map(|i| i.kind())); - self - } - - /// Add Services menu item to the submenu. - /// - /// ## Platform-specific: - /// - /// - **Windows / Linux:** Unsupported. - pub fn services(mut self) -> Self { - self - .items - .push(PredefinedMenuItem::services(self.manager, None).map(|i| i.kind())); - self - } - - /// Builds this submenu - pub fn build(self) -> crate::Result> { - let submenu = if let Some(id) = self.id { - Submenu::with_id(self.manager, id, self.text, self.enabled)? - } else { - Submenu::new(self.manager, self.text, self.enabled)? - }; - - for item in self.items { - let item = item?; - submenu.append(&item)?; - } - - Ok(submenu) - } -}