Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 45 additions & 13 deletions arcade/gui/experimental/scroll_area.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
Property,
Surface,
UIEvent,
UIKeyPressEvent,
UILayout,
UIMouseDragEvent,
UIMouseEvent,
Expand Down Expand Up @@ -42,7 +43,7 @@ def __init__(self, scroll_area: UIScrollArea, vertical: bool = True):
self.with_border(color=arcade.uicolor.GRAY_CONCRETE)
self.vertical = vertical

self._scroll_bar_size = 20
# self._scroll_bar_size = 20

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

def on_event(self, event: UIEvent) -> Optional[bool]:
# check if we are scrollable
if not self._scrollable():
return EVENT_UNHANDLED

# detect if event is mouse down and inside the scroll thumb
# if so, start dragging the thumb
thumb_rect_relative = self._thumb_rect()
Expand All @@ -68,20 +73,20 @@ def on_event(self, event: UIEvent) -> Optional[bool]:
# if so, update the scroll position
if isinstance(event, UIMouseDragEvent) and self._dragging:
sx, sy = event.pos - self.rect.bottom_left
sx -= self._scroll_bar_size / 2
sy -= self._scroll_bar_size / 2
sx -= self._scroll_bar_size() / 2
sy -= self._scroll_bar_size() / 2

scroll_area = self.scroll_area

if self.vertical:
available_track_size = self.content_height - self._scroll_bar_size
available_track_size = self.content_height - self._scroll_bar_size()
target_progress = 1 - sy / available_track_size
target_progress = max(0, min(1, target_progress))

scroll_range = scroll_area.surface.height - scroll_area.content_height
scroll_area.scroll_y = -target_progress * scroll_range
else:
available_track_size = self.content_width - self._scroll_bar_size
available_track_size = self.content_width - self._scroll_bar_size()
target_progress = sx / available_track_size
target_progress = max(0, min(1, target_progress))
scroll_range = scroll_area.surface.width - scroll_area.content_width
Expand All @@ -95,8 +100,33 @@ def on_event(self, event: UIEvent) -> Optional[bool]:
self._dragging = False
return True

if isinstance(event, UIKeyPressEvent):
print(self._scroll_bar_size())

return EVENT_UNHANDLED

def _scroll_bar_size(self):
# based on: https://stackoverflow.com/a/16367035

content_size = (
self.scroll_area.surface.height if self.vertical else self.scroll_area.surface.width
)
view_size = (
self.scroll_area.content_height if self.vertical else self.scroll_area.content_width
)
ratio = view_size / content_size

scoll_range = self.content_height if self.vertical else self.content_width

return scoll_range * ratio

def _scrollable(self):
return (
self.scroll_area.surface.height - self.scroll_area.content_height
if self.vertical
else self.scroll_area.surface.width - self.scroll_area.content_width
) > 0

def _thumb_rect(self):
"""Calculate the rect of the thumb."""
scroll_area = self.scroll_area
Expand All @@ -108,24 +138,26 @@ def _thumb_rect(self):
else scroll_area.surface.width - scroll_area.content_width
)

if scroll_range <= 0:
# content is smaller than the scroll area, no need for a thumb
return XYWH(0, 0, 0, 0)
if not self._scrollable():
# content is smaller than the scroll area, full size thumb
return LBWH(0, 0, self.content_width, self.content_height)

scroll_progress = -scroll_value / scroll_range

content_size = self.content_height if self.vertical else self.content_width
available_track_size = content_size - self._scroll_bar_size
available_track_size = content_size - self._scroll_bar_size()

if self.vertical:
scroll_bar_y = self._scroll_bar_size / 2 + available_track_size * (1 - scroll_progress)
scroll_bar_y = self._scroll_bar_size() / 2 + available_track_size * (
1 - scroll_progress
)
scroll_bar_x = self.content_width / 2
return XYWH(scroll_bar_x, scroll_bar_y, self.content_width, self._scroll_bar_size)
return XYWH(scroll_bar_x, scroll_bar_y, self.content_width, self._scroll_bar_size())

else:
scroll_bar_x = self._scroll_bar_size / 2 + available_track_size * scroll_progress
scroll_bar_x = self._scroll_bar_size() / 2 + available_track_size * scroll_progress
scroll_bar_y = self.content_height / 2
return XYWH(scroll_bar_x, scroll_bar_y, self._scroll_bar_size, self.content_height)
return XYWH(scroll_bar_x, scroll_bar_y, self._scroll_bar_size(), self.content_height)

def do_render(self, surface: Surface):
"""Render the scroll bar."""
Expand Down
Loading