Skip to main content

dear_imgui_rs/ui/
core.rs

1use super::*;
2use crate::context::binding::{CTX_MUTEX, with_bound_context};
3
4impl Ui {
5    pub(super) fn assert_finite_f32(caller: &str, name: &str, value: f32) {
6        assert!(value.is_finite(), "{caller} {name} must be finite");
7    }
8
9    pub(super) fn assert_finite_vec2(caller: &str, name: &str, value: [f32; 2]) {
10        assert!(
11            value[0].is_finite() && value[1].is_finite(),
12            "{caller} {name} must contain finite values"
13        );
14    }
15
16    /// Creates a new Ui instance
17    ///
18    /// This should only be called by Context::create()
19    pub(crate) fn new(ctx: *mut sys::ImGuiContext, ctx_alive: crate::ContextAliveToken) -> Self {
20        Ui {
21            ctx,
22            ctx_alive,
23            buffer: UnsafeCell::new(UiBuffer::new(1024)),
24        }
25    }
26
27    pub(crate) fn context_raw(&self) -> *mut sys::ImGuiContext {
28        self.ctx
29    }
30
31    pub(crate) fn context_alive_token(&self) -> crate::ContextAliveToken {
32        self.ctx_alive.clone()
33    }
34
35    pub(crate) fn run_with_bound_context<R>(&self, f: impl FnOnce() -> R) -> R {
36        let _guard = CTX_MUTEX.lock();
37        with_bound_context(self.ctx, f)
38    }
39
40    /// Runs a closure while this `Ui`'s owning ImGui context is current.
41    ///
42    /// The previously current context is restored before this method returns,
43    /// including when the closure panics. This is primarily intended for
44    /// extension crates that need to call raw Dear ImGui-adjacent FFI while
45    /// still honoring the `Ui` that created the safe wrapper.
46    pub fn with_bound_context<R>(&self, f: impl FnOnce() -> R) -> R {
47        self.run_with_bound_context(f)
48    }
49
50    /// Returns an immutable reference to the inputs/outputs object
51    #[doc(alias = "GetIO")]
52    pub fn io(&self) -> &crate::io::Io {
53        self.run_with_bound_context(|| unsafe {
54            let io = sys::igGetIO_Nil();
55            if io.is_null() {
56                panic!("Ui::io() requires an active ImGui context");
57            }
58            &*(io as *const crate::io::Io)
59        })
60    }
61
62    /// Internal method to push a single text to our scratch buffer.
63    pub(crate) fn scratch_txt(&self, txt: impl AsRef<str>) -> *const std::os::raw::c_char {
64        unsafe {
65            let handle = &mut *self.buffer.get();
66            handle.scratch_txt(txt)
67        }
68    }
69
70    /// Helper method for two strings
71    pub(crate) fn scratch_txt_two(
72        &self,
73        txt_0: impl AsRef<str>,
74        txt_1: impl AsRef<str>,
75    ) -> (*const std::os::raw::c_char, *const std::os::raw::c_char) {
76        unsafe {
77            let handle = &mut *self.buffer.get();
78            handle.scratch_txt_two(txt_0, txt_1)
79        }
80    }
81
82    /// Helper method with one optional value
83    pub(crate) fn scratch_txt_with_opt(
84        &self,
85        txt_0: impl AsRef<str>,
86        txt_1: Option<impl AsRef<str>>,
87    ) -> (*const std::os::raw::c_char, *const std::os::raw::c_char) {
88        unsafe {
89            let handle = &mut *self.buffer.get();
90            handle.scratch_txt_with_opt(txt_0, txt_1)
91        }
92    }
93
94    /// Get access to the scratch buffer for complex string operations
95    pub(crate) fn scratch_buffer(&self) -> &UnsafeCell<UiBuffer> {
96        &self.buffer
97    }
98
99    /// Returns an ID from a string label in the current ID scope.
100    ///
101    /// This mirrors `ImGui::GetID(label)`. Useful for building stable IDs
102    /// for widgets or dockspaces inside the current window/scope.
103    #[doc(alias = "GetID")]
104    pub fn get_id(&self, label: &str) -> Id {
105        let label = self.scratch_txt(label);
106        self.run_with_bound_context(|| unsafe { Id::from(sys::igGetID_Str(label)) })
107    }
108}