teksilo_widgets/table_view/
row_navigator.rs1use std::rc::Rc;
12
13pub(crate) trait RowNavigator {
17 fn row_count(&self) -> usize;
18
19 fn next_row(&self, current: usize) -> Option<usize> {
20 let n = self.row_count();
21 if n == 0 {
22 return None;
23 }
24 let next = current + 1;
25 if next < n { Some(next) } else { None }
26 }
27
28 fn prev_row(&self, current: usize) -> Option<usize> {
29 if current == 0 {
30 None
31 } else {
32 Some(current - 1)
33 }
34 }
35
36 fn first_row(&self) -> Option<usize> {
37 if self.row_count() == 0 { None } else { Some(0) }
38 }
39
40 fn last_row(&self) -> Option<usize> {
41 let n = self.row_count();
42 if n == 0 { None } else { Some(n - 1) }
43 }
44
45 #[allow(dead_code)]
50 fn depth(&self, _row: usize) -> Option<usize> {
51 None
52 }
53
54 fn has_children(&self, _row: usize) -> bool {
55 false
56 }
57
58 fn is_expanded(&self, _row: usize) -> bool {
59 false
60 }
61
62 fn toggle_expanded(&self, _row: usize) {}
63}
64
65pub(crate) struct FlatNavigator {
68 pub(crate) len_fn: Rc<dyn Fn() -> usize>,
69}
70
71impl FlatNavigator {
72 pub(crate) fn new(len_fn: Rc<dyn Fn() -> usize>) -> Self {
73 Self { len_fn }
74 }
75}
76
77impl RowNavigator for FlatNavigator {
78 fn row_count(&self) -> usize {
79 (self.len_fn)()
80 }
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86 use std::cell::Cell;
87
88 #[test]
89 fn flat_navigator_steps_through_rows() {
90 let count = Rc::new(Cell::new(5));
91 let c = count.clone();
92 let nav = FlatNavigator::new(Rc::new(move || c.get()));
93 assert_eq!(nav.row_count(), 5);
94 assert_eq!(nav.first_row(), Some(0));
95 assert_eq!(nav.last_row(), Some(4));
96 assert_eq!(nav.next_row(0), Some(1));
97 assert_eq!(nav.next_row(4), None);
98 assert_eq!(nav.prev_row(0), None);
99 assert_eq!(nav.prev_row(2), Some(1));
100 }
101
102 #[test]
103 fn empty_navigator_returns_none_for_first_last() {
104 let nav = FlatNavigator::new(Rc::new(|| 0));
105 assert_eq!(nav.first_row(), None);
106 assert_eq!(nav.last_row(), None);
107 assert_eq!(nav.next_row(0), None);
108 assert_eq!(nav.prev_row(0), None);
109 }
110
111 #[test]
112 fn flat_default_tree_methods_are_noops() {
113 let nav = FlatNavigator::new(Rc::new(|| 5));
114 assert_eq!(nav.depth(0), None);
115 assert!(!nav.has_children(0));
116 assert!(!nav.is_expanded(0));
117 nav.toggle_expanded(0); }
119}