Skip to main content

freya_components/scrollviews/
scrollthumb.rs

1use freya_core::prelude::*;
2use torin::{
3    prelude::{
4        Alignment,
5        Gaps,
6    },
7    size::Size,
8};
9
10use crate::{
11    get_theme,
12    scrollviews::{
13        Axis,
14        ScrollBarThemePartial,
15        ScrollBarThemePreference,
16        ScrollBarThumbEvents,
17    },
18};
19
20#[derive(PartialEq)]
21enum ScrollThumbState {
22    Idle,
23    Hovering,
24}
25
26#[derive(Clone, PartialEq)]
27pub struct ScrollThumb {
28    pub theme: Option<ScrollBarThemePartial>,
29    pub clicking_scrollbar: State<Option<(Axis, f64)>>,
30    pub thumb_events: ScrollBarThumbEvents,
31    pub axis: Axis,
32    pub size: f32,
33    pub cross_size: f32,
34    pub cross_gap: f32,
35}
36
37impl ComponentOwned for ScrollThumb {
38    fn render(self) -> impl IntoElement {
39        let scrollbar_theme = get_theme!(&self.theme, ScrollBarThemePreference, "scrollbar");
40        let mut state = use_state(|| ScrollThumbState::Idle);
41
42        let (width, height, pill_width, pill_height, padding, main_align, cross_align) =
43            match self.axis {
44                Axis::X => (
45                    Size::px(self.size),
46                    Size::fill(),
47                    Size::fill(),
48                    Size::px(self.cross_size),
49                    Gaps::new(0., 0., self.cross_gap, 0.),
50                    Alignment::end(),
51                    Alignment::start(),
52                ),
53                Axis::Y => (
54                    Size::fill(),
55                    Size::px(self.size),
56                    Size::px(self.cross_size),
57                    Size::fill(),
58                    Gaps::new(0., self.cross_gap, 0., 0.),
59                    Alignment::start(),
60                    Alignment::end(),
61                ),
62            };
63
64        let thumb_background = match *state.read() {
65            _ if self.clicking_scrollbar.read().is_some() => {
66                scrollbar_theme.active_thumb_background
67            }
68            ScrollThumbState::Hovering => scrollbar_theme.hover_thumb_background,
69            ScrollThumbState::Idle => scrollbar_theme.thumb_background,
70        };
71
72        let on_pointer_over = move |_| state.set_if_modified(ScrollThumbState::Hovering);
73        let on_pointer_out = move |_| state.set_if_modified(ScrollThumbState::Idle);
74
75        rect()
76            .width(width)
77            .height(height)
78            .padding(padding)
79            .main_align(main_align)
80            .cross_align(cross_align)
81            .on_pointer_over(on_pointer_over)
82            .on_pointer_out(on_pointer_out)
83            .on_pointer_down(self.thumb_events.on_pointer_down)
84            .on_pointer_press(self.thumb_events.on_pointer_press)
85            .child(
86                rect()
87                    .width(pill_width)
88                    .height(pill_height)
89                    .background(thumb_background)
90                    .corner_radius(8.),
91            )
92    }
93}