arcdps_imgui\widget/menu.rs
1// use crate::string::ImStr;
2use crate::sys;
3use crate::Ui;
4
5/// # Widgets: Menus
6impl<'ui> Ui<'ui> {
7 /// Creates and starts appending to a full-screen menu bar.
8 ///
9 /// Returns `Some(MainMenuBarToken)` if the menu bar is visible. After content has been
10 /// rendered, the token must be ended by calling `.end()`.
11 ///
12 /// Returns `None` if the menu bar is not visible and no content should be rendered.
13 #[must_use]
14 #[doc(alias = "BeginMainMenuBar")]
15 pub fn begin_main_menu_bar(&self) -> Option<MainMenuBarToken<'ui>> {
16 if unsafe { sys::igBeginMainMenuBar() } {
17 Some(MainMenuBarToken::new(self))
18 } else {
19 None
20 }
21 }
22 /// Creates a full-screen main menu bar and runs a closure to construct the contents.
23 ///
24 /// Note: the closure is not called if the menu bar is not visible.
25 #[doc(alias = "BeginMenuBar")]
26 pub fn main_menu_bar<F: FnOnce()>(&self, f: F) {
27 if let Some(_menu_bar) = self.begin_main_menu_bar() {
28 f();
29 }
30 }
31 /// Creates and starts appending to the menu bar of the current window.
32 ///
33 /// Returns `Some(MenuBarToken)` if the menu bar is visible. After content has been
34 /// rendered, the token must be ended by calling `.end()`.
35 ///
36 /// Returns `None` if the menu bar is not visible and no content should be rendered.
37 #[must_use]
38 #[doc(alias = "BeginMenuBar")]
39 pub fn begin_menu_bar(&self) -> Option<MenuBarToken<'_>> {
40 if unsafe { sys::igBeginMenuBar() } {
41 Some(MenuBarToken::new(self))
42 } else {
43 None
44 }
45 }
46 /// Creates a menu bar in the current window and runs a closure to construct the contents.
47 ///
48 /// Note: the closure is not called if the menu bar is not visible.
49 #[doc(alias = "BeginMenuBar")]
50 pub fn menu_bar<F: FnOnce()>(&self, f: F) {
51 if let Some(_menu_bar) = self.begin_menu_bar() {
52 f();
53 }
54 }
55
56 /// Creates and starts appending to a sub-menu entry.
57 ///
58 /// Returns `Some(MenuToken)` if the menu is visible. After content has been
59 /// rendered, the token must be ended by calling `.end()`.
60 ///
61 /// Returns `None` if the menu is not visible and no content should be rendered.
62 ///
63 /// This is the equivalent of [begin_menu_with_enabled](Self::begin_menu_with_enabled)
64 /// with `enabled` set to `true`.
65 #[must_use]
66 #[doc(alias = "BeginMenu")]
67 pub fn begin_menu(&self, label: impl AsRef<str>) -> Option<MenuToken<'_>> {
68 self.begin_menu_with_enabled(label, true)
69 }
70
71 /// Creates and starts appending to a sub-menu entry.
72 ///
73 /// Returns `Some(MenuToken)` if the menu is visible. After content has been
74 /// rendered, the token must be ended by calling `.end()`.
75 ///
76 /// Returns `None` if the menu is not visible and no content should be rendered.
77 #[must_use]
78 #[doc(alias = "BeginMenu")]
79 pub fn begin_menu_with_enabled(
80 &self,
81 label: impl AsRef<str>,
82 enabled: bool,
83 ) -> Option<MenuToken<'_>> {
84 if unsafe { sys::igBeginMenu(self.scratch_txt(label), enabled) } {
85 Some(MenuToken::new(self))
86 } else {
87 None
88 }
89 }
90 /// Creates a menu and runs a closure to construct the contents.
91 ///
92 /// Note: the closure is not called if the menu is not visible.
93 ///
94 /// This is the equivalent of [menu_with_enabled](Self::menu_with_enabled)
95 /// with `enabled` set to `true`.
96 #[doc(alias = "BeginMenu")]
97 pub fn menu<F: FnOnce()>(&self, label: impl AsRef<str>, f: F) {
98 self.menu_with_enabled(label, true, f);
99 }
100
101 /// Creates a menu and runs a closure to construct the contents.
102 ///
103 /// Note: the closure is not called if the menu is not visible.
104 #[doc(alias = "BeginMenu")]
105 pub fn menu_with_enabled<F: FnOnce()>(&self, label: impl AsRef<str>, enabled: bool, f: F) {
106 if let Some(_menu) = self.begin_menu_with_enabled(label, enabled) {
107 f();
108 }
109 }
110}
111
112/// Builder for a menu item.
113#[derive(Copy, Clone, Debug)]
114#[must_use]
115pub struct MenuItem<Label, Shortcut = &'static str> {
116 label: Label,
117 shortcut: Option<Shortcut>,
118 selected: bool,
119 enabled: bool,
120}
121
122impl<Label: AsRef<str>> MenuItem<Label> {
123 /// Construct a new menu item builder.
124 pub fn new(label: Label) -> Self {
125 MenuItem {
126 label,
127 shortcut: None,
128 selected: false,
129 enabled: true,
130 }
131 }
132}
133
134impl<Label: AsRef<str>, Shortcut: AsRef<str>> MenuItem<Label, Shortcut> {
135 /// Sets the menu item shortcut.
136 ///
137 /// Shortcuts are displayed for convenience only and are not automatically handled.
138 #[inline]
139 pub fn shortcut<Shortcut2: AsRef<str>>(
140 self,
141 shortcut: Shortcut2,
142 ) -> MenuItem<Label, Shortcut2> {
143 MenuItem {
144 label: self.label,
145 shortcut: Some(shortcut),
146 selected: self.selected,
147 enabled: self.enabled,
148 }
149 }
150 /// Sets the selected state of the menu item.
151 ///
152 /// Default: false
153 #[inline]
154 pub fn selected(mut self, selected: bool) -> Self {
155 self.selected = selected;
156 self
157 }
158 /// Enables/disables the menu item.
159 ///
160 /// Default: enabled
161 #[inline]
162 pub fn enabled(mut self, enabled: bool) -> Self {
163 self.enabled = enabled;
164 self
165 }
166 /// Builds the menu item.
167 ///
168 /// Returns true if the menu item is activated.
169 #[doc(alias = "MenuItemBool")]
170 pub fn build(self, ui: &Ui<'_>) -> bool {
171 unsafe {
172 let (label, shortcut) = ui.scratch_txt_with_opt(self.label, self.shortcut);
173 sys::igMenuItem_Bool(label, shortcut, self.selected, self.enabled)
174 }
175 }
176
177 #[doc(alias = "MenuItemBool")]
178 /// Builds the menu item using a mutable reference to selected state.
179 pub fn build_with_ref(self, ui: &Ui<'_>, selected: &mut bool) -> bool {
180 if self.selected(*selected).build(ui) {
181 *selected = !*selected;
182 true
183 } else {
184 false
185 }
186 }
187}
188
189create_token!(
190 /// Tracks a main menu bar that can be ended by calling `.end()`
191 /// or by dropping
192 pub struct MainMenuBarToken<'ui>;
193
194 /// Ends a main menu bar
195 drop { sys::igEndMainMenuBar() }
196);
197
198create_token!(
199 /// Tracks a menu bar that can be ended by calling `.end()`
200 /// or by dropping
201 pub struct MenuBarToken<'ui>;
202
203 /// Ends a menu bar
204 drop { sys::igEndMenuBar() }
205);
206
207create_token!(
208 /// Tracks a menu that can be ended by calling `.end()`
209 /// or by dropping
210 pub struct MenuToken<'ui>;
211
212 /// Ends a menu
213 drop { sys::igEndMenu() }
214);