dear_imgui_rs/widget/
popup.rs1#![allow(
7 clippy::cast_possible_truncation,
8 clippy::cast_sign_loss,
9 clippy::as_conversions
10)]
11use crate::sys;
12use crate::ui::Ui;
13use crate::window::WindowFlags;
14
15impl Ui {
17 #[doc(alias = "OpenPopup")]
28 pub fn open_popup(&self, str_id: impl AsRef<str>) {
29 let str_id_ptr = self.scratch_txt(str_id);
30 unsafe { sys::igOpenPopup_Str(str_id_ptr, PopupFlags::NONE.bits()) }
31 }
32
33 #[doc(alias = "OpenPopup")]
35 pub fn open_popup_with_flags(&self, str_id: impl AsRef<str>, flags: PopupFlags) {
36 let str_id_ptr = self.scratch_txt(str_id);
37 unsafe {
38 sys::igOpenPopup_Str(str_id_ptr, flags.bits());
39 }
40 }
41
42 #[doc(alias = "BeginPopup")]
47 pub fn begin_popup(&self, str_id: impl AsRef<str>) -> Option<PopupToken<'_>> {
48 self.begin_popup_with_flags(str_id, WindowFlags::empty())
49 }
50
51 #[doc(alias = "BeginPopup")]
53 pub fn begin_popup_with_flags(
54 &self,
55 str_id: impl AsRef<str>,
56 flags: WindowFlags,
57 ) -> Option<PopupToken<'_>> {
58 let str_id_ptr = self.scratch_txt(str_id);
59 let render = unsafe { sys::igBeginPopup(str_id_ptr, flags.bits()) };
60
61 if render {
62 Some(PopupToken::new(self))
63 } else {
64 None
65 }
66 }
67
68 #[doc(alias = "BeginPopup")]
73 pub fn popup<F>(&self, str_id: impl AsRef<str>, f: F)
74 where
75 F: FnOnce(),
76 {
77 if let Some(_token) = self.begin_popup(str_id) {
78 f();
79 }
80 }
81
82 #[doc(alias = "BeginPopupModal")]
86 pub fn begin_modal_popup(&self, name: impl AsRef<str>) -> Option<ModalPopupToken<'_>> {
87 let name_ptr = self.scratch_txt(name);
88 let render = unsafe {
89 sys::igBeginPopupModal(name_ptr, std::ptr::null_mut(), WindowFlags::empty().bits())
90 };
91
92 if render {
93 Some(ModalPopupToken::new(self))
94 } else {
95 None
96 }
97 }
98
99 #[doc(alias = "BeginPopupModal")]
108 pub fn begin_modal_popup_with_opened(
109 &self,
110 name: impl AsRef<str>,
111 opened: &mut bool,
112 ) -> Option<ModalPopupToken<'_>> {
113 let name_ptr = self.scratch_txt(name);
114 let opened_ptr = opened as *mut bool;
115 let render =
116 unsafe { sys::igBeginPopupModal(name_ptr, opened_ptr, WindowFlags::empty().bits()) };
117
118 if render {
119 Some(ModalPopupToken::new(self))
120 } else {
121 None
122 }
123 }
124
125 pub fn begin_modal_popup_config<'a>(&'a self, name: &'a str) -> ModalPopup<'a> {
127 ModalPopup {
128 name,
129 opened: None,
130 flags: WindowFlags::empty(),
131 ui: self,
132 }
133 }
134
135 pub fn modal_popup<F, R>(&self, name: impl AsRef<str>, f: F) -> Option<R>
139 where
140 F: FnOnce() -> R,
141 {
142 self.begin_modal_popup(name).map(|_token| f())
143 }
144
145 pub fn modal_popup_with_opened<F, R>(
150 &self,
151 name: impl AsRef<str>,
152 opened: &mut bool,
153 f: F,
154 ) -> Option<R>
155 where
156 F: FnOnce() -> R,
157 {
158 self.begin_modal_popup_with_opened(name, opened)
159 .map(|_token| f())
160 }
161
162 #[doc(alias = "CloseCurrentPopup")]
164 pub fn close_current_popup(&self) {
165 unsafe {
166 sys::igCloseCurrentPopup();
167 }
168 }
169
170 #[doc(alias = "IsPopupOpen")]
172 pub fn is_popup_open(&self, str_id: impl AsRef<str>) -> bool {
173 let str_id_ptr = self.scratch_txt(str_id);
174 unsafe { sys::igIsPopupOpen_Str(str_id_ptr, PopupFlags::NONE.bits()) }
175 }
176
177 #[doc(alias = "IsPopupOpen")]
179 pub fn is_popup_open_with_flags(&self, str_id: impl AsRef<str>, flags: PopupFlags) -> bool {
180 let str_id_ptr = self.scratch_txt(str_id);
181 unsafe { sys::igIsPopupOpen_Str(str_id_ptr, flags.bits()) }
182 }
183
184 #[doc(alias = "BeginPopupContextItem")]
187 pub fn begin_popup_context_item(&self) -> Option<PopupToken<'_>> {
188 self.begin_popup_context_item_with_label(None)
189 }
190
191 #[doc(alias = "BeginPopupContextItem")]
193 pub fn begin_popup_context_item_with_label(
194 &self,
195 str_id: Option<&str>,
196 ) -> Option<PopupToken<'_>> {
197 let str_id_ptr = str_id
198 .map(|s| self.scratch_txt(s))
199 .unwrap_or(std::ptr::null());
200
201 let render = unsafe {
202 sys::igBeginPopupContextItem(str_id_ptr, PopupFlags::MOUSE_BUTTON_RIGHT.bits())
203 };
204
205 if render {
206 Some(PopupToken::new(self))
207 } else {
208 None
209 }
210 }
211
212 #[doc(alias = "BeginPopupContextWindow")]
214 pub fn begin_popup_context_window(&self) -> Option<PopupToken<'_>> {
215 self.begin_popup_context_window_with_label(None)
216 }
217
218 #[doc(alias = "BeginPopupContextWindow")]
220 pub fn begin_popup_context_window_with_label(
221 &self,
222 str_id: Option<&str>,
223 ) -> Option<PopupToken<'_>> {
224 let str_id_ptr = str_id
225 .map(|s| self.scratch_txt(s))
226 .unwrap_or(std::ptr::null());
227
228 let render = unsafe {
229 sys::igBeginPopupContextWindow(str_id_ptr, PopupFlags::MOUSE_BUTTON_RIGHT.bits())
230 };
231
232 if render {
233 Some(PopupToken::new(self))
234 } else {
235 None
236 }
237 }
238
239 #[doc(alias = "BeginPopupContextVoid")]
241 pub fn begin_popup_context_void(&self) -> Option<PopupToken<'_>> {
242 self.begin_popup_context_void_with_label(None)
243 }
244
245 #[doc(alias = "BeginPopupContextVoid")]
247 pub fn begin_popup_context_void_with_label(
248 &self,
249 str_id: Option<&str>,
250 ) -> Option<PopupToken<'_>> {
251 let str_id_ptr = str_id
252 .map(|s| self.scratch_txt(s))
253 .unwrap_or(std::ptr::null());
254
255 let render = unsafe {
256 sys::igBeginPopupContextVoid(str_id_ptr, PopupFlags::MOUSE_BUTTON_RIGHT.bits())
257 };
258
259 if render {
260 Some(PopupToken::new(self))
261 } else {
262 None
263 }
264 }
265}
266
267bitflags::bitflags! {
268 #[repr(transparent)]
270 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
271 pub struct PopupFlags: i32 {
272 const NONE = sys::ImGuiPopupFlags_None as i32;
274 const MOUSE_BUTTON_LEFT = sys::ImGuiPopupFlags_MouseButtonLeft as i32;
276 const MOUSE_BUTTON_RIGHT = sys::ImGuiPopupFlags_MouseButtonRight as i32;
278 const MOUSE_BUTTON_MIDDLE = sys::ImGuiPopupFlags_MouseButtonMiddle as i32;
280 const NO_OPEN_OVER_EXISTING_POPUP = sys::ImGuiPopupFlags_NoOpenOverExistingPopup as i32;
282 const NO_OPEN_OVER_ITEMS = sys::ImGuiPopupFlags_NoOpenOverItems as i32;
284 const ANY_POPUP_ID = sys::ImGuiPopupFlags_AnyPopupId as i32;
286 const ANY_POPUP_LEVEL = sys::ImGuiPopupFlags_AnyPopupLevel as i32;
288 const ANY_POPUP = Self::ANY_POPUP_ID.bits() | Self::ANY_POPUP_LEVEL.bits();
290 }
291}
292
293#[derive(Debug)]
295#[must_use]
296pub struct ModalPopup<'ui> {
297 name: &'ui str,
298 opened: Option<&'ui mut bool>,
299 flags: WindowFlags,
300 ui: &'ui Ui,
301}
302
303impl<'ui> ModalPopup<'ui> {
304 pub fn opened(mut self, opened: &'ui mut bool) -> Self {
306 self.opened = Some(opened);
307 self
308 }
309
310 pub fn flags(mut self, flags: WindowFlags) -> Self {
312 self.flags = flags;
313 self
314 }
315
316 pub fn begin(self) -> Option<ModalPopupToken<'ui>> {
318 let name_ptr = self.ui.scratch_txt(self.name);
319 let opened_ptr = self
320 .opened
321 .map(|o| o as *mut bool)
322 .unwrap_or(std::ptr::null_mut());
323
324 let render = unsafe { sys::igBeginPopupModal(name_ptr, opened_ptr, self.flags.bits()) };
325
326 if render {
327 Some(ModalPopupToken::new(self.ui))
328 } else {
329 None
330 }
331 }
332}
333
334#[must_use]
336pub struct PopupToken<'ui> {
337 ui: &'ui Ui,
338}
339
340impl<'ui> PopupToken<'ui> {
341 fn new(ui: &'ui Ui) -> Self {
343 PopupToken { ui }
344 }
345
346 pub fn end(self) {
348 }
350}
351
352impl<'ui> Drop for PopupToken<'ui> {
353 fn drop(&mut self) {
354 unsafe {
355 sys::igEndPopup();
356 }
357 }
358}
359
360#[must_use]
362pub struct ModalPopupToken<'ui> {
363 ui: &'ui Ui,
364}
365
366impl<'ui> ModalPopupToken<'ui> {
367 fn new(ui: &'ui Ui) -> Self {
369 ModalPopupToken { ui }
370 }
371
372 pub fn end(self) {
374 }
376}
377
378impl<'ui> Drop for ModalPopupToken<'ui> {
379 fn drop(&mut self) {
380 unsafe {
381 sys::igEndPopup();
382 }
383 }
384}