screen_buffer_ui/
scrollable.rs1pub trait Scrollable {
2 fn selected(&self) -> usize;
3 fn len(&self) -> usize;
4 fn set_selected(&mut self, selected: usize) -> bool;
5 fn element_height(&self, index: usize) -> u16;
6 fn visible_range(&self, height: u16) -> Box<dyn Iterator<Item = usize>>;
7 fn visible_start_end(&self, height: u16) -> (usize, usize);
8 fn up(&mut self, how_much: usize);
9 fn down(&mut self, how_much: usize);
10}
11
12#[macro_export]
13macro_rules! scrollable {
14 ($x:ty, $($y:item),*) => {
15 impl Scrollable for $x {
16 fn up(&mut self, how_much: usize) {
17 let how_much = how_much % self.len();
18
19 self.set_selected((self.len() + self.selected() - how_much) % self.len());
20 }
21 fn down(&mut self, how_much: usize) {
22 let how_much = how_much % self.len();
23
24 self.set_selected((how_much + self.selected()) % self.len());
25 }
26 fn visible_range(&self, height: u16) -> Box<dyn Iterator<Item = usize>> {
27 let (a, b) = self.visible_start_end(height);
28
29 Box::new((a..b).into_iter())
30 }
31 fn visible_start_end(&self, height: u16) -> (usize, usize) {
32 let mut last_first = 0;
33 let mut current_height = 0;
34 let mut i = 0;
35 while i < self.len() {
36 let eh = self.element_height(i);
37 if current_height + eh > height {
38 if i > self.selected() {
39 break;
40 }
41 current_height = eh;
42 last_first = i;
43 } else {
44 current_height += eh;
45 }
46
47 i += 1;
48 }
49
50 (last_first, i)
51 }
52 $($y)*
53 }
54 }
55}