dear_imgui_rs/
columns.rs

1//! Legacy columns API
2//!
3//! Thin wrappers for the old Columns layout system. New code should prefer
4//! the `table` API (`widget::table`) which supersedes Columns with more
5//! features and better user experience.
6//!
7#![allow(
8    clippy::cast_possible_truncation,
9    clippy::cast_sign_loss,
10    clippy::as_conversions
11)]
12use crate::Ui;
13use crate::sys;
14use bitflags::bitflags;
15
16bitflags! {
17    /// Flags for old columns system
18    #[repr(transparent)]
19    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
20    pub struct OldColumnFlags: i32 {
21        /// No flags
22        const NONE = sys::ImGuiOldColumnFlags_None as i32;
23        /// Disable column dividers
24        const NO_BORDER = sys::ImGuiOldColumnFlags_NoBorder as i32;
25        /// Disable resizing columns by dragging dividers
26        const NO_RESIZE = sys::ImGuiOldColumnFlags_NoResize as i32;
27        /// Disable column width preservation when the total width changes
28        const NO_PRESERVE_WIDTHS = sys::ImGuiOldColumnFlags_NoPreserveWidths as i32;
29        /// Disable forcing columns to fit within window
30        const NO_FORCE_WITHIN_WINDOW = sys::ImGuiOldColumnFlags_NoForceWithinWindow as i32;
31        /// Restore pre-1.51 behavior of extending the parent window contents size
32        const GROW_PARENT_CONTENTS_SIZE = sys::ImGuiOldColumnFlags_GrowParentContentsSize as i32;
33    }
34}
35
36impl Default for OldColumnFlags {
37    fn default() -> Self {
38        OldColumnFlags::NONE
39    }
40}
41
42/// # Columns
43impl Ui {
44    /// Creates columns layout.
45    ///
46    /// # Arguments
47    /// * `count` - Number of columns (must be >= 1)
48    /// * `id` - Optional ID for the columns (can be empty string)
49    /// * `border` - Whether to draw borders between columns
50    #[doc(alias = "Columns")]
51    pub fn columns(&self, count: i32, id: impl AsRef<str>, border: bool) {
52        unsafe { sys::igColumns(count, self.scratch_txt(id), border) }
53    }
54
55    /// Begin columns layout with advanced flags.
56    ///
57    /// # Arguments
58    /// * `id` - ID for the columns
59    /// * `count` - Number of columns (must be >= 1)
60    /// * `flags` - Column flags
61    #[doc(alias = "BeginColumns")]
62    pub fn begin_columns(&self, id: impl AsRef<str>, count: i32, flags: OldColumnFlags) {
63        unsafe { sys::igBeginColumns(self.scratch_txt(id), count, flags.bits()) }
64    }
65
66    /// Begin columns layout with advanced flags and return a token that ends columns on drop.
67    #[doc(alias = "BeginColumns")]
68    pub fn begin_columns_token(
69        &self,
70        id: impl AsRef<str>,
71        count: i32,
72        flags: OldColumnFlags,
73    ) -> ColumnsToken<'_> {
74        self.begin_columns(id, count, flags);
75        ColumnsToken { ui: self }
76    }
77
78    /// End columns layout.
79    #[doc(alias = "EndColumns")]
80    pub fn end_columns(&self) {
81        unsafe { sys::igEndColumns() }
82    }
83
84    /// Switches to the next column.
85    ///
86    /// If the current row is finished, switches to first column of the next row
87    #[doc(alias = "NextColumn")]
88    pub fn next_column(&self) {
89        unsafe { sys::igNextColumn() }
90    }
91
92    /// Returns the index of the current column
93    #[doc(alias = "GetColumnIndex")]
94    pub fn current_column_index(&self) -> i32 {
95        unsafe { sys::igGetColumnIndex() }
96    }
97
98    /// Returns the width of the current column (in pixels)
99    #[doc(alias = "GetColumnWidth")]
100    pub fn current_column_width(&self) -> f32 {
101        unsafe { sys::igGetColumnWidth(-1) }
102    }
103
104    /// Returns the width of the given column (in pixels)
105    #[doc(alias = "GetColumnWidth")]
106    pub fn column_width(&self, column_index: i32) -> f32 {
107        unsafe { sys::igGetColumnWidth(column_index) }
108    }
109
110    /// Sets the width of the current column (in pixels)
111    #[doc(alias = "SetColumnWidth")]
112    pub fn set_current_column_width(&self, width: f32) {
113        unsafe { sys::igSetColumnWidth(-1, width) };
114    }
115
116    /// Sets the width of the given column (in pixels)
117    #[doc(alias = "SetColumnWidth")]
118    pub fn set_column_width(&self, column_index: i32, width: f32) {
119        unsafe { sys::igSetColumnWidth(column_index, width) };
120    }
121
122    /// Returns the offset of the current column (in pixels from the left side of the content region)
123    #[doc(alias = "GetColumnOffset")]
124    pub fn current_column_offset(&self) -> f32 {
125        unsafe { sys::igGetColumnOffset(-1) }
126    }
127
128    /// Returns the offset of the given column (in pixels from the left side of the content region)
129    #[doc(alias = "GetColumnOffset")]
130    pub fn column_offset(&self, column_index: i32) -> f32 {
131        unsafe { sys::igGetColumnOffset(column_index) }
132    }
133
134    /// Sets the offset of the current column (in pixels from the left side of the content region)
135    #[doc(alias = "SetColumnOffset")]
136    pub fn set_current_column_offset(&self, offset_x: f32) {
137        unsafe { sys::igSetColumnOffset(-1, offset_x) };
138    }
139
140    /// Sets the offset of the given column (in pixels from the left side of the content region)
141    #[doc(alias = "SetColumnOffset")]
142    pub fn set_column_offset(&self, column_index: i32, offset_x: f32) {
143        unsafe { sys::igSetColumnOffset(column_index, offset_x) };
144    }
145
146    /// Returns the current amount of columns
147    #[doc(alias = "GetColumnsCount")]
148    pub fn column_count(&self) -> i32 {
149        unsafe { sys::igGetColumnsCount() }
150    }
151
152    // ============================================================================
153    // Advanced column utilities
154    // ============================================================================
155
156    /// Push column clip rect for the given column index.
157    /// This is useful for custom drawing within columns.
158    #[doc(alias = "PushColumnClipRect")]
159    pub fn push_column_clip_rect(&self, column_index: i32) {
160        unsafe { sys::igPushColumnClipRect(column_index) }
161    }
162
163    /// Push columns background for drawing.
164    #[doc(alias = "PushColumnsBackground")]
165    pub fn push_columns_background(&self) {
166        unsafe { sys::igPushColumnsBackground() }
167    }
168
169    /// Pop columns background.
170    #[doc(alias = "PopColumnsBackground")]
171    pub fn pop_columns_background(&self) {
172        unsafe { sys::igPopColumnsBackground() }
173    }
174
175    /// Get columns ID for the given string ID and count.
176    #[doc(alias = "GetColumnsID")]
177    pub fn get_columns_id(&self, str_id: impl AsRef<str>, count: i32) -> u32 {
178        unsafe { sys::igGetColumnsID(self.scratch_txt(str_id), count) }
179    }
180
181    // ============================================================================
182    // Column state utilities
183    // ============================================================================
184
185    /// Check if any column is being resized.
186    /// Note: This is a placeholder implementation as the underlying C++ function is not available
187    pub fn is_any_column_resizing(&self) -> bool {
188        // TODO: Implement when the proper C++ binding is available
189        // The ImGui_GetCurrentWindow function is not available in our bindings
190        false
191    }
192
193    /// Get the total width of all columns.
194    pub fn get_columns_total_width(&self) -> f32 {
195        let count = self.column_count();
196        if count <= 0 {
197            return 0.0;
198        }
199
200        let mut total_width = 0.0;
201        for i in 0..count {
202            total_width += self.column_width(i);
203        }
204        total_width
205    }
206
207    /// Set all columns to equal width.
208    pub fn set_columns_equal_width(&self) {
209        let count = self.column_count();
210        if count <= 1 {
211            return;
212        }
213
214        let total_width = self.get_columns_total_width();
215        let equal_width = total_width / count as f32;
216
217        for i in 0..count {
218            self.set_column_width(i, equal_width);
219        }
220    }
221
222    /// Get column width as a percentage of total width.
223    pub fn get_column_width_percentage(&self, column_index: i32) -> f32 {
224        let total_width = self.get_columns_total_width();
225        if total_width <= 0.0 {
226            return 0.0;
227        }
228
229        let column_width = self.column_width(column_index);
230        (column_width / total_width) * 100.0
231    }
232
233    /// Set column width as a percentage of total width.
234    pub fn set_column_width_percentage(&self, column_index: i32, percentage: f32) {
235        let total_width = self.get_columns_total_width();
236        if total_width <= 0.0 {
237            return;
238        }
239
240        let new_width = (total_width * percentage) / 100.0;
241        self.set_column_width(column_index, new_width);
242    }
243}
244
245/// Token representing an active columns layout.
246#[must_use]
247pub struct ColumnsToken<'ui> {
248    ui: &'ui Ui,
249}
250
251impl Drop for ColumnsToken<'_> {
252    fn drop(&mut self) {
253        self.ui.end_columns();
254    }
255}