#[derive(Debug, Clone, Default)]
pub struct ScrollState {
pub offset: u16,
pub content_height: u16,
pub viewport_height: u16,
pub sticky_bottom: bool,
}
impl ScrollState {
pub fn new() -> Self {
Self {
offset: 0,
content_height: 0,
viewport_height: 0,
sticky_bottom: true,
}
}
fn max_offset(&self) -> u16 {
self.content_height.saturating_sub(self.viewport_height)
}
pub fn clamp(&mut self) {
self.offset = self.offset.min(self.max_offset());
}
pub fn effective_offset(&self) -> u16 {
if self.sticky_bottom {
self.max_offset()
} else {
self.offset.min(self.max_offset())
}
}
pub fn scroll_up(&mut self, n: u16) {
self.sticky_bottom = false;
self.offset = self.offset.saturating_sub(n);
}
pub fn scroll_down(&mut self, n: u16) {
self.sticky_bottom = false;
self.offset = (self.offset + n).min(self.max_offset());
if self.offset >= self.max_offset() {
self.sticky_bottom = true;
}
}
pub fn scroll_to_bottom(&mut self) {
self.sticky_bottom = true;
self.offset = self.max_offset();
}
pub fn page_up(&mut self) {
self.scroll_up(self.viewport_height.saturating_sub(2));
}
pub fn page_down(&mut self) {
self.scroll_down(self.viewport_height.saturating_sub(2));
}
pub fn update_dimensions(&mut self, content_height: u16, viewport_height: u16) {
self.content_height = content_height;
self.viewport_height = viewport_height;
self.clamp();
}
}