1use crate::Id;
16use crate::draw::DrawListMut;
17use crate::input::MouseCursor;
18use crate::internal::RawWrapper;
19use crate::string::UiBuffer;
20use crate::sys;
21use crate::texture::TextureRef;
22use std::cell::UnsafeCell;
23
24#[derive(Debug)]
26pub struct Ui {
27 buffer: UnsafeCell<UiBuffer>,
29}
30
31impl Ui {
32 fn assert_finite_f32(caller: &str, name: &str, value: f32) {
33 assert!(value.is_finite(), "{caller} {name} must be finite");
34 }
35
36 fn assert_finite_vec2(caller: &str, name: &str, value: [f32; 2]) {
37 assert!(
38 value[0].is_finite() && value[1].is_finite(),
39 "{caller} {name} must contain finite values"
40 );
41 }
42
43 #[doc(alias = "GetMainViewport")]
50 pub fn main_viewport(&self) -> &crate::platform_io::Viewport {
51 unsafe {
52 let ptr = sys::igGetMainViewport();
53 if ptr.is_null() {
54 panic!("Ui::main_viewport() requires an active ImGui context");
55 }
56 crate::platform_io::Viewport::from_raw(ptr as *const sys::ImGuiViewport)
57 }
58 }
59 pub(crate) fn new() -> Self {
63 Ui {
64 buffer: UnsafeCell::new(UiBuffer::new(1024)),
65 }
66 }
67
68 #[doc(alias = "GetIO")]
70 pub fn io(&self) -> &crate::io::Io {
71 unsafe {
72 let io = sys::igGetIO_Nil();
73 if io.is_null() {
74 panic!("Ui::io() requires an active ImGui context");
75 }
76 &*(io as *const crate::io::Io)
77 }
78 }
79
80 pub(crate) fn scratch_txt(&self, txt: impl AsRef<str>) -> *const std::os::raw::c_char {
82 unsafe {
83 let handle = &mut *self.buffer.get();
84 handle.scratch_txt(txt)
85 }
86 }
87
88 pub(crate) fn scratch_txt_two(
90 &self,
91 txt_0: impl AsRef<str>,
92 txt_1: impl AsRef<str>,
93 ) -> (*const std::os::raw::c_char, *const std::os::raw::c_char) {
94 unsafe {
95 let handle = &mut *self.buffer.get();
96 handle.scratch_txt_two(txt_0, txt_1)
97 }
98 }
99
100 pub(crate) fn scratch_txt_with_opt(
102 &self,
103 txt_0: impl AsRef<str>,
104 txt_1: Option<impl AsRef<str>>,
105 ) -> (*const std::os::raw::c_char, *const std::os::raw::c_char) {
106 unsafe {
107 let handle = &mut *self.buffer.get();
108 handle.scratch_txt_with_opt(txt_0, txt_1)
109 }
110 }
111
112 pub(crate) fn scratch_buffer(&self) -> &UnsafeCell<UiBuffer> {
114 &self.buffer
115 }
116
117 #[doc(alias = "TextUnformatted")]
119 pub fn text<T: AsRef<str>>(&self, text: T) {
120 let s = text.as_ref();
121 unsafe {
122 let start = s.as_ptr();
123 let end = start.add(s.len());
124 crate::sys::igTextUnformatted(
125 start as *const std::os::raw::c_char,
126 end as *const std::os::raw::c_char,
127 );
128 }
129 }
130
131 #[doc(alias = "SetNextWindowViewport")]
136 pub fn set_next_window_viewport(&self, viewport_id: Id) {
137 unsafe { sys::igSetNextWindowViewport(viewport_id.into()) }
138 }
139
140 #[doc(alias = "GetWindowViewport")]
144 pub fn window_viewport(&self) -> &crate::platform_io::Viewport {
145 unsafe {
146 let ptr = sys::igGetWindowViewport();
147 if ptr.is_null() {
148 panic!("Ui::window_viewport() requires a current window");
149 }
150 crate::platform_io::Viewport::from_raw(ptr as *const sys::ImGuiViewport)
151 }
152 }
153
154 #[doc(alias = "FindViewportByID")]
156 pub fn find_viewport_by_id(&self, viewport_id: Id) -> Option<&crate::platform_io::Viewport> {
157 unsafe {
158 let ptr = sys::igFindViewportByID(viewport_id.raw());
159 if ptr.is_null() {
160 None
161 } else {
162 Some(crate::platform_io::Viewport::from_raw(
163 ptr as *const sys::ImGuiViewport,
164 ))
165 }
166 }
167 }
168
169 #[doc(alias = "FindViewportByPlatformHandle")]
173 #[allow(clippy::not_unsafe_ptr_arg_deref)]
174 pub fn find_viewport_by_platform_handle(
175 &self,
176 platform_handle: *mut std::ffi::c_void,
177 ) -> Option<&crate::platform_io::Viewport> {
178 unsafe {
179 let ptr = sys::igFindViewportByPlatformHandle(platform_handle);
180 if ptr.is_null() {
181 None
182 } else {
183 Some(crate::platform_io::Viewport::from_raw(
184 ptr as *const sys::ImGuiViewport,
185 ))
186 }
187 }
188 }
189
190 #[doc(alias = "GetID")]
195 pub fn get_id(&self, label: &str) -> Id {
196 unsafe { Id::from(sys::igGetID_Str(self.scratch_txt(label))) }
197 }
198
199 #[doc(alias = "GetWindowDrawList")]
201 pub fn get_window_draw_list(&self) -> DrawListMut<'_> {
202 DrawListMut::window(self)
203 }
204
205 #[doc(alias = "GetBackgroundDrawList")]
207 pub fn get_background_draw_list(&self) -> DrawListMut<'_> {
208 DrawListMut::background(self)
209 }
210
211 #[doc(alias = "GetForegroundDrawList")]
213 pub fn get_foreground_draw_list(&self) -> DrawListMut<'_> {
214 DrawListMut::foreground(self)
215 }
216
217 pub fn window<'ui>(
219 &'ui self,
220 name: impl Into<std::borrow::Cow<'ui, str>>,
221 ) -> crate::window::Window<'ui> {
222 crate::window::Window::new(self, name)
223 }
224
225 #[doc(alias = "ShowDemoWindow")]
228 pub fn show_demo_window(&self, opened: &mut bool) {
229 unsafe {
230 crate::sys::igShowDemoWindow(opened);
231 }
232 }
233
234 #[doc(alias = "ImageWithBg")]
238 pub fn image_with_bg(
239 &self,
240 texture: impl Into<TextureRef>,
241 size: [f32; 2],
242 bg_color: [f32; 4],
243 tint_color: [f32; 4],
244 ) {
245 crate::widget::image::Image::new(self, texture, size).build_with_bg(bg_color, tint_color)
246 }
247
248 #[doc(alias = "ShowAboutWindow")]
252 pub fn show_about_window(&self, opened: &mut bool) {
253 unsafe {
254 crate::sys::igShowAboutWindow(opened);
255 }
256 }
257
258 #[doc(alias = "ShowMetricsWindow")]
263 pub fn show_metrics_window(&self, opened: &mut bool) {
264 unsafe {
265 crate::sys::igShowMetricsWindow(opened);
266 }
267 }
268
269 #[doc(alias = "ShowStyleEditor")]
271 pub fn show_style_editor(&self, style: &mut crate::style::Style) {
272 unsafe {
273 crate::sys::igShowStyleEditor(style.raw_mut());
274 }
275 }
276
277 #[doc(alias = "ShowStyleEditor")]
279 pub fn show_default_style_editor(&self) {
280 unsafe {
281 crate::sys::igShowStyleEditor(std::ptr::null_mut());
282 }
283 }
284
285 #[doc(alias = "ShowUserGuide")]
287 pub fn show_user_guide(&self) {
288 unsafe {
289 crate::sys::igShowUserGuide();
290 }
291 }
292
293 #[doc(alias = "DragFloat")]
297 pub fn drag_float(&self, label: impl AsRef<str>, value: &mut f32) -> bool {
298 crate::widget::drag::Drag::new(label).build(self, value)
299 }
300
301 #[doc(alias = "DragFloat")]
303 pub fn drag_float_config<L: AsRef<str>>(&self, label: L) -> crate::widget::drag::Drag<f32, L> {
304 crate::widget::drag::Drag::new(label)
305 }
306
307 #[doc(alias = "DragInt")]
309 pub fn drag_int(&self, label: impl AsRef<str>, value: &mut i32) -> bool {
310 crate::widget::drag::Drag::new(label).build(self, value)
311 }
312
313 #[doc(alias = "DragInt")]
315 pub fn drag_int_config<L: AsRef<str>>(&self, label: L) -> crate::widget::drag::Drag<i32, L> {
316 crate::widget::drag::Drag::new(label)
317 }
318
319 #[doc(alias = "DragFloatRange2")]
321 pub fn drag_float_range2(&self, label: impl AsRef<str>, min: &mut f32, max: &mut f32) -> bool {
322 crate::widget::drag::DragRange::<f32, _>::new(label).build(self, min, max)
323 }
324
325 #[doc(alias = "DragFloatRange2")]
327 pub fn drag_float_range2_config<L: AsRef<str>>(
328 &self,
329 label: L,
330 ) -> crate::widget::drag::DragRange<f32, L> {
331 crate::widget::drag::DragRange::new(label)
332 }
333
334 #[doc(alias = "DragIntRange2")]
336 pub fn drag_int_range2(&self, label: impl AsRef<str>, min: &mut i32, max: &mut i32) -> bool {
337 crate::widget::drag::DragRange::<i32, _>::new(label).build(self, min, max)
338 }
339
340 #[doc(alias = "DragIntRange2")]
342 pub fn drag_int_range2_config<L: AsRef<str>>(
343 &self,
344 label: L,
345 ) -> crate::widget::drag::DragRange<i32, L> {
346 crate::widget::drag::DragRange::new(label)
347 }
348
349 #[doc(alias = "GetMouseCursor")]
353 pub fn mouse_cursor(&self) -> Option<MouseCursor> {
354 unsafe {
355 match sys::igGetMouseCursor() {
356 sys::ImGuiMouseCursor_Arrow => Some(MouseCursor::Arrow),
357 sys::ImGuiMouseCursor_TextInput => Some(MouseCursor::TextInput),
358 sys::ImGuiMouseCursor_ResizeAll => Some(MouseCursor::ResizeAll),
359 sys::ImGuiMouseCursor_ResizeNS => Some(MouseCursor::ResizeNS),
360 sys::ImGuiMouseCursor_ResizeEW => Some(MouseCursor::ResizeEW),
361 sys::ImGuiMouseCursor_ResizeNESW => Some(MouseCursor::ResizeNESW),
362 sys::ImGuiMouseCursor_ResizeNWSE => Some(MouseCursor::ResizeNWSE),
363 sys::ImGuiMouseCursor_Hand => Some(MouseCursor::Hand),
364 sys::ImGuiMouseCursor_NotAllowed => Some(MouseCursor::NotAllowed),
365 _ => None,
366 }
367 }
368 }
369
370 #[doc(alias = "SetMouseCursor")]
374 pub fn set_mouse_cursor(&self, cursor_type: Option<MouseCursor>) {
375 unsafe {
376 let val: sys::ImGuiMouseCursor = cursor_type
377 .map(|x| x as sys::ImGuiMouseCursor)
378 .unwrap_or(sys::ImGuiMouseCursor_None);
379 sys::igSetMouseCursor(val);
380 }
381 }
382
383 #[doc(alias = "SetKeyboardFocusHere")]
392 pub fn set_keyboard_focus_here(&self) {
393 self.set_keyboard_focus_here_with_offset(0);
394 }
395
396 #[doc(alias = "SetKeyboardFocusHere")]
400 pub fn set_keyboard_focus_here_with_offset(&self, offset: i32) {
401 unsafe {
402 sys::igSetKeyboardFocusHere(offset);
403 }
404 }
405
406 #[doc(alias = "SetNavCursorVisible")]
408 pub fn set_nav_cursor_visible(&self, visible: bool) {
409 unsafe { sys::igSetNavCursorVisible(visible) }
410 }
411
412 #[doc(alias = "SetWindowFocus")]
418 pub fn set_window_focus(&self, name: Option<&str>) {
419 unsafe {
420 match name {
421 Some(name) => sys::igSetWindowFocus_Str(self.scratch_txt(name)),
422 None => sys::igSetWindowFocus_Nil(),
423 }
424 }
425 }
426
427 #[doc(alias = "SetWindowPos")]
429 pub fn set_window_pos(&self, pos: [f32; 2]) {
430 self.set_window_pos_with_cond(pos, crate::Condition::Always);
431 }
432
433 #[doc(alias = "SetWindowPos")]
435 pub fn set_window_pos_with_cond(&self, pos: [f32; 2], cond: crate::Condition) {
436 Self::assert_finite_vec2("Ui::set_window_pos_with_cond()", "position", pos);
437 let pos_vec = sys::ImVec2_c {
438 x: pos[0],
439 y: pos[1],
440 };
441 unsafe { sys::igSetWindowPos_Vec2(pos_vec, cond as sys::ImGuiCond) }
442 }
443
444 #[doc(alias = "SetWindowPos")]
446 pub fn set_window_pos_by_name(&self, name: impl AsRef<str>, pos: [f32; 2]) {
447 self.set_window_pos_by_name_with_cond(name, pos, crate::Condition::Always);
448 }
449
450 #[doc(alias = "SetWindowPos")]
452 pub fn set_window_pos_by_name_with_cond(
453 &self,
454 name: impl AsRef<str>,
455 pos: [f32; 2],
456 cond: crate::Condition,
457 ) {
458 Self::assert_finite_vec2("Ui::set_window_pos_by_name_with_cond()", "position", pos);
459 let pos_vec = sys::ImVec2_c {
460 x: pos[0],
461 y: pos[1],
462 };
463 unsafe { sys::igSetWindowPos_Str(self.scratch_txt(name), pos_vec, cond as sys::ImGuiCond) }
464 }
465
466 #[doc(alias = "SetWindowSize")]
468 pub fn set_window_size(&self, size: [f32; 2]) {
469 self.set_window_size_with_cond(size, crate::Condition::Always);
470 }
471
472 #[doc(alias = "SetWindowSize")]
474 pub fn set_window_size_with_cond(&self, size: [f32; 2], cond: crate::Condition) {
475 Self::assert_finite_vec2("Ui::set_window_size_with_cond()", "size", size);
476 let size_vec = sys::ImVec2_c {
477 x: size[0],
478 y: size[1],
479 };
480 unsafe { sys::igSetWindowSize_Vec2(size_vec, cond as sys::ImGuiCond) }
481 }
482
483 #[doc(alias = "SetWindowSize")]
485 pub fn set_window_size_by_name(&self, name: impl AsRef<str>, size: [f32; 2]) {
486 self.set_window_size_by_name_with_cond(name, size, crate::Condition::Always);
487 }
488
489 #[doc(alias = "SetWindowSize")]
491 pub fn set_window_size_by_name_with_cond(
492 &self,
493 name: impl AsRef<str>,
494 size: [f32; 2],
495 cond: crate::Condition,
496 ) {
497 Self::assert_finite_vec2("Ui::set_window_size_by_name_with_cond()", "size", size);
498 let size_vec = sys::ImVec2_c {
499 x: size[0],
500 y: size[1],
501 };
502 unsafe {
503 sys::igSetWindowSize_Str(self.scratch_txt(name), size_vec, cond as sys::ImGuiCond);
504 }
505 }
506
507 #[doc(alias = "SetWindowCollapsed")]
509 pub fn set_window_collapsed(&self, collapsed: bool) {
510 self.set_window_collapsed_with_cond(collapsed, crate::Condition::Always);
511 }
512
513 #[doc(alias = "SetWindowCollapsed")]
515 pub fn set_window_collapsed_with_cond(&self, collapsed: bool, cond: crate::Condition) {
516 unsafe { sys::igSetWindowCollapsed_Bool(collapsed, cond as sys::ImGuiCond) }
517 }
518
519 #[doc(alias = "SetWindowCollapsed")]
521 pub fn set_window_collapsed_by_name(&self, name: impl AsRef<str>, collapsed: bool) {
522 self.set_window_collapsed_by_name_with_cond(name, collapsed, crate::Condition::Always);
523 }
524
525 #[doc(alias = "SetWindowCollapsed")]
527 pub fn set_window_collapsed_by_name_with_cond(
528 &self,
529 name: impl AsRef<str>,
530 collapsed: bool,
531 cond: crate::Condition,
532 ) {
533 unsafe {
534 sys::igSetWindowCollapsed_Str(
535 self.scratch_txt(name),
536 collapsed,
537 cond as sys::ImGuiCond,
538 );
539 }
540 }
541
542 #[doc(alias = "SetNextItemOpen")]
546 pub fn set_next_item_open(&self, is_open: bool) {
547 unsafe {
548 sys::igSetNextItemOpen(is_open, 0); }
550 }
551
552 #[doc(alias = "SetNextItemOpen")]
554 pub fn set_next_item_open_with_cond(&self, is_open: bool, cond: crate::Condition) {
555 unsafe { sys::igSetNextItemOpen(is_open, cond as sys::ImGuiCond) }
556 }
557
558 #[doc(alias = "SetNextItemWidth")]
562 pub fn set_next_item_width(&self, item_width: f32) {
563 Self::assert_finite_f32("Ui::set_next_item_width()", "item_width", item_width);
564 unsafe {
565 sys::igSetNextItemWidth(item_width);
566 }
567 }
568
569 #[doc(alias = "GetStyle")]
585 pub unsafe fn style(&self) -> &crate::Style {
586 unsafe {
587 &*(sys::igGetStyle() as *const crate::Style)
589 }
590 }
591
592 #[doc(alias = "GetStyle")]
596 pub fn clone_style(&self) -> crate::Style {
597 unsafe { self.style().clone() }
598 }
599
600 #[doc(alias = "StyleColorsDark")]
602 pub fn style_colors_dark(&self) {
603 unsafe { sys::igStyleColorsDark(std::ptr::null_mut()) }
604 }
605
606 #[doc(alias = "StyleColorsLight")]
608 pub fn style_colors_light(&self) {
609 unsafe { sys::igStyleColorsLight(std::ptr::null_mut()) }
610 }
611
612 #[doc(alias = "StyleColorsClassic")]
614 pub fn style_colors_classic(&self) {
615 unsafe { sys::igStyleColorsClassic(std::ptr::null_mut()) }
616 }
617
618 #[doc(alias = "StyleColorsDark")]
620 pub fn style_colors_dark_into(&self, dst: &mut crate::Style) {
621 unsafe { sys::igStyleColorsDark(dst.raw_mut() as *mut sys::ImGuiStyle) }
622 }
623
624 #[doc(alias = "StyleColorsLight")]
626 pub fn style_colors_light_into(&self, dst: &mut crate::Style) {
627 unsafe { sys::igStyleColorsLight(dst.raw_mut() as *mut sys::ImGuiStyle) }
628 }
629
630 #[doc(alias = "StyleColorsClassic")]
632 pub fn style_colors_classic_into(&self, dst: &mut crate::Style) {
633 unsafe { sys::igStyleColorsClassic(dst.raw_mut() as *mut sys::ImGuiStyle) }
634 }
635
636 #[doc(alias = "GetWindowDpiScale")]
638 pub fn window_dpi_scale(&self) -> f32 {
639 unsafe { sys::igGetWindowDpiScale() }
640 }
641
642 #[doc(alias = "Value")]
644 pub fn value_bool(&self, prefix: impl AsRef<str>, v: bool) {
645 unsafe { sys::igValue_Bool(self.scratch_txt(prefix), v) }
646 }
647
648 #[doc(alias = "GetWindowWidth")]
650 pub fn window_width(&self) -> f32 {
651 unsafe { sys::igGetWindowWidth() }
652 }
653
654 #[doc(alias = "GetWindowHeight")]
656 pub fn window_height(&self) -> f32 {
657 unsafe { sys::igGetWindowHeight() }
658 }
659
660 #[doc(alias = "GetWindowPos")]
662 pub fn window_pos(&self) -> [f32; 2] {
663 let v = unsafe { sys::igGetWindowPos() };
664 [v.x, v.y]
665 }
666
667 #[doc(alias = "GetWindowSize")]
669 pub fn window_size(&self) -> [f32; 2] {
670 let v = unsafe { sys::igGetWindowSize() };
671 [v.x, v.y]
672 }
673
674 #[doc(alias = "ShowDebugLogWindow")]
682 pub fn show_debug_log_window(&self, opened: &mut bool) {
683 unsafe {
684 sys::igShowDebugLogWindow(opened);
685 }
686 }
687
688 #[doc(alias = "ShowIDStackToolWindow")]
692 pub fn show_id_stack_tool_window(&self, opened: &mut bool) {
693 unsafe {
694 sys::igShowIDStackToolWindow(opened);
695 }
696 }
697
698 #[doc(alias = "ShowStyleSelector")]
702 pub fn show_style_selector(&self, label: impl AsRef<str>) -> bool {
703 unsafe { sys::igShowStyleSelector(self.scratch_txt(label)) }
704 }
705
706 #[doc(alias = "ShowFontSelector")]
708 pub fn show_font_selector(&self, label: impl AsRef<str>) {
709 unsafe {
710 sys::igShowFontSelector(self.scratch_txt(label));
711 }
712 }
713
714 #[doc(alias = "GetVersion")]
716 pub fn get_version(&self) -> &str {
717 unsafe {
718 let version_ptr = sys::igGetVersion();
719 if version_ptr.is_null() {
720 return "Unknown";
721 }
722 let c_str = std::ffi::CStr::from_ptr(version_ptr);
723 c_str.to_str().unwrap_or("Unknown")
724 }
725 }
726}