muda_win/items/
submenu.rs1use std::{cell::RefCell, mem, rc::Rc};
2
3use crate::{
4 dpi::Position, sealed::IsMenuItemBase, util::AddOp, ContextMenu, IsMenuItem, MenuId,
5 MenuItemKind,
6};
7
8#[derive(Clone)]
12pub struct Submenu {
13 pub(crate) id: Rc<MenuId>,
14 pub(crate) inner: Rc<RefCell<crate::platform_impl::MenuChild>>,
15}
16
17impl IsMenuItemBase for Submenu {}
18impl IsMenuItem for Submenu {
19 fn kind(&self) -> MenuItemKind {
20 MenuItemKind::Submenu(self.clone())
21 }
22
23 fn id(&self) -> &MenuId {
24 self.id()
25 }
26
27 fn into_id(self) -> MenuId {
28 self.into_id()
29 }
30}
31
32impl Submenu {
33 pub fn new<S: AsRef<str>>(text: S, enabled: bool) -> Self {
38 let submenu = crate::platform_impl::MenuChild::new_submenu(text.as_ref(), enabled, None);
39 Self {
40 id: Rc::new(submenu.id().clone()),
41 inner: Rc::new(RefCell::new(submenu)),
42 }
43 }
44
45 pub fn with_id<I: Into<MenuId>, S: AsRef<str>>(id: I, text: S, enabled: bool) -> Self {
50 let id = id.into();
51
52 Self {
53 id: Rc::new(id.clone()),
54 inner: Rc::new(RefCell::new(crate::platform_impl::MenuChild::new_submenu(
55 text.as_ref(),
56 enabled,
57 Some(id),
58 ))),
59 }
60 }
61
62 pub fn with_items<S: AsRef<str>>(
64 text: S,
65 enabled: bool,
66 items: &[&dyn IsMenuItem],
67 ) -> crate::Result<Self> {
68 let menu = Self::new(text, enabled);
69 menu.append_items(items)?;
70 Ok(menu)
71 }
72
73 pub fn with_id_and_items<I: Into<MenuId>, S: AsRef<str>>(
75 id: I,
76 text: S,
77 enabled: bool,
78 items: &[&dyn IsMenuItem],
79 ) -> crate::Result<Self> {
80 let menu = Self::with_id(id, text, enabled);
81 menu.append_items(items)?;
82 Ok(menu)
83 }
84
85 pub fn id(&self) -> &MenuId {
87 &self.id
88 }
89
90 pub fn append(&self, item: &dyn IsMenuItem) -> crate::Result<()> {
92 self.inner.borrow_mut().add_menu_item(item, AddOp::Append)
93 }
94
95 pub fn append_items(&self, items: &[&dyn IsMenuItem]) -> crate::Result<()> {
97 for item in items {
98 self.append(*item)?
99 }
100
101 Ok(())
102 }
103
104 pub fn prepend(&self, item: &dyn IsMenuItem) -> crate::Result<()> {
106 self.inner
107 .borrow_mut()
108 .add_menu_item(item, AddOp::Insert(0))
109 }
110
111 pub fn prepend_items(&self, items: &[&dyn IsMenuItem]) -> crate::Result<()> {
115 self.insert_items(items, 0)
116 }
117
118 pub fn insert(&self, item: &dyn IsMenuItem, position: usize) -> crate::Result<()> {
120 self.inner
121 .borrow_mut()
122 .add_menu_item(item, AddOp::Insert(position))
123 }
124
125 pub fn insert_items(&self, items: &[&dyn IsMenuItem], position: usize) -> crate::Result<()> {
127 for (i, item) in items.iter().enumerate() {
128 self.insert(*item, position + i)?
129 }
130
131 Ok(())
132 }
133
134 pub fn remove(&self, item: &dyn IsMenuItem) -> crate::Result<()> {
136 self.inner.borrow_mut().remove(item)
137 }
138
139 pub fn remove_at(&self, position: usize) -> Option<MenuItemKind> {
141 let mut items = self.items();
142 if items.len() > position {
143 let item = items.remove(position);
144 let _ = self.remove(item.as_ref());
145 Some(item)
146 } else {
147 None
148 }
149 }
150
151 pub fn items(&self) -> Vec<MenuItemKind> {
153 self.inner.borrow().items()
154 }
155
156 pub fn text(&self) -> String {
158 self.inner.borrow().text()
159 }
160
161 pub fn set_text<S: AsRef<str>>(&self, text: S) {
165 self.inner.borrow_mut().set_text(text.as_ref())
166 }
167
168 pub fn is_enabled(&self) -> bool {
170 self.inner.borrow().is_enabled()
171 }
172
173 pub fn set_enabled(&self, enabled: bool) {
175 self.inner.borrow_mut().set_enabled(enabled)
176 }
177
178 pub fn into_id(mut self) -> MenuId {
180 if let Some(id) = Rc::get_mut(&mut self.id) {
182 mem::take(id)
183 } else {
184 self.id().clone()
185 }
186 }
187}
188
189impl ContextMenu for Submenu {
190 fn hpopupmenu(&self) -> isize {
191 self.inner.borrow().hpopupmenu()
192 }
193
194 unsafe fn show_context_menu_for_hwnd(&self, hwnd: isize, position: Option<Position>) -> bool {
195 self.inner
196 .borrow_mut()
197 .show_context_menu_for_hwnd(hwnd, position)
198 }
199
200 unsafe fn attach_menu_subclass_for_hwnd(&self, hwnd: isize) {
201 self.inner.borrow().attach_menu_subclass_for_hwnd(hwnd)
202 }
203
204 unsafe fn detach_menu_subclass_from_hwnd(&self, hwnd: isize) {
205 self.inner.borrow().detach_menu_subclass_from_hwnd(hwnd)
206 }
207}