term_wm_layout_engine/
scroll.rs1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub struct ScrollState {
7 pub offset: usize,
8 pub pending: isize,
9}
10
11impl ScrollState {
12 pub fn new() -> Self {
13 Self {
14 offset: 0,
15 pending: 0,
16 }
17 }
18
19 pub fn reset(&mut self) {
20 self.offset = 0;
21 self.pending = 0;
22 }
23
24 pub fn bump(&mut self, delta: isize) {
25 self.pending = self.pending.saturating_add(delta);
26 }
27
28 pub fn apply(&mut self, total: usize, view: usize) {
29 let max_offset = total.saturating_sub(view);
30 let new_offset = (self.offset as isize).saturating_add(self.pending).max(0) as usize;
31 self.offset = new_offset.min(max_offset);
32 self.pending = 0;
33 }
34}
35
36impl Default for ScrollState {
37 fn default() -> Self {
38 Self::new()
39 }
40}
41
42#[cfg(test)]
43mod tests {
44 use super::*;
45
46 #[test]
47 fn scroll_apply_clamps_to_max() {
48 let mut s = ScrollState::new();
49 s.bump(100);
50 s.apply(50, 10); assert_eq!(s.offset, 40);
52 }
53
54 #[test]
55 fn scroll_apply_clamps_to_zero() {
56 let mut s = ScrollState::new();
57 s.bump(-10);
58 s.apply(50, 10);
59 assert_eq!(s.offset, 0);
60 }
61
62 #[test]
63 fn scroll_apply_normal() {
64 let mut s = ScrollState::new();
65 s.bump(5);
66 s.apply(50, 10); assert_eq!(s.offset, 5);
68 }
69
70 #[test]
71 fn scroll_reset() {
72 let mut s = ScrollState::new();
73 s.bump(10);
74 s.apply(100, 20);
75 assert_eq!(s.offset, 10);
76 s.reset();
77 assert_eq!(s.offset, 0);
78 assert_eq!(s.pending, 0);
79 }
80}