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 = "OpenPopupOnItemClick")]
46 pub fn open_popup_on_item_click(&self, str_id: Option<&str>) {
47 self.open_popup_on_item_click_with_flags(str_id, PopupFlags::MOUSE_BUTTON_RIGHT);
48 }
49
50 #[doc(alias = "OpenPopupOnItemClick")]
52 pub fn open_popup_on_item_click_with_flags(&self, str_id: Option<&str>, flags: PopupFlags) {
53 let str_id_ptr = str_id
54 .map(|s| self.scratch_txt(s))
55 .unwrap_or(std::ptr::null());
56 unsafe { sys::igOpenPopupOnItemClick(str_id_ptr, flags.bits()) }
57 }
58
59 #[doc(alias = "BeginPopup")]
64 pub fn begin_popup(&self, str_id: impl AsRef<str>) -> Option<PopupToken<'_>> {
65 self.begin_popup_with_flags(str_id, WindowFlags::empty())
66 }
67
68 #[doc(alias = "BeginPopup")]
70 pub fn begin_popup_with_flags(
71 &self,
72 str_id: impl AsRef<str>,
73 flags: WindowFlags,
74 ) -> Option<PopupToken<'_>> {
75 let str_id_ptr = self.scratch_txt(str_id);
76 let render = unsafe { sys::igBeginPopup(str_id_ptr, flags.bits()) };
77
78 if render {
79 Some(PopupToken::new(self))
80 } else {
81 None
82 }
83 }
84
85 #[doc(alias = "BeginPopup")]
90 pub fn popup<F>(&self, str_id: impl AsRef<str>, f: F)
91 where
92 F: FnOnce(),
93 {
94 if let Some(_token) = self.begin_popup(str_id) {
95 f();
96 }
97 }
98
99 #[doc(alias = "BeginPopupModal")]
103 pub fn begin_modal_popup(&self, name: impl AsRef<str>) -> Option<ModalPopupToken<'_>> {
104 let name_ptr = self.scratch_txt(name);
105 let render = unsafe {
106 sys::igBeginPopupModal(name_ptr, std::ptr::null_mut(), WindowFlags::empty().bits())
107 };
108
109 if render {
110 Some(ModalPopupToken::new(self))
111 } else {
112 None
113 }
114 }
115
116 #[doc(alias = "BeginPopupModal")]
125 pub fn begin_modal_popup_with_opened(
126 &self,
127 name: impl AsRef<str>,
128 opened: &mut bool,
129 ) -> Option<ModalPopupToken<'_>> {
130 let name_ptr = self.scratch_txt(name);
131 let opened_ptr = opened as *mut bool;
132 let render =
133 unsafe { sys::igBeginPopupModal(name_ptr, opened_ptr, WindowFlags::empty().bits()) };
134
135 if render {
136 Some(ModalPopupToken::new(self))
137 } else {
138 None
139 }
140 }
141
142 pub fn begin_modal_popup_config<'a>(&'a self, name: &'a str) -> ModalPopup<'a> {
144 ModalPopup {
145 name,
146 opened: None,
147 flags: WindowFlags::empty(),
148 ui: self,
149 }
150 }
151
152 pub fn modal_popup<F, R>(&self, name: impl AsRef<str>, f: F) -> Option<R>
156 where
157 F: FnOnce() -> R,
158 {
159 self.begin_modal_popup(name).map(|_token| f())
160 }
161
162 pub fn modal_popup_with_opened<F, R>(
167 &self,
168 name: impl AsRef<str>,
169 opened: &mut bool,
170 f: F,
171 ) -> Option<R>
172 where
173 F: FnOnce() -> R,
174 {
175 self.begin_modal_popup_with_opened(name, opened)
176 .map(|_token| f())
177 }
178
179 #[doc(alias = "CloseCurrentPopup")]
181 pub fn close_current_popup(&self) {
182 unsafe {
183 sys::igCloseCurrentPopup();
184 }
185 }
186
187 #[doc(alias = "IsPopupOpen")]
189 pub fn is_popup_open(&self, str_id: impl AsRef<str>) -> bool {
190 let str_id_ptr = self.scratch_txt(str_id);
191 unsafe { sys::igIsPopupOpen_Str(str_id_ptr, PopupFlags::NONE.bits()) }
192 }
193
194 #[doc(alias = "IsPopupOpen")]
196 pub fn is_popup_open_with_flags(&self, str_id: impl AsRef<str>, flags: PopupFlags) -> bool {
197 let str_id_ptr = self.scratch_txt(str_id);
198 unsafe { sys::igIsPopupOpen_Str(str_id_ptr, flags.bits()) }
199 }
200
201 #[doc(alias = "BeginPopupContextItem")]
204 pub fn begin_popup_context_item(&self) -> Option<PopupToken<'_>> {
205 self.begin_popup_context_item_with_label(None)
206 }
207
208 #[doc(alias = "BeginPopupContextItem")]
210 pub fn begin_popup_context_item_with_label(
211 &self,
212 str_id: Option<&str>,
213 ) -> Option<PopupToken<'_>> {
214 let str_id_ptr = str_id
215 .map(|s| self.scratch_txt(s))
216 .unwrap_or(std::ptr::null());
217
218 let render = unsafe {
219 sys::igBeginPopupContextItem(str_id_ptr, PopupFlags::MOUSE_BUTTON_RIGHT.bits())
220 };
221
222 if render {
223 Some(PopupToken::new(self))
224 } else {
225 None
226 }
227 }
228
229 #[doc(alias = "BeginPopupContextWindow")]
231 pub fn begin_popup_context_window(&self) -> Option<PopupToken<'_>> {
232 self.begin_popup_context_window_with_label(None)
233 }
234
235 #[doc(alias = "BeginPopupContextWindow")]
237 pub fn begin_popup_context_window_with_label(
238 &self,
239 str_id: Option<&str>,
240 ) -> Option<PopupToken<'_>> {
241 let str_id_ptr = str_id
242 .map(|s| self.scratch_txt(s))
243 .unwrap_or(std::ptr::null());
244
245 let render = unsafe {
246 sys::igBeginPopupContextWindow(str_id_ptr, PopupFlags::MOUSE_BUTTON_RIGHT.bits())
247 };
248
249 if render {
250 Some(PopupToken::new(self))
251 } else {
252 None
253 }
254 }
255
256 #[doc(alias = "BeginPopupContextVoid")]
258 pub fn begin_popup_context_void(&self) -> Option<PopupToken<'_>> {
259 self.begin_popup_context_void_with_label(None)
260 }
261
262 #[doc(alias = "BeginPopupContextVoid")]
264 pub fn begin_popup_context_void_with_label(
265 &self,
266 str_id: Option<&str>,
267 ) -> Option<PopupToken<'_>> {
268 let str_id_ptr = str_id
269 .map(|s| self.scratch_txt(s))
270 .unwrap_or(std::ptr::null());
271
272 let render = unsafe {
273 sys::igBeginPopupContextVoid(str_id_ptr, PopupFlags::MOUSE_BUTTON_RIGHT.bits())
274 };
275
276 if render {
277 Some(PopupToken::new(self))
278 } else {
279 None
280 }
281 }
282}
283
284bitflags::bitflags! {
285 #[repr(transparent)]
287 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
288 pub struct PopupFlags: i32 {
289 const NONE = sys::ImGuiPopupFlags_None as i32;
291 const MOUSE_BUTTON_LEFT = sys::ImGuiPopupFlags_MouseButtonLeft as i32;
293 const MOUSE_BUTTON_RIGHT = sys::ImGuiPopupFlags_MouseButtonRight as i32;
295 const MOUSE_BUTTON_MIDDLE = sys::ImGuiPopupFlags_MouseButtonMiddle as i32;
297 const NO_OPEN_OVER_EXISTING_POPUP = sys::ImGuiPopupFlags_NoOpenOverExistingPopup as i32;
299 const NO_OPEN_OVER_ITEMS = sys::ImGuiPopupFlags_NoOpenOverItems as i32;
301 const ANY_POPUP_ID = sys::ImGuiPopupFlags_AnyPopupId as i32;
303 const ANY_POPUP_LEVEL = sys::ImGuiPopupFlags_AnyPopupLevel as i32;
305 const ANY_POPUP = Self::ANY_POPUP_ID.bits() | Self::ANY_POPUP_LEVEL.bits();
307 }
308}
309
310#[derive(Debug)]
312#[must_use]
313pub struct ModalPopup<'ui> {
314 name: &'ui str,
315 opened: Option<&'ui mut bool>,
316 flags: WindowFlags,
317 ui: &'ui Ui,
318}
319
320impl<'ui> ModalPopup<'ui> {
321 pub fn opened(mut self, opened: &'ui mut bool) -> Self {
323 self.opened = Some(opened);
324 self
325 }
326
327 pub fn flags(mut self, flags: WindowFlags) -> Self {
329 self.flags = flags;
330 self
331 }
332
333 pub fn begin(self) -> Option<ModalPopupToken<'ui>> {
335 let name_ptr = self.ui.scratch_txt(self.name);
336 let opened_ptr = self
337 .opened
338 .map(|o| o as *mut bool)
339 .unwrap_or(std::ptr::null_mut());
340
341 let render = unsafe { sys::igBeginPopupModal(name_ptr, opened_ptr, self.flags.bits()) };
342
343 if render {
344 Some(ModalPopupToken::new(self.ui))
345 } else {
346 None
347 }
348 }
349}
350
351#[must_use]
353pub struct PopupToken<'ui> {
354 ui: &'ui Ui,
355}
356
357impl<'ui> PopupToken<'ui> {
358 fn new(ui: &'ui Ui) -> Self {
360 PopupToken { ui }
361 }
362
363 pub fn end(self) {
365 }
367}
368
369impl<'ui> Drop for PopupToken<'ui> {
370 fn drop(&mut self) {
371 unsafe {
372 sys::igEndPopup();
373 }
374 }
375}
376
377#[must_use]
379pub struct ModalPopupToken<'ui> {
380 ui: &'ui Ui,
381}
382
383impl<'ui> ModalPopupToken<'ui> {
384 fn new(ui: &'ui Ui) -> Self {
386 ModalPopupToken { ui }
387 }
388
389 pub fn end(self) {
391 }
393}
394
395impl<'ui> Drop for ModalPopupToken<'ui> {
396 fn drop(&mut self) {
397 unsafe {
398 sys::igEndPopup();
399 }
400 }
401}