Repository: MyreMylar/pygame_gui
Pull request #652 (2024-11-03 18:14:25)

Minor fixes to sliders & scrollbars to make it easier to have custom image arrow buttons
As title


Patch:
diff --git a/pygame_gui/core/drawable_shapes/drawable_shape.py b/pygame_gui/core/drawable_shapes/drawable_shape.py
index 8ec5c7f..affaa06 100644
--- a/pygame_gui/core/drawable_shapes/drawable_shape.py
+++ b/pygame_gui/core/drawable_shapes/drawable_shape.py
@@ -494,7 +494,7 @@ class DrawableShape:
         containing_rect_when_text_built = self.containing_rect.copy()
         # Draw any text
         if 'text' in self.theming and 'font' in self.theming and self.theming['text'] is not None:
-            # we need two rectangles for the text. One is has actual area the
+            # we need two rectangles for the text. One has actual area the
             # text surface takes up, which may be larger than the displayed area,
             # and its position on the final surface. The other is the amount of
             # area of the text surface which we blit from, which may be much smaller
diff --git a/pygame_gui/core/ui_appearance_theme.py b/pygame_gui/core/ui_appearance_theme.py
index 2fe3d84..700e0bb 100644
--- a/pygame_gui/core/ui_appearance_theme.py
+++ b/pygame_gui/core/ui_appearance_theme.py
@@ -103,7 +103,7 @@ class UIAppearanceTheme(IUIAppearanceThemeInterface):
             self.need_to_rebuild_data_manually_changed = False
             return True
         return False
-
+    
     @staticmethod
     def _json_to_dict(json_data):
         if isinstance(json_data, dict):
@@ -574,19 +574,16 @@ class UIAppearanceTheme(IUIAppearanceThemeInterface):
 
         :return IGUIFontInterface: An interface to a pygame font object wrapper.
         """
-        font = None
-        
+        # set the default font as the final fall back
+        font = self.font_dict.get_default_font()
+
         for combined_element_id in combined_element_ids:
             if combined_element_id in self.ele_font_res:
                 if self._locale in self.ele_font_res[combined_element_id]:
-                    font = self.ele_font_res[combined_element_id][self._locale].loaded_font
+                    return self.ele_font_res[combined_element_id][self._locale].loaded_font
                 else:
-                    font = self.ele_font_res[combined_element_id]['en'].loaded_font
-                break
+                    return self.ele_font_res[combined_element_id]['en'].loaded_font
 
-        # set the default font as the final fall back
-        if font is None:
-            font = self.font_dict.get_default_font()
         return font
 
     def get_misc_data(self, misc_data_id: str, combined_element_ids: List[str]) -> Union[str, Dict]:
@@ -770,7 +767,7 @@ class UIAppearanceTheme(IUIAppearanceThemeInterface):
                     self._load_element_font_data_from_theme(file_dict,
                                                             element_name)
 
-            if data_type == 'colours' or data_type == 'colors':
+            if data_type == 'colours':
                 self._load_element_colour_data_from_theme(data_type,
                                                           element_name,
                                                           element_theming)
@@ -1048,7 +1045,7 @@ class UIAppearanceTheme(IUIAppearanceThemeInterface):
         :param theme_dict: The data dictionary from the theming file to load data from.
         """
         for data_type in theme_dict['defaults']:
-            if data_type == 'colours' or data_type == 'colors':
+            if data_type == 'colours':
                 colours_dict = theme_dict['defaults'][data_type]
                 for colour_key in colours_dict:
                     colour = self._load_colour_or_gradient_from_theme(colours_dict,
diff --git a/pygame_gui/data/default_theme.json b/pygame_gui/data/default_theme.json
index d0bd651..25e6e69 100644
--- a/pygame_gui/data/default_theme.json
+++ b/pygame_gui/data/default_theme.json
@@ -101,15 +101,18 @@
     {
         "prototype": "#no_frills_button"
     },
+    "horizontal_slider.@arrow_button":
+    {
+        "font": {
+            "name": "fira_code_symbols",
+            "size": "14"
+        }
+    },
     "horizontal_slider.#left_button":
     {
         "misc":
         {
             "text_horiz_alignment_method": "left_triangle"
-        },
-        "font": {
-            "name": "fira_code_symbols",
-            "size": "14"
         }
     },
     "horizontal_slider.#right_button":
@@ -117,10 +120,6 @@
         "misc":
         {
             "text_horiz_alignment_method": "right_triangle"
-        },
-        "font": {
-            "name": "fira_code_symbols",
-            "size": "14"
         }
     },
     "horizontal_slider.#sliding_button":
diff --git a/pygame_gui/elements/ui_horizontal_scroll_bar.py b/pygame_gui/elements/ui_horizontal_scroll_bar.py
index 3e55855..35ef557 100644
--- a/pygame_gui/elements/ui_horizontal_scroll_bar.py
+++ b/pygame_gui/elements/ui_horizontal_scroll_bar.py
@@ -81,6 +81,8 @@ class UIHorizontalScrollBar(UIElement):
 
         self.drawable_shape = None
         self.shape = 'rectangle'
+        self.left_arrow_text = '◀'
+        self.right_arrow_text = '▶'
 
         self.background_rect = None  # type: Union[None, pygame.Rect]
 
@@ -179,7 +181,7 @@ class UIHorizontalScrollBar(UIElement):
                 self.left_button = UIButton(pygame.Rect((0, 0),
                                                         (self.arrow_button_width,
                                                          self.background_rect.height)),
-                                            '◀', self.ui_manager,
+                                            self.left_arrow_text, self.ui_manager,
                                             container=self.button_container,
                                             starting_height=1,
                                             parent_element=self,
@@ -195,7 +197,7 @@ class UIHorizontalScrollBar(UIElement):
                 self.right_button = UIButton(pygame.Rect((-self.arrow_button_width, 0),
                                                          (self.arrow_button_width,
                                                           self.background_rect.height)),
-                                             '▶', self.ui_manager,
+                                             self.right_arrow_text, self.ui_manager,
                                              container=self.button_container,
                                              starting_height=1,
                                              parent_element=self,
diff --git a/pygame_gui/elements/ui_horizontal_slider.py b/pygame_gui/elements/ui_horizontal_slider.py
index 179c13f..9487741 100644
--- a/pygame_gui/elements/ui_horizontal_slider.py
+++ b/pygame_gui/elements/ui_horizontal_slider.py
@@ -65,6 +65,9 @@ class UIHorizontalSlider(UIElement):
         self.left_limit_position = 0.0
         self.starting_grab_x_difference = 0
 
+        self.left_arrow_text = '◀'
+        self.right_arrow_text = '▶'
+
         if (isinstance(start_value, int) and
                 isinstance(value_range[0], int) and
                 isinstance(value_range[1], int)):
@@ -181,7 +184,7 @@ class UIHorizontalSlider(UIElement):
                 self.left_button = UIButton(pygame.Rect((0, 0),
                                                         (self.arrow_button_width,
                                                          self.background_rect.height)),
-                                            '◀', self.ui_manager,
+                                            self.left_arrow_text, self.ui_manager,
                                             container=self.button_container,
                                             starting_height=1,
                                             parent_element=self,
@@ -197,7 +200,7 @@ class UIHorizontalSlider(UIElement):
                 self.right_button = UIButton(pygame.Rect((-self.arrow_button_width, 0),
                                                          (self.arrow_button_width,
                                                           self.background_rect.height)),
-                                             '▶', self.ui_manager,
+                                             self.right_arrow_text, self.ui_manager,
                                              container=self.button_container,
                                              starting_height=1,
                                              parent_element=self,
diff --git a/pygame_gui/elements/ui_image.py b/pygame_gui/elements/ui_image.py
index 22abbf4..232893e 100644
--- a/pygame_gui/elements/ui_image.py
+++ b/pygame_gui/elements/ui_image.py
@@ -37,8 +37,7 @@ class UIImage(UIElement):
                  anchors: Optional[Dict[str, Union[str, UIElement]]] = None,
                  visible: int = 1,
                  *,
-                 starting_height: int = 1,
-                 scale_func=pygame.transform.smoothscale):
+                 starting_height: int = 1,):
 
         super().__init__(relative_rect, manager, container,
                          starting_height=starting_height,
@@ -51,7 +50,7 @@ class UIImage(UIElement):
 
         self.original_image = None
 
-        self.set_image(image_surface, image_is_alpha_premultiplied, scale_func)
+        self.set_image(image_surface, image_is_alpha_premultiplied)
         self.rebuild_from_changed_theme_data()
 
     def rebuild_from_changed_theme_data(self):
@@ -80,8 +79,7 @@ class UIImage(UIElement):
 
     def set_image(self,
                   new_image: Union[pygame.surface.Surface, None],
-                  image_is_alpha_premultiplied: bool = False,
-                  scale_func = pygame.transform.smoothscale) -> None:
+                  image_is_alpha_premultiplied: bool = False) -> None:
         """
         Allows users to change the image displayed on a UIImage element during run time, without recreating
         the element.
@@ -99,6 +97,6 @@ class UIImage(UIElement):
         if (image_surface.get_width() != self.rect.width or
                 image_surface.get_height() != self.rect.height):
             self.original_image = image_surface
-            self._set_image(scale_func(self.original_image, self.rect.size))
+            self._set_image(pygame.transform.smoothscale(self.original_image, self.rect.size))
         else:
             self._set_image(image_surface)
diff --git a/pygame_gui/elements/ui_vertical_scroll_bar.py b/pygame_gui/elements/ui_vertical_scroll_bar.py
index bf5d26b..8289fef 100644
--- a/pygame_gui/elements/ui_vertical_scroll_bar.py
+++ b/pygame_gui/elements/ui_vertical_scroll_bar.py
@@ -91,6 +91,8 @@ class UIVerticalScrollBar(UIElement):
         self.bottom_button = None
         self.sliding_button = None
         self.enable_arrow_buttons = True
+        self.top_arrow_text = '▲'
+        self.bottom_arrow_text = '▼'
 
         self.rebuild_from_changed_theme_data()
 
@@ -175,7 +177,7 @@ class UIVerticalScrollBar(UIElement):
                 self.top_button = UIButton(pygame.Rect((0, 0),
                                                        (self.background_rect.width,
                                                         self.arrow_button_height)),
-                                           '▲', self.ui_manager,
+                                           self.top_arrow_text, self.ui_manager,
                                            container=self.button_container,
                                            starting_height=1,
                                            parent_element=self,
@@ -191,7 +193,7 @@ class UIVerticalScrollBar(UIElement):
                 self.bottom_button = UIButton(pygame.Rect((0, -self.arrow_button_height),
                                                           (self.background_rect.width,
                                                            self.arrow_button_height)),
-                                              '▼', self.ui_manager,
+                                              self.bottom_arrow_text, self.ui_manager,
                                               container=self.button_container,
                                               starting_height=1,
                                               parent_element=self,


Test patch:
diff --git a/tests/test_core/test_ui_appearance_theme.py b/tests/test_core/test_ui_appearance_theme.py
index 3920cbe..2d2c206 100644
--- a/tests/test_core/test_ui_appearance_theme.py
+++ b/tests/test_core/test_ui_appearance_theme.py
@@ -192,11 +192,8 @@ class TestUIAppearanceTheme:
         assert shadow_width == '0'
 
     def test_get_font(self, _init_pygame, _display_surface_return_none: None):
-        resource_loader = BlockingThreadedResourceLoader()
-        theme = UIAppearanceTheme(resource_loader, locale='nonsense_locale')
+        theme = UIAppearanceTheme(BlockingThreadedResourceLoader(), locale='nonsense_locale')
         theme.load_theme(os.path.join("tests", "data", "themes", "ui_button_non_default.json"))
-        resource_loader.start()
-        resource_loader.update()
         assert theme.get_font_info(['button']) == theme.ui_element_fonts_info['button']['en']
         assert theme.get_font(['button']) == theme.ele_font_res['button']['en'].loaded_font
 
diff --git a/tests/test_windows/test_ui_file_dialog.py b/tests/test_windows/test_ui_file_dialog.py
index abdbe9c..8f87048 100644
--- a/tests/test_windows/test_ui_file_dialog.py
+++ b/tests/test_windows/test_ui_file_dialog.py
@@ -1,3 +1,4 @@
+import platform
 from pathlib import Path
 
 import pygame
@@ -396,12 +397,13 @@ class TestUIUIFileDialog:
 
         assert Path(file_dialog.current_directory_path).name == 'images'
 
-        file_dialog.file_path_text_line.set_text('/')
+        if platform.system().upper() == 'WINDOWS':
+            file_dialog.file_path_text_line.set_text('/')
 
-        file_dialog.process_event(pygame.event.Event(UI_TEXT_ENTRY_FINISHED,
-                                                     {'ui_element': file_dialog.file_path_text_line}))
+            file_dialog.process_event(pygame.event.Event(UI_TEXT_ENTRY_FINISHED,
+                                                         {'ui_element': file_dialog.file_path_text_line}))
 
-        assert Path(file_dialog.current_directory_path).name == ''
+            assert Path(file_dialog.current_directory_path).name == ''
 
     def test_show(self, _init_pygame, default_ui_manager, _display_surface_return_none):
         file_dialog = UIFileDialog(rect=pygame.Rect(100, 100, 440, 500),