Skip to main content

tree_table/api/
tree_open_close.rs

1use crate::Change;
2use crate::EventData;
3use crate::Table;
4use crate::args::TreeOpenArgs;
5use crate::utils::consecutive_ranges::consecutive_ranges_borrowed;
6use alloc::rc::Rc;
7use alloc::string::String;
8use alloc::vec::Vec;
9use core::cell::RefCell;
10use hashbrown::HashSet;
11
12impl Table {
13    // Sets IndexCells to open/close and returns a Set of rows to show/hide.
14    pub(crate) fn cr_tree_open_close<I>(
15        &mut self,
16        rows: I,
17        open: bool,
18        event_data: Option<&mut EventData>,
19    ) -> Result<Vec<usize>, String>
20    where
21        I: IntoIterator<Item = usize>,
22    {
23        // Rows to be shown after opening `rows`
24        let mut to_show_or_hide: Vec<usize> = Vec::new();
25        // Helper to determine if a row is visible
26        let mut vis_check: HashSet<usize> = HashSet::new();
27
28        match event_data {
29            Some(event_data_mut) => {
30                // literally rows passed to fn, deduped and sorted
31                for rn in rows {
32                    let cell = Self::acr_icell_mut(&mut self.grid.index.cells, rn)?;
33                    event_data_mut.changes.push(Change::IndexCell {
34                        row: rn,
35                        change: cell.record_set_open(open),
36                    });
37
38                    if !cell.chn.is_empty() && (cell.vis || vis_check.contains(&rn)) {
39                        for res in Self::acr_tree_descendants_rows(
40                            &self.grid.index.cells,
41                            &self.grid.index.iid_to_row,
42                            rn,
43                            true,
44                        ) {
45                            let did_row = res?;
46                            if open {
47                                vis_check.insert(did_row);
48                            }
49                            to_show_or_hide.push(did_row);
50                        }
51                    }
52                }
53            }
54            None => {
55                for rn in rows {
56                    let cell = Self::acr_icell_mut(&mut self.grid.index.cells, rn)?;
57                    cell.open = open;
58                    if !cell.chn.is_empty() && (cell.vis || vis_check.contains(&rn)) {
59                        for res in Self::acr_tree_descendants_rows(
60                            &self.grid.index.cells,
61                            &self.grid.index.iid_to_row,
62                            rn,
63                            true,
64                        ) {
65                            let did_row = res?;
66                            if open {
67                                vis_check.insert(did_row);
68                            }
69                            to_show_or_hide.push(did_row);
70                        }
71                    }
72                }
73            }
74        }
75
76        to_show_or_hide.sort_unstable();
77        to_show_or_hide.dedup();
78
79        Ok(to_show_or_hide)
80    }
81
82    pub(crate) fn tree_set_open_or_closed(
83        &mut self,
84        kwargs: TreeOpenArgs,
85        open: bool,
86    ) -> Result<Option<Rc<RefCell<EventData>>>, String> {
87        // Adds selection boxes to event data
88        let mut event_data: EventData = self.cr_new_event(true);
89
90        let result = (|| -> Result<(), String> {
91            // Adds rows arg to event data
92            let to_show_or_hide = if kwargs.rows.is_empty() {
93                let end_row = Self::acr_total_rows(&self.grid.index.cells);
94                self.cr_tree_open_close((0..end_row).into_iter(), open, Some(&mut event_data))?
95            } else {
96                let mut rows = Vec::new();
97                for iid in kwargs.rows.into_iter() {
98                    rows.push(Self::acr_pos(&self.grid.index.iid_to_row, &iid)?);
99                }
100                rows.sort_unstable();
101                rows.dedup();
102                self.cr_tree_open_close(rows.into_iter(), open, Some(&mut event_data))?
103            };
104
105            // Adds any descendants rows to event data
106            if !to_show_or_hide.is_empty() {
107                self.acr_adjust_selections_after_row_visibility_change(&to_show_or_hide, open);
108
109                Self::acr_set_row_vis(
110                    &mut self.grid.index.cells,
111                    to_show_or_hide.into_iter(),
112                    open,
113                    Some(&mut event_data),
114                )?;
115                Self::acr_remake_rows(
116                    &mut self.grid.canvas_rows,
117                    &mut self.grid.disp_rows,
118                    &self.grid.index.cells,
119                    self.opts.horizontal_grid_line_width.clone(),
120                );
121            }
122            Ok(())
123        })();
124
125        match result {
126            Err(e) => {
127                self.cr_roll_back(Rc::new(RefCell::new(event_data)));
128                return Err(e);
129            }
130            _ => {}
131        }
132
133        self.cr_finalize_event_if_any_non_selection_change(
134            event_data,
135            kwargs.undo,
136            kwargs.emit,
137            false,
138        )
139    }
140
141    pub(crate) fn acr_adjust_selections_after_row_visibility_change(
142        &mut self,
143        changed_data_rows: &[usize], // already sorted + deduped data indices
144        becoming_visible: bool,
145    ) {
146        if changed_data_rows.is_empty() {
147            return;
148        }
149
150        if becoming_visible {
151            // Expand = multiple inserts into displayed list
152            let mut cumulative_added = 0usize;
153            for (start, end) in consecutive_ranges_borrowed(changed_data_rows.iter()) {
154                let num = end - start + 1;
155                let base_disp = Self::acr_compute_disp_insert_pos(&self.grid.disp_rows, start);
156                let disp_insert_pos = base_disp + cumulative_added;
157                self.acr_adjust_selections_after_row_insert(disp_insert_pos, num);
158                cumulative_added += num;
159            }
160        } else {
161            // Collapse
162            self.cr_adjust_selections_after_row_delete(
163                &changed_data_rows
164                    .iter()
165                    .filter_map(|&d| Self::acr_data_to_disp_row_opt(&self.grid.disp_rows, d))
166                    .collect::<Vec<_>>(),
167            );
168        }
169    }
170
171    /// Sets items/rows to open. If used without args then all rows are opened.
172    pub fn tree_open(
173        &mut self,
174        kwargs: Option<TreeOpenArgs>,
175    ) -> Result<Option<Rc<RefCell<EventData>>>, String> {
176        self.tree_set_open_or_closed(kwargs.unwrap_or_default(), true)
177    }
178
179    /// Sets items/rows to closed. If used without args then all rows are closed.
180    pub fn tree_close(
181        &mut self,
182        kwargs: Option<TreeOpenArgs>,
183    ) -> Result<Option<Rc<RefCell<EventData>>>, String> {
184        self.tree_set_open_or_closed(kwargs.unwrap_or_default(), false)
185    }
186}