1#[derive(Debug, Clone)]
5pub struct Viewport {
6 pub width: f32,
7 pub height: f32,
8 pub scroll_offset: f32,
9 pub total_content_height: f32,
10 pub top_offset: f32,
13 pub pinned_to_bottom: bool,
16}
17
18impl Viewport {
19 pub fn new(width: f32, height: f32) -> Self {
20 Self {
21 width,
22 height,
23 scroll_offset: 0.0,
24 total_content_height: 0.0,
25 top_offset: 0.0,
26 pinned_to_bottom: true,
27 }
28 }
29
30 pub fn scroll(&mut self, delta: f32) {
32 let max_scroll = (self.total_content_height - self.height).max(0.0);
33 self.scroll_offset = (self.scroll_offset + delta).clamp(0.0, max_scroll);
34 self.pinned_to_bottom = (max_scroll - self.scroll_offset) < 1.0;
35 }
36
37 pub fn scroll_to_top(&mut self) {
39 self.scroll_offset = 0.0;
40 self.pinned_to_bottom = false;
41 }
42
43 pub fn scroll_to_bottom(&mut self) {
45 let max_scroll = (self.total_content_height - self.height).max(0.0);
46 self.scroll_offset = max_scroll;
47 self.pinned_to_bottom = true;
48 }
49
50 pub fn scroll_to(&mut self, y: f32) {
52 let max_scroll = (self.total_content_height - self.height).max(0.0);
53 self.scroll_offset = y.clamp(0.0, max_scroll);
54 self.pinned_to_bottom = (max_scroll - self.scroll_offset) < 1.0;
55 }
56
57 pub fn resize(&mut self, width: f32, height: f32) {
58 self.width = width;
59 self.height = height;
60 }
61
62 pub fn is_visible(&self, y: f32, h: f32) -> bool {
64 let top = self.scroll_offset;
65 let bottom = self.scroll_offset + self.height;
66 y + h > top && y < bottom
67 }
68
69 pub fn content_to_screen_y(&self, content_y: f32) -> f32 {
71 content_y - self.scroll_offset + self.top_offset
72 }
73}