Skip to main content

dear_imgui_rs/layout/
spacing.rs

1use super::validation::{assert_finite_f32, assert_finite_vec2};
2use crate::Ui;
3use crate::sys;
4
5/// Tracks an indentation scope started with [`Ui::begin_indent`] or
6/// [`Ui::begin_indent_by`].
7#[must_use]
8pub struct IndentToken<'ui> {
9    ui: &'ui Ui,
10    width: f32,
11}
12
13impl IndentToken<'_> {
14    /// Ends the indentation scope explicitly.
15    pub fn end(self) {
16        // Drop restores the previous indentation.
17    }
18}
19
20impl Drop for IndentToken<'_> {
21    fn drop(&mut self) {
22        self.ui.unindent_by(self.width);
23    }
24}
25
26impl Ui {
27    /// Call between widgets or groups to layout them horizontally.
28    ///
29    /// X position is given in window coordinates.
30    ///
31    /// This is equivalent to calling [same_line_with_pos](Self::same_line_with_pos)
32    /// with the `pos` set to 0.0, which uses `Style::item_spacing`.
33    #[doc(alias = "SameLine")]
34    pub fn same_line(&self) {
35        self.same_line_with_pos(0.0);
36    }
37
38    /// Call between widgets or groups to layout them horizontally.
39    ///
40    /// X position is given in window coordinates.
41    ///
42    /// This is equivalent to calling [same_line_with_spacing](Self::same_line_with_spacing)
43    /// with the `spacing` set to -1.0, which means no extra spacing.
44    #[doc(alias = "SameLine")]
45    pub fn same_line_with_pos(&self, pos_x: f32) {
46        self.same_line_with_spacing(pos_x, -1.0)
47    }
48
49    /// Call between widgets or groups to layout them horizontally.
50    ///
51    /// X position is given in window coordinates.
52    #[doc(alias = "SameLine")]
53    pub fn same_line_with_spacing(&self, pos_x: f32, spacing_w: f32) {
54        assert_finite_f32("Ui::same_line_with_spacing()", "pos_x", pos_x);
55        assert_finite_f32("Ui::same_line_with_spacing()", "spacing_w", spacing_w);
56        self.run_with_bound_context(|| unsafe { sys::igSameLine(pos_x, spacing_w) });
57    }
58
59    /// Undo a `same_line` call or force a new line when in horizontal layout mode
60    #[doc(alias = "NewLine")]
61    pub fn new_line(&self) {
62        self.run_with_bound_context(|| unsafe { sys::igNewLine() });
63    }
64
65    /// Adds vertical spacing
66    #[doc(alias = "Spacing")]
67    pub fn spacing(&self) {
68        self.run_with_bound_context(|| unsafe { sys::igSpacing() });
69    }
70
71    /// Fills a space of `size` in pixels with nothing on the current window.
72    ///
73    /// Can be used to move the cursor on the window.
74    #[doc(alias = "Dummy")]
75    pub fn dummy(&self, size: impl Into<[f32; 2]>) {
76        let size = size.into();
77        assert_finite_vec2("Ui::dummy()", "size", size);
78        let size_vec: sys::ImVec2 = size.into();
79        self.run_with_bound_context(|| unsafe { sys::igDummy(size_vec) });
80    }
81
82    /// Moves content position to the right by `Style::indent_spacing`
83    ///
84    /// This is equivalent to [indent_by](Self::indent_by) with `width` set to
85    /// `Style::indent_spacing`.
86    #[doc(alias = "Indent")]
87    pub fn indent(&self) {
88        self.indent_by(0.0)
89    }
90
91    /// Moves content position to the right by `width`
92    #[doc(alias = "Indent")]
93    pub fn indent_by(&self, width: f32) {
94        assert_finite_f32("Ui::indent_by()", "width", width);
95        self.run_with_bound_context(|| unsafe { sys::igIndent(width) });
96    }
97
98    /// Starts an indentation scope using `Style::indent_spacing`.
99    ///
100    /// The returned token restores the previous indentation when it is dropped
101    /// or explicitly ended.
102    #[doc(alias = "Indent")]
103    pub fn begin_indent(&self) -> IndentToken<'_> {
104        let width = self.run_with_bound_context(|| {
105            // SAFETY: the bound Ui owns a live current context, so `igGetStyle` is non-null. The
106            // spacing value is copied immediately and no reference escapes this call.
107            unsafe { (*sys::igGetStyle()).IndentSpacing }
108        });
109        self.begin_indent_by(width)
110    }
111
112    /// Starts an indentation scope with a custom width.
113    ///
114    /// The returned token restores the previous indentation when it is dropped
115    /// or explicitly ended.
116    #[doc(alias = "Indent")]
117    pub fn begin_indent_by(&self, width: f32) -> IndentToken<'_> {
118        self.indent_by(width);
119        IndentToken { ui: self, width }
120    }
121
122    /// Moves content position to the left by `Style::indent_spacing`
123    ///
124    /// This is equivalent to [unindent_by](Self::unindent_by) with `width` set to
125    /// `Style::indent_spacing`.
126    #[doc(alias = "Unindent")]
127    pub fn unindent(&self) {
128        self.unindent_by(0.0)
129    }
130
131    /// Moves content position to the left by `width`
132    #[doc(alias = "Unindent")]
133    pub fn unindent_by(&self, width: f32) {
134        assert_finite_f32("Ui::unindent_by()", "width", width);
135        self.run_with_bound_context(|| unsafe { sys::igUnindent(width) });
136    }
137}
138
139impl Ui {
140    /// Vertically align upcoming text baseline to FramePadding.y (align text to framed items).
141    #[doc(alias = "AlignTextToFramePadding")]
142    pub fn align_text_to_frame_padding(&self) {
143        self.run_with_bound_context(|| unsafe { sys::igAlignTextToFramePadding() });
144    }
145}