freya_components/scrollviews/
scrollbar.rs1use freya_core::prelude::*;
2use torin::{
3 prelude::{
4 Alignment,
5 Direction,
6 },
7 size::Size,
8};
9
10use crate::{
11 get_theme,
12 scrollviews::{
13 ScrollThumb,
14 shared::Axis,
15 },
16 theming::component_themes::ScrollBarThemePartial,
17};
18
19#[derive(Clone, Copy, PartialEq, Debug)]
20enum ScrollBarState {
21 Idle,
22 Hovering,
23}
24
25#[derive(Clone, PartialEq)]
26pub struct ScrollBar {
27 pub(crate) theme: Option<ScrollBarThemePartial>,
28 pub clicking_scrollbar: State<Option<(Axis, f64)>>,
29 pub axis: Axis,
30 pub offset: f32,
31 pub thumb: ScrollThumb,
32}
33
34impl RenderOwned for ScrollBar {
35 fn render(self) -> impl IntoElement {
36 let scrollbar_theme = get_theme!(&self.theme, scrollbar);
37
38 let mut state = use_state(|| ScrollBarState::Idle);
39
40 let (size, opacity) = match *state.read() {
41 _ if self.clicking_scrollbar.read().is_some() => (16., 160),
42 ScrollBarState::Idle => (5., 0),
43 ScrollBarState::Hovering => (16., 160),
44 };
45
46 let (
47 width,
48 height,
49 offset_x,
50 offset_y,
51 inner_offset_x,
52 inner_offset_y,
53 inner_width,
54 inner_height,
55 ) = match self.axis {
56 Axis::X => (
57 Size::fill(),
58 Size::px(16.),
59 0.,
60 -16.,
61 self.offset,
62 0.,
63 Size::fill(),
64 Size::px(size),
65 ),
66 Axis::Y => (
67 Size::px(16.),
68 Size::fill(),
69 -16.,
70 0.,
71 0.,
72 self.offset,
73 Size::px(size),
74 Size::fill(),
75 ),
76 };
77
78 let on_pointer_enter = move |_| {
79 state.set(ScrollBarState::Hovering);
80 };
81 let on_pointer_leave = move |_| state.set(ScrollBarState::Idle);
82
83 rect()
84 .width(width)
85 .height(height)
86 .offset_x(offset_x)
87 .offset_y(offset_y)
88 .layer(999)
89 .child(
90 rect()
91 .width(Size::fill())
92 .height(Size::fill())
93 .direction(if self.axis == Axis::Y {
94 Direction::vertical()
95 } else {
96 Direction::horizontal()
97 })
98 .cross_align(Alignment::end())
99 .background(scrollbar_theme.background.with_a(opacity))
100 .on_pointer_enter(on_pointer_enter)
101 .on_pointer_leave(on_pointer_leave)
102 .child(
103 rect()
104 .width(inner_width)
105 .height(inner_height)
106 .offset_x(inner_offset_x)
107 .offset_y(inner_offset_y)
108 .child(self.thumb),
109 ),
110 )
111 }
112}