#[derive(Debug, Clone, Default)]
pub struct TableNav {
pub active_row: usize,
pub active_col: usize,
}
impl TableNav {
pub fn new() -> Self {
Self::default()
}
pub fn move_up(&mut self, total_rows: usize) -> bool {
if total_rows == 0 {
return false;
}
if self.active_row > 0 {
self.active_row -= 1;
true
} else {
false
}
}
pub fn move_down(&mut self, total_rows: usize) -> bool {
if total_rows == 0 {
return false;
}
if self.active_row + 1 < total_rows {
self.active_row += 1;
true
} else {
false
}
}
pub fn move_left(&mut self, total_cols: usize) -> bool {
if total_cols == 0 {
return false;
}
if self.active_col > 0 {
self.active_col -= 1;
true
} else {
false
}
}
pub fn move_right(&mut self, total_cols: usize) -> bool {
if total_cols == 0 {
return false;
}
if self.active_col + 1 < total_cols {
self.active_col += 1;
true
} else {
false
}
}
pub fn move_home_row(&mut self) -> bool {
if self.active_row != 0 {
self.active_row = 0;
true
} else {
false
}
}
pub fn move_end_row(&mut self, total_rows: usize) -> bool {
let last = total_rows.saturating_sub(1);
if self.active_row != last {
self.active_row = last;
true
} else {
false
}
}
pub fn page_up(&mut self, page_size: usize) -> bool {
let new_row = self.active_row.saturating_sub(page_size);
if new_row != self.active_row {
self.active_row = new_row;
true
} else {
false
}
}
pub fn page_down(&mut self, total_rows: usize, page_size: usize) -> bool {
if total_rows == 0 {
return false;
}
let new_row = (self.active_row + page_size).min(total_rows.saturating_sub(1));
if new_row != self.active_row {
self.active_row = new_row;
true
} else {
false
}
}
pub fn set_position(&mut self, row: usize, col: usize) {
self.active_row = row;
self.active_col = col;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_is_top_left() {
let nav = TableNav::new();
assert_eq!(nav.active_row, 0);
assert_eq!(nav.active_col, 0);
}
#[test]
fn move_down_increments_row() {
let mut nav = TableNav::new();
assert!(nav.move_down(5));
assert_eq!(nav.active_row, 1);
}
#[test]
fn move_down_clamps_at_last_row() {
let mut nav = TableNav::new();
nav.active_row = 4;
assert!(!nav.move_down(5)); assert_eq!(nav.active_row, 4);
}
#[test]
fn move_up_clamps_at_zero() {
let mut nav = TableNav::new();
assert!(!nav.move_up(5));
assert_eq!(nav.active_row, 0);
}
#[test]
fn move_left_right() {
let mut nav = TableNav::new();
assert!(!nav.move_left(3));
assert!(nav.move_right(3));
assert_eq!(nav.active_col, 1);
nav.active_col = 2;
assert!(!nav.move_right(3));
assert_eq!(nav.active_col, 2);
}
#[test]
fn page_up_down() {
let mut nav = TableNav::new();
nav.active_row = 10;
assert!(nav.page_up(4));
assert_eq!(nav.active_row, 6);
assert!(nav.page_down(20, 4));
assert_eq!(nav.active_row, 10);
assert!(nav.page_down(12, 100));
assert_eq!(nav.active_row, 11);
}
#[test]
fn home_end() {
let mut nav = TableNav::new();
nav.active_row = 7;
assert!(nav.move_home_row());
assert_eq!(nav.active_row, 0);
assert!(!nav.move_home_row());
assert!(nav.move_end_row(10));
assert_eq!(nav.active_row, 9);
assert!(!nav.move_end_row(10));
}
#[test]
fn no_op_on_zero_rows() {
let mut nav = TableNav::new();
assert!(!nav.move_up(0));
assert!(!nav.move_down(0));
assert!(!nav.page_down(0, 5));
assert!(!nav.move_end_row(0));
assert_eq!(nav.active_row, 0);
}
#[test]
fn set_position_updates() {
let mut nav = TableNav::new();
nav.set_position(5, 3);
assert_eq!(nav.active_row, 5);
assert_eq!(nav.active_col, 3);
}
}