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 size: Size,
33 pub thumb: ScrollThumb,
34}
35
36impl ComponentOwned for ScrollBar {
37 fn render(self) -> impl IntoElement {
38 let scrollbar_theme = get_theme!(&self.theme, scrollbar);
39
40 let mut state = use_state(|| ScrollBarState::Idle);
41
42 let (cross_size, cross_offset, opacity) = match *state.read() {
43 _ if self.clicking_scrollbar.read().is_some() => (16., 0., 160),
44 ScrollBarState::Idle => (12., 3., 0),
45 ScrollBarState::Hovering => (16., 0., 160),
46 };
47
48 let (
49 width,
50 height,
51 offset_x,
52 offset_y,
53 inner_offset_x,
54 inner_offset_y,
55 inner_width,
56 inner_height,
57 ) = match self.axis {
58 Axis::X => (
59 self.size.clone(),
60 Size::px(16.),
61 0.,
62 -16.,
63 self.offset,
64 cross_offset,
65 self.size.clone(),
66 Size::px(cross_size),
67 ),
68 Axis::Y => (
69 Size::px(16.),
70 self.size.clone(),
71 -16.,
72 0.,
73 cross_offset,
74 self.offset,
75 Size::px(cross_size),
76 self.size.clone(),
77 ),
78 };
79
80 let on_pointer_enter = move |_| {
81 state.set(ScrollBarState::Hovering);
82 };
83 let on_pointer_leave = move |_| state.set(ScrollBarState::Idle);
84
85 rect()
86 .position(Position::new_absolute())
87 .width(width)
88 .height(height)
89 .offset_x(offset_x)
90 .offset_y(offset_y)
91 .layer(999)
92 .child(
93 rect()
94 .width(Size::fill())
95 .height(Size::fill())
96 .direction(if self.axis == Axis::Y {
97 Direction::vertical()
98 } else {
99 Direction::horizontal()
100 })
101 .cross_align(Alignment::end())
102 .background(scrollbar_theme.background.with_a(opacity))
103 .on_pointer_enter(on_pointer_enter)
104 .on_pointer_leave(on_pointer_leave)
105 .child(
106 rect()
107 .width(inner_width)
108 .height(inner_height)
109 .offset_x(inner_offset_x)
110 .offset_y(inner_offset_y)
111 .child(self.thumb),
112 ),
113 )
114 }
115}