Skip to content

Commit

Permalink
improve handling of disabling/hiding for container elements
Browse files Browse the repository at this point in the history
  • Loading branch information
MyreMylar committed Apr 17, 2023
1 parent 2ecf673 commit 463d8c5
Show file tree
Hide file tree
Showing 20 changed files with 177 additions and 74 deletions.
9 changes: 6 additions & 3 deletions pygame_gui/core/drawable_shapes/drawable_shape.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,14 +344,14 @@ def full_rebuild_on_size_change(self):
self.should_trigger_full_rebuild = False
self.full_rebuild_countdown = self.time_until_full_rebuild_after_changing_size

def redraw_all_states(self):
def redraw_all_states(self, force_full_redraw: bool = False):
"""
Starts the redrawing process for all states of this shape that auto pre-generate.
Redrawing is done one state at a time so will take a few loops of the game to
complete if this shape has many states.
"""
self.states_to_redraw_queue = deque([state_id for state_id, state in self.states.items()
if state.should_auto_pregen])
if (state.should_auto_pregen or force_full_redraw)])
initial_state = self.states_to_redraw_queue.popleft()
self.redraw_state(initial_state)

Expand Down Expand Up @@ -595,7 +595,10 @@ def set_text(self, text: str):
"""
self.theming['text'] = text
self.build_text_layout()
self.redraw_all_states()
if 'disabled' in self.states and self.active_state == self.states['disabled']:
self.redraw_all_states(force_full_redraw=True)
else:
self.redraw_all_states()

def set_text_alpha(self, alpha: int):
"""
Expand Down
5 changes: 4 additions & 1 deletion pygame_gui/core/drawable_shapes/ellipse_drawable_shape.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,10 @@ def full_rebuild_on_size_change(self):
self.border_width + self.shadow_width),
(self.click_area_shape.width - (2 * self.border_width),
self.click_area_shape.height - (2 * self.border_width)))
self.redraw_all_states()
if 'disabled' in self.states and self.active_state == self.states['disabled']:
self.redraw_all_states(force_full_redraw=True)
else:
self.redraw_all_states()

def collide_point(self, point: Union[pygame.math.Vector2,
Tuple[int, int],
Expand Down
5 changes: 4 additions & 1 deletion pygame_gui/core/drawable_shapes/rect_drawable_shape.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,10 @@ def full_rebuild_on_size_change(self):
self.border_width + self.shadow_width),
(self.click_area_shape.width - (2 * self.border_width),
self.click_area_shape.height - (2 * self.border_width)))
self.redraw_all_states()
if 'disabled' in self.states and self.active_state == self.states['disabled']:
self.redraw_all_states(force_full_redraw=True)
else:
self.redraw_all_states()

def collide_point(self, point: Union[pygame.math.Vector2,
Tuple[int, int],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,10 @@ def full_rebuild_on_size_change(self):
self.border_width + self.shadow_width),
(self.click_area_shape.width - (2 * self.border_width),
self.click_area_shape.height - (2 * self.border_width)))
self.redraw_all_states()
if 'disabled' in self.states and self.active_state == self.states['disabled']:
self.redraw_all_states(force_full_redraw=True)
else:
self.redraw_all_states()

def collide_point(self, point: Union[pygame.math.Vector2,
Tuple[int, int],
Expand Down
5 changes: 5 additions & 0 deletions pygame_gui/core/ui_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ def add_element(self, element: IUIElementInterface):
element.change_layer(self._layer + element.get_starting_height())
self.elements.append(element)
self.calc_add_element_changes_thickness(element)
if not self.is_enabled:
element.disable()
if not self.visible:
if hasattr(element, 'hide'):
element.hide()

This comment has been minimized.

Copy link
@robclewley

robclewley Apr 20, 2023

Contributor

sadly, this change breaks some things elsewhere. For instance (I haven't checked exhaustively what else this might affect) UI Panel can't be created now b/c this hide occurs during the super().__init__ of UIPanel on L57. That calls ui_panel.hide which calls self.panel_container.hide(), but the panel container hasn't been created yet (L95). I haven't tested to see if it's safe to move up that definition to be before the super but there might need to be a deferred call to hide if it needs to wait for sub-elements to be created.

This comment has been minimized.

Copy link
@robclewley

robclewley Apr 20, 2023

Contributor

@MyreMylar no idea if you'd get a notification on a commit to a closed PR so mentioning you here just in case you didn't


def remove_element(self, element: IUIElementInterface):
"""
Expand Down
2 changes: 2 additions & 0 deletions pygame_gui/core/ui_element.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ def __init__(self, relative_rect: Union[pygame.Rect, Tuple[int, int, int, int]],
self.border_width = None # type: Union[None, int]
self.shape_corner_radius = None # type: Union[None, int]

self.tool_tip = None

self._setup_container(container)

self.dirty = 1
Expand Down
14 changes: 10 additions & 4 deletions pygame_gui/elements/ui_button.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ def __init__(self, relative_rect: Union[pygame.Rect, Tuple[float, float], pygame
self.tool_tip_text_kwargs = {}
if tool_tip_text_kwargs is not None:
self.tool_tip_text_kwargs = tool_tip_text_kwargs
self.tool_tip = None
self.tool_tip_object_id = tool_tip_object_id
self.ui_root_container = self.ui_manager.get_root_container()

Expand Down Expand Up @@ -282,7 +281,8 @@ def on_unhovered(self):
Called when we leave the hover state. Resets the colours and images to normal and kills any
tooltip that was created while we were hovering the button.
"""
self.drawable_shape.set_active_state(self._get_appropriate_state_name())
if self.drawable_shape is not None:
self.drawable_shape.set_active_state(self._get_appropriate_state_name())
if self.tool_tip is not None:
self.tool_tip.kill()
self.tool_tip = None
Expand Down Expand Up @@ -430,7 +430,8 @@ def disable(self):
"""
if self.is_enabled:
self.is_enabled = False
self.drawable_shape.set_active_state('disabled')
if self.drawable_shape is not None:
self.drawable_shape.set_active_state('disabled')

# clear other button state
self.held = False
Expand All @@ -444,7 +445,8 @@ def enable(self):
"""
if not self.is_enabled:
self.is_enabled = True
self.drawable_shape.set_active_state('normal')
if self.drawable_shape is not None:
self.drawable_shape.set_active_state('normal')

def _set_active(self):
"""
Expand Down Expand Up @@ -768,6 +770,10 @@ def rebuild(self):
['normal', 'hovered', 'disabled',
'selected', 'active'], self.ui_manager)

if not self.is_enabled:
if self.drawable_shape is not None:
self.drawable_shape.set_active_state('disabled')

self.on_fresh_drawable_shape_ready()

self._on_contents_changed()
Expand Down
33 changes: 21 additions & 12 deletions pygame_gui/elements/ui_drop_down_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,19 +418,23 @@ def disable(self):
"""
Disables the closed state so that it is no longer interactive.
"""
self.selected_option_button.disable()
if self.selected_option_button is not None:
self.selected_option_button.disable()
if self.open_button is not None:
self.open_button.disable()
self.drop_down_menu_ui.drawable_shape.set_active_state('disabled')
if self.drop_down_menu_ui.drawable_shape is not None:
self.drop_down_menu_ui.drawable_shape.set_active_state('disabled')

def enable(self):
"""
Re-enables the closed state so we can once again interact with it.
"""
self.selected_option_button.enable()
if self.selected_option_button is not None:
self.selected_option_button.enable()
if self.open_button is not None:
self.open_button.enable()
self.drop_down_menu_ui.drawable_shape.set_active_state('normal')
if self.drop_down_menu_ui.drawable_shape is not None:
self.drop_down_menu_ui.drawable_shape.set_active_state('normal')

def rebuild(self):
"""
Expand Down Expand Up @@ -916,12 +920,15 @@ 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):
"""
Sets the dimensions of this drop down, updating all subordinate button
elements at the same time.
: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.
"""
super().set_dimensions(dimensions)
Expand All @@ -941,20 +948,22 @@ def disable(self):
if self.is_enabled:
self.is_enabled = False
# switch back to the closed state if we are in the expanded state
if self.current_state is self.menu_states['expanded']:
self.current_state.finish()
self.current_state = self.menu_states['closed']
self.current_state.selected_option = self.selected_option
self.current_state.start()
self.current_state.disable()
if self.current_state is not None:
if self.current_state is self.menu_states['expanded']:
self.current_state.finish()
self.current_state = self.menu_states['closed']
self.current_state.selected_option = self.selected_option
self.current_state.start()
self.current_state.disable()

def enable(self):
"""
Re-enables the button so we can once again interact with it.
"""
if not self.is_enabled:
self.is_enabled = True
self.current_state.enable()
if self.current_state is not None:
self.current_state.enable()

def show(self):
"""
Expand Down
25 changes: 18 additions & 7 deletions pygame_gui/elements/ui_horizontal_scroll_bar.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ def __init__(self,
anchors: Optional[Dict[str, Union[str, UIElement]]] = None,
visible: int = 1):

# Need to move some declarations early as they are indirectly referenced via the ui element
# constructor
self.button_container = None

super().__init__(relative_rect, manager, container,
layer_thickness=2,
starting_height=1,
Expand Down Expand Up @@ -509,11 +513,14 @@ 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):
"""
Method to directly set the dimensions of an element.
: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.
"""
super().set_dimensions(dimensions)
Expand Down Expand Up @@ -547,19 +554,23 @@ def disable(self):
"""
if self.is_enabled:
self.is_enabled = False
self.button_container.disable()
if self.button_container is not None:
self.button_container.disable()

self.drawable_shape.set_active_state('disabled')
if self.drawable_shape is not None:
self.drawable_shape.set_active_state('disabled')

def enable(self):
"""
Enables the scroll bar so it is interactive once again.
"""
if not self.is_enabled:
self.is_enabled = True
self.button_container.enable()
if self.button_container is not None:
self.button_container.enable()

self.drawable_shape.set_active_state('normal')
if self.drawable_shape is not None:
self.drawable_shape.set_active_state('normal')

def show(self):
"""
Expand All @@ -576,5 +587,5 @@ def hide(self):
will propagate and hide all the buttons.
"""
super().hide()

self.button_container.hide()
if self.button_container is not None:
self.button_container.hide()
22 changes: 16 additions & 6 deletions pygame_gui/elements/ui_horizontal_slider.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ def __init__(self,
click_increment: Union[float, int] = 1
):

self.sliding_button = None
self.button_container = None
super().__init__(relative_rect, manager, container,
layer_thickness=2,
starting_height=1,
Expand Down Expand Up @@ -491,11 +493,14 @@ 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):
"""
Method to directly set the dimensions of an element.
: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.
"""
super().set_dimensions(dimensions)
Expand Down Expand Up @@ -525,25 +530,29 @@ def disable(self):
"""
if self.is_enabled:
self.is_enabled = False
self.sliding_button.disable()
if self.sliding_button is not None:
self.sliding_button.disable()
if self.left_button:
self.left_button.disable()
if self.right_button:
self.right_button.disable()
self.drawable_shape.set_active_state('disabled')
if self.drawable_shape is not None:
self.drawable_shape.set_active_state('disabled')

def enable(self):
"""
Enable the slider. It should become interactive and will use the normal theme colours.
"""
if not self.is_enabled:
self.is_enabled = True
self.sliding_button.enable()
if self.sliding_button is not None:
self.sliding_button.enable()
if self.left_button:
self.left_button.enable()
if self.right_button:
self.right_button.enable()
self.drawable_shape.set_active_state('normal')
if self.drawable_shape is not None:
self.drawable_shape.set_active_state('normal')

def show(self):
"""
Expand All @@ -563,6 +572,7 @@ def hide(self):
"""
super().hide()

self.sliding_button.hide()
if self.sliding_button is not None:
self.sliding_button.hide()
if self.button_container is not None:
self.button_container.hide()
5 changes: 4 additions & 1 deletion pygame_gui/elements/ui_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,14 @@ def __init__(self,

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 dimensions of this image, scaling the image surface to match.
:param dimensions: The new dimensions of the image.
:param clamp_to_container: Whether we should clamp the dimensions to the
dimensions of the container or not.
"""
super().set_dimensions(dimensions)
Expand Down
6 changes: 4 additions & 2 deletions pygame_gui/elements/ui_label.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,15 +270,17 @@ def disable(self):
"""
if self.is_enabled:
self.is_enabled = False
self.drawable_shape.set_active_state('disabled')
if self.drawable_shape is not None:
self.drawable_shape.set_active_state('disabled')

def enable(self):
"""
Re-enables the label so that its text changes to the normal colour
"""
if not self.is_enabled:
self.is_enabled = True
self.drawable_shape.set_active_state('normal')
if self.drawable_shape is not None:
self.drawable_shape.set_active_state('normal')

def on_locale_changed(self):
font = self.ui_theme.get_font(self.combined_element_ids)
Expand Down
Loading

0 comments on commit 463d8c5

Please sign in to comment.