From c846285de00995bdfdc87a22895d8967a1f3337a Mon Sep 17 00:00:00 2001 From: Amr Bashir Date: Wed, 2 Aug 2023 21:38:14 +0300 Subject: [PATCH] remove extranouse result return from `MenuBuilder` and `SubmenuBuilder` methods thanks to the awesome @lucasfernog Co-authored-by: Lucas Nogueira --- core/tauri/src/menu/builders/menu.rs | 231 +++++++++++----------- core/tauri/src/menu/builders/submenu.rs | 247 ++++++++++++------------ core/tauri/src/menu/mod.rs | 28 +++ 3 files changed, 268 insertions(+), 238 deletions(-) diff --git a/core/tauri/src/menu/builders/menu.rs b/core/tauri/src/menu/builders/menu.rs index 662b46694c6..60c1bbd38e8 100644 --- a/core/tauri/src/menu/builders/menu.rs +++ b/core/tauri/src/menu/builders/menu.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -use crate::{menu::*, AppHandle, Icon, Manager, Runtime}; +use crate::{menu::*, Icon, Manager, Runtime}; /// A builder type for [`Menu`] /// @@ -19,7 +19,7 @@ use crate::{menu::*, AppHandle, Icon, Manager, Runtime}; /// # height: 0, /// # }; /// # let icon2 = icon1.clone(); -/// let menu = MenuBuilder::new(&handle) +/// let menu = MenuBuilder::new(&handle, "File") /// .item(&MenuItem::new(&handle, "MenuItem 1", true, None))? /// .items(&[ /// &CheckMenuItem::new(&handle, "CheckMenuItem 1", true, true, None), @@ -38,62 +38,56 @@ use crate::{menu::*, AppHandle, Icon, Manager, Runtime}; /// Ok(()) /// }); /// ``` -pub struct MenuBuilder { - menu: Menu, - app_handle: AppHandle, +pub struct MenuBuilder<'m, R: Runtime, M: Manager> { + manager: &'m M, + items: Vec>, } -impl MenuBuilder { +impl<'m, R: Runtime, M: Manager> MenuBuilder<'m, R, M> { /// Create a new menu builder. - pub fn new>(manager: &M) -> Self { + pub fn new>(manager: &'m M) -> Self { Self { - menu: Menu::new(manager), - app_handle: manager.app_handle(), + items: Vec::new(), + manager, } } /// Add this item to the menu. - pub fn item(self, item: &dyn IsMenuItem) -> crate::Result { - self.menu.append(item)?; - Ok(self) + pub fn item(mut self, item: &dyn IsMenuItem) -> Self { + self.items.push(item.kind()); + self } /// Add these items to the menu. - pub fn items(self, items: &[&dyn IsMenuItem]) -> crate::Result { - self.menu.append_items(items)?; - Ok(self) + pub fn items(mut self, items: &[&dyn IsMenuItem]) -> Self { + for item in items { + self = self.item(*item); + } + self } /// Add a [MenuItem] to the menu. - pub fn text>(self, text: S) -> crate::Result { + pub fn text>(mut self, text: S) -> Self { + self + .items + .push(MenuItem::new(self.manager, text, true, None).kind()); self - .menu - .append(&MenuItem::new(&self.app_handle, text, true, None))?; - Ok(self) } /// Add a [CheckMenuItem] to the menu. - pub fn check>(self, text: S) -> crate::Result { - self.menu.append(&CheckMenuItem::new( - &self.app_handle, - text, - true, - true, - None, - ))?; - Ok(self) + pub fn check>(mut self, text: S) -> Self { + self + .items + .push(CheckMenuItem::new(self.manager, text, true, true, None).kind()); + self } /// Add an [IconMenuItem] to the menu. - pub fn icon>(self, text: S, icon: Icon) -> crate::Result { - self.menu.append(&IconMenuItem::new( - &self.app_handle, - text, - true, - Some(icon), - None, - ))?; - Ok(self) + pub fn icon>(mut self, text: S, icon: Icon) -> Self { + self + .items + .push(IconMenuItem::new(self.manager, text, true, Some(icon), None).kind()); + self } /// Add an [IconMenuItem] with a native icon to the menu. @@ -101,55 +95,51 @@ impl MenuBuilder { /// ## Platform-specific: /// /// - **Windows / Linux**: Unsupported. - pub fn native_icon>(self, text: S, icon: NativeIcon) -> crate::Result { - self.menu.append(&IconMenuItem::with_native_icon( - &self.app_handle, - text, - true, - Some(icon), - None, - ))?; - Ok(self) + pub fn native_icon>(mut self, text: S, icon: NativeIcon) -> Self { + self + .items + .push(IconMenuItem::with_native_icon(self.manager, text, true, Some(icon), None).kind()); + self } /// Add Separator menu item to the menu. - pub fn separator(self) -> crate::Result { + pub fn separator(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::separator(self.manager).kind()); self - .menu - .append(&PredefinedMenuItem::separator(&self.app_handle))?; - Ok(self) } /// Add Copy menu item to the menu. - pub fn copy(self) -> crate::Result { + pub fn copy(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::copy(self.manager, None).kind()); self - .menu - .append(&PredefinedMenuItem::copy(&self.app_handle, None))?; - Ok(self) } /// Add Cut menu item to the menu. - pub fn cut(self) -> crate::Result { + pub fn cut(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::cut(self.manager, None).kind()); self - .menu - .append(&PredefinedMenuItem::cut(&self.app_handle, None))?; - Ok(self) } /// Add Paste menu item to the menu. - pub fn paste(self) -> crate::Result { + pub fn paste(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::paste(self.manager, None).kind()); self - .menu - .append(&PredefinedMenuItem::paste(&self.app_handle, None))?; - Ok(self) } /// Add SelectAll menu item to the menu. - pub fn select_all(self) -> crate::Result { + pub fn select_all(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::select_all(self.manager, None).kind()); self - .menu - .append(&PredefinedMenuItem::select_all(&self.app_handle, None))?; - Ok(self) } /// Add Undo menu item to the menu. @@ -157,22 +147,22 @@ impl MenuBuilder { /// ## Platform-specific: /// /// - **Windows / Linux:** Unsupported. - pub fn undo(self) -> crate::Result { + pub fn undo(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::undo(self.manager, None).kind()); self - .menu - .append(&PredefinedMenuItem::undo(&self.app_handle, None))?; - Ok(self) } /// Add Redo menu item to the menu. /// /// ## Platform-specific: /// /// - **Windows / Linux:** Unsupported. - pub fn redo(self) -> crate::Result { + pub fn redo(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::redo(self.manager, None).kind()); self - .menu - .append(&PredefinedMenuItem::redo(&self.app_handle, None))?; - Ok(self) } /// Add Minimize window menu item to the menu. @@ -180,11 +170,11 @@ impl MenuBuilder { /// ## Platform-specific: /// /// - **Linux:** Unsupported. - pub fn minimize(self) -> crate::Result { + pub fn minimize(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::minimize(self.manager, None).kind()); self - .menu - .append(&PredefinedMenuItem::minimize(&self.app_handle, None))?; - Ok(self) } /// Add Maximize window menu item to the menu. @@ -192,11 +182,11 @@ impl MenuBuilder { /// ## Platform-specific: /// /// - **Linux:** Unsupported. - pub fn maximize(self) -> crate::Result { + pub fn maximize(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::maximize(self.manager, None).kind()); self - .menu - .append(&PredefinedMenuItem::maximize(&self.app_handle, None))?; - Ok(self) } /// Add Fullscreen menu item to the menu. @@ -204,11 +194,11 @@ impl MenuBuilder { /// ## Platform-specific: /// /// - **Windows / Linux:** Unsupported. - pub fn fullscreen(self) -> crate::Result { + pub fn fullscreen(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::fullscreen(self.manager, None).kind()); self - .menu - .append(&PredefinedMenuItem::fullscreen(&self.app_handle, None))?; - Ok(self) } /// Add Hide window menu item to the menu. @@ -216,11 +206,11 @@ impl MenuBuilder { /// ## Platform-specific: /// /// - **Linux:** Unsupported. - pub fn hide(self) -> crate::Result { + pub fn hide(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::hide(self.manager, None).kind()); self - .menu - .append(&PredefinedMenuItem::hide(&self.app_handle, None))?; - Ok(self) } /// Add Hide other windows menu item to the menu. @@ -228,11 +218,11 @@ impl MenuBuilder { /// ## Platform-specific: /// /// - **Linux:** Unsupported. - pub fn hide_others(self) -> crate::Result { + pub fn hide_others(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::hide_others(self.manager, None).kind()); self - .menu - .append(&PredefinedMenuItem::hide_others(&self.app_handle, None))?; - Ok(self) } /// Add Show all app windows menu item to the menu. @@ -240,11 +230,11 @@ impl MenuBuilder { /// ## Platform-specific: /// /// - **Windows / Linux:** Unsupported. - pub fn show_all(self) -> crate::Result { + pub fn show_all(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::show_all(self.manager, None).kind()); self - .menu - .append(&PredefinedMenuItem::show_all(&self.app_handle, None))?; - Ok(self) } /// Add Close window menu item to the menu. @@ -252,11 +242,11 @@ impl MenuBuilder { /// ## Platform-specific: /// /// - **Linux:** Unsupported. - pub fn close_window(self) -> crate::Result { + pub fn close_window(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::close_window(self.manager, None).kind()); self - .menu - .append(&PredefinedMenuItem::close_window(&self.app_handle, None))?; - Ok(self) } /// Add Quit app menu item to the menu. @@ -264,19 +254,19 @@ impl MenuBuilder { /// ## Platform-specific: /// /// - **Linux:** Unsupported. - pub fn quit(self) -> crate::Result { + pub fn quit(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::quit(self.manager, None).kind()); self - .menu - .append(&PredefinedMenuItem::quit(&self.app_handle, None))?; - Ok(self) } /// Add About app menu item to the menu. - pub fn about(self, metadata: Option) -> crate::Result { + pub fn about(mut self, metadata: Option) -> Self { + self + .items + .push(PredefinedMenuItem::about(self.manager, None, metadata).kind()); self - .menu - .append(&PredefinedMenuItem::about(&self.app_handle, None, metadata))?; - Ok(self) } /// Add Services menu item to the menu. @@ -284,15 +274,24 @@ impl MenuBuilder { /// ## Platform-specific: /// /// - **Windows / Linux:** Unsupported. - pub fn services(self) -> crate::Result { + pub fn services(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::services(self.manager, None).kind()); self - .menu - .append(&PredefinedMenuItem::services(&self.app_handle, None))?; - Ok(self) } /// Builds this menu - pub fn build(self) -> Menu { - self.menu + pub fn build(self) -> crate::Result> { + if self.items.is_empty() { + Ok(Menu::new(self.manager)) + } else { + let items = self + .items + .iter() + .map(|i| i as &dyn IsMenuItem) + .collect::>(); + Menu::with_items(self.manager, &items) + } } } diff --git a/core/tauri/src/menu/builders/submenu.rs b/core/tauri/src/menu/builders/submenu.rs index 12423f52930..66ab1dd2221 100644 --- a/core/tauri/src/menu/builders/submenu.rs +++ b/core/tauri/src/menu/builders/submenu.rs @@ -2,9 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -use crate::{menu::*, AppHandle, Icon, Manager, Runtime}; +use crate::{menu::*, Icon, Manager, Runtime}; -/// A builder type for [`Menu`] +/// A builder type for [`Submenu`] /// /// # Example /// @@ -40,68 +40,66 @@ use crate::{menu::*, AppHandle, Icon, Manager, Runtime}; /// Ok(()) /// }); /// ``` -pub struct SubmenuBuilder { - submenu: Submenu, - app_handle: AppHandle, +pub struct SubmenuBuilder<'m, R: Runtime, M: Manager> { + manager: &'m M, + text: String, + enabled: bool, + items: Vec>, } -impl SubmenuBuilder { - /// Create a new menu builder. - pub fn new, S: AsRef>(manager: &M, text: S) -> Self { +impl<'m, R: Runtime, M: Manager> SubmenuBuilder<'m, R, M> { + /// Create a new submenu builder. + pub fn new>(manager: &'m M, text: S) -> Self { Self { - submenu: Submenu::new(manager, text, true), - app_handle: manager.app_handle(), + items: Vec::new(), + text: text.as_ref().to_string(), + enabled: false, + manager, } } - /// Set the enabled state for submenu. - pub fn enabled(self, enabled: bool) -> crate::Result { - self.submenu.set_enabled(enabled)?; - Ok(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(self, item: &dyn IsMenuItem) -> crate::Result { - self.submenu.append(item)?; - Ok(self) + pub fn item(mut self, item: &dyn IsMenuItem) -> Self { + self.items.push(item.kind()); + self } /// Add these items to the submenu. - pub fn items(self, items: &[&dyn IsMenuItem]) -> crate::Result { - self.submenu.append_items(items)?; - Ok(self) + 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>(self, text: S) -> crate::Result { + pub fn text>(mut self, text: S) -> Self { + self + .items + .push(MenuItem::new(self.manager, text, true, None).kind()); self - .submenu - .append(&MenuItem::new(&self.app_handle, text, true, None))?; - Ok(self) } /// Add a [CheckMenuItem] to the submenu. - pub fn check>(self, text: S) -> crate::Result { - self.submenu.append(&CheckMenuItem::new( - &self.app_handle, - text, - true, - true, - None, - ))?; - Ok(self) + pub fn check>(mut self, text: S) -> Self { + self + .items + .push(CheckMenuItem::new(self.manager, text, true, true, None).kind()); + self } /// Add an [IconMenuItem] to the submenu. - pub fn icon>(self, text: S, icon: Icon) -> crate::Result { - self.submenu.append(&IconMenuItem::new( - &self.app_handle, - text, - true, - Some(icon), - None, - ))?; - Ok(self) + pub fn icon>(mut self, text: S, icon: Icon) -> Self { + self + .items + .push(IconMenuItem::new(self.manager, text, true, Some(icon), None).kind()); + self } /// Add an [IconMenuItem] with a native icon to the submenu. @@ -109,55 +107,51 @@ impl SubmenuBuilder { /// ## Platform-specific: /// /// - **Windows / Linux**: Unsupported. - pub fn native_icon>(self, text: S, icon: NativeIcon) -> crate::Result { - self.submenu.append(&IconMenuItem::with_native_icon( - &self.app_handle, - text, - true, - Some(icon), - None, - ))?; - Ok(self) + pub fn native_icon>(mut self, text: S, icon: NativeIcon) -> Self { + self + .items + .push(IconMenuItem::with_native_icon(self.manager, text, true, Some(icon), None).kind()); + self } /// Add Separator menu item to the submenu. - pub fn separator(self) -> crate::Result { + pub fn separator(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::separator(self.manager).kind()); self - .submenu - .append(&PredefinedMenuItem::separator(&self.app_handle))?; - Ok(self) } /// Add Copy menu item to the submenu. - pub fn copy(self) -> crate::Result { + pub fn copy(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::copy(self.manager, None).kind()); self - .submenu - .append(&PredefinedMenuItem::copy(&self.app_handle, None))?; - Ok(self) } /// Add Cut menu item to the submenu. - pub fn cut(self) -> crate::Result { + pub fn cut(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::cut(self.manager, None).kind()); self - .submenu - .append(&PredefinedMenuItem::cut(&self.app_handle, None))?; - Ok(self) } /// Add Paste menu item to the submenu. - pub fn paste(self) -> crate::Result { + pub fn paste(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::paste(self.manager, None).kind()); self - .submenu - .append(&PredefinedMenuItem::paste(&self.app_handle, None))?; - Ok(self) } /// Add SelectAll menu item to the submenu. - pub fn select_all(self) -> crate::Result { + pub fn select_all(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::select_all(self.manager, None).kind()); self - .submenu - .append(&PredefinedMenuItem::select_all(&self.app_handle, None))?; - Ok(self) } /// Add Undo menu item to the submenu. @@ -165,22 +159,22 @@ impl SubmenuBuilder { /// ## Platform-specific: /// /// - **Windows / Linux:** Unsupported. - pub fn undo(self) -> crate::Result { + pub fn undo(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::undo(self.manager, None).kind()); self - .submenu - .append(&PredefinedMenuItem::undo(&self.app_handle, None))?; - Ok(self) } /// Add Redo menu item to the submenu. /// /// ## Platform-specific: /// /// - **Windows / Linux:** Unsupported. - pub fn redo(self) -> crate::Result { + pub fn redo(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::redo(self.manager, None).kind()); self - .submenu - .append(&PredefinedMenuItem::redo(&self.app_handle, None))?; - Ok(self) } /// Add Minimize window menu item to the submenu. @@ -188,11 +182,11 @@ impl SubmenuBuilder { /// ## Platform-specific: /// /// - **Linux:** Unsupported. - pub fn minimize(self) -> crate::Result { + pub fn minimize(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::minimize(self.manager, None).kind()); self - .submenu - .append(&PredefinedMenuItem::minimize(&self.app_handle, None))?; - Ok(self) } /// Add Maximize window menu item to the submenu. @@ -200,11 +194,11 @@ impl SubmenuBuilder { /// ## Platform-specific: /// /// - **Linux:** Unsupported. - pub fn maximize(self) -> crate::Result { + pub fn maximize(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::maximize(self.manager, None).kind()); self - .submenu - .append(&PredefinedMenuItem::maximize(&self.app_handle, None))?; - Ok(self) } /// Add Fullscreen menu item to the submenu. @@ -212,11 +206,11 @@ impl SubmenuBuilder { /// ## Platform-specific: /// /// - **Windows / Linux:** Unsupported. - pub fn fullscreen(self) -> crate::Result { + pub fn fullscreen(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::fullscreen(self.manager, None).kind()); self - .submenu - .append(&PredefinedMenuItem::fullscreen(&self.app_handle, None))?; - Ok(self) } /// Add Hide window menu item to the submenu. @@ -224,11 +218,11 @@ impl SubmenuBuilder { /// ## Platform-specific: /// /// - **Linux:** Unsupported. - pub fn hide(self) -> crate::Result { + pub fn hide(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::hide(self.manager, None).kind()); self - .submenu - .append(&PredefinedMenuItem::hide(&self.app_handle, None))?; - Ok(self) } /// Add Hide other windows menu item to the submenu. @@ -236,11 +230,11 @@ impl SubmenuBuilder { /// ## Platform-specific: /// /// - **Linux:** Unsupported. - pub fn hide_others(self) -> crate::Result { + pub fn hide_others(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::hide_others(self.manager, None).kind()); self - .submenu - .append(&PredefinedMenuItem::hide_others(&self.app_handle, None))?; - Ok(self) } /// Add Show all app windows menu item to the submenu. @@ -248,11 +242,11 @@ impl SubmenuBuilder { /// ## Platform-specific: /// /// - **Windows / Linux:** Unsupported. - pub fn show_all(self) -> crate::Result { + pub fn show_all(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::show_all(self.manager, None).kind()); self - .submenu - .append(&PredefinedMenuItem::show_all(&self.app_handle, None))?; - Ok(self) } /// Add Close window menu item to the submenu. @@ -260,11 +254,11 @@ impl SubmenuBuilder { /// ## Platform-specific: /// /// - **Linux:** Unsupported. - pub fn close_window(self) -> crate::Result { + pub fn close_window(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::close_window(self.manager, None).kind()); self - .submenu - .append(&PredefinedMenuItem::close_window(&self.app_handle, None))?; - Ok(self) } /// Add Quit app menu item to the submenu. @@ -272,19 +266,19 @@ impl SubmenuBuilder { /// ## Platform-specific: /// /// - **Linux:** Unsupported. - pub fn quit(self) -> crate::Result { + pub fn quit(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::quit(self.manager, None).kind()); self - .submenu - .append(&PredefinedMenuItem::quit(&self.app_handle, None))?; - Ok(self) } /// Add About app menu item to the submenu. - pub fn about(self, metadata: Option) -> crate::Result { + pub fn about(mut self, metadata: Option) -> Self { + self + .items + .push(PredefinedMenuItem::about(self.manager, None, metadata).kind()); self - .submenu - .append(&PredefinedMenuItem::about(&self.app_handle, None, metadata))?; - Ok(self) } /// Add Services menu item to the submenu. @@ -292,15 +286,24 @@ impl SubmenuBuilder { /// ## Platform-specific: /// /// - **Windows / Linux:** Unsupported. - pub fn services(self) -> crate::Result { + pub fn services(mut self) -> Self { + self + .items + .push(PredefinedMenuItem::services(self.manager, None).kind()); self - .submenu - .append(&PredefinedMenuItem::services(&self.app_handle, None))?; - Ok(self) } - /// Builds this menu - pub fn build(self) -> Submenu { - self.submenu + /// Builds this submenu + pub fn build(self) -> crate::Result> { + if self.items.is_empty() { + Ok(Submenu::new(self.manager, self.text, self.enabled)) + } else { + let items = self + .items + .iter() + .map(|i| i as &dyn IsMenuItem) + .collect::>(); + Submenu::with_items(self.manager, self.text, self.enabled, &items) + } } } diff --git a/core/tauri/src/menu/mod.rs b/core/tauri/src/menu/mod.rs index 3c52b0285fe..41d4cdc4263 100644 --- a/core/tauri/src/menu/mod.rs +++ b/core/tauri/src/menu/mod.rs @@ -145,6 +145,34 @@ impl MenuItemKind { } } +impl Clone for MenuItemKind { + fn clone(&self) -> Self { + match self { + Self::MenuItem(i) => Self::MenuItem(i.clone()), + Self::Submenu(i) => Self::Submenu(i.clone()), + Self::Predefined(i) => Self::Predefined(i.clone()), + Self::Check(i) => Self::Check(i.clone()), + Self::Icon(i) => Self::Icon(i.clone()), + } + } +} + +impl sealed::IsMenuItemBase for MenuItemKind { + fn inner(&self) -> &dyn muda::IsMenuItem { + self.inner().inner() + } +} + +impl IsMenuItem for MenuItemKind { + fn kind(&self) -> MenuItemKind { + self.clone() + } + + fn id(&self) -> u32 { + self.id() + } +} + /// A trait that defines a generic item in a menu, which may be one of [`MenuItemKind`] /// /// # Safety