1#![allow(
36 clippy::cast_possible_truncation,
37 clippy::cast_sign_loss,
38 clippy::as_conversions
39)]
40use crate::draw::ImColor32;
41use crate::sys;
42use crate::ui::Ui;
43use crate::widget::{
44 TableColumnFlags, TableColumnIndent, TableColumnStateFlags, TableColumnWidth, TableFlags,
45 TableOptions, TableSizingPolicy,
46};
47#[cfg(feature = "serde")]
48use serde::{Deserialize, Serialize};
49use std::borrow::Cow;
50use std::ffi::CStr;
51
52#[derive(Clone, Debug)]
54pub struct TableColumnSetup<Name> {
55 pub name: Name,
56 pub flags: TableColumnFlags,
57 pub width: Option<TableColumnWidth>,
58 pub indent: Option<TableColumnIndent>,
59 pub user_id: u32,
60}
61
62impl<Name> TableColumnSetup<Name> {
63 pub fn new(name: Name) -> Self {
65 Self {
66 name,
67 flags: TableColumnFlags::NONE,
68 width: None,
69 indent: None,
70 user_id: 0,
71 }
72 }
73
74 pub fn flags(mut self, flags: TableColumnFlags) -> Self {
76 self.flags = flags;
77 self
78 }
79
80 pub fn fixed_width(mut self, width: f32) -> Self {
82 self.width = Some(TableColumnWidth::Fixed(width));
83 self
84 }
85
86 pub fn stretch_weight(mut self, weight: f32) -> Self {
88 self.width = Some(TableColumnWidth::Stretch(weight));
89 self
90 }
91
92 pub fn indent(mut self, indent: TableColumnIndent) -> Self {
94 self.indent = Some(indent);
95 self
96 }
97
98 pub fn indent_enabled(mut self, enabled: bool) -> Self {
100 self.indent = Some(if enabled {
101 TableColumnIndent::Enable
102 } else {
103 TableColumnIndent::Disable
104 });
105 self
106 }
107
108 pub fn user_id(mut self, id: u32) -> Self {
110 self.user_id = id;
111 self
112 }
113}
114
115impl Ui {
117 pub fn table<'ui>(&'ui self, str_id: impl Into<Cow<'ui, str>>) -> TableBuilder<'ui> {
138 TableBuilder::new(self, str_id)
139 }
140 #[must_use = "if return is dropped immediately, table is ended immediately."]
146 pub fn begin_table(
147 &self,
148 str_id: impl AsRef<str>,
149 column_count: usize,
150 ) -> Option<TableToken<'_>> {
151 self.begin_table_with_flags(str_id, column_count, TableFlags::NONE)
152 }
153
154 #[must_use = "if return is dropped immediately, table is ended immediately."]
156 pub fn begin_table_with_flags(
157 &self,
158 str_id: impl AsRef<str>,
159 column_count: usize,
160 flags: impl Into<TableOptions>,
161 ) -> Option<TableToken<'_>> {
162 self.begin_table_with_sizing(str_id, column_count, flags, [0.0, 0.0], 0.0)
163 }
164
165 #[must_use = "if return is dropped immediately, table is ended immediately."]
168 pub fn begin_table_with_sizing(
169 &self,
170 str_id: impl AsRef<str>,
171 column_count: usize,
172 flags: impl Into<TableOptions>,
173 outer_size: impl Into<[f32; 2]>,
174 inner_width: f32,
175 ) -> Option<TableToken<'_>> {
176 let options = flags.into();
177 let str_id_ptr = self.scratch_txt(str_id);
178 let outer_size_vec: sys::ImVec2 = outer_size.into().into();
179
180 let should_render = unsafe {
181 sys::igBeginTable(
182 str_id_ptr,
183 column_count as i32,
184 options.raw(),
185 outer_size_vec,
186 inner_width,
187 )
188 };
189
190 if should_render {
191 Some(TableToken::new(self))
192 } else {
193 None
194 }
195 }
196
197 #[must_use = "if return is dropped immediately, table is ended immediately."]
202 pub fn begin_table_header<Name: AsRef<str>, const N: usize>(
203 &self,
204 str_id: impl AsRef<str>,
205 column_data: [TableColumnSetup<Name>; N],
206 ) -> Option<TableToken<'_>> {
207 self.begin_table_header_with_flags(str_id, column_data, TableFlags::NONE)
208 }
209
210 #[must_use = "if return is dropped immediately, table is ended immediately."]
215 pub fn begin_table_header_with_flags<Name: AsRef<str>, const N: usize>(
216 &self,
217 str_id: impl AsRef<str>,
218 column_data: [TableColumnSetup<Name>; N],
219 flags: impl Into<TableOptions>,
220 ) -> Option<TableToken<'_>> {
221 if let Some(token) = self.begin_table_with_flags(str_id, N, flags) {
222 for column in &column_data {
224 self.table_setup_column_with_indent(
225 &column.name,
226 column.flags,
227 column.width,
228 column.indent,
229 column.user_id,
230 );
231 }
232 self.table_headers_row();
233 Some(token)
234 } else {
235 None
236 }
237 }
238
239 pub fn table_setup_column(
241 &self,
242 label: impl AsRef<str>,
243 flags: TableColumnFlags,
244 width: Option<TableColumnWidth>,
245 user_id: u32,
246 ) {
247 self.table_setup_column_with_indent(label, flags, width, None, user_id);
248 }
249
250 pub fn table_setup_column_with_indent(
252 &self,
253 label: impl AsRef<str>,
254 flags: TableColumnFlags,
255 width: Option<TableColumnWidth>,
256 indent: Option<TableColumnIndent>,
257 user_id: u32,
258 ) {
259 let label_ptr = self.scratch_txt(label);
260 let raw_flags = flags.bits()
261 | width.map_or(0, TableColumnWidth::raw_flags)
262 | indent.map_or(0, TableColumnIndent::raw_flags);
263 let init_width_or_weight = width.map_or(0.0, TableColumnWidth::value);
264 unsafe {
265 sys::igTableSetupColumn(label_ptr, raw_flags, init_width_or_weight, user_id);
266 }
267 }
268
269 pub fn table_setup_column_fixed_width(
271 &self,
272 label: impl AsRef<str>,
273 flags: TableColumnFlags,
274 width: f32,
275 user_id: u32,
276 ) {
277 self.table_setup_column(label, flags, Some(TableColumnWidth::Fixed(width)), user_id);
278 }
279
280 pub fn table_setup_column_stretch_weight(
282 &self,
283 label: impl AsRef<str>,
284 flags: TableColumnFlags,
285 weight: f32,
286 user_id: u32,
287 ) {
288 self.table_setup_column(
289 label,
290 flags,
291 Some(TableColumnWidth::Stretch(weight)),
292 user_id,
293 );
294 }
295
296 pub fn table_headers_row(&self) {
298 unsafe {
299 sys::igTableHeadersRow();
300 }
301 }
302
303 pub fn table_next_column(&self) -> bool {
305 unsafe { sys::igTableNextColumn() }
306 }
307
308 pub fn table_set_column_index(&self, column_n: i32) -> bool {
310 unsafe { sys::igTableSetColumnIndex(column_n) }
311 }
312
313 pub fn table_next_row(&self) {
315 self.table_next_row_with_flags(TableRowFlags::NONE, 0.0);
316 }
317
318 pub fn table_next_row_with_flags(&self, flags: TableRowFlags, min_row_height: f32) {
320 unsafe {
321 sys::igTableNextRow(flags.bits(), min_row_height);
322 }
323 }
324
325 #[doc(alias = "TableSetupScrollFreeze")]
327 pub fn table_setup_scroll_freeze(&self, frozen_cols: i32, frozen_rows: i32) {
328 unsafe { sys::igTableSetupScrollFreeze(frozen_cols, frozen_rows) }
329 }
330
331 #[doc(alias = "TableHeader")]
333 pub fn table_header(&self, label: impl AsRef<str>) {
334 let label_ptr = self.scratch_txt(label);
335 unsafe { sys::igTableHeader(label_ptr) }
336 }
337
338 #[doc(alias = "TableGetColumnCount")]
340 pub fn table_get_column_count(&self) -> i32 {
341 unsafe { sys::igTableGetColumnCount() }
342 }
343
344 #[doc(alias = "TableGetColumnIndex")]
346 pub fn table_get_column_index(&self) -> i32 {
347 unsafe { sys::igTableGetColumnIndex() }
348 }
349
350 #[doc(alias = "TableGetRowIndex")]
352 pub fn table_get_row_index(&self) -> i32 {
353 unsafe { sys::igTableGetRowIndex() }
354 }
355
356 #[doc(alias = "TableGetColumnName")]
358 pub fn table_get_column_name(&self, column_n: i32) -> &str {
359 unsafe {
360 let ptr = sys::igTableGetColumnName_Int(column_n);
361 if ptr.is_null() {
362 ""
363 } else {
364 CStr::from_ptr(ptr).to_str().unwrap_or("")
365 }
366 }
367 }
368
369 #[doc(alias = "TableGetColumnFlags")]
371 pub fn table_get_column_flags(&self, column_n: i32) -> TableColumnStateFlags {
372 unsafe { TableColumnStateFlags::from_bits_truncate(sys::igTableGetColumnFlags(column_n)) }
373 }
374
375 #[doc(alias = "TableSetColumnEnabled")]
377 pub fn table_set_column_enabled(&self, column_n: i32, enabled: bool) {
378 unsafe { sys::igTableSetColumnEnabled(column_n, enabled) }
379 }
380
381 #[doc(alias = "TableGetHoveredColumn")]
383 pub fn table_get_hovered_column(&self) -> i32 {
384 unsafe { sys::igTableGetHoveredColumn() }
385 }
386
387 #[doc(alias = "TableSetColumnWidth")]
389 pub fn table_set_column_width(&self, column_n: i32, width: f32) {
390 unsafe { sys::igTableSetColumnWidth(column_n, width) }
391 }
392
393 #[doc(alias = "TableSetBgColor")]
398 pub fn table_set_bg_color_u32(&self, target: TableBgTarget, color: u32, column_n: i32) {
399 unsafe { sys::igTableSetBgColor(target as i32, color, column_n) }
400 }
401
402 pub fn table_set_bg_color(&self, target: TableBgTarget, rgba: [f32; 4], column_n: i32) {
404 let col = crate::colors::Color::from_array(rgba).to_imgui_u32();
406 unsafe { sys::igTableSetBgColor(target as i32, col, column_n) }
407 }
408
409 #[doc(alias = "TableGetHoveredRow")]
411 pub fn table_get_hovered_row(&self) -> i32 {
412 unsafe { sys::igTableGetHoveredRow() }
413 }
414
415 #[doc(alias = "TableGetHeaderRowHeight")]
417 pub fn table_get_header_row_height(&self) -> f32 {
418 unsafe { sys::igTableGetHeaderRowHeight() }
419 }
420
421 #[doc(alias = "TableSetColumnSortDirection")]
423 pub fn table_set_column_sort_direction(
424 &self,
425 column_n: i32,
426 dir: SortDirection,
427 append_to_sort_specs: bool,
428 ) {
429 unsafe { sys::igTableSetColumnSortDirection(column_n, dir.into(), append_to_sort_specs) }
430 }
431
432 #[doc(alias = "TableGetSortSpecs")]
436 pub fn table_get_sort_specs(&self) -> Option<TableSortSpecs<'_>> {
437 unsafe {
438 let ptr = sys::igTableGetSortSpecs();
439 if ptr.is_null() {
440 None
441 } else {
442 Some(TableSortSpecs::from_raw(ptr))
443 }
444 }
445 }
446}
447
448bitflags::bitflags! {
449 #[repr(transparent)]
451 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
452 pub struct TableRowFlags: i32 {
453 const NONE = 0;
455 const HEADERS = sys::ImGuiTableRowFlags_Headers as i32;
457 }
458}
459
460#[cfg(feature = "serde")]
461impl Serialize for TableRowFlags {
462 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
463 where
464 S: serde::Serializer,
465 {
466 serializer.serialize_i32(self.bits())
467 }
468}
469
470#[cfg(feature = "serde")]
471impl<'de> Deserialize<'de> for TableRowFlags {
472 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
473 where
474 D: serde::Deserializer<'de>,
475 {
476 let bits = i32::deserialize(deserializer)?;
477 Ok(TableRowFlags::from_bits_truncate(bits))
478 }
479}
480
481#[repr(i32)]
483#[derive(Copy, Clone, Debug, PartialEq, Eq)]
484#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
485pub enum TableBgTarget {
486 None = sys::ImGuiTableBgTarget_None as i32,
488 RowBg0 = sys::ImGuiTableBgTarget_RowBg0 as i32,
490 RowBg1 = sys::ImGuiTableBgTarget_RowBg1 as i32,
492 CellBg = sys::ImGuiTableBgTarget_CellBg as i32,
494}
495
496#[repr(u8)]
498#[derive(Copy, Clone, Debug, PartialEq, Eq)]
499#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
500pub enum SortDirection {
501 None = sys::ImGuiSortDirection_None as u8,
502 Ascending = sys::ImGuiSortDirection_Ascending as u8,
503 Descending = sys::ImGuiSortDirection_Descending as u8,
504}
505
506impl From<SortDirection> for sys::ImGuiSortDirection {
507 #[inline]
508 fn from(value: SortDirection) -> sys::ImGuiSortDirection {
509 match value {
510 SortDirection::None => sys::ImGuiSortDirection_None,
511 SortDirection::Ascending => sys::ImGuiSortDirection_Ascending,
512 SortDirection::Descending => sys::ImGuiSortDirection_Descending,
513 }
514 }
515}
516
517#[derive(Copy, Clone, Debug)]
519pub struct TableColumnSortSpec {
520 pub column_user_id: u32,
521 pub column_index: i16,
522 pub sort_order: i16,
523 pub sort_direction: SortDirection,
524}
525
526pub struct TableSortSpecs<'a> {
528 raw: *mut sys::ImGuiTableSortSpecs,
529 _marker: std::marker::PhantomData<&'a Ui>,
530}
531
532impl<'a> TableSortSpecs<'a> {
533 pub(crate) unsafe fn from_raw(raw: *mut sys::ImGuiTableSortSpecs) -> Self {
536 Self {
537 raw,
538 _marker: std::marker::PhantomData,
539 }
540 }
541
542 pub fn is_dirty(&self) -> bool {
544 unsafe { (*self.raw).SpecsDirty }
545 }
546
547 pub fn clear_dirty(&mut self) {
549 unsafe { (*self.raw).SpecsDirty = false }
550 }
551
552 pub fn len(&self) -> usize {
554 unsafe { (*self.raw).SpecsCount as usize }
555 }
556
557 pub fn is_empty(&self) -> bool {
558 self.len() == 0
559 }
560
561 pub fn iter(&self) -> TableSortSpecsIter<'_> {
563 TableSortSpecsIter {
564 specs: self,
565 index: 0,
566 }
567 }
568}
569
570pub struct TableSortSpecsIter<'a> {
572 specs: &'a TableSortSpecs<'a>,
573 index: usize,
574}
575
576impl<'a> Iterator for TableSortSpecsIter<'a> {
577 type Item = TableColumnSortSpec;
578 fn next(&mut self) -> Option<Self::Item> {
579 if self.index >= self.specs.len() {
580 return None;
581 }
582 unsafe {
583 let ptr = (*self.specs.raw).Specs;
584 if ptr.is_null() {
585 return None;
586 }
587 let spec = &*ptr.add(self.index);
588 self.index += 1;
589 let d = spec.SortDirection as u8;
590 let dir = if d == sys::ImGuiSortDirection_None as u8 {
591 SortDirection::None
592 } else if d == sys::ImGuiSortDirection_Ascending as u8 {
593 SortDirection::Ascending
594 } else if d == sys::ImGuiSortDirection_Descending as u8 {
595 SortDirection::Descending
596 } else {
597 SortDirection::None
598 };
599 Some(TableColumnSortSpec {
600 column_user_id: spec.ColumnUserID,
601 column_index: spec.ColumnIndex,
602 sort_order: spec.SortOrder,
603 sort_direction: dir,
604 })
605 }
606 }
607}
608
609#[must_use]
611pub struct TableToken<'ui> {
612 _ui: &'ui Ui,
613}
614
615impl<'ui> TableToken<'ui> {
616 fn new(ui: &'ui Ui) -> Self {
618 TableToken { _ui: ui }
619 }
620
621 pub fn end(self) {
623 }
625}
626
627impl<'ui> Drop for TableToken<'ui> {
628 fn drop(&mut self) {
629 unsafe {
630 sys::igEndTable();
631 }
632 }
633}
634
635#[derive(Copy, Clone, Debug, PartialEq)]
641pub struct TableHeaderData {
642 pub index: i16,
643 pub text_color: ImColor32,
644 pub bg_color0: ImColor32,
645 pub bg_color1: ImColor32,
646}
647
648impl TableHeaderData {
649 pub fn new(
650 index: i16,
651 text_color: ImColor32,
652 bg_color0: ImColor32,
653 bg_color1: ImColor32,
654 ) -> Self {
655 Self {
656 index,
657 text_color,
658 bg_color0,
659 bg_color1,
660 }
661 }
662}
663impl Ui {
664 #[doc(alias = "TableGetHeaderAngledMaxLabelWidth")]
666 pub fn table_get_header_angled_max_label_width(&self) -> f32 {
667 unsafe { sys::igTableGetHeaderAngledMaxLabelWidth() }
668 }
669
670 #[doc(alias = "TableAngledHeadersRow")]
672 pub fn table_angled_headers_row(&self) {
673 unsafe { sys::igTableAngledHeadersRow() }
674 }
675
676 pub fn table_angled_headers_row_ex_with_data(
685 &self,
686 row_id: u32,
687 angle: f32,
688 max_label_width: f32,
689 headers: &[TableHeaderData],
690 ) {
691 if headers.is_empty() {
692 unsafe { sys::igTableAngledHeadersRow() }
693 return;
694 }
695 let count = match i32::try_from(headers.len()) {
696 Ok(n) => n,
697 Err(_) => return,
698 };
699 let mut data: Vec<sys::ImGuiTableHeaderData> = Vec::with_capacity(headers.len());
700 for h in headers {
701 data.push(sys::ImGuiTableHeaderData {
702 Index: h.index as sys::ImGuiTableColumnIdx,
703 TextColor: u32::from(h.text_color),
704 BgColor0: u32::from(h.bg_color0),
705 BgColor1: u32::from(h.bg_color1),
706 });
707 }
708 unsafe {
709 sys::igTableAngledHeadersRowEx(row_id, angle, max_label_width, data.as_ptr(), count);
710 }
711 }
712
713 #[doc(alias = "TablePushBackgroundChannel")]
715 pub fn table_push_background_channel(&self) {
716 unsafe { sys::igTablePushBackgroundChannel() }
717 }
718
719 #[doc(alias = "TablePopBackgroundChannel")]
721 pub fn table_pop_background_channel(&self) {
722 unsafe { sys::igTablePopBackgroundChannel() }
723 }
724
725 #[doc(alias = "TablePushColumnChannel")]
727 pub fn table_push_column_channel(&self, column_n: i32) {
728 unsafe { sys::igTablePushColumnChannel(column_n) }
729 }
730
731 #[doc(alias = "TablePopColumnChannel")]
733 pub fn table_pop_column_channel(&self) {
734 unsafe { sys::igTablePopColumnChannel() }
735 }
736
737 pub fn with_table_background_channel<R>(&self, f: impl FnOnce() -> R) -> R {
739 self.table_push_background_channel();
740 let result = f();
741 self.table_pop_background_channel();
742 result
743 }
744
745 pub fn with_table_column_channel<R>(&self, column_n: i32, f: impl FnOnce() -> R) -> R {
747 self.table_push_column_channel(column_n);
748 let result = f();
749 self.table_pop_column_channel();
750 result
751 }
752
753 #[doc(alias = "TableOpenContextMenu")]
755 pub fn table_open_context_menu(&self, column_n: Option<i32>) {
756 unsafe { sys::igTableOpenContextMenu(column_n.unwrap_or(-1)) }
757 }
758}
759
760#[derive(Debug)]
768pub struct TableBuilder<'ui> {
769 ui: &'ui Ui,
770 id: Cow<'ui, str>,
771 flags: TableFlags,
772 sizing_policy: Option<TableSizingPolicy>,
773 outer_size: [f32; 2],
774 inner_width: f32,
775 columns: Vec<TableColumnSetup<Cow<'ui, str>>>,
776 use_headers: bool,
777 freeze: Option<(i32, i32)>,
778}
779
780impl<'ui> TableBuilder<'ui> {
781 pub fn new(ui: &'ui Ui, str_id: impl Into<Cow<'ui, str>>) -> Self {
783 Self {
784 ui,
785 id: str_id.into(),
786 flags: TableFlags::NONE,
787 sizing_policy: None,
788 outer_size: [0.0, 0.0],
789 inner_width: 0.0,
790 columns: Vec::new(),
791 use_headers: false,
792 freeze: None,
793 }
794 }
795
796 pub fn flags(mut self, flags: TableFlags) -> Self {
798 self.flags = flags;
799 self
800 }
801
802 pub fn sizing_policy(mut self, policy: TableSizingPolicy) -> Self {
804 self.sizing_policy = Some(policy);
805 self
806 }
807
808 pub fn outer_size(mut self, size: [f32; 2]) -> Self {
810 self.outer_size = size;
811 self
812 }
813
814 pub fn inner_width(mut self, width: f32) -> Self {
816 self.inner_width = width;
817 self
818 }
819
820 pub fn freeze(mut self, frozen_cols: i32, frozen_rows: i32) -> Self {
822 self.freeze = Some((frozen_cols, frozen_rows));
823 self
824 }
825
826 pub fn column(self, name: impl Into<Cow<'ui, str>>) -> ColumnBuilder<'ui> {
829 ColumnBuilder::new(self, name)
830 }
831
832 pub fn columns<Name: Into<Cow<'ui, str>>>(
834 mut self,
835 cols: impl IntoIterator<Item = TableColumnSetup<Name>>,
836 ) -> Self {
837 self.columns.clear();
838 for c in cols {
839 self.columns.push(TableColumnSetup {
840 name: c.name.into(),
841 flags: c.flags,
842 width: c.width,
843 indent: c.indent,
844 user_id: c.user_id,
845 });
846 }
847 self
848 }
849
850 pub fn add_column<Name: Into<Cow<'ui, str>>>(mut self, col: TableColumnSetup<Name>) -> Self {
852 self.columns.push(TableColumnSetup {
853 name: col.name.into(),
854 flags: col.flags,
855 width: col.width,
856 indent: col.indent,
857 user_id: col.user_id,
858 });
859 self
860 }
861
862 pub fn headers(mut self, enabled: bool) -> Self {
864 self.use_headers = enabled;
865 self
866 }
867
868 pub fn build(self, f: impl FnOnce(&Ui)) {
870 let mut options = TableOptions::from(self.flags);
871 if let Some(policy) = self.sizing_policy {
872 options = options.sizing_policy(policy);
873 }
874 let Some(token) = self.ui.begin_table_with_sizing(
875 self.id.as_ref(),
876 self.columns.len(),
877 options,
878 self.outer_size,
879 self.inner_width,
880 ) else {
881 return;
882 };
883
884 if let Some((fc, fr)) = self.freeze {
885 self.ui.table_setup_scroll_freeze(fc, fr);
886 }
887
888 if !self.columns.is_empty() {
889 for col in &self.columns {
890 self.ui.table_setup_column_with_indent(
891 col.name.as_ref(),
892 col.flags,
893 col.width,
894 col.indent,
895 col.user_id,
896 );
897 }
898 if self.use_headers {
899 self.ui.table_headers_row();
900 }
901 }
902
903 f(self.ui);
904
905 token.end();
907 }
908}
909
910#[derive(Debug)]
912pub struct ColumnBuilder<'ui> {
913 parent: TableBuilder<'ui>,
914 name: Cow<'ui, str>,
915 flags: TableColumnFlags,
916 width: Option<TableColumnWidth>,
917 indent: Option<TableColumnIndent>,
918 user_id: u32,
919}
920
921impl<'ui> ColumnBuilder<'ui> {
922 fn new(parent: TableBuilder<'ui>, name: impl Into<Cow<'ui, str>>) -> Self {
923 Self {
924 parent,
925 name: name.into(),
926 flags: TableColumnFlags::NONE,
927 width: None,
928 indent: None,
929 user_id: 0,
930 }
931 }
932
933 pub fn flags(mut self, flags: TableColumnFlags) -> Self {
935 self.flags = flags;
936 self
937 }
938
939 pub fn width(mut self, width: f32) -> Self {
941 self.width = Some(TableColumnWidth::Fixed(width));
942 self
943 }
944
945 pub fn weight(mut self, weight: f32) -> Self {
947 self.width = Some(TableColumnWidth::Stretch(weight));
948 self
949 }
950
951 pub fn indent(mut self, indent: TableColumnIndent) -> Self {
953 self.indent = Some(indent);
954 self
955 }
956
957 pub fn indent_enabled(mut self, enabled: bool) -> Self {
959 self.indent = Some(if enabled {
960 TableColumnIndent::Enable
961 } else {
962 TableColumnIndent::Disable
963 });
964 self
965 }
966
967 pub fn angled_header(mut self, enabled: bool) -> Self {
969 if enabled {
970 self.flags.insert(TableColumnFlags::ANGLED_HEADER);
971 } else {
972 self.flags.remove(TableColumnFlags::ANGLED_HEADER);
973 }
974 self
975 }
976
977 pub fn user_id(mut self, id: u32) -> Self {
979 self.user_id = id;
980 self
981 }
982
983 pub fn done(mut self) -> TableBuilder<'ui> {
985 self.parent.columns.push(TableColumnSetup {
986 name: self.name,
987 flags: self.flags,
988 width: self.width,
989 indent: self.indent,
990 user_id: self.user_id,
991 });
992 self.parent
993 }
994}