freya_components/scrollviews/
scrollthumb.rs1use freya_core::prelude::*;
2use torin::size::Size;
3
4use crate::{
5 get_theme,
6 scrollviews::{
7 ScrollBarThemePartial,
8 ScrollBarThemePreference,
9 shared::Axis,
10 },
11};
12
13enum ScrollThumbState {
14 Idle,
15 Hovering,
16}
17
18#[derive(Clone, PartialEq)]
19pub struct ScrollThumb {
20 pub(crate) theme: Option<ScrollBarThemePartial>,
21 pub clicking_scrollbar: State<Option<(Axis, f64)>>,
22 pub axis: Axis,
23 pub size: f32,
24}
25
26impl ComponentOwned for ScrollThumb {
27 fn render(mut self) -> impl IntoElement {
28 let scrollbar_theme = get_theme!(&self.theme, ScrollBarThemePreference, "scrollbar");
29 let mut state = use_state(|| ScrollThumbState::Idle);
30
31 let (width, height) = match self.axis {
32 Axis::X => (Size::px(self.size), Size::fill()),
33 Axis::Y => (Size::fill(), Size::px(self.size)),
34 };
35 let thumb_background = match *state.read() {
36 _ if self.clicking_scrollbar.read().is_some() => {
37 scrollbar_theme.active_thumb_background
38 }
39 ScrollThumbState::Idle => scrollbar_theme.thumb_background,
40 ScrollThumbState::Hovering => scrollbar_theme.hover_thumb_background,
41 };
42
43 let on_pointer_over = move |_| state.set(ScrollThumbState::Hovering);
44 let on_pointer_out = move |_| state.set(ScrollThumbState::Idle);
45
46 rect()
47 .width(width)
48 .height(height)
49 .padding(4.)
50 .on_pointer_over(on_pointer_over)
51 .on_pointer_out(on_pointer_out)
52 .on_pointer_down(move |e: Event<PointerEventData>| {
53 if !e.data().is_primary() {
54 return;
55 }
56 if self.axis == Axis::X {
57 self.clicking_scrollbar
58 .set(Some((self.axis, e.element_location().x)));
59 } else {
60 self.clicking_scrollbar
61 .set(Some((self.axis, e.element_location().y)));
62 }
63 })
64 .on_pointer_press(move |e: Event<PointerEventData>| {
65 e.prevent_default();
66 e.stop_propagation();
67 self.clicking_scrollbar.set(None);
68 })
69 .child(
70 rect()
71 .width(Size::fill())
72 .height(Size::fill())
73 .background(thumb_background)
74 .corner_radius(8.),
75 )
76 }
77}