muda/items/check.rs
1// Copyright 2022-2022 Tauri Programme within The Commons Conservancy
2// SPDX-License-Identifier: Apache-2.inner
3// SPDX-License-Identifier: MIT
4
5use std::{cell::RefCell, mem, rc::Rc};
6
7use crate::{
8 accelerator::{Accelerator, KeyAccelerator},
9 sealed::IsMenuItemBase,
10 IsMenuItem, MenuId, MenuItemKind,
11};
12
13/// A check menu item inside a [`Menu`] or [`Submenu`]
14/// and usually contains a text and a check mark or a similar toggle
15/// that corresponds to a checked and unchecked states.
16///
17/// [`Menu`]: crate::Menu
18/// [`Submenu`]: crate::Submenu
19#[derive(Clone)]
20pub struct CheckMenuItem {
21 pub(crate) id: Rc<MenuId>,
22 pub(crate) inner: Rc<RefCell<crate::platform_impl::MenuChild>>,
23}
24
25impl IsMenuItemBase for CheckMenuItem {}
26impl IsMenuItem for CheckMenuItem {
27 fn kind(&self) -> MenuItemKind {
28 MenuItemKind::Check(self.clone())
29 }
30
31 fn id(&self) -> &MenuId {
32 self.id()
33 }
34
35 fn into_id(self) -> MenuId {
36 self.into_id()
37 }
38}
39
40impl CheckMenuItem {
41 /// Create a new check menu item.
42 ///
43 /// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic
44 /// for this check menu item. To display a `&` without assigning a mnemenonic, use `&&`.
45 pub fn new<S: AsRef<str>>(
46 text: S,
47 enabled: bool,
48 checked: bool,
49 accelerator: Option<Accelerator>,
50 ) -> Self {
51 let item = crate::platform_impl::MenuChild::new_check(
52 text.as_ref(),
53 enabled,
54 checked,
55 accelerator.map(KeyAccelerator::from),
56 None,
57 );
58 Self {
59 id: Rc::new(item.id().clone()),
60 inner: Rc::new(RefCell::new(item)),
61 }
62 }
63
64 /// Create a new check menu item with the specified id.
65 ///
66 /// - `text` could optionally contain an `&` before a character to assign this character as the mnemonic
67 /// for this check menu item. To display a `&` without assigning a mnemenonic, use `&&`.
68 pub fn with_id<I: Into<MenuId>, S: AsRef<str>>(
69 id: I,
70 text: S,
71 enabled: bool,
72 checked: bool,
73 accelerator: Option<Accelerator>,
74 ) -> Self {
75 let id = id.into();
76 Self {
77 id: Rc::new(id.clone()),
78 inner: Rc::new(RefCell::new(crate::platform_impl::MenuChild::new_check(
79 text.as_ref(),
80 enabled,
81 checked,
82 accelerator.map(KeyAccelerator::from),
83 Some(id),
84 ))),
85 }
86 }
87
88 /// Returns a unique identifier associated with this submenu.
89 pub fn id(&self) -> &MenuId {
90 &self.id
91 }
92
93 /// Get the text for this check menu item.
94 pub fn text(&self) -> String {
95 self.inner.borrow().text()
96 }
97
98 /// Set the text for this check menu item. `text` could optionally contain
99 /// an `&` before a character to assign this character as the mnemonic
100 /// for this check menu item. To display a `&` without assigning a mnemenonic, use `&&`.
101 pub fn set_text<S: AsRef<str>>(&self, text: S) {
102 self.inner.borrow_mut().set_text(text.as_ref())
103 }
104
105 /// Get whether this check menu item is enabled or not.
106 pub fn is_enabled(&self) -> bool {
107 self.inner.borrow().is_enabled()
108 }
109
110 /// Enable or disable this check menu item.
111 pub fn set_enabled(&self, enabled: bool) {
112 self.inner.borrow_mut().set_enabled(enabled)
113 }
114
115 /// Set this check menu item accelerator.
116 ///
117 /// (Note that setting an accelerator will override any existing [.set_key_accelerator()](Self::set_key_accelerator))
118 pub fn set_accelerator(&self, accelerator: Option<Accelerator>) -> crate::Result<()> {
119 self.inner
120 .borrow_mut()
121 .set_key_accelerator(accelerator.map(KeyAccelerator::from))
122 }
123
124 /// Set this check menu item accelerator using a [`KeyAccelerator`].
125 ///
126 /// (Note that setting a key_accelerator will override any existing [.set_accelerator()](Self::set_accelerator))
127 pub fn set_key_accelerator(&self, accelerator: Option<KeyAccelerator>) -> crate::Result<()> {
128 self.inner.borrow_mut().set_key_accelerator(accelerator)
129 }
130
131 /// Get whether this check menu item is checked or not.
132 pub fn is_checked(&self) -> bool {
133 self.inner.borrow().is_checked()
134 }
135
136 /// Check or Uncheck this check menu item.
137 pub fn set_checked(&self, checked: bool) {
138 self.inner.borrow_mut().set_checked(checked)
139 }
140
141 /// Convert this menu item into its menu ID.
142 pub fn into_id(mut self) -> MenuId {
143 // Note: `Rc::into_inner` is available from Rust 1.70
144 if let Some(id) = Rc::get_mut(&mut self.id) {
145 mem::take(id)
146 } else {
147 self.id().clone()
148 }
149 }
150}