dear_imgui_rs/widget/table/
headers.rs1use crate::draw::ImColor32;
2use crate::internal::len_i32;
3use crate::sys;
4use crate::ui::Ui;
5use crate::widget::table::{
6 TableColumnIndex, TableContextMenuTarget, assert_current_table, assert_current_table_cell,
7 assert_non_negative_finite_f32, assert_table_before_first_row, assert_valid_table_column,
8 assert_valid_table_column_in,
9};
10
11use super::tokens::TableChannelGuard;
12
13#[derive(Copy, Clone, Debug, PartialEq)]
15pub struct TableHeaderData {
16 pub index: TableColumnIndex,
17 pub text_color: ImColor32,
18 pub bg_color0: ImColor32,
19 pub bg_color1: ImColor32,
20}
21
22impl TableHeaderData {
23 pub fn new(
24 index: impl Into<TableColumnIndex>,
25 text_color: ImColor32,
26 bg_color0: ImColor32,
27 bg_color1: ImColor32,
28 ) -> Self {
29 Self {
30 index: index.into(),
31 text_color,
32 bg_color0,
33 bg_color1,
34 }
35 }
36}
37impl Ui {
38 #[doc(alias = "TableGetHeaderAngledMaxLabelWidth")]
44 pub fn table_get_header_angled_max_label_width(&self) -> f32 {
45 self.run_with_bound_context(|| {
46 assert_current_table("Ui::table_get_header_angled_max_label_width()");
47 unsafe { sys::igTableGetHeaderAngledMaxLabelWidth() }
48 })
49 }
50
51 #[doc(alias = "TableAngledHeadersRow")]
58 pub fn table_angled_headers_row(&self) {
59 self.run_with_bound_context(|| {
60 assert_table_before_first_row("Ui::table_angled_headers_row()");
61 self.assert_no_active_table_channel("Ui::table_angled_headers_row()");
62 unsafe { sys::igTableAngledHeadersRow() };
63 });
64 }
65
66 pub fn table_angled_headers_row_ex_with_data(
81 &self,
82 row_id: u32,
83 angle: f32,
84 max_label_width: f32,
85 headers: &[TableHeaderData],
86 ) {
87 assert!(
88 angle.is_finite(),
89 "Ui::table_angled_headers_row_ex_with_data() angle must be finite"
90 );
91 assert!(
92 (-std::f32::consts::FRAC_PI_2..std::f32::consts::FRAC_PI_2).contains(&angle),
93 "Ui::table_angled_headers_row_ex_with_data() angle must be between -PI/2 and PI/2"
94 );
95 assert_non_negative_finite_f32(
96 "Ui::table_angled_headers_row_ex_with_data()",
97 "max_label_width",
98 max_label_width,
99 );
100 if headers.is_empty() {
101 self.table_angled_headers_row();
102 return;
103 }
104 let count = len_i32(
105 "Ui::table_angled_headers_row_ex_with_data()",
106 "headers",
107 headers.len(),
108 );
109 let mut data: Vec<sys::ImGuiTableHeaderData> = Vec::with_capacity(headers.len());
110 self.run_with_bound_context(|| {
111 let table =
112 assert_table_before_first_row("Ui::table_angled_headers_row_ex_with_data()");
113 self.assert_no_active_table_channel(
114 "Ui::table_angled_headers_row_ex_with_data()",
115 );
116 let columns = unsafe { (*table).Columns.Data };
117 assert!(
118 !columns.is_null(),
119 "Ui::table_angled_headers_row_ex_with_data() table columns are unavailable"
120 );
121 let mut previous_display_order = -1;
122 for h in headers {
123 let column_n = assert_valid_table_column_in(
124 table,
125 h.index,
126 "Ui::table_angled_headers_row_ex_with_data()",
127 );
128 let display_order = i32::from(unsafe {
129 (*columns.add(column_n as usize)).DisplayOrder
130 });
131 assert!(
132 display_order > previous_display_order,
133 "Ui::table_angled_headers_row_ex_with_data() headers must be ordered left to right without duplicates"
134 );
135 previous_display_order = display_order;
136 data.push(sys::ImGuiTableHeaderData {
137 Index: h
138 .index
139 .into_imgui_column_idx("Ui::table_angled_headers_row_ex_with_data()"),
140 TextColor: u32::from(h.text_color),
141 BgColor0: u32::from(h.bg_color0),
142 BgColor1: u32::from(h.bg_color1),
143 });
144 }
145 unsafe {
146 sys::igTableAngledHeadersRowEx(
147 row_id,
148 angle,
149 max_label_width,
150 data.as_ptr(),
151 count,
152 );
153 }
154 });
155 }
156
157 #[doc(
166 alias = "TablePushBackgroundChannel",
167 alias = "TablePopBackgroundChannel"
168 )]
169 pub fn with_table_background_channel<R>(&self, f: impl FnOnce() -> R) -> R {
170 self.run_with_bound_context(|| {
171 assert_current_table_cell("Ui::with_table_background_channel()");
172 self.assert_no_active_table_channel("Ui::with_table_background_channel()");
173 unsafe { sys::igTablePushBackgroundChannel() };
174 });
175 let guard = TableChannelGuard::background(self);
176 let result = f();
177 drop(guard);
178 result
179 }
180
181 #[doc(alias = "TablePushColumnChannel", alias = "TablePopColumnChannel")]
191 pub fn with_table_column_channel<R>(
192 &self,
193 column: impl Into<TableColumnIndex>,
194 f: impl FnOnce() -> R,
195 ) -> R {
196 let column = column.into();
197 self.run_with_bound_context(|| {
198 assert_current_table_cell("Ui::with_table_column_channel()");
199 self.assert_no_active_table_channel("Ui::with_table_column_channel()");
200 let column_n = assert_valid_table_column(column, "Ui::with_table_column_channel()");
201 unsafe { sys::igTablePushColumnChannel(column_n) };
202 });
203 let guard = TableChannelGuard::column(self);
204 let result = f();
205 drop(guard);
206 result
207 }
208
209 #[doc(alias = "TableOpenContextMenu")]
215 pub fn table_open_context_menu(&self, target: impl Into<TableContextMenuTarget>) {
216 let target = target.into();
217 self.run_with_bound_context(|| {
218 let table = assert_current_table("Ui::table_open_context_menu()");
219 let column_n = match target {
220 TableContextMenuTarget::CurrentColumn => -1,
221 TableContextMenuTarget::Column(index) => {
222 assert_valid_table_column_in(table, index, "Ui::table_open_context_menu()")
223 }
224 TableContextMenuTarget::Table => unsafe { (*table).ColumnsCount },
225 };
226 unsafe { sys::igTableOpenContextMenu(column_n) }
227 });
228 }
229}