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 fn depth(&self, _row: usize) -> Option<usize> {
48 None
49 }
50
51 fn parent_row(&self, row: usize) -> Option<usize> {
60 let depth = self.depth(row)?;
61 if depth == 0 {
62 return None;
63 }
64 (0..row)
65 .rev()
66 .find(|&i| self.depth(i).is_some_and(|d| d < depth))
67 }
68
69 fn has_children(&self, _row: usize) -> bool {
70 false
71 }
72
73 fn is_expanded(&self, _row: usize) -> bool {
74 false
75 }
76
77 fn toggle_expanded(&self, _row: usize) {}
78
79 fn spans_all_columns(&self, _row: usize) -> bool {
86 false
87 }
88
89 fn reveal_scroll(
94 &self,
95 _row: usize,
96 _scroll: f32,
97 _viewport: f32,
98 _max_scroll: f32,
99 ) -> Option<f32> {
100 None
101 }
102}
103
104pub(crate) struct FlatNavigator {
107 pub(crate) len_fn: Rc<dyn Fn() -> usize>,
108}
109
110impl FlatNavigator {
111 pub(crate) fn new(len_fn: Rc<dyn Fn() -> usize>) -> Self {
112 Self { len_fn }
113 }
114}
115
116impl RowNavigator for FlatNavigator {
117 fn row_count(&self) -> usize {
118 (self.len_fn)()
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125 use std::cell::Cell;
126
127 #[test]
128 fn flat_navigator_steps_through_rows() {
129 let count = Rc::new(Cell::new(5));
130 let c = count.clone();
131 let nav = FlatNavigator::new(Rc::new(move || c.get()));
132 assert_eq!(nav.row_count(), 5);
133 assert_eq!(nav.first_row(), Some(0));
134 assert_eq!(nav.last_row(), Some(4));
135 assert_eq!(nav.next_row(0), Some(1));
136 assert_eq!(nav.next_row(4), None);
137 assert_eq!(nav.prev_row(0), None);
138 assert_eq!(nav.prev_row(2), Some(1));
139 }
140
141 #[test]
142 fn empty_navigator_returns_none_for_first_last() {
143 let nav = FlatNavigator::new(Rc::new(|| 0));
144 assert_eq!(nav.first_row(), None);
145 assert_eq!(nav.last_row(), None);
146 assert_eq!(nav.next_row(0), None);
147 assert_eq!(nav.prev_row(0), None);
148 }
149
150 #[test]
151 fn flat_default_tree_methods_are_noops() {
152 let nav = FlatNavigator::new(Rc::new(|| 5));
153 assert_eq!(nav.depth(0), None);
154 assert!(!nav.has_children(0));
155 assert!(!nav.is_expanded(0));
156 nav.toggle_expanded(0); }
158}