Skip to main content

dear_imgui_rs/widget/table/
sort.rs

1use crate::ui::Ui;
2use crate::widget::table::{TableColumnIndex, optional_user_id_from_raw};
3use crate::{Id, sys};
4#[cfg(feature = "serde")]
5use serde::{Deserialize, Serialize};
6
7/// Sorting direction for table columns.
8#[repr(u8)]
9#[derive(Copy, Clone, Debug, PartialEq, Eq)]
10#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
11pub enum SortDirection {
12    None = sys::ImGuiSortDirection_None as u8,
13    Ascending = sys::ImGuiSortDirection_Ascending as u8,
14    Descending = sys::ImGuiSortDirection_Descending as u8,
15}
16
17impl From<SortDirection> for sys::ImGuiSortDirection {
18    #[inline]
19    fn from(value: SortDirection) -> sys::ImGuiSortDirection {
20        match value {
21            SortDirection::None => sys::ImGuiSortDirection_None,
22            SortDirection::Ascending => sys::ImGuiSortDirection_Ascending,
23            SortDirection::Descending => sys::ImGuiSortDirection_Descending,
24        }
25    }
26}
27
28/// One column sort spec.
29#[derive(Copy, Clone, Debug)]
30pub struct TableColumnSortSpec {
31    pub column_user_id: Option<Id>,
32    pub column_index: TableColumnIndex,
33    pub sort_order: i16,
34    pub sort_direction: SortDirection,
35}
36
37/// Table sort specs view.
38pub struct TableSortSpecs<'a> {
39    raw: *mut sys::ImGuiTableSortSpecs,
40    _marker: std::marker::PhantomData<&'a Ui>,
41}
42
43impl<'a> TableSortSpecs<'a> {
44    /// # Safety
45    /// `raw` must be a valid pointer returned by ImGui_TableGetSortSpecs for the current table.
46    pub(crate) unsafe fn from_raw(raw: *mut sys::ImGuiTableSortSpecs) -> Self {
47        Self {
48            raw,
49            _marker: std::marker::PhantomData,
50        }
51    }
52
53    /// Whether the specs are marked dirty by dear imgui (you should resort your data).
54    pub fn is_dirty(&self) -> bool {
55        unsafe { (*self.raw).SpecsDirty }
56    }
57
58    /// Clear the dirty flag after you've applied sorting to your data.
59    pub fn clear_dirty(&mut self) {
60        unsafe { (*self.raw).SpecsDirty = false }
61    }
62
63    /// Number of column specs.
64    pub fn len(&self) -> usize {
65        unsafe { (*self.raw).SpecsCount as usize }
66    }
67
68    pub fn is_empty(&self) -> bool {
69        self.len() == 0
70    }
71
72    /// Iterate over column sort specs.
73    pub fn iter(&self) -> TableSortSpecsIter<'_> {
74        TableSortSpecsIter {
75            specs: self,
76            index: 0,
77        }
78    }
79}
80
81/// Iterator over [`TableColumnSortSpec`].
82pub struct TableSortSpecsIter<'a> {
83    specs: &'a TableSortSpecs<'a>,
84    index: usize,
85}
86
87impl<'a> Iterator for TableSortSpecsIter<'a> {
88    type Item = TableColumnSortSpec;
89    fn next(&mut self) -> Option<Self::Item> {
90        if self.index >= self.specs.len() {
91            return None;
92        }
93        unsafe {
94            let ptr = (*self.specs.raw).Specs;
95            if ptr.is_null() {
96                return None;
97            }
98            let spec = &*ptr.add(self.index);
99            self.index += 1;
100            let d = spec.SortDirection as u8;
101            let dir = if d == sys::ImGuiSortDirection_None as u8 {
102                SortDirection::None
103            } else if d == sys::ImGuiSortDirection_Ascending as u8 {
104                SortDirection::Ascending
105            } else if d == sys::ImGuiSortDirection_Descending as u8 {
106                SortDirection::Descending
107            } else {
108                SortDirection::None
109            };
110            Some(TableColumnSortSpec {
111                column_user_id: optional_user_id_from_raw(spec.ColumnUserID),
112                column_index: TableColumnIndex::from_imgui_column_idx(
113                    spec.ColumnIndex,
114                    "TableSortSpecsIter::next()",
115                ),
116                sort_order: spec.SortOrder,
117                sort_direction: dir,
118            })
119        }
120    }
121}