#[must_use]
pub fn calculate_horizontal_scroll(cursor_pos: usize, terminal_width: u16) -> u16 {
let inner_width = terminal_width.saturating_sub(3) as usize;
if cursor_pos >= inner_width {
(cursor_pos + 1).saturating_sub(inner_width) as u16
} else {
0
}
}
#[must_use]
pub fn update_scroll_offset(cursor_pos: usize, current_offset: u16, visible_width: usize) -> u16 {
if cursor_pos < current_offset as usize {
cursor_pos as u16
}
else if cursor_pos >= current_offset as usize + visible_width {
(cursor_pos + 1).saturating_sub(visible_width) as u16
}
else {
current_offset
}
}
#[must_use]
pub fn calculate_visible_range(
total_items: usize,
viewport_start: usize,
viewport_size: usize,
) -> (usize, usize) {
let start = viewport_start.min(total_items);
let end = (viewport_start + viewport_size).min(total_items);
(start, end)
}
#[must_use]
pub fn calculate_page_jump(
current_pos: usize,
page_size: usize,
total_items: usize,
direction_up: bool,
) -> usize {
if direction_up {
current_pos.saturating_sub(page_size)
} else {
(current_pos + page_size).min(total_items.saturating_sub(1))
}
}
#[must_use]
pub fn calculate_centered_viewport(
target_pos: usize,
viewport_size: usize,
total_items: usize,
) -> usize {
if total_items <= viewport_size {
0
} else if target_pos < viewport_size / 2 {
0
} else if target_pos > total_items.saturating_sub(viewport_size / 2) {
total_items.saturating_sub(viewport_size)
} else {
target_pos.saturating_sub(viewport_size / 2)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_horizontal_scroll() {
assert_eq!(calculate_horizontal_scroll(5, 80), 0);
assert_eq!(calculate_horizontal_scroll(100, 80), 24); }
#[test]
fn test_update_scroll_offset() {
assert_eq!(update_scroll_offset(5, 10, 20), 5);
assert_eq!(update_scroll_offset(15, 10, 20), 10);
assert_eq!(update_scroll_offset(35, 10, 20), 16); }
#[test]
fn test_visible_range() {
assert_eq!(calculate_visible_range(100, 10, 20), (10, 30));
assert_eq!(calculate_visible_range(100, 90, 20), (90, 100));
assert_eq!(calculate_visible_range(5, 0, 10), (0, 5));
}
#[test]
fn test_page_jump() {
assert_eq!(calculate_page_jump(50, 10, 100, true), 40);
assert_eq!(calculate_page_jump(5, 10, 100, true), 0);
assert_eq!(calculate_page_jump(50, 10, 100, false), 60);
assert_eq!(calculate_page_jump(95, 10, 100, false), 99);
}
#[test]
fn test_centered_viewport() {
assert_eq!(calculate_centered_viewport(5, 20, 10), 0);
assert_eq!(calculate_centered_viewport(5, 20, 100), 0);
assert_eq!(calculate_centered_viewport(95, 20, 100), 80);
assert_eq!(calculate_centered_viewport(50, 20, 100), 40);
}
}