Skip to main content

tree_table/api/
progress_bar.rs

1use alloc::{rc::Rc, string::String};
2use core::cell::RefCell;
3
4use crate::args::args_progress_bar::{AddProgressBarPosArgs, SetProgressBarArgs};
5use crate::args::{AddProgressBarArgs, DelProgressBarArgs};
6use crate::{DelProgressBarNameArgs, EventData, ProgressBar, SetProgressBarNameArgs, Table};
7use crate::{str_err, try_hex_to_color3};
8
9impl Table {
10    pub fn add_progress_bar(
11        &mut self,
12        kwargs: AddProgressBarArgs,
13    ) -> Result<Option<Rc<RefCell<EventData>>>, String> {
14        let progress_bar = Some(ProgressBar {
15            bg: try_hex_to_color3(kwargs.bg)?,
16            fg: try_hex_to_color3(kwargs.fg)?,
17            pc: kwargs.percent,
18            remove_on_complete: kwargs.remove_on_complete,
19        });
20        let row = Self::acr_pos(&self.grid.index.iid_to_row, &kwargs.row)?;
21        let col = Self::acr_pos(&self.grid.header.iid_to_col, &kwargs.col)?;
22        let mut event_data: EventData = self.cr_new_event(kwargs.save_selection);
23        Self::acr_event_data_set_tprogressbar(
24            &mut self.grid.index.cells,
25            row,
26            col,
27            progress_bar,
28            &self.opts.empty_val,
29            &mut event_data,
30        )?;
31        self.cr_finalize_event(event_data, kwargs.undo, kwargs.emit)
32    }
33
34    pub fn add_progress_bar_i(
35        &mut self,
36        kwargs: AddProgressBarPosArgs,
37    ) -> Result<Option<Rc<RefCell<EventData>>>, String> {
38        let progress_bar = Some(ProgressBar {
39            bg: try_hex_to_color3(kwargs.bg)?,
40            fg: try_hex_to_color3(kwargs.fg)?,
41            pc: kwargs.percent,
42            remove_on_complete: kwargs.remove_on_complete,
43        });
44        let mut event_data: EventData = self.cr_new_event(kwargs.save_selection);
45        Self::acr_event_data_set_iprogressbar(
46            &mut self.grid.index.cells,
47            kwargs.pos as usize,
48            progress_bar,
49            &mut event_data,
50        )?;
51        self.cr_finalize_event(event_data, kwargs.undo, kwargs.emit)
52    }
53
54    pub fn add_progress_bar_h(
55        &mut self,
56        kwargs: AddProgressBarPosArgs,
57    ) -> Result<Option<Rc<RefCell<EventData>>>, String> {
58        let progress_bar = Some(ProgressBar {
59            bg: try_hex_to_color3(kwargs.bg)?,
60            fg: try_hex_to_color3(kwargs.fg)?,
61            pc: kwargs.percent,
62            remove_on_complete: kwargs.remove_on_complete,
63        });
64        let mut event_data: EventData = self.cr_new_event(kwargs.save_selection);
65        Self::acr_event_data_set_hprogressbar(
66            &mut self.grid.header.cells,
67            kwargs.pos as usize,
68            progress_bar,
69            &mut event_data,
70        )?;
71        self.cr_finalize_event(event_data, kwargs.undo, kwargs.emit)
72    }
73
74    pub fn del_progress_bar(
75        &mut self,
76        kwargs: DelProgressBarArgs,
77    ) -> Result<Option<Rc<RefCell<EventData>>>, String> {
78        let row = Self::acr_pos(&self.grid.index.iid_to_row, &kwargs.row)?;
79        let col = Self::acr_pos(&self.grid.header.iid_to_col, &kwargs.col)?;
80        let mut event_data: EventData = self.cr_new_event(kwargs.save_selection);
81        Self::acr_event_data_set_tprogressbar(
82            &mut self.grid.index.cells,
83            row,
84            col,
85            None,
86            &self.opts.empty_val,
87            &mut event_data,
88        )?;
89        self.cr_finalize_event(event_data, kwargs.undo, kwargs.emit)
90    }
91
92    pub fn del_progress_bar_i(
93        &mut self,
94        kwargs: DelProgressBarNameArgs,
95    ) -> Result<Option<Rc<RefCell<EventData>>>, String> {
96        let name = kwargs.name;
97        let pos = Self::acr_pos(&self.grid.index.iid_to_row, name.as_str())?;
98        let mut event_data: EventData = self.cr_new_event(kwargs.save_selection);
99        Self::acr_event_data_set_iprogressbar(
100            &mut self.grid.index.cells,
101            pos,
102            None,
103            &mut event_data,
104        )?;
105        self.cr_finalize_event(event_data, kwargs.undo, kwargs.emit)
106    }
107
108    pub fn del_progress_bar_h(
109        &mut self,
110        kwargs: DelProgressBarNameArgs,
111    ) -> Result<Option<Rc<RefCell<EventData>>>, String> {
112        let name = kwargs.name;
113        let pos = Self::acr_pos(&self.grid.header.iid_to_col, name.as_str())?;
114        let mut event_data: EventData = self.cr_new_event(kwargs.save_selection);
115        Self::acr_event_data_set_hprogressbar(
116            &mut self.grid.header.cells,
117            pos,
118            None,
119            &mut event_data,
120        )?;
121        self.cr_finalize_event(event_data, kwargs.undo, kwargs.emit)
122    }
123
124    pub fn set_progress_bar(
125        &mut self,
126        kwargs: SetProgressBarArgs,
127    ) -> Result<Option<Rc<RefCell<EventData>>>, String> {
128        let row = Self::acr_pos(&self.grid.index.iid_to_row, &kwargs.row)?;
129        let col = Self::acr_pos(&self.grid.header.iid_to_col, &kwargs.col)?;
130        let mut event_data: EventData = self.cr_new_event(kwargs.save_selection);
131
132        // Get current progress bar (if any)
133        let current_pb = {
134            let cell = Table::acr_icell_mut(&mut self.grid.index.cells, row)?;
135            cell.vals
136                .get(&col)
137                .and_then(|tc| tc.props.as_ref())
138                .and_then(|p| p.progress_bar.as_ref())
139                .cloned()
140        };
141
142        // Determine final state to check for removal rule
143        let mut final_pc = current_pb.as_ref().map(|p| p.pc).unwrap_or(0.0);
144        let mut final_remove = current_pb
145            .as_ref()
146            .map(|p| p.remove_on_complete)
147            .unwrap_or(false);
148
149        if let Some(p) = kwargs.percent {
150            final_pc = p;
151        }
152        if let Some(r) = kwargs.remove_on_complete {
153            final_remove = r;
154        }
155
156        // Special rule: if pc >= 1.0 and remove_on_complete is true → delete the bar entirely
157        if final_pc >= 1.0 && final_remove {
158            Self::acr_event_data_set_tprogressbar(
159                &mut self.grid.index.cells,
160                row,
161                col,
162                None,
163                &self.opts.empty_val,
164                &mut event_data,
165            )?;
166        } else {
167            let result = (|| -> Result<(), String> {
168                // Normal granular updates (only the fields that were supplied)
169                if let Some(bg_opt) = kwargs.bg {
170                    let bg = try_hex_to_color3(bg_opt)?;
171                    Self::acr_event_data_set_tprogressbar_bg(
172                        &mut self.grid.index.cells,
173                        row,
174                        col,
175                        bg,
176                        &self.opts.empty_val,
177                        &mut event_data,
178                    )?;
179                }
180
181                if let Some(fg_opt) = kwargs.fg {
182                    let fg = try_hex_to_color3(fg_opt)?;
183                    Self::acr_event_data_set_tprogressbar_fg(
184                        &mut self.grid.index.cells,
185                        row,
186                        col,
187                        fg,
188                        &self.opts.empty_val,
189                        &mut event_data,
190                    )?;
191                }
192
193                if let Some(percent) = kwargs.percent {
194                    Self::acr_event_data_set_tprogressbar_pc(
195                        &mut self.grid.index.cells,
196                        row,
197                        col,
198                        percent,
199                        &self.opts.empty_val,
200                        &mut event_data,
201                    )?;
202                }
203
204                if let Some(remove_on_complete) = kwargs.remove_on_complete {
205                    Self::acr_event_data_set_tprogressbar_remove_on_complete(
206                        &mut self.grid.index.cells,
207                        row,
208                        col,
209                        remove_on_complete,
210                        &self.opts.empty_val,
211                        &mut event_data,
212                    )?;
213                }
214                Ok(())
215            })();
216
217            match result {
218                Err(e) => {
219                    self.cr_roll_back(Rc::new(RefCell::new(event_data)));
220                    return Err(e);
221                }
222                _ => {}
223            }
224        }
225
226        self.cr_finalize_event_if_any_non_selection_change(
227            event_data,
228            kwargs.undo,
229            kwargs.emit,
230            true,
231        )
232    }
233
234    pub fn set_progress_bar_i(
235        &mut self,
236        kwargs: SetProgressBarNameArgs,
237    ) -> Result<Option<Rc<RefCell<EventData>>>, String> {
238        let name = kwargs.name.clone();
239        let pos = match Self::acr_pos(&self.grid.index.iid_to_row, &name) {
240            Ok(p) => p,
241            Err(_) => {
242                if kwargs.err_if_not_found {
243                    return Err(str_err!("Index progress bar '{}' not found", name));
244                } else {
245                    return Ok(None);
246                }
247            }
248        };
249
250        let mut event_data: EventData = self.cr_new_event(kwargs.save_selection);
251
252        // Get current progress bar state (if any)
253        let current_pb = {
254            let cell = Table::acr_icell_mut(&mut self.grid.index.cells, pos)?;
255            cell.props
256                .as_ref()
257                .and_then(|p| p.progress_bar.as_ref())
258                .cloned()
259        };
260
261        // Determine final state to check for removal rule
262        let mut final_pc = current_pb.as_ref().map(|p| p.pc).unwrap_or(0.0);
263        let mut final_remove = current_pb
264            .as_ref()
265            .map(|p| p.remove_on_complete)
266            .unwrap_or(false);
267
268        if let Some(p) = kwargs.percent {
269            final_pc = p;
270        }
271        if let Some(r) = kwargs.remove_on_complete {
272            final_remove = r;
273        }
274
275        // Special rule: if pc >= 1.0 and remove_on_complete is true → delete the bar entirely
276        if final_pc >= 1.0 && final_remove {
277            Self::acr_event_data_set_iprogressbar(
278                &mut self.grid.index.cells,
279                pos,
280                None,
281                &mut event_data,
282            )?;
283        } else {
284            let result = (|| -> Result<(), String> {
285                // Normal granular updates (only the fields that were supplied)
286                if let Some(bg_opt) = kwargs.bg {
287                    let bg = try_hex_to_color3(bg_opt)?;
288                    Self::acr_event_data_set_iprogressbar_bg(
289                        &mut self.grid.index.cells,
290                        pos,
291                        bg,
292                        &mut event_data,
293                    )?;
294                }
295
296                if let Some(fg_opt) = kwargs.fg {
297                    let fg = try_hex_to_color3(fg_opt)?;
298                    Self::acr_event_data_set_iprogressbar_fg(
299                        &mut self.grid.index.cells,
300                        pos,
301                        fg,
302                        &mut event_data,
303                    )?;
304                }
305
306                if let Some(percent) = kwargs.percent {
307                    Self::acr_event_data_set_iprogressbar_pc(
308                        &mut self.grid.index.cells,
309                        pos,
310                        percent,
311                        &mut event_data,
312                    )?;
313                }
314
315                if let Some(remove_on_complete) = kwargs.remove_on_complete {
316                    Self::acr_event_data_set_iprogressbar_remove_on_complete(
317                        &mut self.grid.index.cells,
318                        pos,
319                        remove_on_complete,
320                        &mut event_data,
321                    )?;
322                }
323                Ok(())
324            })();
325
326            match result {
327                Err(e) => {
328                    self.cr_roll_back(Rc::new(RefCell::new(event_data)));
329                    return Err(e);
330                }
331                _ => {}
332            }
333        }
334
335        self.cr_finalize_event_if_any_non_selection_change(
336            event_data,
337            kwargs.undo,
338            kwargs.emit,
339            true,
340        )
341    }
342
343    pub fn set_progress_bar_h(
344        &mut self,
345        kwargs: SetProgressBarNameArgs,
346    ) -> Result<Option<Rc<RefCell<EventData>>>, String> {
347        let name = kwargs.name.clone();
348        let pos = match Self::acr_pos(&self.grid.header.iid_to_col, &name) {
349            Ok(p) => p,
350            Err(_) => {
351                if kwargs.err_if_not_found {
352                    return Err(str_err!("Header progress bar '{}' not found", name));
353                } else {
354                    return Ok(None);
355                }
356            }
357        };
358
359        let mut event_data: EventData = self.cr_new_event(kwargs.save_selection);
360
361        // Get current progress bar state (if any)
362        let current_pb = {
363            let cell = Table::acr_hcell_mut(&mut self.grid.header.cells, pos)?;
364            cell.props
365                .as_ref()
366                .and_then(|p| p.progress_bar.as_ref())
367                .cloned()
368        };
369
370        // Determine final state to check for removal rule
371        let mut final_pc = current_pb.as_ref().map(|p| p.pc).unwrap_or(0.0);
372        let mut final_remove = current_pb
373            .as_ref()
374            .map(|p| p.remove_on_complete)
375            .unwrap_or(false);
376
377        if let Some(p) = kwargs.percent {
378            final_pc = p;
379        }
380        if let Some(r) = kwargs.remove_on_complete {
381            final_remove = r;
382        }
383
384        // Special rule: if pc >= 1.0 and remove_on_complete is true → delete the bar entirely
385        if final_pc >= 1.0 && final_remove {
386            Self::acr_event_data_set_hprogressbar(
387                &mut self.grid.header.cells,
388                pos,
389                None,
390                &mut event_data,
391            )?;
392        } else {
393            let result = (|| -> Result<(), String> {
394                // Normal granular updates (only the fields that were supplied)
395                if let Some(bg_opt) = kwargs.bg {
396                    let bg = try_hex_to_color3(bg_opt)?;
397                    Self::acr_event_data_set_hprogressbar_bg(
398                        &mut self.grid.header.cells,
399                        pos,
400                        bg,
401                        &mut event_data,
402                    )?;
403                }
404
405                if let Some(fg_opt) = kwargs.fg {
406                    let fg = try_hex_to_color3(fg_opt)?;
407                    Self::acr_event_data_set_hprogressbar_fg(
408                        &mut self.grid.header.cells,
409                        pos,
410                        fg,
411                        &mut event_data,
412                    )?;
413                }
414
415                if let Some(percent) = kwargs.percent {
416                    Self::acr_event_data_set_hprogressbar_pc(
417                        &mut self.grid.header.cells,
418                        pos,
419                        percent,
420                        &mut event_data,
421                    )?;
422                }
423
424                if let Some(remove_on_complete) = kwargs.remove_on_complete {
425                    Self::acr_event_data_set_hprogressbar_remove_on_complete(
426                        &mut self.grid.header.cells,
427                        pos,
428                        remove_on_complete,
429                        &mut event_data,
430                    )?;
431                }
432                Ok(())
433            })();
434
435            match result {
436                Err(e) => {
437                    self.cr_roll_back(Rc::new(RefCell::new(event_data)));
438                    return Err(e);
439                }
440                _ => {}
441            }
442        }
443
444        self.cr_finalize_event_if_any_non_selection_change(
445            event_data,
446            kwargs.undo,
447            kwargs.emit,
448            true,
449        )
450    }
451}