Skip to main content

tree_table/api/
move_cols.rs

1use alloc::{rc::Rc, string::String, vec, vec::Vec};
2use core::cell::RefCell;
3use hashbrown::{HashMap, HashSet};
4
5use crate::args::MoveArgs;
6use crate::statics::{
7    default_emit_event_for_api, default_save_selection_for_api, default_undo_for_api,
8};
9use crate::utils::consecutive_ranges::consecutive_ranges_borrowed;
10use crate::{Change, EventData, NO_END, Table, str_err};
11
12impl Table {
13    pub fn move_cols(
14        &mut self,
15        kwargs: Option<MoveArgs>,
16    ) -> Result<Option<Rc<RefCell<EventData>>>, String> {
17        let num_cols = Self::acr_total_cols(&self.grid.header.cells) as u64;
18        if num_cols == 0 {
19            return Ok(None);
20        }
21        let kwargs: MoveArgs = kwargs.unwrap_or(MoveArgs {
22            old_to_new: Some(vec![(0, num_cols.saturating_sub(1))]),
23            select: false,
24            emit: default_emit_event_for_api(),
25            undo: default_undo_for_api(),
26            save_selection: default_save_selection_for_api(),
27        });
28        // Validate old_to_new, create inverse
29        let mut seen_old: HashSet<usize> = HashSet::new();
30        let mut seen_new: HashSet<usize> = HashSet::new();
31        let mut old_to_new: Vec<(usize, usize)> = Vec::new();
32        let mut new_to_old: HashMap<usize, usize> = HashMap::new();
33
34        for (old_pos, new_pos) in kwargs
35            .old_to_new
36            .unwrap_or(vec![(0, num_cols.saturating_sub(1))])
37            .iter()
38        {
39            let size_old_pos = *old_pos as usize;
40            let size_new_pos = *new_pos as usize;
41            // Validation
42            if old_pos >= &num_cols {
43                // Check if old pos is within bounds
44                return Err(str_err!(
45                    "Old pos {} is out of bounds. Number of cols: {}",
46                    old_pos,
47                    num_cols
48                ));
49            } else if new_pos >= &num_cols {
50                // Check if new pos exceeds num_cols
51                return Err(str_err!(
52                    "New pos {} exceeds number of cols. Number of cols: {}",
53                    new_pos,
54                    num_cols
55                ));
56            } else if !seen_old.insert(size_old_pos) {
57                // Check for duplicate old indices
58                return Err(str_err!("Duplicate old pos: {}", old_pos));
59            } else if !seen_new.insert(size_new_pos) {
60                // Check for duplicate new indices
61                return Err(str_err!("Duplicate new pos: {}", new_pos));
62            } else {
63                old_to_new.push((size_old_pos, size_new_pos));
64                new_to_old.insert(size_new_pos, size_old_pos);
65            }
66        }
67
68        if old_to_new.is_empty() {
69            return Ok(None);
70        }
71
72        let mut event_data = self.cr_new_event(kwargs.save_selection);
73        self.cr_move_cols(&mut event_data, seen_old, old_to_new, &new_to_old)?;
74
75        if kwargs.select {
76            Self::acr_deselect_all(&mut self.sel, None);
77            let mut moved: Vec<usize> = event_data
78                .changes
79                .iter()
80                .filter_map(|change| match change {
81                    Change::MoveCols(moves) => Some(moves.iter().map(|&(_, to)| to)),
82                    _ => None,
83                })
84                .flatten()
85                .filter_map(|n| Self::acr_data_to_disp_col_opt(&self.grid.disp_cols, n))
86                .collect();
87
88            if !moved.is_empty() {
89                moved.sort_unstable();
90                for (start, end) in consecutive_ranges_borrowed(moved.iter()) {
91                    Self::acr_add_selection_box(
92                        &mut self.sel,
93                        &self.grid,
94                        start,
95                        end,
96                        0,
97                        NO_END,
98                        true,
99                    );
100                }
101            }
102        }
103
104        self.cr_finalize_event(event_data, kwargs.undo, kwargs.emit)
105    }
106}