From 784909af8f6b6d9537256d1e5ac46620b905b19c Mon Sep 17 00:00:00 2001 From: Maic Siemering Date: Fri, 28 Mar 2025 10:50:02 +0100 Subject: [PATCH 1/2] gui: improve scroll bar thumb size and appearance --- arcade/gui/experimental/scroll_area.py | 53 +++++++++++++++++++------- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/arcade/gui/experimental/scroll_area.py b/arcade/gui/experimental/scroll_area.py index b33c907782..7d03419658 100644 --- a/arcade/gui/experimental/scroll_area.py +++ b/arcade/gui/experimental/scroll_area.py @@ -18,7 +18,7 @@ UIMouseReleaseEvent, UIMouseScrollEvent, UIWidget, - bind, + bind, UIKeyPressEvent, ) from arcade.types import LBWH @@ -42,7 +42,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) @@ -52,6 +52,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() @@ -68,20 +72,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 @@ -95,7 +99,28 @@ 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.""" @@ -108,24 +133,24 @@ 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.""" From 65ee7e516d71b1e79b80042f81c27d89929a1976 Mon Sep 17 00:00:00 2001 From: Maic Siemering Date: Fri, 28 Mar 2025 10:58:39 +0100 Subject: [PATCH 2/2] fix linter --- arcade/gui/experimental/scroll_area.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/arcade/gui/experimental/scroll_area.py b/arcade/gui/experimental/scroll_area.py index 7d03419658..4722c01c96 100644 --- a/arcade/gui/experimental/scroll_area.py +++ b/arcade/gui/experimental/scroll_area.py @@ -10,6 +10,7 @@ Property, Surface, UIEvent, + UIKeyPressEvent, UILayout, UIMouseDragEvent, UIMouseEvent, @@ -18,7 +19,7 @@ UIMouseReleaseEvent, UIMouseScrollEvent, UIWidget, - bind, UIKeyPressEvent, + bind, ) from arcade.types import LBWH @@ -103,12 +104,16 @@ def on_event(self, event: UIEvent) -> Optional[bool]: 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 + 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 @@ -135,7 +140,7 @@ def _thumb_rect(self): if not self._scrollable(): # content is smaller than the scroll area, full size thumb - return LBWH(0,0, self.content_width, self.content_height) + return LBWH(0, 0, self.content_width, self.content_height) scroll_progress = -scroll_value / scroll_range @@ -143,7 +148,9 @@ def _thumb_rect(self): 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())