formualizer_eval/engine/
row_visibility.rs1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2pub enum RowVisibilitySource {
3 Manual,
4 Filter,
5}
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8pub enum VisibilityMaskMode {
9 IncludeAll,
10 ExcludeManualHidden,
11 ExcludeFilterHidden,
12 ExcludeManualOrFilterHidden,
13}
14
15#[derive(Debug, Clone, Default, PartialEq, Eq)]
16struct RowBitSet {
17 words: Vec<u64>,
18}
19
20impl RowBitSet {
21 fn is_empty(&self) -> bool {
22 self.words.iter().all(|w| *w == 0)
23 }
24
25 fn get(&self, row0: u32) -> bool {
26 let word_idx = (row0 / 64) as usize;
27 let bit_idx = row0 % 64;
28 self.words
29 .get(word_idx)
30 .map(|word| (word & (1u64 << bit_idx)) != 0)
31 .unwrap_or(false)
32 }
33
34 fn set(&mut self, row0: u32, hidden: bool) -> bool {
35 let word_idx = (row0 / 64) as usize;
36 let bit_idx = row0 % 64;
37
38 if word_idx >= self.words.len() {
39 if !hidden {
40 return false;
41 }
42 self.words.resize(word_idx + 1, 0);
43 }
44
45 let mask = 1u64 << bit_idx;
46 let word = &mut self.words[word_idx];
47 let old = (*word & mask) != 0;
48 if old == hidden {
49 return false;
50 }
51
52 if hidden {
53 *word |= mask;
54 } else {
55 *word &= !mask;
56 self.trim_trailing_zeros();
57 }
58 true
59 }
60
61 fn set_range(&mut self, start_row0: u32, end_row0: u32, hidden: bool) -> bool {
62 if start_row0 > end_row0 {
63 return false;
64 }
65
66 let mut changed = false;
67 for row0 in start_row0..=end_row0 {
68 changed |= self.set(row0, hidden);
69 }
70 changed
71 }
72
73 fn insert_rows(&mut self, before0: u32, count: u32) -> bool {
74 if count == 0 {
75 return false;
76 }
77
78 let old_rows = self.collect_set_rows();
79 if old_rows.is_empty() {
80 return false;
81 }
82
83 let mut changed = false;
84 let mut new_rows = Vec::with_capacity(old_rows.len());
85 for row0 in old_rows {
86 let shifted = if row0 >= before0 {
87 changed = true;
88 row0.saturating_add(count)
89 } else {
90 row0
91 };
92 new_rows.push(shifted);
93 }
94
95 if changed {
96 self.rebuild_from_set_rows(&new_rows);
97 }
98 changed
99 }
100
101 fn delete_rows(&mut self, start0: u32, count: u32) -> bool {
102 if count == 0 {
103 return false;
104 }
105
106 let old_rows = self.collect_set_rows();
107 if old_rows.is_empty() {
108 return false;
109 }
110
111 let end0 = start0.saturating_add(count.saturating_sub(1));
112 let mut changed = false;
113 let mut new_rows = Vec::with_capacity(old_rows.len());
114
115 for row0 in old_rows {
116 if row0 < start0 {
117 new_rows.push(row0);
118 continue;
119 }
120 if row0 <= end0 {
121 changed = true;
122 continue;
123 }
124
125 changed = true;
126 new_rows.push(row0 - count);
127 }
128
129 if changed {
130 self.rebuild_from_set_rows(&new_rows);
131 }
132 changed
133 }
134
135 fn collect_set_rows(&self) -> Vec<u32> {
136 let mut rows = Vec::new();
137 for (word_idx, word) in self.words.iter().copied().enumerate() {
138 let mut bits = word;
139 while bits != 0 {
140 let tz = bits.trailing_zeros();
141 rows.push((word_idx as u32) * 64 + tz);
142 bits &= bits - 1;
143 }
144 }
145 rows
146 }
147
148 fn rebuild_from_set_rows(&mut self, rows: &[u32]) {
149 self.words.clear();
150 for row0 in rows {
151 let _ = self.set(*row0, true);
152 }
153 }
154
155 fn trim_trailing_zeros(&mut self) {
156 while self.words.last().copied() == Some(0) {
157 self.words.pop();
158 }
159 }
160}
161
162#[derive(Debug, Clone, Default, PartialEq, Eq)]
163pub struct RowVisibilityState {
164 manual_hidden: RowBitSet,
165 filter_hidden: RowBitSet,
166 version: u64,
167}
168
169impl RowVisibilityState {
170 pub fn version(&self) -> u64 {
171 self.version
172 }
173
174 pub fn is_empty(&self) -> bool {
175 self.manual_hidden.is_empty() && self.filter_hidden.is_empty()
176 }
177
178 pub fn set_row_hidden(&mut self, row0: u32, hidden: bool, source: RowVisibilitySource) -> bool {
179 let changed = match source {
180 RowVisibilitySource::Manual => self.manual_hidden.set(row0, hidden),
181 RowVisibilitySource::Filter => self.filter_hidden.set(row0, hidden),
182 };
183 if changed {
184 self.version = self.version.saturating_add(1);
185 }
186 changed
187 }
188
189 pub fn set_rows_hidden(
190 &mut self,
191 start_row0: u32,
192 end_row0: u32,
193 hidden: bool,
194 source: RowVisibilitySource,
195 ) -> bool {
196 let changed = match source {
197 RowVisibilitySource::Manual => {
198 self.manual_hidden.set_range(start_row0, end_row0, hidden)
199 }
200 RowVisibilitySource::Filter => {
201 self.filter_hidden.set_range(start_row0, end_row0, hidden)
202 }
203 };
204 if changed {
205 self.version = self.version.saturating_add(1);
206 }
207 changed
208 }
209
210 pub fn is_row_hidden(&self, row0: u32, source: Option<RowVisibilitySource>) -> bool {
211 match source {
212 Some(RowVisibilitySource::Manual) => self.manual_hidden.get(row0),
213 Some(RowVisibilitySource::Filter) => self.filter_hidden.get(row0),
214 None => self.manual_hidden.get(row0) || self.filter_hidden.get(row0),
215 }
216 }
217
218 pub fn rows_hidden(
219 &self,
220 start_row0: u32,
221 end_row0: u32,
222 source: Option<RowVisibilitySource>,
223 ) -> Vec<bool> {
224 if start_row0 > end_row0 {
225 return Vec::new();
226 }
227 (start_row0..=end_row0)
228 .map(|row0| self.is_row_hidden(row0, source))
229 .collect()
230 }
231
232 pub fn insert_rows(&mut self, before0: u32, count: u32) -> bool {
233 let changed = self.manual_hidden.insert_rows(before0, count)
234 | self.filter_hidden.insert_rows(before0, count);
235 if changed {
236 self.version = self.version.saturating_add(1);
237 }
238 changed
239 }
240
241 pub fn delete_rows(&mut self, start0: u32, count: u32) -> bool {
242 let changed = self.manual_hidden.delete_rows(start0, count)
243 | self.filter_hidden.delete_rows(start0, count);
244 if changed {
245 self.version = self.version.saturating_add(1);
246 }
247 changed
248 }
249}