logisheets_controller/range_manager/executors/
mod.rs

1mod delete_block_line;
2mod delete_line;
3mod input;
4mod insert_block_line;
5mod insert_line;
6mod occupy_addr_range;
7mod remove_block;
8mod utils;
9use std::collections::HashSet;
10
11use delete_block_line::delete_block_line;
12use delete_line::delete_line;
13use input::input;
14use insert_block_line::insert_block_line;
15use insert_line::insert_line;
16use logisheets_base::{errors::BasicError, BlockRange, NormalRange, Range, RangeId, SheetId};
17use remove_block::remove_block;
18
19use crate::{
20    edit_action::EditPayload, range_manager::executors::occupy_addr_range::occupy_addr_range, Error,
21};
22
23use super::{ctx::RangeExecCtx, manager::RangeManager};
24
25pub struct RangeExecutor {
26    pub manager: RangeManager,
27    pub dirty_ranges: HashSet<(SheetId, RangeId)>,
28    pub removed_ranges: HashSet<(SheetId, RangeId)>,
29}
30
31impl RangeExecutor {
32    pub fn new(manager: RangeManager) -> Self {
33        Self {
34            manager,
35            dirty_ranges: HashSet::new(),
36            removed_ranges: HashSet::new(),
37        }
38    }
39
40    pub fn execute<C: RangeExecCtx>(self, ctx: &C, payload: EditPayload) -> Result<Self, Error> {
41        match payload {
42            EditPayload::MoveBlock(move_block) => {
43                let sheet_id = ctx
44                    .fetch_sheet_id_by_index(move_block.sheet_idx)
45                    .map_err(|l| BasicError::SheetIdxExceed(l))?;
46                let (row_cnt, col_cnt) = ctx.get_block_size(sheet_id, move_block.id).unwrap();
47                if ctx.any_other_blocks_in(
48                    sheet_id,
49                    move_block.id,
50                    move_block.new_master_row,
51                    move_block.new_master_col,
52                    row_cnt + move_block.new_master_row - 1,
53                    col_cnt + move_block.new_master_col - 1,
54                ) {
55                    Ok(self)
56                } else {
57                    let start = ctx
58                        .fetch_norm_cell_id(
59                            &sheet_id,
60                            move_block.new_master_row,
61                            move_block.new_master_col,
62                        )
63                        .unwrap();
64                    let end = ctx
65                        .fetch_norm_cell_id(
66                            &sheet_id,
67                            move_block.new_master_row + row_cnt - 1,
68                            move_block.new_master_col + col_cnt - 1,
69                        )
70                        .unwrap();
71                    let res = occupy_addr_range(self, sheet_id, start, end, ctx);
72                    Ok(res)
73                }
74            }
75            EditPayload::RemoveBlock(p) => {
76                let sheet_id = ctx
77                    .fetch_sheet_id_by_index(p.sheet_idx)
78                    .map_err(|l| BasicError::SheetIdxExceed(l))?;
79                let res = remove_block(self, sheet_id, p.id);
80                Ok(res)
81            }
82            EditPayload::CreateBlock(create_block) => {
83                let sheet_id = ctx
84                    .fetch_sheet_id_by_index(create_block.sheet_idx)
85                    .map_err(|l| BasicError::SheetIdxExceed(l))?;
86                let start = ctx.fetch_norm_cell_id(
87                    &sheet_id,
88                    create_block.master_row,
89                    create_block.master_col,
90                )?;
91                let end = ctx.fetch_norm_cell_id(
92                    &sheet_id,
93                    create_block.master_row + create_block.row_cnt - 1,
94                    create_block.master_col + create_block.col_cnt - 1,
95                )?;
96                let result = occupy_addr_range(self, sheet_id, start, end, ctx);
97                Ok(result)
98            }
99            EditPayload::CellInput(p) => {
100                let sheet_id = ctx
101                    .fetch_sheet_id_by_index(p.sheet_idx)
102                    .map_err(|l| BasicError::SheetIdxExceed(l))?;
103                let res = input(self, sheet_id, p.row, p.col, ctx)?;
104                Ok(res)
105            }
106            EditPayload::CellClear(p) => {
107                let sheet_id = ctx
108                    .fetch_sheet_id_by_index(p.sheet_idx)
109                    .map_err(|l| BasicError::SheetIdxExceed(l))?;
110                let res = input(self, sheet_id, p.row, p.col, ctx)?;
111                Ok(res)
112            }
113            EditPayload::DeleteSheet(_) => todo!(),
114            EditPayload::InsertCols(insert_cols) => {
115                let sheet_id = ctx
116                    .fetch_sheet_id_by_index(insert_cols.sheet_idx)
117                    .map_err(|l| BasicError::SheetIdxExceed(l))?;
118                let result = insert_line(
119                    self,
120                    sheet_id,
121                    false,
122                    insert_cols.start,
123                    insert_cols.count as u32,
124                    ctx,
125                );
126                Ok(result)
127            }
128            EditPayload::DeleteCols(delete_cols) => {
129                let sheet_id = ctx
130                    .fetch_sheet_id_by_index(delete_cols.sheet_idx)
131                    .map_err(|l| BasicError::SheetIdxExceed(l))?;
132                let result = delete_line(
133                    self,
134                    sheet_id,
135                    false,
136                    delete_cols.start,
137                    delete_cols.count as u32,
138                    ctx,
139                );
140                Ok(result)
141            }
142            EditPayload::InsertRows(insert_rows) => {
143                let sheet_id = ctx
144                    .fetch_sheet_id_by_index(insert_rows.sheet_idx)
145                    .map_err(|l| BasicError::SheetIdxExceed(l))?;
146                let result = insert_line(
147                    self,
148                    sheet_id,
149                    true,
150                    insert_rows.start,
151                    insert_rows.count as u32,
152                    ctx,
153                );
154                Ok(result)
155            }
156            EditPayload::DeleteRows(delete_rows) => {
157                let sheet_id = ctx
158                    .fetch_sheet_id_by_index(delete_rows.sheet_idx)
159                    .map_err(|l| BasicError::SheetIdxExceed(l))?;
160                let result = delete_line(
161                    self,
162                    sheet_id,
163                    true,
164                    delete_rows.start,
165                    delete_rows.count as u32,
166                    ctx,
167                );
168                Ok(result)
169            }
170            EditPayload::InsertColsInBlock(p) => {
171                let sheet_id = ctx
172                    .fetch_sheet_id_by_index(p.sheet_idx)
173                    .map_err(|l| BasicError::SheetIdxExceed(l))?;
174                let res = insert_block_line(
175                    self,
176                    sheet_id,
177                    p.block_id,
178                    false,
179                    p.start as u32,
180                    p.cnt as u32,
181                    ctx,
182                );
183                Ok(res)
184            }
185            EditPayload::DeleteColsInBlock(p) => {
186                let sheet_id = ctx
187                    .fetch_sheet_id_by_index(p.sheet_idx)
188                    .map_err(|l| BasicError::SheetIdxExceed(l))?;
189                let res = delete_block_line(
190                    self,
191                    sheet_id,
192                    p.block_id,
193                    false,
194                    p.start as u32,
195                    p.cnt as u32,
196                    ctx,
197                );
198                Ok(res)
199            }
200            EditPayload::InsertRowsInBlock(p) => {
201                let sheet_id = ctx
202                    .fetch_sheet_id_by_index(p.sheet_idx)
203                    .map_err(|l| BasicError::SheetIdxExceed(l))?;
204                let res = insert_block_line(
205                    self,
206                    sheet_id,
207                    p.block_id,
208                    true,
209                    p.start as u32,
210                    p.cnt as u32,
211                    ctx,
212                );
213                Ok(res)
214            }
215            EditPayload::DeleteRowsInBlock(p) => {
216                let sheet_id = ctx
217                    .fetch_sheet_id_by_index(p.sheet_idx)
218                    .map_err(|l| BasicError::SheetIdxExceed(l))?;
219                let res = delete_block_line(
220                    self,
221                    sheet_id,
222                    p.block_id,
223                    true,
224                    p.start as u32,
225                    p.cnt as u32,
226                    ctx,
227                );
228                Ok(res)
229            }
230            _ => Ok(self),
231        }
232    }
233
234    pub fn normal_range_update<F>(mut self, sheet_id: &SheetId, func: &mut F) -> Self
235    where
236        F: FnMut(&NormalRange, &RangeId) -> RangeUpdateType,
237    {
238        let mut to_update = HashSet::new();
239        let mut to_remove = HashSet::new();
240        let manager = self.manager.get_sheet_range_manager(sheet_id);
241        let mut dirty_ranges = self.dirty_ranges;
242        let mut removed_ranges = self.removed_ranges;
243        manager
244            .normal_range_to_id
245            .iter()
246            .for_each(|(range, range_id)| match func(range, range_id) {
247                RangeUpdateType::Dirty => {
248                    dirty_ranges.insert((*sheet_id, *range_id));
249                }
250                RangeUpdateType::UpdateTo(new_range) => {
251                    dirty_ranges.insert((*sheet_id, new_range.id));
252                    to_update.insert(new_range);
253                }
254                RangeUpdateType::None => {}
255                RangeUpdateType::Removed => {
256                    to_remove.insert(range_id.clone());
257                    dirty_ranges.insert((*sheet_id, *range_id));
258                }
259            });
260        to_update.into_iter().for_each(|new_range| {
261            if let Range::Normal(range) = new_range.range {
262                manager
263                    .id_to_normal_range
264                    .insert(new_range.id, range.clone());
265                manager.normal_range_to_id.insert(range, new_range.id);
266            }
267        });
268        to_remove.into_iter().for_each(|range_id| {
269            if let Some(data) = manager.id_to_normal_range.get(&range_id) {
270                manager.normal_range_to_id.remove(data);
271                manager.id_to_normal_range.remove(&range_id);
272                removed_ranges.insert((*sheet_id, range_id));
273            }
274        });
275        RangeExecutor {
276            manager: self.manager,
277            removed_ranges,
278            dirty_ranges,
279        }
280    }
281
282    pub fn block_range_update<F>(mut self, sheet_id: &SheetId, func: &mut F) -> Self
283    where
284        F: FnMut(&BlockRange, &RangeId) -> RangeUpdateType,
285    {
286        let mut dirty_ranges = self.dirty_ranges;
287        let mut removed_ranges = self.removed_ranges;
288        let mut to_update = HashSet::new();
289        let mut to_remove = HashSet::new();
290        let manager = self.manager.get_sheet_range_manager(sheet_id);
291        manager
292            .block_range_to_id
293            .iter()
294            .for_each(|(range, range_id)| match func(range, range_id) {
295                RangeUpdateType::Dirty => {
296                    dirty_ranges.insert((*sheet_id, *range_id));
297                }
298                RangeUpdateType::UpdateTo(new_range) => {
299                    dirty_ranges.insert((*sheet_id, new_range.id));
300                    to_update.insert(new_range);
301                }
302                RangeUpdateType::None => {}
303                RangeUpdateType::Removed => {
304                    to_remove.insert(range_id.clone());
305                    dirty_ranges.insert((*sheet_id, *range_id));
306                }
307            });
308        to_update.into_iter().for_each(|new_range| {
309            if let Range::Block(range) = new_range.range {
310                manager
311                    .id_to_block_range
312                    .insert(new_range.id, range.clone());
313                manager.block_range_to_id.insert(range, new_range.id);
314            }
315        });
316        to_remove.into_iter().for_each(|range_id| {
317            if let Some(data) = manager.id_to_normal_range.get(&range_id) {
318                manager.normal_range_to_id.remove(data);
319                manager.id_to_normal_range.remove(&range_id);
320                removed_ranges.insert((*sheet_id, range_id));
321            }
322        });
323        RangeExecutor {
324            manager: self.manager,
325            dirty_ranges,
326            removed_ranges,
327        }
328    }
329}
330
331#[derive(Debug, Clone, Hash, Eq, PartialEq)]
332pub struct NewRange {
333    pub id: RangeId,
334    pub range: Range,
335}
336
337pub enum RangeUpdateType {
338    Dirty,
339    UpdateTo(NewRange),
340    None,
341    Removed,
342}