diff --git a/.changes/item-into-id.md b/.changes/item-into-id.md new file mode 100644 index 00000000..b98c36f3 --- /dev/null +++ b/.changes/item-into-id.md @@ -0,0 +1,5 @@ +--- +"muda": "patch" +--- + +Added `into_id` method to `MenuItem`, `CheckMenuItem`, `PredefinedMenuItem`, `Submenu`, and `MenuItemKind`. It moves the menu item into its menu ID. diff --git a/src/items/check.rs b/src/items/check.rs index 6cd92ea3..a994f167 100644 --- a/src/items/check.rs +++ b/src/items/check.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.inner // SPDX-License-Identifier: MIT -use std::{cell::RefCell, rc::Rc}; +use std::{cell::RefCell, mem, rc::Rc}; use crate::{accelerator::Accelerator, IsMenuItem, MenuId, MenuItemKind}; @@ -117,4 +117,14 @@ impl CheckMenuItem { pub fn set_checked(&self, checked: bool) { self.inner.borrow_mut().set_checked(checked) } + + /// Convert this menu item into its menu ID. + pub fn into_id(mut self) -> MenuId { + // Note: `Rc::into_inner` is available from Rust 1.70 + if let Some(id) = Rc::get_mut(&mut self.id) { + mem::take(id) + } else { + self.id().clone() + } + } } diff --git a/src/items/icon.rs b/src/items/icon.rs index 1e3a44b1..6738ec5e 100644 --- a/src/items/icon.rs +++ b/src/items/icon.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.inner // SPDX-License-Identifier: MIT -use std::{cell::RefCell, rc::Rc}; +use std::{cell::RefCell, mem, rc::Rc}; use crate::{ accelerator::Accelerator, @@ -180,4 +180,14 @@ impl IconMenuItem { #[cfg(target_os = "macos")] self.inner.borrow_mut().set_native_icon(_icon) } + + /// Convert this menu item into its menu ID. + pub fn into_id(mut self) -> MenuId { + // Note: `Rc::into_inner` is available from Rust 1.70 + if let Some(id) = Rc::get_mut(&mut self.id) { + mem::take(id) + } else { + self.id().clone() + } + } } diff --git a/src/items/mod.rs b/src/items/mod.rs index a79a77ec..401f6390 100644 --- a/src/items/mod.rs +++ b/src/items/mod.rs @@ -16,7 +16,7 @@ pub use submenu::*; #[cfg(test)] mod test { - use crate::{CheckMenuItem, IconMenuItem, MenuId, MenuItem, Submenu}; + use crate::{CheckMenuItem, IconMenuItem, MenuId, MenuItem, PredefinedMenuItem, Submenu}; #[test] fn it_returns_same_id() { @@ -32,4 +32,29 @@ mod test { IconMenuItem::with_id(id.clone(), "", true, None, None).id() ); } + + #[test] + fn test_convert_from_id_and_into_id() { + let id = "TEST ID"; + let expected = MenuId(id.to_string()); + + let item = CheckMenuItem::with_id(id, "test", true, true, None); + assert_eq!(item.id(), &expected); + assert_eq!(item.into_id(), expected); + + let item = IconMenuItem::with_id(id, "test", true, None, None); + assert_eq!(item.id(), &expected); + assert_eq!(item.into_id(), expected); + + let item = MenuItem::with_id(id, "test", true, None); + assert_eq!(item.id(), &expected); + assert_eq!(item.into_id(), expected); + + let item = Submenu::with_id(id, "test", true); + assert_eq!(item.id(), &expected); + assert_eq!(item.into_id(), expected); + + let item = PredefinedMenuItem::separator(); + assert_eq!(item.id().clone(), item.into_id()); + } } diff --git a/src/items/normal.rs b/src/items/normal.rs index 52a79e8e..fef0dee6 100644 --- a/src/items/normal.rs +++ b/src/items/normal.rs @@ -1,4 +1,4 @@ -use std::{cell::RefCell, rc::Rc}; +use std::{cell::RefCell, mem, rc::Rc}; use crate::{accelerator::Accelerator, IsMenuItem, MenuId, MenuItemKind}; @@ -88,4 +88,14 @@ impl MenuItem { pub fn set_accelerator(&self, acccelerator: Option) -> crate::Result<()> { self.inner.borrow_mut().set_accelerator(acccelerator) } + + /// Convert this menu item into its menu ID. + pub fn into_id(mut self) -> MenuId { + // Note: `Rc::into_inner` is available from Rust 1.70 + if let Some(id) = Rc::get_mut(&mut self.id) { + mem::take(id) + } else { + self.id().clone() + } + } } diff --git a/src/items/predefined.rs b/src/items/predefined.rs index af01c0c6..a9c80e06 100644 --- a/src/items/predefined.rs +++ b/src/items/predefined.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.inner // SPDX-License-Identifier: MIT -use std::{cell::RefCell, rc::Rc}; +use std::{cell::RefCell, mem, rc::Rc}; use crate::{ accelerator::{Accelerator, CMD_OR_CTRL}, @@ -181,6 +181,16 @@ impl PredefinedMenuItem { pub fn set_text>(&self, text: S) { self.inner.borrow_mut().set_text(text.as_ref()) } + + /// Convert this menu item into its menu ID. + pub fn into_id(mut self) -> MenuId { + // Note: `Rc::into_inner` is available from Rust 1.70 + if let Some(id) = Rc::get_mut(&mut self.id) { + mem::take(id) + } else { + self.id().clone() + } + } } #[test] diff --git a/src/items/submenu.rs b/src/items/submenu.rs index c8b4555b..a6f15245 100644 --- a/src/items/submenu.rs +++ b/src/items/submenu.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.inner // SPDX-License-Identifier: MIT -use std::{cell::RefCell, rc::Rc}; +use std::{cell::RefCell, mem, rc::Rc}; use crate::{util::AddOp, ContextMenu, IsMenuItem, MenuId, MenuItemKind, Position}; @@ -190,6 +190,16 @@ impl Submenu { pub fn set_as_help_menu_for_nsapp(&self) { self.inner.borrow_mut().set_as_help_menu_for_nsapp() } + + /// Convert this submenu into its menu ID. + pub fn into_id(mut self) -> MenuId { + // Note: `Rc::into_inner` is available from Rust 1.70 + if let Some(id) = Rc::get_mut(&mut self.id) { + mem::take(id) + } else { + self.id().clone() + } + } } impl ContextMenu for Submenu { diff --git a/src/lib.rs b/src/lib.rs index 524a2cf4..ebefc8ca 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -256,6 +256,17 @@ impl MenuItemKind { _ => panic!("Not an IconMenuItem"), } } + + /// Convert this item into its menu ID. + pub fn into_id(self) -> MenuId { + match self { + MenuItemKind::MenuItem(i) => i.into_id(), + MenuItemKind::Submenu(i) => i.into_id(), + MenuItemKind::Predefined(i) => i.into_id(), + MenuItemKind::Check(i) => i.into_id(), + MenuItemKind::Icon(i) => i.into_id(), + } + } } /// A trait that defines a generic item in a menu, which may be one of [`MenuItemKind`]