dear-imgui-rs 0.17.0

High-level Rust bindings to Dear ImGui v1.92.9b with docking, WGPU/GL backends, and extensions (ImPlot/ImPlot3D, ImNodes, ImGuizmo, file browser, reflection-based UI)
Documentation
use crate::sys;

use super::super::util::finite_vec2;
use super::DrawListMut;

/// Tracks a clip rectangle pushed onto a draw-list clip stack.
///
/// The clip rectangle is popped when the token is dropped or when [`Self::pop`]
/// is called. Tokens for the same draw list must finish in reverse creation order. A token from a
/// window draw list must also finish in the exact window `Begin` scope that created the draw-list
/// view. Prefer [`DrawListMut::with_clip_rect`] for ordinary scoped use.
#[must_use]
pub struct DrawListClipRectToken<'draw_list> {
    scope: crate::scope::NativeScopeToken<'draw_list>,
}

impl<'draw_list> DrawListClipRectToken<'draw_list> {
    fn new(
        ui: &'draw_list crate::Ui,
        draw_list: *mut sys::ImDrawList,
        window_scoped: bool,
    ) -> Self {
        Self {
            scope: ui.begin_native_scope(
                crate::scope::NativeScopePop::DrawListPopClipRect {
                    draw_list,
                    window_scoped,
                },
                "DrawListClipRectToken",
            ),
        }
    }

    /// Pop the clip rectangle immediately instead of waiting for drop.
    ///
    /// # Panics
    ///
    /// Panics before FFI if a later clip token for the same draw list is active or a window-scoped
    /// draw list is no longer in its originating window `Begin` scope.
    #[doc(alias = "PopClipRect")]
    pub fn pop(self) {}

    /// Pop the clip rectangle immediately instead of waiting for drop.
    ///
    /// # Panics
    ///
    /// Panics under the same conditions as [`Self::pop`].
    #[doc(alias = "PopClipRect")]
    pub fn end(self) {}
}

impl Drop for DrawListClipRectToken<'_> {
    fn drop(&mut self) {
        self.scope.finish();
    }
}

impl<'ui> DrawListMut<'ui> {
    /// Push a clip rectangle, optionally intersecting with the current clip rect.
    #[doc(alias = "PushClipRect")]
    pub fn push_clip_rect(
        &self,
        clip_rect_min: impl Into<sys::ImVec2>,
        clip_rect_max: impl Into<sys::ImVec2>,
        intersect_with_current: bool,
    ) -> DrawListClipRectToken<'_> {
        let clip_rect_min = finite_vec2(
            "DrawListMut::push_clip_rect()",
            "clip_rect_min",
            clip_rect_min,
        );
        let clip_rect_max = finite_vec2(
            "DrawListMut::push_clip_rect()",
            "clip_rect_max",
            clip_rect_max,
        );

        self.assert_scope("DrawListMut::push_clip_rect()");
        self.ui().run_with_bound_context(|| unsafe {
            sys::ImDrawList_PushClipRect(
                self.draw_list,
                clip_rect_min,
                clip_rect_max,
                intersect_with_current,
            )
        });
        DrawListClipRectToken::new(self.ui(), self.draw_list, self.is_window_scoped())
    }

    /// Push a full-screen clip rectangle.
    #[doc(alias = "PushClipRectFullScreen")]
    pub fn push_clip_rect_full_screen(&self) -> DrawListClipRectToken<'_> {
        self.assert_scope("DrawListMut::push_clip_rect_full_screen()");
        self.ui().run_with_bound_context(|| unsafe {
            sys::ImDrawList_PushClipRectFullScreen(self.draw_list)
        });
        DrawListClipRectToken::new(self.ui(), self.draw_list, self.is_window_scoped())
    }

    /// Get current minimum clip rectangle point.
    pub fn clip_rect_min(&self) -> [f32; 2] {
        let out = unsafe { sys::ImDrawList_GetClipRectMin(self.draw_list) };
        out.into()
    }

    /// Get current maximum clip rectangle point.
    pub fn clip_rect_max(&self) -> [f32; 2] {
        let out = unsafe { sys::ImDrawList_GetClipRectMax(self.draw_list) };
        out.into()
    }

    /// Convenience: push a clip rect, run f, pop.
    pub fn with_clip_rect<F, R>(
        &self,
        clip_rect_min: impl Into<sys::ImVec2>,
        clip_rect_max: impl Into<sys::ImVec2>,
        f: F,
    ) -> R
    where
        F: FnOnce() -> R,
    {
        let clip_rect = self.push_clip_rect(clip_rect_min, clip_rect_max, false);
        let result = f();
        drop(clip_rect);
        result
    }
}