pub fn calculate_scroll_offset(
selected_index: usize,
visible_count: usize,
total_count: usize,
) -> usize {
if total_count <= visible_count {
return 0;
}
let half_visible = visible_count / 2;
if selected_index <= half_visible {
0
} else if selected_index >= total_count - half_visible {
total_count.saturating_sub(visible_count)
} else {
selected_index.saturating_sub(half_visible)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_all_items_visible() {
assert_eq!(calculate_scroll_offset(0, 10, 5), 0);
assert_eq!(calculate_scroll_offset(4, 10, 5), 0);
assert_eq!(calculate_scroll_offset(5, 10, 5), 0);
}
#[test]
fn test_selected_at_start() {
assert_eq!(calculate_scroll_offset(0, 5, 20), 0);
assert_eq!(calculate_scroll_offset(1, 5, 20), 0);
assert_eq!(calculate_scroll_offset(2, 5, 20), 0);
}
#[test]
fn test_selected_at_end() {
assert_eq!(calculate_scroll_offset(18, 5, 20), 15);
assert_eq!(calculate_scroll_offset(19, 5, 20), 15);
}
#[test]
fn test_selected_in_middle() {
assert_eq!(calculate_scroll_offset(10, 5, 20), 8);
assert_eq!(calculate_scroll_offset(9, 5, 20), 7);
assert_eq!(calculate_scroll_offset(11, 5, 20), 9);
}
#[test]
fn test_edge_cases() {
assert_eq!(calculate_scroll_offset(0, 1, 1), 0);
assert_eq!(calculate_scroll_offset(0, 1, 100), 0);
assert_eq!(calculate_scroll_offset(99, 1, 100), 99);
assert_eq!(calculate_scroll_offset(0, 3, 10), 0);
assert_eq!(calculate_scroll_offset(1, 3, 10), 0);
assert_eq!(calculate_scroll_offset(2, 3, 10), 0);
assert_eq!(calculate_scroll_offset(3, 3, 10), 1);
assert_eq!(calculate_scroll_offset(6, 3, 10), 4);
assert_eq!(calculate_scroll_offset(7, 3, 10), 5);
assert_eq!(calculate_scroll_offset(8, 3, 10), 7);
assert_eq!(calculate_scroll_offset(9, 3, 10), 7);
}
}