1#![doc = include_str!("../README.md")]
2
3pub mod draw;
4pub mod viewer;
5
6pub use draw::{Renderer, Style};
7pub use viewer::{RowViewer, UiAction};
8
9pub extern crate egui;
11
12pub struct DataTable<R> {
18    rows: Vec<R>,
29
30    dirty_flag: bool,
31
32    ui: Option<Box<draw::state::UiState<R>>>,
34}
35
36impl<R: std::fmt::Debug> std::fmt::Debug for DataTable<R> {
37    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38        f.debug_struct("Spreadsheet")
39            .field("rows", &self.rows)
40            .finish()
41    }
42}
43
44impl<R> Default for DataTable<R> {
45    fn default() -> Self {
46        Self {
47            rows: Default::default(),
48            ui: Default::default(),
49            dirty_flag: false,
50        }
51    }
52}
53
54impl<R> FromIterator<R> for DataTable<R> {
55    fn from_iter<T: IntoIterator<Item = R>>(iter: T) -> Self {
56        Self {
57            rows: iter.into_iter().collect(),
58            ..Default::default()
59        }
60    }
61}
62
63impl<R> DataTable<R> {
64    pub fn new() -> Self {
65        Default::default()
66    }
67
68    pub fn take(&mut self) -> Vec<R> {
69        self.mark_dirty();
70        std::mem::take(&mut self.rows)
71    }
72
73    pub fn replace(&mut self, new: Vec<R>) -> Vec<R> {
75        self.mark_dirty();
76        std::mem::replace(&mut self.rows, new)
77    }
78
79    pub fn retain(&mut self, mut f: impl FnMut(&R) -> bool) {
82        let mut removed_any = false;
83        self.rows.retain(|row| {
84            let retain = f(row);
85            removed_any |= !retain;
86            retain
87        });
88
89        if removed_any {
90            self.mark_dirty();
91        }
92    }
93
94    pub fn is_dirty(&self) -> bool {
96        self.ui.as_ref().is_some_and(|ui| ui.cc_is_dirty())
97    }
98
99    #[deprecated(
100        since = "0.5.1",
101        note = "user-driven dirty flag clearance is redundant"
102    )]
103    pub fn clear_dirty_flag(&mut self) {
104        }
106
107    fn mark_dirty(&mut self) {
108        let Some(state) = self.ui.as_mut() else {
109            return;
110        };
111
112        state.force_mark_dirty();
113    }
114
115    pub fn has_user_modification(&self) -> bool {
117        self.dirty_flag
118    }
119
120    pub fn clear_user_modification_flag(&mut self) {
122        self.dirty_flag = false;
123    }
124}
125
126impl<R> Extend<R> for DataTable<R> {
127    fn extend<T: IntoIterator<Item = R>>(&mut self, iter: T) {
129        self.ui = None;
131        self.rows.extend(iter);
132    }
133}
134
135fn default<T: Default>() -> T {
136    T::default()
137}
138
139impl<R> std::ops::Deref for DataTable<R> {
140    type Target = Vec<R>;
141
142    fn deref(&self) -> &Self::Target {
143        &self.rows
144    }
145}
146
147impl<R> std::ops::DerefMut for DataTable<R> {
148    fn deref_mut(&mut self) -> &mut Self::Target {
149        self.mark_dirty();
150        &mut self.rows
151    }
152}
153
154impl<R: Clone> Clone for DataTable<R> {
155    fn clone(&self) -> Self {
156        Self {
157            rows: self.rows.clone(),
158            ui: None,
160            dirty_flag: self.dirty_flag,
161        }
162    }
163}