muda/items/
normal.rs

1use std::{cell::RefCell, mem, rc::Rc};
2
3use crate::{accelerator::Accelerator, sealed::IsMenuItemBase, IsMenuItem, MenuId, MenuItemKind};
4
5/// A menu item inside a [`Menu`] or [`Submenu`] and contains only text.
6///
7/// [`Menu`]: crate::Menu
8/// [`Submenu`]: crate::Submenu
9#[derive(Clone)]
10pub struct MenuItem {
11    pub(crate) id: Rc<MenuId>,
12    pub(crate) inner: Rc<RefCell<crate::platform_impl::MenuChild>>,
13}
14
15impl IsMenuItemBase for MenuItem {}
16impl IsMenuItem for MenuItem {
17    fn kind(&self) -> MenuItemKind {
18        MenuItemKind::MenuItem(self.clone())
19    }
20
21    fn id(&self) -> &MenuId {
22        self.id()
23    }
24
25    fn into_id(self) -> MenuId {
26        self.into_id()
27    }
28}
29
30impl MenuItem {
31    /// Create a new menu item.
32    ///
33    /// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic
34    ///   for this menu item. To display a `&` without assigning a mnemenonic, use `&&`.
35    pub fn new<S: AsRef<str>>(text: S, enabled: bool, accelerator: Option<Accelerator>) -> Self {
36        let item = crate::platform_impl::MenuChild::new(text.as_ref(), enabled, accelerator, None);
37        Self {
38            id: Rc::new(item.id().clone()),
39            inner: Rc::new(RefCell::new(item)),
40        }
41    }
42
43    /// Create a new menu item with the specified id.
44    ///
45    /// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic
46    ///   for this menu item. To display a `&` without assigning a mnemenonic, use `&&`.
47    pub fn with_id<I: Into<MenuId>, S: AsRef<str>>(
48        id: I,
49        text: S,
50        enabled: bool,
51        accelerator: Option<Accelerator>,
52    ) -> Self {
53        let id = id.into();
54        Self {
55            id: Rc::new(id.clone()),
56            inner: Rc::new(RefCell::new(crate::platform_impl::MenuChild::new(
57                text.as_ref(),
58                enabled,
59                accelerator,
60                Some(id),
61            ))),
62        }
63    }
64
65    /// Returns a unique identifier associated with this menu item.
66    pub fn id(&self) -> &MenuId {
67        &self.id
68    }
69
70    /// Set the text for this menu item.
71    pub fn text(&self) -> String {
72        self.inner.borrow().text()
73    }
74
75    /// Set the text for this menu item. `text` could optionally contain
76    /// an `&` before a character to assign this character as the mnemonic
77    /// for this menu item. To display a `&` without assigning a mnemenonic, use `&&`.
78    pub fn set_text<S: AsRef<str>>(&self, text: S) {
79        self.inner.borrow_mut().set_text(text.as_ref())
80    }
81
82    /// Get whether this menu item is enabled or not.
83    pub fn is_enabled(&self) -> bool {
84        self.inner.borrow().is_enabled()
85    }
86
87    /// Enable or disable this menu item.
88    pub fn set_enabled(&self, enabled: bool) {
89        self.inner.borrow_mut().set_enabled(enabled)
90    }
91
92    /// Set this menu item accelerator.
93    pub fn set_accelerator(&self, accelerator: Option<Accelerator>) -> crate::Result<()> {
94        self.inner.borrow_mut().set_accelerator(accelerator)
95    }
96
97    /// Convert this menu item into its menu ID.
98    pub fn into_id(mut self) -> MenuId {
99        // Note: `Rc::into_inner` is available from Rust 1.70
100        if let Some(id) = Rc::get_mut(&mut self.id) {
101            mem::take(id)
102        } else {
103            self.id().clone()
104        }
105    }
106}