#[derive(Debug, Clone)]
pub struct ListNavigation {
pub selected_index: usize,
pub scroll_offset: usize,
}
impl ListNavigation {
pub fn new() -> Self {
Self {
selected_index: 0,
scroll_offset: 0,
}
}
pub fn move_up(&mut self) {
if self.selected_index > 0 {
self.selected_index -= 1;
if self.selected_index < self.scroll_offset {
self.scroll_offset = self.selected_index;
}
}
}
pub fn move_down(&mut self, max_len: usize) {
if max_len > 0 && self.selected_index < max_len - 1 {
self.selected_index += 1;
}
}
pub fn adjust_scroll(&mut self, visible_lines: usize) {
if visible_lines == 0 {
return;
}
if self.selected_index >= self.scroll_offset + visible_lines {
self.scroll_offset = self.selected_index - visible_lines + 1;
}
}
pub fn reset(&mut self) {
self.selected_index = 0;
self.scroll_offset = 0;
}
}
impl Default for ListNavigation {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_initializes_to_zero() {
let nav = ListNavigation::new();
assert_eq!(nav.selected_index, 0);
assert_eq!(nav.scroll_offset, 0);
}
#[test]
fn test_move_up_decrements_index() {
let mut nav = ListNavigation::new();
nav.selected_index = 3;
nav.move_up();
assert_eq!(nav.selected_index, 2);
}
#[test]
fn test_move_up_does_not_go_below_zero() {
let mut nav = ListNavigation::new();
nav.move_up();
assert_eq!(nav.selected_index, 0);
}
#[test]
fn test_move_up_adjusts_scroll_offset() {
let mut nav = ListNavigation::new();
nav.selected_index = 5;
nav.scroll_offset = 5;
nav.move_up();
assert_eq!(nav.selected_index, 4);
assert_eq!(nav.scroll_offset, 4);
}
#[test]
fn test_move_down_increments_index() {
let mut nav = ListNavigation::new();
nav.move_down(5);
assert_eq!(nav.selected_index, 1);
}
#[test]
fn test_move_down_does_not_exceed_max() {
let mut nav = ListNavigation::new();
nav.selected_index = 4;
nav.move_down(5);
assert_eq!(nav.selected_index, 4);
}
#[test]
fn test_move_down_empty_list() {
let mut nav = ListNavigation::new();
nav.move_down(0);
assert_eq!(nav.selected_index, 0);
}
#[test]
fn test_adjust_scroll_scrolls_down() {
let mut nav = ListNavigation::new();
nav.selected_index = 10;
nav.adjust_scroll(5);
assert_eq!(nav.scroll_offset, 6);
}
#[test]
fn test_adjust_scroll_zero_visible() {
let mut nav = ListNavigation::new();
nav.selected_index = 10;
nav.adjust_scroll(0);
assert_eq!(nav.scroll_offset, 0);
}
#[test]
fn test_reset() {
let mut nav = ListNavigation::new();
nav.selected_index = 5;
nav.scroll_offset = 3;
nav.reset();
assert_eq!(nav.selected_index, 0);
assert_eq!(nav.scroll_offset, 0);
}
}