#[derive(Debug, Clone)]
pub struct Viewport {
pub width: f32,
pub height: f32,
pub scroll_offset: f32,
pub total_content_height: f32,
pub top_offset: f32,
pub pinned_to_bottom: bool,
}
impl Viewport {
pub fn new(width: f32, height: f32) -> Self {
Self {
width,
height,
scroll_offset: 0.0,
total_content_height: 0.0,
top_offset: 0.0,
pinned_to_bottom: true,
}
}
pub fn scroll(&mut self, delta: f32) {
let max_scroll = (self.total_content_height - self.height).max(0.0);
self.scroll_offset = (self.scroll_offset + delta).clamp(0.0, max_scroll);
self.pinned_to_bottom = (max_scroll - self.scroll_offset) < 1.0;
}
pub fn scroll_to_top(&mut self) {
self.scroll_offset = 0.0;
self.pinned_to_bottom = false;
}
pub fn scroll_to_bottom(&mut self) {
let max_scroll = (self.total_content_height - self.height).max(0.0);
self.scroll_offset = max_scroll;
self.pinned_to_bottom = true;
}
pub fn scroll_to(&mut self, y: f32) {
let max_scroll = (self.total_content_height - self.height).max(0.0);
self.scroll_offset = y.clamp(0.0, max_scroll);
self.pinned_to_bottom = (max_scroll - self.scroll_offset) < 1.0;
}
pub fn resize(&mut self, width: f32, height: f32) {
self.width = width;
self.height = height;
}
pub fn is_visible(&self, y: f32, h: f32) -> bool {
let top = self.scroll_offset;
let bottom = self.scroll_offset + self.height;
y + h > top && y < bottom
}
pub fn content_to_screen_y(&self, content_y: f32) -> f32 {
content_y - self.scroll_offset + self.top_offset
}
}