Skip to main content

tree_table/api/
move_rows.rs

1use crate::Change;
2use crate::EventData;
3use crate::Table;
4use crate::args::MoveArgs;
5use crate::statics::default_emit_event_for_api;
6use crate::statics::default_save_selection_for_api;
7use crate::statics::default_undo_for_api;
8use crate::str_err;
9use alloc::rc::Rc;
10use alloc::string::String;
11use alloc::vec;
12use alloc::vec::Vec;
13use core::cell::RefCell;
14use hashbrown::HashMap;
15use hashbrown::HashSet;
16
17impl Table {
18    pub fn move_rows(
19        &mut self,
20        kwargs: Option<MoveArgs>,
21    ) -> Result<Option<Rc<RefCell<EventData>>>, String> {
22        let num_rows = Self::acr_total_rows(&self.grid.index.cells) as u64;
23        if num_rows == 0 {
24            return Ok(None);
25        }
26
27        let kwargs: MoveArgs = kwargs.unwrap_or(MoveArgs {
28            old_to_new: Some(vec![(0, num_rows.saturating_sub(1))]),
29            select: false,
30            emit: default_emit_event_for_api(),
31            undo: default_undo_for_api(),
32            save_selection: default_save_selection_for_api(),
33        });
34
35        // Build old_to_new and new_to_old as Vec<(usize, usize)>
36        let mut seen_old: HashSet<usize> = HashSet::new();
37        let mut seen_new: HashSet<usize> = HashSet::new();
38        let mut old_to_new: Vec<(usize, usize)> = Vec::new();
39        let mut new_to_old: HashMap<usize, usize> = HashMap::new();
40
41        for (old_pos, new_pos) in kwargs
42            .old_to_new
43            .unwrap_or(vec![(0, num_rows.saturating_sub(1))])
44        {
45            let old = old_pos as usize;
46            let new = new_pos as usize;
47
48            if old >= num_rows as usize {
49                return Err(str_err!(
50                    "Old pos {} is out of bounds. Number of rows: {}",
51                    old,
52                    num_rows
53                ));
54            }
55            if new >= num_rows as usize {
56                return Err(str_err!(
57                    "New pos {} exceeds number of rows. Number of rows: {}",
58                    new,
59                    num_rows
60                ));
61            }
62            if !seen_old.insert(old) {
63                return Err(str_err!("Duplicate old pos: {}", old));
64            }
65            if !seen_new.insert(new) {
66                return Err(str_err!("Duplicate new pos: {}", new));
67            }
68
69            old_to_new.push((old, new));
70            new_to_old.insert(new, old);
71        }
72
73        if old_to_new.is_empty() {
74            return Ok(None);
75        }
76
77        let mut event_data = self.cr_new_event(kwargs.save_selection);
78
79        match self.cr_move_rows(
80            &mut event_data,
81            seen_old,
82            old_to_new,
83            new_to_old,
84            None,
85            true,
86        ) {
87            Err(e) => {
88                self.cr_roll_back(Rc::new(RefCell::new(event_data)));
89                return Err(e);
90            }
91            _ => {}
92        };
93
94        if kwargs.select {
95            Self::acr_deselect_all(&mut self.sel, None);
96            let mut moved: Vec<usize> = self.extract_disp_moved_rows(&event_data);
97            if !moved.is_empty() {
98                moved.sort_unstable();
99                self.cr_select_rows_from(moved);
100            }
101        }
102
103        self.cr_finalize_event(event_data, kwargs.undo, kwargs.emit)
104    }
105
106    pub(crate) fn extract_disp_moved_rows(&self, event_data: &EventData) -> Vec<usize> {
107        let moved: Vec<usize> = event_data
108            .changes
109            .iter()
110            .filter_map(|change| match change {
111                Change::MoveRows(moves) => Some(moves.iter().map(|&(_, to)| to)),
112                _ => None,
113            })
114            .flatten()
115            .filter_map(|n| Self::acr_data_to_disp_row_opt(&self.grid.disp_rows, n))
116            .collect();
117        moved
118    }
119}