1use gpui::{Bounds, ListState, Pixels, Point, ScrollHandle, point, px};
4
5#[derive(Clone)]
17pub enum Scroller {
18 Pane(ScrollHandle),
19 List(ListState),
20}
21
22impl Scroller {
23 pub fn bounds(&self) -> Bounds<Pixels> {
25 match self {
26 Self::Pane(handle) => handle.bounds(),
27 Self::List(state) => state.viewport_bounds(),
28 }
29 }
30
31 pub fn offset(&self) -> Point<Pixels> {
32 match self {
33 Self::Pane(handle) => {
34 let (offset, max) = (handle.offset(), handle.max_offset());
35 point(
36 offset.x.clamp(-max.x, px(0.)),
37 offset.y.clamp(-max.y, px(0.)),
38 )
39 }
40 Self::List(state) => {
41 let offset = state.scroll_px_offset_for_scrollbar();
42 point(offset.x, offset.y.max(-state.max_offset_for_scrollbar().y))
43 }
44 }
45 }
46
47 pub fn max_offset(&self) -> Point<Pixels> {
48 match self {
49 Self::Pane(handle) => handle.max_offset(),
50 Self::List(state) => state.max_offset_for_scrollbar(),
51 }
52 }
53
54 pub fn set_offset(&self, offset: Point<Pixels>) {
56 match self {
57 Self::Pane(handle) => handle.set_offset(offset),
58 Self::List(state) => state.set_offset_from_scrollbar(offset),
59 }
60 }
61
62 pub fn scroll_to_end(&self) {
66 match self {
67 Self::Pane(handle) => {
68 handle.set_offset(point(handle.offset().x, -handle.max_offset().y))
69 }
70 Self::List(state) => state.scroll_to_end(),
71 }
72 }
73}
74
75impl From<ScrollHandle> for Scroller {
76 fn from(handle: ScrollHandle) -> Self {
77 Self::Pane(handle)
78 }
79}
80
81impl From<&ScrollHandle> for Scroller {
82 fn from(handle: &ScrollHandle) -> Self {
83 Self::Pane(handle.clone())
84 }
85}
86
87impl From<ListState> for Scroller {
88 fn from(state: ListState) -> Self {
89 Self::List(state)
90 }
91}
92
93impl From<&ListState> for Scroller {
94 fn from(state: &ListState) -> Self {
95 Self::List(state.clone())
96 }
97}