1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#![deny(missing_docs)]
extern crate input;
use input::GenericEvent;
#[derive(Clone, Debug)]
pub struct ScrollSettings {
speed: f64,
}
impl ScrollSettings {
pub fn new() -> ScrollSettings {
ScrollSettings {
speed: 1.0,
}
}
pub fn speed(mut self, val: f64) -> ScrollSettings {
self.speed = val;
self
}
}
#[derive(Clone, Debug)]
pub struct ScrollController {
cursor: [f64; 2],
pub offset: [f64; 2],
pub bounds: [f64; 4],
pub area: [f64; 2],
pub speed: f64,
}
impl ScrollController {
pub fn new(bounds: [f64; 4], area: [f64; 2], settings: &ScrollSettings) -> ScrollController {
ScrollController {
cursor: [0.0; 2],
offset: [0.0; 2],
bounds: bounds,
area: area,
speed: settings.speed,
}
}
pub fn visible_area_rect(&self) -> [f64; 4] {
[
-self.offset[0],
-self.offset[1],
self.bounds[2].min(self.area[0]),
self.bounds[3].min(self.area[1])
]
}
pub fn rect_from_area_to_view(&self, rect: [f64; 4]) -> [f64; 4] {
[
self.bounds[0] - self.offset[0] - rect[0],
self.bounds[1] - self.offset[1] - rect[1],
rect[2],
rect[3]
]
}
fn cursor_inside(&self) -> bool {
let c = self.cursor;
let b = self.bounds;
c[0] >= b[0] && c[1] >= b[1] && c[0] < b[0] + b[2] && c[1] < b[1] + b[3]
}
fn clamp_offset_to_scroll_area(&self, offset: [f64; 2]) -> [f64; 2] {
let b = self.bounds;
let a = self.area;
[
if offset[0] > 0.0 || b[2] > a[0] {
0.0
} else if offset[0] < -(a[0] - b[2]) {
-(a[0] - b[2])
} else {
offset[0]
},
if offset[1] > 0.0 || b[3] > a[1] {
0.0
} else if a[1] > b[3] && offset[1] < -(a[1] - b[3]) {
-(a[1] - b[3])
} else {
offset[1]
}
]
}
pub fn event<E: GenericEvent>(&mut self, e: &E) {
if let Some(pos) = e.mouse_cursor_args() {
self.cursor = pos;
}
if let Some(pos) = e.mouse_scroll_args() {
if self.cursor_inside() {
let new_offset = [
self.offset[0] - pos[0] * self.speed,
self.offset[1] + pos[1] * self.speed
];
self.offset = self.clamp_offset_to_scroll_area(new_offset);
}
}
}
}