muda_win/items/
icon.rs

1use std::{cell::RefCell, mem, rc::Rc};
2
3use crate::{
4    accelerator::Accelerator,
5    icon::{Icon, NativeIcon},
6    sealed::IsMenuItemBase,
7    IsMenuItem, MenuId, MenuItemKind,
8};
9
10/// An icon menu item inside a [`Menu`] or [`Submenu`]
11/// and usually contains an icon and a text.
12///
13/// [`Menu`]: crate::Menu
14/// [`Submenu`]: crate::Submenu
15#[derive(Clone)]
16pub struct IconMenuItem {
17    pub(crate) id: Rc<MenuId>,
18    pub(crate) inner: Rc<RefCell<crate::platform_impl::MenuChild>>,
19}
20
21impl IsMenuItemBase for IconMenuItem {}
22impl IsMenuItem for IconMenuItem {
23    fn kind(&self) -> MenuItemKind {
24        MenuItemKind::Icon(self.clone())
25    }
26
27    fn id(&self) -> &MenuId {
28        self.id()
29    }
30
31    fn into_id(self) -> MenuId {
32        self.into_id()
33    }
34}
35
36impl IconMenuItem {
37    /// Create a new icon menu item.
38    ///
39    /// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic
40    ///   for this icon menu item. To display a `&` without assigning a mnemenonic, use `&&`.
41    pub fn new<S: AsRef<str>>(
42        text: S,
43        enabled: bool,
44        icon: Option<Icon>,
45        accelerator: Option<Accelerator>,
46    ) -> Self {
47        let item = crate::platform_impl::MenuChild::new_icon(
48            text.as_ref(),
49            enabled,
50            icon,
51            accelerator,
52            None,
53        );
54        Self {
55            id: Rc::new(item.id().clone()),
56            inner: Rc::new(RefCell::new(item)),
57        }
58    }
59
60    /// Create a new icon menu item with the specified id.
61    ///
62    /// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic
63    ///   for this icon menu item. To display a `&` without assigning a mnemenonic, use `&&`.
64    pub fn with_id<I: Into<MenuId>, S: AsRef<str>>(
65        id: I,
66        text: S,
67        enabled: bool,
68        icon: Option<Icon>,
69        accelerator: Option<Accelerator>,
70    ) -> Self {
71        let id = id.into();
72        Self {
73            id: Rc::new(id.clone()),
74            inner: Rc::new(RefCell::new(crate::platform_impl::MenuChild::new_icon(
75                text.as_ref(),
76                enabled,
77                icon,
78                accelerator,
79                Some(id),
80            ))),
81        }
82    }
83
84    /// Create a new icon menu item but with a native icon.
85    ///
86    /// See [`IconMenuItem::new`] for more info.
87    ///
88    /// ## Platform-specific:
89    ///
90    /// - **Windows / Linux**: Unsupported.
91    pub fn with_native_icon<S: AsRef<str>>(
92        text: S,
93        enabled: bool,
94        native_icon: Option<NativeIcon>,
95        accelerator: Option<Accelerator>,
96    ) -> Self {
97        let item = crate::platform_impl::MenuChild::new_native_icon(
98            text.as_ref(),
99            enabled,
100            native_icon,
101            accelerator,
102            None,
103        );
104        Self {
105            id: Rc::new(item.id().clone()),
106            inner: Rc::new(RefCell::new(item)),
107        }
108    }
109
110    /// Create a new icon menu item but with the specified id and a native icon.
111    ///
112    /// See [`IconMenuItem::new`] for more info.
113    ///
114    /// ## Platform-specific:
115    ///
116    /// - **Windows / Linux**: Unsupported.
117    pub fn with_id_and_native_icon<I: Into<MenuId>, S: AsRef<str>>(
118        id: I,
119        text: S,
120        enabled: bool,
121        native_icon: Option<NativeIcon>,
122        accelerator: Option<Accelerator>,
123    ) -> Self {
124        let id = id.into();
125        Self {
126            id: Rc::new(id.clone()),
127            inner: Rc::new(RefCell::new(
128                crate::platform_impl::MenuChild::new_native_icon(
129                    text.as_ref(),
130                    enabled,
131                    native_icon,
132                    accelerator,
133                    Some(id),
134                ),
135            )),
136        }
137    }
138
139    /// Returns a unique identifier associated with this submenu.
140    pub fn id(&self) -> &MenuId {
141        &self.id
142    }
143
144    /// Get the text for this check menu item.
145    pub fn text(&self) -> String {
146        self.inner.borrow().text()
147    }
148
149    /// Set the text for this check menu item. `text` could optionally contain
150    /// an `&` before a character to assign this character as the mnemonic
151    /// for this check menu item. To display a `&` without assigning a mnemenonic, use `&&`.
152    pub fn set_text<S: AsRef<str>>(&self, text: S) {
153        self.inner.borrow_mut().set_text(text.as_ref())
154    }
155
156    /// Get whether this check menu item is enabled or not.
157    pub fn is_enabled(&self) -> bool {
158        self.inner.borrow().is_enabled()
159    }
160
161    /// Enable or disable this check menu item.
162    pub fn set_enabled(&self, enabled: bool) {
163        self.inner.borrow_mut().set_enabled(enabled)
164    }
165
166    /// Set this icon menu item accelerator.
167    pub fn set_accelerator(&self, accelerator: Option<Accelerator>) -> crate::Result<()> {
168        self.inner.borrow_mut().set_accelerator(accelerator)
169    }
170
171    /// Change this menu item icon or remove it.
172    pub fn set_icon(&self, icon: Option<Icon>) {
173        self.inner.borrow_mut().set_icon(icon)
174    }
175
176    /// Convert this menu item into its menu ID.
177    pub fn into_id(mut self) -> MenuId {
178        // Note: `Rc::into_inner` is available from Rust 1.70
179        if let Some(id) = Rc::get_mut(&mut self.id) {
180            mem::take(id)
181        } else {
182            self.id().clone()
183        }
184    }
185}