use crate::ui::scrollbar::draw_scrollbar; use std::cell::Cell; use tui::{backend::Backend, layout::Rect, Frame}; pub struct VerticalScroll { top: Cell, max_top: Cell, } impl VerticalScroll { pub const fn new() -> Self { Self { top: Cell::new(0), max_top: Cell::new(0), } } pub fn get_top(&self) -> usize { self.top.get() } pub fn reset(&self) { self.top.set(0); } pub fn update(&self, selection: usize, selection_max: usize, visual_height: usize) -> usize { let new_top = calc_scroll_top(self.get_top(), visual_height, selection, selection_max); self.top.set(new_top); if visual_height == 0 { self.max_top.set(0); } else { let new_max = selection_max.saturating_sub(visual_height); self.max_top.set(new_max); } new_top } pub fn draw(&self, f: &mut Frame, r: Rect) { draw_scrollbar(f, r, self.max_top.get(), self.top.get()); } } const fn calc_scroll_top( current_top: usize, height_in_lines: usize, selection: usize, selection_max: usize, ) -> usize { if height_in_lines == 0 { return 0; } if selection_max <= height_in_lines { return 0; } if current_top + height_in_lines <= selection { selection.saturating_sub(height_in_lines) + 1 } else if current_top > selection { selection } else { current_top } }