use crate::draw::ImColor32;
use crate::internal::len_i32;
use crate::sys;
use crate::ui::Ui;
use crate::widget::table::{
TableColumnIndex, TableContextMenuTarget, assert_current_table, assert_current_table_cell,
assert_non_negative_finite_f32, assert_table_before_first_row, assert_valid_table_column,
assert_valid_table_column_in,
};
use super::tokens::TableChannelGuard;
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct TableHeaderData {
pub index: TableColumnIndex,
pub text_color: ImColor32,
pub bg_color0: ImColor32,
pub bg_color1: ImColor32,
}
impl TableHeaderData {
pub fn new(
index: impl Into<TableColumnIndex>,
text_color: ImColor32,
bg_color0: ImColor32,
bg_color1: ImColor32,
) -> Self {
Self {
index: index.into(),
text_color,
bg_color0,
bg_color1,
}
}
}
impl Ui {
#[doc(alias = "TableGetHeaderAngledMaxLabelWidth")]
pub fn table_get_header_angled_max_label_width(&self) -> f32 {
self.run_with_bound_context(|| {
assert_current_table("Ui::table_get_header_angled_max_label_width()");
unsafe { sys::igTableGetHeaderAngledMaxLabelWidth() }
})
}
#[doc(alias = "TableAngledHeadersRow")]
pub fn table_angled_headers_row(&self) {
self.run_with_bound_context(|| {
assert_table_before_first_row("Ui::table_angled_headers_row()");
self.assert_no_active_table_channel("Ui::table_angled_headers_row()");
unsafe { sys::igTableAngledHeadersRow() };
});
}
pub fn table_angled_headers_row_ex_with_data(
&self,
row_id: u32,
angle: f32,
max_label_width: f32,
headers: &[TableHeaderData],
) {
assert!(
angle.is_finite(),
"Ui::table_angled_headers_row_ex_with_data() angle must be finite"
);
assert!(
(-std::f32::consts::FRAC_PI_2..std::f32::consts::FRAC_PI_2).contains(&angle),
"Ui::table_angled_headers_row_ex_with_data() angle must be between -PI/2 and PI/2"
);
assert_non_negative_finite_f32(
"Ui::table_angled_headers_row_ex_with_data()",
"max_label_width",
max_label_width,
);
if headers.is_empty() {
self.table_angled_headers_row();
return;
}
let count = len_i32(
"Ui::table_angled_headers_row_ex_with_data()",
"headers",
headers.len(),
);
let mut data: Vec<sys::ImGuiTableHeaderData> = Vec::with_capacity(headers.len());
self.run_with_bound_context(|| {
let table =
assert_table_before_first_row("Ui::table_angled_headers_row_ex_with_data()");
self.assert_no_active_table_channel(
"Ui::table_angled_headers_row_ex_with_data()",
);
let columns = unsafe { (*table).Columns.Data };
assert!(
!columns.is_null(),
"Ui::table_angled_headers_row_ex_with_data() table columns are unavailable"
);
let mut previous_display_order = -1;
for h in headers {
let column_n = assert_valid_table_column_in(
table,
h.index,
"Ui::table_angled_headers_row_ex_with_data()",
);
let display_order = i32::from(unsafe {
(*columns.add(column_n as usize)).DisplayOrder
});
assert!(
display_order > previous_display_order,
"Ui::table_angled_headers_row_ex_with_data() headers must be ordered left to right without duplicates"
);
previous_display_order = display_order;
data.push(sys::ImGuiTableHeaderData {
Index: h
.index
.into_imgui_column_idx("Ui::table_angled_headers_row_ex_with_data()"),
TextColor: u32::from(h.text_color),
BgColor0: u32::from(h.bg_color0),
BgColor1: u32::from(h.bg_color1),
});
}
unsafe {
sys::igTableAngledHeadersRowEx(
row_id,
angle,
max_label_width,
data.as_ptr(),
count,
);
}
});
}
#[doc(
alias = "TablePushBackgroundChannel",
alias = "TablePopBackgroundChannel"
)]
pub fn with_table_background_channel<R>(&self, f: impl FnOnce() -> R) -> R {
self.run_with_bound_context(|| {
assert_current_table_cell("Ui::with_table_background_channel()");
self.assert_no_active_table_channel("Ui::with_table_background_channel()");
unsafe { sys::igTablePushBackgroundChannel() };
});
let guard = TableChannelGuard::background(self);
let result = f();
drop(guard);
result
}
#[doc(alias = "TablePushColumnChannel", alias = "TablePopColumnChannel")]
pub fn with_table_column_channel<R>(
&self,
column: impl Into<TableColumnIndex>,
f: impl FnOnce() -> R,
) -> R {
let column = column.into();
self.run_with_bound_context(|| {
assert_current_table_cell("Ui::with_table_column_channel()");
self.assert_no_active_table_channel("Ui::with_table_column_channel()");
let column_n = assert_valid_table_column(column, "Ui::with_table_column_channel()");
unsafe { sys::igTablePushColumnChannel(column_n) };
});
let guard = TableChannelGuard::column(self);
let result = f();
drop(guard);
result
}
#[doc(alias = "TableOpenContextMenu")]
pub fn table_open_context_menu(&self, target: impl Into<TableContextMenuTarget>) {
let target = target.into();
self.run_with_bound_context(|| {
let table = assert_current_table("Ui::table_open_context_menu()");
let column_n = match target {
TableContextMenuTarget::CurrentColumn => -1,
TableContextMenuTarget::Column(index) => {
assert_valid_table_column_in(table, index, "Ui::table_open_context_menu()")
}
TableContextMenuTarget::Table => unsafe { (*table).ColumnsCount },
};
unsafe { sys::igTableOpenContextMenu(column_n) }
});
}
}