Skip to content

Commit

Permalink
Dynamic sizing fixes part 1
Browse files Browse the repository at this point in the history
  • Loading branch information
MyreMylar committed Apr 16, 2023
1 parent f4126fd commit 2fa1be3
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 72 deletions.
5 changes: 4 additions & 1 deletion pygame_gui/core/interfaces/element_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,17 @@ def set_position(self, position: Union[pygame.math.Vector2,
@abstractmethod
def set_dimensions(self, dimensions: Union[pygame.math.Vector2,
Tuple[int, int],
Tuple[float, float]]):
Tuple[float, float]],
clamp_to_container: bool = False):
"""
Method to directly set the dimensions of an element.
NOTE: Using this on elements inside containers with non-default anchoring arrangements
may make a mess of them.
:param dimensions: The new dimensions to set.
:param clamp_to_container: Whether we should clamp the dimensions to the
dimensions of the container or not.
"""

Expand Down
6 changes: 5 additions & 1 deletion pygame_gui/core/ui_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,12 +198,16 @@ def set_relative_position(self, position: Union[pygame.math.Vector2,

def set_dimensions(self, dimensions: Union[pygame.math.Vector2,
Tuple[int, int],
Tuple[float, float]]):
Tuple[float, float]],
clamp_to_container: bool = False
):
"""
Set the dimension of this container and update the positions of elements within it
accordingly.
:param dimensions: the new dimensions.
:param clamp_to_container: Whether we should clamp the dimensions to the
dimensions of the container or not.
"""
super().set_dimensions(dimensions)
Expand Down
29 changes: 14 additions & 15 deletions pygame_gui/elements/ui_button.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,6 @@ def __init__(self, relative_rect: Union[pygame.Rect, Tuple[float, float], pygame
if text_kwargs is not None:
self.text_kwargs = text_kwargs

self.dynamic_width = False
self.dynamic_height = False
self.dynamic_dimensions_orig_top_left = rel_rect.topleft
# support for an optional 'tool tip' element attached to this button
self.tool_tip_text = tool_tip_text
Expand Down Expand Up @@ -502,7 +500,7 @@ def set_text(self, text: str, *, text_kwargs: Optional[Dict[str, str]] = None):
any_changed = True

if any_changed:
if self.dynamic_width:
if self.dynamic_width or self.dynamic_height:
self.rebuild()
else:
self.drawable_shape.set_text(translate(self.text, **self.text_kwargs))
Expand Down Expand Up @@ -708,11 +706,6 @@ def rebuild(self):
A complete rebuild of the drawable shape used by this button.
"""
self.rect.width = -1 if self.dynamic_width else self.rect.width
self.relative_rect.width = -1 if self.dynamic_width else self.relative_rect.width

self.rect.height = -1 if self.dynamic_height else self.rect.height
self.relative_rect.height = -1 if self.dynamic_height else self.relative_rect.height

theming_parameters = {'normal_bg': self.colours['normal_bg'],
'normal_text': self.colours['normal_text'],
Expand Down Expand Up @@ -756,25 +749,31 @@ def rebuild(self):
'shape_corner_radius': self.shape_corner_radius,
'transitions': self.state_transitions}

drawable_shape_rect = self.rect.copy()
if self.dynamic_width:
drawable_shape_rect.width = -1
if self.dynamic_height:
drawable_shape_rect.height = -1

if self.shape == 'rectangle':
self.drawable_shape = RectDrawableShape(self.rect, theming_parameters,
self.drawable_shape = RectDrawableShape(drawable_shape_rect, theming_parameters,
['normal', 'hovered', 'disabled',
'selected', 'active'], self.ui_manager)
elif self.shape == 'ellipse':
self.drawable_shape = EllipseDrawableShape(self.rect, theming_parameters,
self.drawable_shape = EllipseDrawableShape(drawable_shape_rect, theming_parameters,
['normal', 'hovered', 'disabled',
'selected', 'active'], self.ui_manager)
elif self.shape == 'rounded_rectangle':
self.drawable_shape = RoundedRectangleShape(self.rect, theming_parameters,
self.drawable_shape = RoundedRectangleShape(drawable_shape_rect, theming_parameters,
['normal', 'hovered', 'disabled',
'selected', 'active'], self.ui_manager)

self.on_fresh_drawable_shape_ready()

if self.relative_rect.width == -1 or self.relative_rect.height == -1:
self.dynamic_width = self.relative_rect.width == -1
self.dynamic_height = self.relative_rect.height == -1
self._on_contents_changed()

def _calc_dynamic_size(self):
if self.dynamic_width or self.dynamic_height:
self.set_dimensions(self.image.get_size())

# if we have anchored the left side of our button to the right of it's container then
Expand Down Expand Up @@ -806,7 +805,7 @@ def on_locale_changed(self):
self.font = font
self.rebuild()
else:
if self.dynamic_width:
if self.dynamic_width or self.dynamic_height:
self.rebuild()
else:
self.drawable_shape.set_text(translate(self.text, **self.text_kwargs))
32 changes: 14 additions & 18 deletions pygame_gui/elements/ui_label.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,6 @@ def __init__(self, relative_rect: pygame.Rect,
object_id=object_id,
element_id='label')

self.dynamic_width = False
self.dynamic_height = False
self.dynamic_dimensions_orig_top_left = relative_rect.topleft

self.text = text
Expand Down Expand Up @@ -97,7 +95,6 @@ def set_text(self, text: str, *, text_kwargs: Optional[Dict[str, str]] = None):
:param text_kwargs: a dictionary of variable arguments to pass to the translated string
useful when you have multiple translations that need variables inserted
in the middle.
"""
any_changed = False
if text != self.text:
Expand All @@ -112,7 +109,7 @@ def set_text(self, text: str, *, text_kwargs: Optional[Dict[str, str]] = None):
any_changed = True

if any_changed:
if self.dynamic_width:
if self.dynamic_width or self.dynamic_height:
self.rebuild()
else:
self.drawable_shape.set_text(translate(self.text, **self.text_kwargs))
Expand All @@ -123,15 +120,9 @@ def rebuild(self):
the displayed text is or remake it with different theming (if the theming has changed).
"""

self.rect.width = -1 if self.dynamic_width else self.rect.width
self.relative_rect.width = -1 if self.dynamic_width else self.relative_rect.width

self.rect.height = -1 if self.dynamic_height else self.rect.height
self.relative_rect.height = -1 if self.dynamic_height else self.relative_rect.height

text_size = self.font.get_rect(translate(self.text, **self.text_kwargs)).size
if ((self.rect.height != -1 and text_size[1] > self.relative_rect.height) or
(self.rect.width != -1 and text_size[0] > self.relative_rect.width)):
if (not (self.dynamic_height or self.dynamic_width) and
((text_size[1] > self.relative_rect.height) or (text_size[0] > self.relative_rect.width))):
width_overlap = self.relative_rect.width - text_size[0]
height_overlap = self.relative_rect.height - text_size[1]
warn_text = ('Label Rect is too small for text: '
Expand Down Expand Up @@ -161,17 +152,22 @@ def rebuild(self):
'text_horiz_alignment_padding': self.text_horiz_alignment_padding,
'text_vert_alignment_padding': self.text_vert_alignment_padding}

self.drawable_shape = RectDrawableShape(self.rect, theming_parameters,
drawable_shape_rect = self.rect.copy()
if self.dynamic_width:
drawable_shape_rect.width = -1
if self.dynamic_height:
drawable_shape_rect.height = -1
self.drawable_shape = RectDrawableShape(drawable_shape_rect, theming_parameters,
['normal', 'disabled'], self.ui_manager)
self.on_fresh_drawable_shape_ready()

if self.relative_rect.width == -1 or self.relative_rect.height == -1:
self.dynamic_width = self.relative_rect.width == -1
self.dynamic_height = self.relative_rect.height == -1
self._on_contents_changed()

def _calc_dynamic_size(self):
if self.dynamic_width or self.dynamic_height:
self.set_dimensions(self.image.get_size())

# if we have anchored the left side of our button to the right of it's container then
# if we have anchored the left side of our button to the right of its container then
# changing the width is going to mess up the horiz position as well.
new_left = self.relative_rect.left
new_top = self.relative_rect.top
Expand Down Expand Up @@ -290,7 +286,7 @@ def on_locale_changed(self):
self.font = font
self.rebuild()
else:
if self.dynamic_width:
if self.dynamic_width or self.dynamic_height:
self.rebuild()
else:
self.drawable_shape.set_text(translate(self.text, **self.text_kwargs))
Expand Down
13 changes: 6 additions & 7 deletions pygame_gui/elements/ui_text_box.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def __init__(self,
allow_split_dashes: bool = True,
plain_text_display_only: bool = False,
should_html_unescape_input_text: bool = False):

relative_rect.height = -1 if wrap_to_height else relative_rect.height
super().__init__(relative_rect, manager, container,
starting_height=starting_height,
layer_thickness=2,
Expand All @@ -125,7 +125,6 @@ def __init__(self,

self._pre_parsing_enabled = pre_parsing_enabled

self.wrap_to_height = wrap_to_height
self.link_hover_chunks = [] # container for any link chunks we have

self.active_text_effect = None # type: Optional[TextEffect]
Expand Down Expand Up @@ -213,17 +212,17 @@ def rebuild(self):
(self.border_width * 2) -
(self.shadow_width * 2) -
(2 * self.rounded_corner_offset))))
if self.wrap_to_height or self.rect[3] == -1:
if self.dynamic_height:
self.text_wrap_rect.height = -1
if self.rect[2] == -1:
if self.dynamic_width:
self.text_wrap_rect.width = -1

drawable_area_size = (self.text_wrap_rect[2], self.text_wrap_rect[3])

# This gives us the height of the text at the 'width' of the text_wrap_area
self.parse_html_into_style_data()
if self.text_box_layout is not None:
if self.wrap_to_height or self.rect[3] == -1 or self.rect[2] == -1:
if self.dynamic_height or self.dynamic_width:
final_text_area_size = self.text_box_layout.layout_rect.size
new_dimensions = ((final_text_area_size[0] + (self.padding[0] * 2) +
(self.border_width * 2) + (self.shadow_width * 2) +
Expand Down Expand Up @@ -573,7 +572,7 @@ def parse_html_into_style_data(self):
default_font_data=default_font_data,
allow_split_dashes=self.allow_split_dashes)
self.parser.empty_layout_queue()
if self.text_wrap_rect[3] == -1:
if not self.dynamic_height:
self.text_box_layout.view_rect.height = self.text_box_layout.layout_rect.height

self._align_all_text_rows()
Expand All @@ -587,7 +586,7 @@ def redraw_from_text_block(self):
"""
if self.rect.width <= 0 or self.rect.height <= 0:
return
if (self.scroll_bar is None and (self.text_wrap_rect[3] != -1) and
if (self.scroll_bar is None and not self.dynamic_height and
(self.text_box_layout.layout_rect.height > self.text_wrap_rect[3])):
self.rebuild()
else:
Expand Down
34 changes: 4 additions & 30 deletions pygame_gui/elements/ui_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,16 @@ def __init__(self,
self._window_root_container = None # type: Optional[UIContainer]
self.resizable = resizable
self.draggable = draggable
self.minimum_dimensions = (100, 100)

self.edge_hovering = [False, False, False, False]

super().__init__(rect, manager, container=None,
starting_height=1,
layer_thickness=1,
visible=visible)

self.minimum_dimensions = (100, 100)

if element_id is None:
element_id = 'window'

Expand Down Expand Up @@ -103,26 +105,6 @@ def set_blocking(self, state: bool):
"""
self.is_blocking = state

def set_minimum_dimensions(self, dimensions: Union[pygame.math.Vector2,
Tuple[int, int],
Tuple[float, float]]):
"""
If this window is resizable, then the dimensions we set here will be the minimum that
users can change the window to. They are also used as the minimum size when
'set_dimensions' is called.
:param dimensions: The new minimum dimension for the window.
"""
self.minimum_dimensions = (min(self.ui_container.rect.width, int(dimensions[0])),
min(self.ui_container.rect.height, int(dimensions[1])))

if ((self.rect.width < self.minimum_dimensions[0]) or
(self.rect.height < self.minimum_dimensions[1])):
new_width = max(self.minimum_dimensions[0], self.rect.width)
new_height = max(self.minimum_dimensions[1], self.rect.height)
self.set_dimensions((new_width, new_height))

def set_dimensions(self, dimensions: Union[pygame.math.Vector2,
Tuple[int, int],
Tuple[float, float]]):
Expand All @@ -133,17 +115,9 @@ def set_dimensions(self, dimensions: Union[pygame.math.Vector2,
:param dimensions: The new dimensions to set.
"""
# clamp to minimum dimensions and container size
dimensions = (min(self.ui_container.rect.width,
max(self.minimum_dimensions[0],
int(dimensions[0]))),
min(self.ui_container.rect.height,
max(self.minimum_dimensions[1],
int(dimensions[1]))))

# Don't use a basic gate on this set dimensions method because the container may be a
# different size to the window
super().set_dimensions(dimensions)
super().set_dimensions(dimensions, clamp_to_container=True)

if self._window_root_container is not None:
new_container_dimensions = (self.relative_rect.width - (2 * self.shadow_width),
Expand Down

0 comments on commit 2fa1be3

Please sign in to comment.