Skip to main content

dear_imgui_rs/columns/
ui.rs

1use crate::sys;
2use crate::{Id, Ui};
3
4use super::counts::{column_count_from_i32, columns_count_to_i32};
5use super::flags::{OldColumnFlags, validate_old_column_flags};
6use super::index::{OldColumnIndex, OldColumnOffsetRef, OldColumnRef};
7use super::numeric::assert_non_negative_f32;
8use super::resolve::{
9    assert_valid_column_in, resolve_column_offset_query_ref, resolve_column_offset_ref,
10    resolve_column_query_ref,
11};
12use super::state::{assert_current_columns, assert_no_current_columns, current_columns};
13use super::token::ColumnsToken;
14
15/// # Columns
16impl Ui {
17    /// Creates columns layout.
18    ///
19    /// # Arguments
20    /// * `count` - Number of columns (must be >= 1)
21    /// * `id` - Optional ID for the columns (can be empty string)
22    /// * `border` - Whether to draw borders between columns
23    #[doc(alias = "Columns")]
24    pub fn columns(&self, count: usize, id: impl AsRef<str>, border: bool) {
25        let count = columns_count_to_i32(count, "Ui::columns()");
26        unsafe { sys::igColumns(count, self.scratch_txt(id), border) }
27    }
28
29    /// Begin columns layout with advanced flags.
30    ///
31    /// # Arguments
32    /// * `id` - ID for the columns
33    /// * `count` - Number of columns (must be >= 1)
34    /// * `flags` - Column flags
35    #[doc(alias = "BeginColumns")]
36    pub fn begin_columns(&self, id: impl AsRef<str>, count: usize, flags: OldColumnFlags) {
37        let count = columns_count_to_i32(count, "Ui::begin_columns()");
38        validate_old_column_flags("Ui::begin_columns()", flags);
39        assert_no_current_columns("Ui::begin_columns()");
40        unsafe { sys::igBeginColumns(self.scratch_txt(id), count, flags.bits()) }
41    }
42
43    /// Begin columns layout with advanced flags and return a token that ends columns on drop.
44    #[doc(alias = "BeginColumns")]
45    pub fn begin_columns_token(
46        &self,
47        id: impl AsRef<str>,
48        count: usize,
49        flags: OldColumnFlags,
50    ) -> ColumnsToken<'_> {
51        self.begin_columns(id, count, flags);
52        ColumnsToken { ui: self }
53    }
54
55    /// End columns layout.
56    #[doc(alias = "EndColumns")]
57    pub fn end_columns(&self) {
58        assert_current_columns("Ui::end_columns()");
59        unsafe { sys::igEndColumns() }
60    }
61
62    /// Switches to the next column.
63    ///
64    /// If the current row is finished, switches to first column of the next row
65    #[doc(alias = "NextColumn")]
66    pub fn next_column(&self) {
67        unsafe { sys::igNextColumn() }
68    }
69
70    /// Returns the index of the current column
71    #[doc(alias = "GetColumnIndex")]
72    pub fn current_column_index(&self) -> OldColumnIndex {
73        OldColumnIndex::from_i32(
74            unsafe { sys::igGetColumnIndex() },
75            "Ui::current_column_index()",
76        )
77    }
78
79    /// Returns the width of the current column (in pixels)
80    #[doc(alias = "GetColumnWidth")]
81    pub fn current_column_width(&self) -> f32 {
82        unsafe { sys::igGetColumnWidth(-1) }
83    }
84
85    /// Returns the width of the given column (in pixels)
86    #[doc(alias = "GetColumnWidth")]
87    pub fn column_width(&self, column: impl Into<OldColumnRef>) -> f32 {
88        let column_index = resolve_column_query_ref(column.into(), "Ui::column_width()");
89        unsafe { sys::igGetColumnWidth(column_index) }
90    }
91
92    /// Sets the width of the current column (in pixels)
93    #[doc(alias = "SetColumnWidth")]
94    pub fn set_current_column_width(&self, width: f32) {
95        assert_current_columns("Ui::set_current_column_width()");
96        assert_non_negative_f32("Ui::set_current_column_width()", "width", width);
97        unsafe { sys::igSetColumnWidth(-1, width) };
98    }
99
100    /// Sets the width of the given column (in pixels)
101    #[doc(alias = "SetColumnWidth")]
102    pub fn set_column_width(&self, column: impl Into<OldColumnIndex>, width: f32) {
103        let columns = assert_current_columns("Ui::set_column_width()");
104        let column_index = assert_valid_column_in(columns, column.into(), "Ui::set_column_width()");
105        assert_non_negative_f32("Ui::set_column_width()", "width", width);
106        unsafe { sys::igSetColumnWidth(column_index, width) };
107    }
108
109    /// Returns the offset of the current column (in pixels from the left side of the content region)
110    #[doc(alias = "GetColumnOffset")]
111    pub fn current_column_offset(&self) -> f32 {
112        unsafe { sys::igGetColumnOffset(-1) }
113    }
114
115    /// Returns the offset of the given column (in pixels from the left side of the content region)
116    #[doc(alias = "GetColumnOffset")]
117    pub fn column_offset(&self, offset: impl Into<OldColumnOffsetRef>) -> f32 {
118        let column_index = resolve_column_offset_query_ref(offset.into(), "Ui::column_offset()");
119        unsafe { sys::igGetColumnOffset(column_index) }
120    }
121
122    /// Sets the offset of the current column (in pixels from the left side of the content region)
123    #[doc(alias = "SetColumnOffset")]
124    pub fn set_current_column_offset(&self, offset_x: f32) {
125        assert_current_columns("Ui::set_current_column_offset()");
126        assert_non_negative_f32("Ui::set_current_column_offset()", "offset_x", offset_x);
127        unsafe { sys::igSetColumnOffset(-1, offset_x) };
128    }
129
130    /// Sets the offset of the given column (in pixels from the left side of the content region)
131    #[doc(alias = "SetColumnOffset")]
132    pub fn set_column_offset(&self, offset: impl Into<OldColumnOffsetRef>, offset_x: f32) {
133        let column_index = resolve_column_offset_ref(offset.into(), "Ui::set_column_offset()");
134        assert_non_negative_f32("Ui::set_column_offset()", "offset_x", offset_x);
135        unsafe { sys::igSetColumnOffset(column_index, offset_x) };
136    }
137
138    /// Returns the current amount of columns
139    #[doc(alias = "GetColumnsCount")]
140    pub fn column_count(&self) -> usize {
141        column_count_from_i32(unsafe { sys::igGetColumnsCount() }, "Ui::column_count()")
142    }
143
144    // ============================================================================
145    // Advanced column utilities
146    // ============================================================================
147
148    /// Push column clip rect for the given column index.
149    /// This is useful for custom drawing within columns.
150    #[doc(alias = "PushColumnClipRect")]
151    pub fn push_column_clip_rect(&self, column: impl Into<OldColumnIndex>) {
152        let columns = assert_current_columns("Ui::push_column_clip_rect()");
153        let column_index =
154            assert_valid_column_in(columns, column.into(), "Ui::push_column_clip_rect()");
155        unsafe { sys::igPushColumnClipRect(column_index) }
156    }
157
158    /// Push columns background for drawing.
159    #[doc(alias = "PushColumnsBackground")]
160    pub fn push_columns_background(&self) {
161        assert_current_columns("Ui::push_columns_background()");
162        unsafe { sys::igPushColumnsBackground() }
163    }
164
165    /// Pop columns background.
166    #[doc(alias = "PopColumnsBackground")]
167    pub fn pop_columns_background(&self) {
168        assert_current_columns("Ui::pop_columns_background()");
169        unsafe { sys::igPopColumnsBackground() }
170    }
171
172    /// Get columns ID for the given string ID and count.
173    #[doc(alias = "GetColumnsID")]
174    pub fn get_columns_id(&self, str_id: impl AsRef<str>, count: usize) -> Id {
175        let count = columns_count_to_i32(count, "Ui::get_columns_id()");
176        unsafe { Id::from(sys::igGetColumnsID(self.scratch_txt(str_id), count)) }
177    }
178
179    // ============================================================================
180    // Column state utilities
181    // ============================================================================
182
183    /// Check if any column in the current legacy columns set is being resized.
184    ///
185    /// Returns `false` when the current window is not inside a legacy columns set.
186    pub fn is_any_column_resizing(&self) -> bool {
187        unsafe {
188            let window = sys::igGetCurrentWindowRead();
189            if window.is_null() {
190                return false;
191            }
192
193            let columns = (*window).DC.CurrentColumns;
194            if columns.is_null() {
195                return false;
196            }
197
198            (*columns).IsBeingResized
199        }
200    }
201
202    /// Get the total width of all columns.
203    pub fn get_columns_total_width(&self) -> f32 {
204        if current_columns().is_null() {
205            return self.current_column_width();
206        }
207
208        let count = self.column_count();
209
210        let mut total_width = 0.0;
211        for i in 0..count {
212            total_width += self.column_width(i);
213        }
214        total_width
215    }
216
217    /// Set all columns to equal width.
218    pub fn set_columns_equal_width(&self) {
219        let count = self.column_count();
220        if count <= 1 {
221            return;
222        }
223
224        let total_width = self.get_columns_total_width();
225        let equal_width = total_width / count as f32;
226
227        for i in 0..count {
228            self.set_column_width(i, equal_width);
229        }
230    }
231
232    /// Get column width as a percentage of total width.
233    pub fn get_column_width_percentage(&self, column: impl Into<OldColumnRef>) -> f32 {
234        let total_width = self.get_columns_total_width();
235        if total_width <= 0.0 {
236            return 0.0;
237        }
238
239        let column_width = self.column_width(column);
240        (column_width / total_width) * 100.0
241    }
242
243    /// Set column width as a percentage of total width.
244    pub fn set_column_width_percentage(&self, column: impl Into<OldColumnIndex>, percentage: f32) {
245        assert_non_negative_f32(
246            "Ui::set_column_width_percentage()",
247            "percentage",
248            percentage,
249        );
250        let total_width = self.get_columns_total_width();
251        if total_width <= 0.0 {
252            return;
253        }
254
255        let new_width = (total_width * percentage) / 100.0;
256        self.set_column_width(column, new_width);
257    }
258}