freya_components/scrollviews/
shared.rs1use freya_core::prelude::*;
2use torin::{
3 prelude::Direction,
4 size::Size,
5};
6
7#[derive(Debug, PartialEq, Eq, Clone, Copy)]
8pub enum Axis {
9 X,
10 Y,
11}
12
13#[doc(hidden)]
14pub fn get_scroll_position_from_wheel(
15 wheel_movement: f32,
16 inner_size: f32,
17 viewport_size: f32,
18 scroll_position: f32,
19) -> i32 {
20 if viewport_size >= inner_size {
21 return 0;
22 }
23
24 let new_position = scroll_position + wheel_movement;
25
26 if new_position >= 0.0 && wheel_movement > 0.0 {
27 return 0;
28 }
29
30 if new_position <= -(inner_size - viewport_size) && wheel_movement < 0.0 {
31 return -(inner_size - viewport_size) as i32;
32 }
33
34 new_position as i32
35}
36
37#[doc(hidden)]
38pub fn get_corrected_scroll_position(
39 inner_size: f32,
40 viewport_size: f32,
41 scroll_position: f32,
42) -> f32 {
43 let overscrolled_start = scroll_position > 0.0;
45 let overscrolled_end = (-scroll_position + viewport_size) > inner_size;
46
47 if overscrolled_start {
48 0f32
49 } else if overscrolled_end {
50 if viewport_size < inner_size {
51 -(inner_size - viewport_size)
52 } else {
53 0f32
54 }
55 } else {
56 scroll_position
57 }
58}
59
60#[doc(hidden)]
61pub fn get_container_sizes(size: Size) -> (Size, Size) {
62 if size == Size::Inner {
63 (size.clone(), size)
64 } else {
65 (Size::percent(100.), Size::fill())
66 }
67}
68
69#[doc(hidden)]
70pub fn is_scrollbar_visible(
71 is_scrollbar_enabled: bool,
72 inner_size: f32,
73 viewport_size: f32,
74) -> bool {
75 if is_scrollbar_enabled {
76 viewport_size > 0. && viewport_size < inner_size
77 } else {
78 false
79 }
80}
81
82const MIN_SCROLLBAR_SIZE: f32 = 50.0;
83
84#[doc(hidden)]
85pub fn get_scrollbar_pos_and_size(
86 inner_size: f32,
87 viewport_size: f32,
88 scroll_position: f32,
89) -> (f32, f32) {
90 if viewport_size >= inner_size {
91 return (0.0, inner_size);
92 }
93
94 let viewable_ratio = viewport_size / inner_size;
95 let mut scrollbar_size = viewport_size * viewable_ratio;
96
97 if scrollbar_size < MIN_SCROLLBAR_SIZE {
98 scrollbar_size = MIN_SCROLLBAR_SIZE;
99 }
100
101 let available_scroll_range = inner_size - viewport_size;
102 let available_thumb_range = viewport_size - scrollbar_size;
103
104 let normalized_scroll = -scroll_position / available_scroll_range;
105 let scrollbar_position = normalized_scroll * available_thumb_range;
106
107 (scrollbar_position, scrollbar_size)
108}
109#[doc(hidden)]
110pub fn get_scroll_position_from_cursor(
111 cursor_position: f32,
112 inner_size: f32,
113 viewport_size: f32,
114) -> i32 {
115 if viewport_size >= inner_size {
116 return 0;
117 }
118
119 let viewable_ratio = viewport_size / inner_size;
120 let mut scrollbar_size = viewport_size * viewable_ratio;
121
122 if scrollbar_size < MIN_SCROLLBAR_SIZE {
123 scrollbar_size = MIN_SCROLLBAR_SIZE;
124 }
125
126 let available_scroll_range = inner_size - viewport_size;
127 let available_thumb_range = viewport_size - scrollbar_size;
128
129 let cursor_clamped = cursor_position.clamp(0.0, available_thumb_range);
131
132 let normalized_scroll = cursor_clamped / available_thumb_range;
133 let new_position = -(normalized_scroll * available_scroll_range);
134
135 new_position as i32
136}
137
138pub fn handle_key_event(
139 key: &Key,
140 (mut x, mut y): (f32, f32),
141 inner_height: f32,
142 inner_width: f32,
143 viewport_height: f32,
144 viewport_width: f32,
145 direction: Direction,
146) -> Option<(f32, f32)> {
147 let y_page_delta = viewport_height;
148 let y_line_delta = y_page_delta / 5.0;
149 let x_page_delta = viewport_width;
150 let x_line_delta = x_page_delta / 5.0;
151
152 match key {
155 Key::ArrowUp => {
156 y = get_corrected_scroll_position(inner_height, viewport_height, y + y_line_delta)
157 }
158 Key::ArrowDown => {
159 y = get_corrected_scroll_position(inner_height, viewport_height, y - y_line_delta)
160 }
161 Key::PageUp => {
162 y = get_corrected_scroll_position(inner_height, viewport_height, y + y_line_delta)
163 }
164 Key::PageDown => {
165 y = get_corrected_scroll_position(inner_height, viewport_height, y - y_line_delta)
166 }
167 Key::ArrowLeft => {
168 x = get_corrected_scroll_position(inner_width, viewport_width, x + x_line_delta)
169 }
170 Key::ArrowRight => {
171 x = get_corrected_scroll_position(inner_width, viewport_width, x - x_line_delta)
172 }
173 Key::Home => {
174 if direction == Direction::Vertical {
175 y = 0.0;
176 } else {
177 x = 0.0;
178 }
179 }
180 Key::End => {
181 if direction == Direction::Vertical {
182 y = -inner_height;
183 } else {
184 x = -inner_width;
185 }
186 }
187 _ => return None,
188 };
189 Some((x, y))
190}