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