use crate::menu_cursor::{CursorResult, MenuCursor};
use agb::fixnum::Vector2D;
use agb::input::ButtonController;
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct ScrollingCursor {
cursor: MenuCursor,
first_visible_row: u8,
visible_row_count: u8,
}
impl ScrollingCursor {
pub fn new(column_count: u8, item_count: u8, visible_row_count: u8) -> Self {
assert!(
visible_row_count > 0,
"ScrollingCursor created with no visible rows {}, {}, {}",
column_count,
item_count,
visible_row_count
);
Self {
cursor: MenuCursor::new(column_count, item_count),
first_visible_row: 0,
visible_row_count,
}
}
}
impl ScrollingCursor {
fn update_first_row(&mut self) {
let (_, row) = self.cursor.pos();
if row < self.first_visible_row {
self.first_visible_row = row;
} else if row >= self.first_visible_row + self.visible_row_count {
self.first_visible_row = row.saturating_sub(self.visible_row_count - 1);
}
}
}
impl ScrollingCursor {
#[inline]
pub fn idx(&self) -> usize {
self.cursor.idx()
}
#[inline]
pub fn pos(&self) -> (u8, u8) {
self.cursor.pos()
}
#[inline]
pub fn pos_usize(&self) -> (usize, usize) {
self.cursor.pos_usize()
}
#[inline]
pub fn vec_pos(&self) -> Vector2D<i32> {
self.cursor.vec_pos()
}
#[inline]
pub fn first_visible_row(&self) -> u8 {
self.first_visible_row
}
#[inline]
pub fn set_idx(&mut self, idx: usize) {
self.cursor.set_idx(idx);
self.update_first_row();
}
pub fn update(&mut self, button_controller: &ButtonController) -> CursorResult {
let result = self.cursor.update(button_controller);
if result != CursorResult::NoChange {
self.update_first_row();
}
result
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test_case]
fn scrolls_to_keep_cursor_visible(_gba: &mut agb::Gba) {
let mut cursor = ScrollingCursor::new(1, 10, 3);
assert_eq!(cursor.first_visible_row(), 0);
cursor.set_idx(2);
assert_eq!(cursor.first_visible_row(), 0);
cursor.set_idx(5);
assert_eq!(cursor.first_visible_row(), 3);
cursor.set_idx(9);
assert_eq!(cursor.first_visible_row(), 7);
cursor.set_idx(7);
assert_eq!(cursor.first_visible_row(), 7);
cursor.set_idx(0);
assert_eq!(cursor.first_visible_row(), 0);
}
}