Skip to content

Commit dab1e62

Browse files
authored
Merge pull request #2619 from pythonarcade/gui/improve_scroll_bar
gui: improve scroll bar thumb size and appearance
2 parents fe5d2d1 + 65ee7e5 commit dab1e62

File tree

1 file changed

+45
-13
lines changed

1 file changed

+45
-13
lines changed

arcade/gui/experimental/scroll_area.py

+45-13
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
Property,
1111
Surface,
1212
UIEvent,
13+
UIKeyPressEvent,
1314
UILayout,
1415
UIMouseDragEvent,
1516
UIMouseEvent,
@@ -42,7 +43,7 @@ def __init__(self, scroll_area: UIScrollArea, vertical: bool = True):
4243
self.with_border(color=arcade.uicolor.GRAY_CONCRETE)
4344
self.vertical = vertical
4445

45-
self._scroll_bar_size = 20
46+
# self._scroll_bar_size = 20
4647

4748
bind(self, "_thumb_hover", self.trigger_render)
4849
bind(self, "_dragging", self.trigger_render)
@@ -52,6 +53,10 @@ def __init__(self, scroll_area: UIScrollArea, vertical: bool = True):
5253
bind(scroll_area, "content_width", self.trigger_full_render)
5354

5455
def on_event(self, event: UIEvent) -> Optional[bool]:
56+
# check if we are scrollable
57+
if not self._scrollable():
58+
return EVENT_UNHANDLED
59+
5560
# detect if event is mouse down and inside the scroll thumb
5661
# if so, start dragging the thumb
5762
thumb_rect_relative = self._thumb_rect()
@@ -68,20 +73,20 @@ def on_event(self, event: UIEvent) -> Optional[bool]:
6873
# if so, update the scroll position
6974
if isinstance(event, UIMouseDragEvent) and self._dragging:
7075
sx, sy = event.pos - self.rect.bottom_left
71-
sx -= self._scroll_bar_size / 2
72-
sy -= self._scroll_bar_size / 2
76+
sx -= self._scroll_bar_size() / 2
77+
sy -= self._scroll_bar_size() / 2
7378

7479
scroll_area = self.scroll_area
7580

7681
if self.vertical:
77-
available_track_size = self.content_height - self._scroll_bar_size
82+
available_track_size = self.content_height - self._scroll_bar_size()
7883
target_progress = 1 - sy / available_track_size
7984
target_progress = max(0, min(1, target_progress))
8085

8186
scroll_range = scroll_area.surface.height - scroll_area.content_height
8287
scroll_area.scroll_y = -target_progress * scroll_range
8388
else:
84-
available_track_size = self.content_width - self._scroll_bar_size
89+
available_track_size = self.content_width - self._scroll_bar_size()
8590
target_progress = sx / available_track_size
8691
target_progress = max(0, min(1, target_progress))
8792
scroll_range = scroll_area.surface.width - scroll_area.content_width
@@ -95,8 +100,33 @@ def on_event(self, event: UIEvent) -> Optional[bool]:
95100
self._dragging = False
96101
return True
97102

103+
if isinstance(event, UIKeyPressEvent):
104+
print(self._scroll_bar_size())
105+
98106
return EVENT_UNHANDLED
99107

108+
def _scroll_bar_size(self):
109+
# based on: https://stackoverflow.com/a/16367035
110+
111+
content_size = (
112+
self.scroll_area.surface.height if self.vertical else self.scroll_area.surface.width
113+
)
114+
view_size = (
115+
self.scroll_area.content_height if self.vertical else self.scroll_area.content_width
116+
)
117+
ratio = view_size / content_size
118+
119+
scoll_range = self.content_height if self.vertical else self.content_width
120+
121+
return scoll_range * ratio
122+
123+
def _scrollable(self):
124+
return (
125+
self.scroll_area.surface.height - self.scroll_area.content_height
126+
if self.vertical
127+
else self.scroll_area.surface.width - self.scroll_area.content_width
128+
) > 0
129+
100130
def _thumb_rect(self):
101131
"""Calculate the rect of the thumb."""
102132
scroll_area = self.scroll_area
@@ -108,24 +138,26 @@ def _thumb_rect(self):
108138
else scroll_area.surface.width - scroll_area.content_width
109139
)
110140

111-
if scroll_range <= 0:
112-
# content is smaller than the scroll area, no need for a thumb
113-
return XYWH(0, 0, 0, 0)
141+
if not self._scrollable():
142+
# content is smaller than the scroll area, full size thumb
143+
return LBWH(0, 0, self.content_width, self.content_height)
114144

115145
scroll_progress = -scroll_value / scroll_range
116146

117147
content_size = self.content_height if self.vertical else self.content_width
118-
available_track_size = content_size - self._scroll_bar_size
148+
available_track_size = content_size - self._scroll_bar_size()
119149

120150
if self.vertical:
121-
scroll_bar_y = self._scroll_bar_size / 2 + available_track_size * (1 - scroll_progress)
151+
scroll_bar_y = self._scroll_bar_size() / 2 + available_track_size * (
152+
1 - scroll_progress
153+
)
122154
scroll_bar_x = self.content_width / 2
123-
return XYWH(scroll_bar_x, scroll_bar_y, self.content_width, self._scroll_bar_size)
155+
return XYWH(scroll_bar_x, scroll_bar_y, self.content_width, self._scroll_bar_size())
124156

125157
else:
126-
scroll_bar_x = self._scroll_bar_size / 2 + available_track_size * scroll_progress
158+
scroll_bar_x = self._scroll_bar_size() / 2 + available_track_size * scroll_progress
127159
scroll_bar_y = self.content_height / 2
128-
return XYWH(scroll_bar_x, scroll_bar_y, self._scroll_bar_size, self.content_height)
160+
return XYWH(scroll_bar_x, scroll_bar_y, self._scroll_bar_size(), self.content_height)
129161

130162
def do_render(self, surface: Surface):
131163
"""Render the scroll bar."""

0 commit comments

Comments
 (0)