Skip to main content

freya_components/scrollviews/
scrollthumb.rs

1use 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 self.axis == Axis::X {
54                    self.clicking_scrollbar
55                        .set(Some((self.axis, e.element_location().x)));
56                } else {
57                    self.clicking_scrollbar
58                        .set(Some((self.axis, e.element_location().y)));
59                }
60            })
61            .on_pointer_press(move |e: Event<PointerEventData>| {
62                e.prevent_default();
63                e.stop_propagation();
64                self.clicking_scrollbar.set(None);
65            })
66            .child(
67                rect()
68                    .width(Size::fill())
69                    .height(Size::fill())
70                    .background(thumb_background)
71                    .corner_radius(8.),
72            )
73    }
74}