Skip to main content

dear_imgui_rs/widget/table/
headers.rs

1use crate::draw::ImColor32;
2use crate::internal::len_i32;
3use crate::sys;
4use crate::ui::Ui;
5use crate::widget::table::{
6    TableBackgroundChannelToken, TableColumnChannelToken, TableColumnIndex, TableContextMenuTarget,
7    assert_current_table, assert_current_table_cell, assert_valid_table_column,
8    assert_valid_table_column_in,
9};
10
11/// Safe description of a single angled header cell.
12#[derive(Copy, Clone, Debug, PartialEq)]
13pub struct TableHeaderData {
14    pub index: TableColumnIndex,
15    pub text_color: ImColor32,
16    pub bg_color0: ImColor32,
17    pub bg_color1: ImColor32,
18}
19
20impl TableHeaderData {
21    pub fn new(
22        index: impl Into<TableColumnIndex>,
23        text_color: ImColor32,
24        bg_color0: ImColor32,
25        bg_color1: ImColor32,
26    ) -> Self {
27        Self {
28            index: index.into(),
29            text_color,
30            bg_color0,
31            bg_color1,
32        }
33    }
34}
35impl Ui {
36    /// Maximum label width used for angled headers (when enabled in style/options).
37    #[doc(alias = "TableGetHeaderAngledMaxLabelWidth")]
38    pub fn table_get_header_angled_max_label_width(&self) -> f32 {
39        unsafe { sys::igTableGetHeaderAngledMaxLabelWidth() }
40    }
41
42    /// Submit angled headers row (requires style/flags enabling angled headers).
43    #[doc(alias = "TableAngledHeadersRow")]
44    pub fn table_angled_headers_row(&self) {
45        unsafe { sys::igTableAngledHeadersRow() }
46    }
47
48    // Removed legacy TableAngledHeadersRowEx(flags) wrapper; use `table_angled_headers_row_ex_with_data`.
49
50    /// Submit angled headers row with explicit data (Ex variant).
51    ///
52    /// - `row_id`: ImGuiID for the row. Use 0 for automatic if not needed.
53    /// - `angle`: Angle in radians for headers.
54    /// - `max_label_width`: Maximum label width for angled headers.
55    /// - `headers`: Per-column header data.
56    pub fn table_angled_headers_row_ex_with_data(
57        &self,
58        row_id: u32,
59        angle: f32,
60        max_label_width: f32,
61        headers: &[TableHeaderData],
62    ) {
63        if headers.is_empty() {
64            unsafe { sys::igTableAngledHeadersRow() }
65            return;
66        }
67        let count = len_i32(
68            "Ui::table_angled_headers_row_ex_with_data()",
69            "headers",
70            headers.len(),
71        );
72        let table = assert_current_table("Ui::table_angled_headers_row_ex_with_data()");
73        let mut data: Vec<sys::ImGuiTableHeaderData> = Vec::with_capacity(headers.len());
74        for h in headers {
75            assert_valid_table_column_in(
76                table,
77                h.index,
78                "Ui::table_angled_headers_row_ex_with_data()",
79            );
80            data.push(sys::ImGuiTableHeaderData {
81                Index: h
82                    .index
83                    .into_imgui_column_idx("Ui::table_angled_headers_row_ex_with_data()"),
84                TextColor: u32::from(h.text_color),
85                BgColor0: u32::from(h.bg_color0),
86                BgColor1: u32::from(h.bg_color1),
87            });
88        }
89        unsafe {
90            sys::igTableAngledHeadersRowEx(row_id, angle, max_label_width, data.as_ptr(), count);
91        }
92    }
93
94    /// Push background draw channel for the current table and return a token to pop it.
95    #[doc(alias = "TablePushBackgroundChannel")]
96    pub fn table_push_background_channel(&self) {
97        assert_current_table_cell("Ui::table_push_background_channel()");
98        unsafe { sys::igTablePushBackgroundChannel() }
99    }
100
101    /// Pop background draw channel for the current table.
102    #[doc(alias = "TablePopBackgroundChannel")]
103    pub fn table_pop_background_channel(&self) {
104        assert_current_table_cell("Ui::table_pop_background_channel()");
105        unsafe { sys::igTablePopBackgroundChannel() }
106    }
107
108    /// Push column draw channel for the given column index and return a token to pop it.
109    #[doc(alias = "TablePushColumnChannel")]
110    pub fn table_push_column_channel(&self, column: impl Into<TableColumnIndex>) {
111        let column_n = assert_valid_table_column(column.into(), "Ui::table_push_column_channel()");
112        unsafe { sys::igTablePushColumnChannel(column_n) }
113    }
114
115    /// Pop column draw channel.
116    #[doc(alias = "TablePopColumnChannel")]
117    pub fn table_pop_column_channel(&self) {
118        assert_current_table_cell("Ui::table_pop_column_channel()");
119        unsafe { sys::igTablePopColumnChannel() }
120    }
121
122    /// Push background draw channel for the current table and return a token to pop it.
123    #[must_use = "dropping the token pops the table background draw channel immediately"]
124    #[doc(alias = "TablePushBackgroundChannel")]
125    pub fn table_background_channel(&self) -> TableBackgroundChannelToken<'_> {
126        self.table_push_background_channel();
127        TableBackgroundChannelToken::new(self)
128    }
129
130    /// Push column draw channel for the given column index and return a token to pop it.
131    #[must_use = "dropping the token pops the table column draw channel immediately"]
132    #[doc(alias = "TablePushColumnChannel")]
133    pub fn table_column_channel(
134        &self,
135        column: impl Into<TableColumnIndex>,
136    ) -> TableColumnChannelToken<'_> {
137        self.table_push_column_channel(column);
138        TableColumnChannelToken::new(self)
139    }
140
141    /// Run a closure after pushing table background channel (auto-pop on return).
142    pub fn with_table_background_channel<R>(&self, f: impl FnOnce() -> R) -> R {
143        let _token = self.table_background_channel();
144        f()
145    }
146
147    /// Run a closure after pushing a table column channel (auto-pop on return).
148    pub fn with_table_column_channel<R>(
149        &self,
150        column: impl Into<TableColumnIndex>,
151        f: impl FnOnce() -> R,
152    ) -> R {
153        let _token = self.table_column_channel(column);
154        f()
155    }
156
157    /// Open the table context menu for the current/default column.
158    #[doc(alias = "TableOpenContextMenu")]
159    pub fn table_open_context_menu(&self, target: impl Into<TableContextMenuTarget>) {
160        let target = target.into();
161        let column_n = match target {
162            TableContextMenuTarget::CurrentColumn => -1,
163            TableContextMenuTarget::Column(index) => {
164                index.into_i32("Ui::table_open_context_menu()")
165            }
166            TableContextMenuTarget::Table => {
167                let table = assert_current_table("Ui::table_open_context_menu()");
168                unsafe { (*table).ColumnsCount }
169            }
170        };
171        unsafe { sys::igTableOpenContextMenu(column_n) }
172    }
173}