1use ratatui::widgets::ListState;
2
3#[derive(Debug)]
5pub struct StatefulList<T> {
6 pub items: Vec<T>,
8 pub state: ListState,
10}
11
12impl<T> StatefulList<T> {
13 pub fn new(items: Vec<T>, state: ListState) -> StatefulList<T> {
15 Self { items, state }
16 }
17
18 pub fn with_items(items: Vec<T>) -> StatefulList<T> {
20 Self::new(items, ListState::default())
21 }
22
23 pub fn selected(&self) -> Option<&T> {
25 self.items.get(self.state.selected()?)
26 }
27
28 pub fn next(&mut self) {
30 let i = match self.state.selected() {
31 Some(i) => {
32 if i >= self.items.len() - 1 {
33 0
34 } else {
35 i + 1
36 }
37 }
38 None => 0,
39 };
40 self.state.select(Some(i));
41 }
42
43 pub fn previous(&mut self) {
45 let i = match self.state.selected() {
46 Some(i) => {
47 if i == 0 {
48 self.items.len() - 1
49 } else {
50 i - 1
51 }
52 }
53 None => 0,
54 };
55 self.state.select(Some(i));
56 }
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62 use pretty_assertions::assert_eq;
63 #[test]
64 fn test_widget_list() {
65 let mut list =
66 StatefulList::with_items(vec!["data1", "data2", "data3"]);
67 list.state.select(Some(1));
68 assert_eq!(Some(&"data2"), list.selected());
69 list.next();
70 assert_eq!(Some(2), list.state.selected());
71 list.previous();
72 assert_eq!(Some(1), list.state.selected());
73 }
74}