Skip to content

Commit

Permalink
Merge pull request #194 from anxuae/master
Browse files Browse the repository at this point in the history
Remove duplicated methods between widget and scroll area
  • Loading branch information
ppizarror committed May 3, 2020
2 parents 73d1a5a + 879d4d7 commit 32535b3
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 100 deletions.
12 changes: 9 additions & 3 deletions pygame_menu/menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -1047,7 +1047,7 @@ def _update_widget_position(self):
for r in range(row):
rwidget = self._widgets[int(self._rows * col + r)] # type: _widgets.core.Widget
ysum += widget_rects[rwidget.get_id()].height + rwidget.get_margin()[1]
y_coord = self._widget_offset[1] + ysum + sel_bottom
y_coord = max(1, self._widget_offset[1]) + ysum + sel_bottom

# Update the position of the widget
widget.set_position(x_coord, y_coord)
Expand All @@ -1062,7 +1062,7 @@ def _get_widget_max_position(self):
max_x = -1e6
max_y = -1e6
for widget in self._widgets: # type: _widgets.core.Widget
_, _, x, y = widget.get_relative_position() # Use only bottom right position
x, y = widget.get_rect().bottomright
max_x = max(max_x, x)
max_y = max(max_y, y)
return max_x, max_y
Expand Down Expand Up @@ -1277,7 +1277,13 @@ def _draw_focus_widget(self, surface, widget):
if widget is None or not widget.active or not self._mouse_motion_selection:
return
window_width, window_height = pygame.display.get_surface().get_size()
x1, y1, x2, y2 = widget.get_absolute_position(self._current._scroll)

rect = widget.get_rect()
if widget.selected and widget.get_selection_effect():
rect = widget.get_selection_effect().inflate(rect)
rect = self._current._scroll.to_real_position(rect, visible=True)

x1, y1, x2, y2 = rect.topleft + rect.bottomright

# Convert to integer
x1 = int(x1)
Expand Down
78 changes: 32 additions & 46 deletions pygame_menu/scrollarea.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,6 @@ def __init__(self,
assert area_width > 0 and area_height > 0, \
'area size must be greater than zero'

self._area_width = area_width
self._area_height = area_height
self._rect = pygame.Rect(0.0, 0.0, area_width, area_height)
self._world = world # type: pygame.Surface
self._scrollbars = []
Expand Down Expand Up @@ -239,35 +237,6 @@ def get_hidden_height(self):
return 0
return max(0, self._world.get_height() - self._view_rect.height)

def get_position(self):
"""
Return the position of the scroll.
:return: Position (x,y)
:rtype: tuple
"""
return self._rect.x, self._rect.y

def get_world_size(self):
"""
Return world size.
:return: width, height in pixels
:rtype: tuple
"""
if self._world is None:
return 0, 0
return self._world.get_width(), self._world.get_height()

def get_area_size(self):
"""
Return the area size.
:return: width, height in pixels
:rtype: tuple
"""
return self._area_width, self._area_height

def get_offsets(self):
"""
Return the offset introduced by the scrollbars in the world.
Expand All @@ -291,7 +260,22 @@ def get_rect(self):
:return: Pygame.Rect object
:rtype: :py:class:`pygame.Rect`
"""
return self._rect
return self._rect.copy()

def get_scrollbar_thickness(self, orientation):
"""
Return the scroll thickness of the area. If it's hidden return zero.
:param orientation: Orientation of the scroll
:type orientation: str
:return: Thickness in px
:rtype: int
"""
if orientation == _locals.ORIENTATION_HORIZONTAL:
return self._rect.height - self._view_rect.height
elif orientation == _locals.ORIENTATION_VERTICAL:
return self._rect.width - self._view_rect.width
return 0

def get_view_rect(self):
"""
Expand Down Expand Up @@ -365,20 +349,16 @@ def get_view_rect(self):

return rect

def get_scrollbar_thickness(self, orientation):
def get_world_size(self):
"""
Return the scroll thickness of the area. If it's hidden return zero.
Return world size.
:param orientation: Orientation of the scroll
:type orientation: str
:return: Thickness in px
:rtype: int
:return: width, height in pixels
:rtype: tuple
"""
if orientation == _locals.ORIENTATION_HORIZONTAL:
return self._rect.height - self._view_rect.height
elif orientation == _locals.ORIENTATION_VERTICAL:
return self._rect.width - self._view_rect.width
return 0
if self._world is None:
return 0, 0
return self._world.get_width(), self._world.get_height()

def _on_horizontal_scroll(self, value):
"""
Expand Down Expand Up @@ -467,14 +447,17 @@ def set_world(self, surface):
self._world = surface
self._apply_size_changes()

def to_real_position(self, virtual):
def to_real_position(self, virtual, visible=False):
"""
Return the real position/Rect according to the scroll area origin
of a position/Rect in the world surface reference.
:param virtual: Position/Rect in the world surface reference
:type virtual: :py:class:`pygame.Rect`, tuple, list
:return: None
:param visible: If a rect is given, return only the visible width/height
:type visible: bool
:return: real rect or real position
:rtype: :py:class:`pygame.Rect`, tuple
"""
assert isinstance(virtual, (pygame.Rect, tuple, list))
offsets = self.get_offsets()
Expand All @@ -483,6 +466,8 @@ def to_real_position(self, virtual):
rect = pygame.Rect(virtual)
rect.x = self._rect.x + virtual.x - offsets[0]
rect.y = self._rect.y + virtual.y - offsets[1]
if visible:
return self._view_rect.clip(rect) # Visible width and height
return rect

x_coord = self._rect.x + virtual[0] - offsets[0]
Expand All @@ -496,7 +481,8 @@ def to_world_position(self, real):
:param real: Position/Rect according scroll area origin
:type real: :py:class:`pygame.Rect`, tuple, list
:return: None
:return: rect in world or position in world
:rtype: :py:class:`pygame.Rect`, tuple
"""
assert isinstance(real, (pygame.Rect, tuple, list))
offsets = self.get_offsets()
Expand Down
14 changes: 14 additions & 0 deletions pygame_menu/widgets/core/selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
-------------------------------------------------------------------------------
"""

import pygame
from pygame_menu.utils import assert_color


Expand Down Expand Up @@ -88,6 +89,19 @@ def get_width(self):
_, l, _, r = self.get_margin()
return l + r

def inflate(self, rect):
"""
Grow or shrink the rectangle size according to margins.
:param rect: rectangle
:type rect: :py:class:`pygame.Rect`
"""
assert isinstance(rect, pygame.Rect)
return pygame.Rect(rect.x - self.margin_left,
rect.y - self.margin_top,
rect.width + self.margin_left + self.margin_right,
rect.height + self.margin_top + self.margin_bottom)

def get_height(self):
"""
Return height as sum of top and bottom margins.
Expand Down
48 changes: 0 additions & 48 deletions pygame_menu/widgets/core/widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -525,54 +525,6 @@ def set_position(self, posx, posy):
self._rect.x = posx
self._rect.y = posy

def get_relative_position(self):
"""
Return a tuple containing the top left and bottom right positions in
the format of (x leftmost, y uppermost, x rightmost, y lowermost).
:return: Tuple of 4 elements, *(x leftmost, y uppermost, x rightmost, y lowermost)*
:rtype: tuple
"""
return self._rect.x, self._rect.y, self._rect.x + self._rect.width, self._rect.y + self._rect.height

def get_absolute_position(self, scroll_area):
"""
Return the absolute position in the scroll area considering the widget is in the given scroll.
The position will not exceed the height of the scroll area.
:param scroll_area: Sroll parent of the widget
:type scroll_area: :py:class:`pygame_menu.scrollarea.ScrollArea`
:return: Tuple of 4 elements, *(x leftmost, y uppermost, x rightmost, y lowermost)*
:rtype: tuple
"""
# This method performs the calculation of the following coordinates:
#
# (x1,y1) ----------.
# | |
# .------------(x2,y2)
#
# This coordinates are added to the position of the scroll area (x0,y0)

# Add selected margin
t, l, b, r = 0, 0, 0, 0 # top, left, bottom, right
if self.selected and self._selection_effect is not None:
t, l, b, r = self._selection_effect.get_margin()

offx, offy = scroll_area.get_offsets()
w, h = scroll_area.get_area_size()

# Add scrollbar if enabled
w -= scroll_area.get_scrollbar_thickness(_locals.ORIENTATION_VERTICAL)
h -= scroll_area.get_scrollbar_thickness(_locals.ORIENTATION_HORIZONTAL)

x0, y0 = scroll_area.get_position()
x1 = min(max(self._rect.x - l - offx, 0), w) + x0
x2 = min(max(self._rect.x + r + self._rect.width - offx, 0), w) + x0
y1 = min(max(self._rect.y - t - offy, 0), h) + y0
y2 = min(max(self._rect.y + b + self._rect.height - offy, 0), h) + y0

return x1, y1, x2, y2

def set_alignment(self, align):
"""
Set the alignment of the widget.
Expand Down
4 changes: 1 addition & 3 deletions pygame_menu/widgets/selection/highlight.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,10 @@ def __init__(self,
margin_top=margin_y / 2 + border_width,
margin_bottom=margin_y / 2 + border_width)
self._border_width = border_width
self._margin_x = margin_x
self._margin_y = margin_y

# noinspection PyMissingOrEmptyDocstring
def draw(self, surface, widget):
pygame.draw.rect(surface,
self.color,
widget.get_rect().inflate(self._margin_x, self._margin_y),
self.inflate(widget.get_rect()),
self._border_width)

0 comments on commit 32535b3

Please sign in to comment.