Skip to main content

dear_imgui_rs/ui/
core.rs

1use super::*;
2
3impl Ui {
4    pub(crate) fn assert_finite_f32(caller: &str, name: &str, value: f32) {
5        assert!(value.is_finite(), "{caller} {name} must be finite");
6    }
7
8    pub(super) fn assert_finite_vec2(caller: &str, name: &str, value: [f32; 2]) {
9        assert!(
10            value[0].is_finite() && value[1].is_finite(),
11            "{caller} {name} must contain finite values"
12        );
13    }
14
15    /// Creates a new Ui instance
16    ///
17    /// This should only be called by Context::create()
18    pub(crate) fn new(
19        ctx: *mut sys::ImGuiContext,
20        ctx_binding: crate::ContextBinding,
21        texture_registry: crate::context::SharedTextureRegistry,
22    ) -> Self {
23        Ui {
24            ctx,
25            ctx_binding,
26            texture_registry,
27            buffer: UnsafeCell::new(UiBuffer::new(1024)),
28        }
29    }
30
31    pub(crate) fn context_raw(&self) -> *mut sys::ImGuiContext {
32        self.ctx
33    }
34
35    /// Returns a persistent capability for the Context that owns this `Ui`.
36    pub fn binding(&self) -> crate::ContextBinding {
37        self.ctx_binding.clone()
38    }
39
40    /// Returns the process-unique identity of the Context that owns this `Ui`.
41    pub fn context_id(&self) -> crate::ContextId {
42        self.ctx_binding.id()
43    }
44
45    pub(crate) fn run_with_bound_context<R>(&self, f: impl FnOnce() -> R) -> R {
46        self.ctx_binding.with_bound_context(f)
47    }
48
49    pub(crate) fn resolve_texture_ref(
50        &self,
51        texture: crate::texture::TextureRef<'_>,
52    ) -> Result<sys::ImTextureRef, crate::texture::ManagedTextureError> {
53        match texture.source() {
54            crate::texture::TextureSource::Legacy(id) => Ok(sys::ImTextureRef {
55                _TexData: std::ptr::null_mut(),
56                _TexID: sys::ImTextureID::from(id),
57            }),
58            crate::texture::TextureSource::Managed(id) => {
59                self.texture_registry.borrow().resolve(id)
60            }
61            crate::texture::TextureSource::FontAtlas { atlas, texture } => {
62                let io = unsafe { sys::igGetIO_ContextPtr(self.ctx) };
63                if io.is_null() || !std::ptr::eq(unsafe { (*io).Fonts }, atlas) {
64                    return Err(crate::texture::ManagedTextureError::ForeignFontAtlas);
65                }
66                Ok(texture)
67            }
68        }
69    }
70
71    /// Resolve a logical texture for an adjacent extension FFI call.
72    ///
73    /// # Safety
74    ///
75    /// A returned managed pointer is valid only for an immediate native call while this `Ui` and
76    /// its frame remain borrowed. It must not be stored, sent, or used after the call returns.
77    #[doc(hidden)]
78    pub unsafe fn resolve_texture_ref_raw(
79        &self,
80        texture: crate::texture::TextureRef<'_>,
81    ) -> Result<sys::ImTextureRef, crate::texture::ManagedTextureError> {
82        self.run_with_bound_context(|| self.resolve_texture_ref(texture))
83    }
84
85    /// Runs a closure while this `Ui`'s owning ImGui context is current.
86    ///
87    /// The previously current context is restored before this method returns,
88    /// including when the closure panics. This is primarily intended for
89    /// extension crates that need to call raw Dear ImGui-adjacent FFI while
90    /// still honoring the `Ui` that created the safe wrapper.
91    pub fn with_bound_context<R>(&self, f: impl FnOnce() -> R) -> R {
92        self.run_with_bound_context(f)
93    }
94
95    /// Returns an immutable reference to the inputs/outputs object
96    #[doc(alias = "GetIO")]
97    pub fn io(&self) -> &crate::io::Io {
98        self.run_with_bound_context(|| unsafe {
99            let io = sys::igGetIO_Nil();
100            if io.is_null() {
101                panic!("Ui::io() requires an active ImGui context");
102            }
103            &*(io as *const crate::io::Io)
104        })
105    }
106
107    /// Internal method to push a single text to our scratch buffer.
108    pub(crate) fn scratch_txt(&self, txt: impl AsRef<str>) -> *const std::os::raw::c_char {
109        unsafe {
110            let handle = &mut *self.buffer.get();
111            handle.scratch_txt(txt)
112        }
113    }
114
115    /// Stages an explicit text range with a readable NUL sentinel at its end.
116    pub(crate) fn scratch_txt_range(
117        &self,
118        txt: impl AsRef<str>,
119    ) -> std::ops::Range<*const std::os::raw::c_char> {
120        unsafe {
121            let handle = &mut *self.buffer.get();
122            handle.scratch_txt_range(txt)
123        }
124    }
125
126    /// Helper method for two strings
127    pub(crate) fn scratch_txt_two(
128        &self,
129        txt_0: impl AsRef<str>,
130        txt_1: impl AsRef<str>,
131    ) -> (*const std::os::raw::c_char, *const std::os::raw::c_char) {
132        unsafe {
133            let handle = &mut *self.buffer.get();
134            handle.scratch_txt_two(txt_0, txt_1)
135        }
136    }
137
138    /// Helper method with one optional value
139    pub(crate) fn scratch_txt_with_opt(
140        &self,
141        txt_0: impl AsRef<str>,
142        txt_1: Option<impl AsRef<str>>,
143    ) -> (*const std::os::raw::c_char, *const std::os::raw::c_char) {
144        unsafe {
145            let handle = &mut *self.buffer.get();
146            handle.scratch_txt_with_opt(txt_0, txt_1)
147        }
148    }
149
150    /// Get access to the scratch buffer for complex string operations
151    pub(crate) fn scratch_buffer(&self) -> &UnsafeCell<UiBuffer> {
152        &self.buffer
153    }
154
155    /// Returns an ID from a string label in the current ID scope.
156    ///
157    /// This mirrors `ImGui::GetID(label)`. Useful for building stable IDs
158    /// for widgets or dockspaces inside the current window/scope.
159    #[doc(alias = "GetID")]
160    pub fn get_id(&self, label: &str) -> Id {
161        let label = self.scratch_txt(label);
162        self.run_with_bound_context(|| unsafe { Id::from(sys::igGetID_Str(label)) })
163    }
164}