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