Repository: MyreMylar/pygame_gui
Pull request #476 (2023-10-11 17:36:31)

Remove support for Python 3.7 and add testing for 3.12
As title.


Patch:
diff --git a/README.md b/README.md
index 7c759e2..850f25a 100644
--- a/README.md
+++ b/README.md
@@ -8,10 +8,10 @@ A GUI system for pygame CE.
  - [Examples](https://github.com/MyreMylar/pygame_gui_examples)
  - [PyPi](https://pypi.org/project/pygame-gui/)
 
-[![pypi](https://badge.fury.io/py/pygame-gui.svg)](https://pypi.python.org/pypi/pygame-gui) [![Documentation Status](https://readthedocs.org/projects/pygame-gui/badge/?version=latest)](https://pygame-gui.readthedocs.io/en/latest/?badge=latest) [![Python 3.7+](https://img.shields.io/badge/python-3.7+-blue.svg)](https://www.python.org/downloads/release/python-360/) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Master](https://travis-ci.com/MyreMylar/pygame_gui.svg?branch=master)](https://travis-ci.com/MyreMylar/pygame_gui) [![codecov](https://codecov.io/gh/MyreMylar/pygame_gui/branch/main/graph/badge.svg?token=zZhkvhgTki)](https://codecov.io/gh/MyreMylar/pygame_gui) [![Downloads](https://pepy.tech/badge/pygame-gui)](https://pepy.tech/project/pygame-gui)
+[![pypi](https://badge.fury.io/py/pygame-gui.svg)](https://pypi.python.org/pypi/pygame-gui) [![Documentation Status](https://readthedocs.org/projects/pygame-gui/badge/?version=latest)](https://pygame-gui.readthedocs.io/en/latest/?badge=latest) [![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/release/python-380/) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Master](https://travis-ci.com/MyreMylar/pygame_gui.svg?branch=master)](https://travis-ci.com/MyreMylar/pygame_gui) [![codecov](https://codecov.io/gh/MyreMylar/pygame_gui/branch/main/graph/badge.svg?token=zZhkvhgTki)](https://codecov.io/gh/MyreMylar/pygame_gui) [![Downloads](https://pepy.tech/badge/pygame-gui)](https://pepy.tech/project/pygame-gui)
 ## Requirements
 
- - Python 3.7+
+ - Python 3.8+
  - Pygame Community Edition 2.1.4+
  - python-i18n (does localization to different languages)
 
diff --git a/pygame_gui/py.typed b/py.typed
similarity index 100%
rename from pygame_gui/py.typed
rename to py.typed
diff --git a/pygame_gui/core/colour_parser.py b/pygame_gui/core/colour_parser.py
index 8f707e4..3cfdf14 100644
--- a/pygame_gui/core/colour_parser.py
+++ b/pygame_gui/core/colour_parser.py
@@ -28,12 +28,8 @@ Developer Notes:
 """
 
 import pygame
-from typing import Callable, Union, Iterable, TypeVar, Optional, List, Tuple, Set, Dict
-# for Python 3.7 compatibility as TypedDict introduced in 3.8
-try:
-    from typing import TypedDict
-except ImportError:
-    from typing_extensions import TypedDict
+from typing import Callable, Union, Iterable, TypeVar, Optional, List, Tuple, Set, Dict, TypedDict
+
 import enum
 from pygame_gui.core.colour_gradient import ColourGradient
 from pygame_gui.core.utility import premul_col
diff --git a/pygame_gui/core/text/text_box_layout.py b/pygame_gui/core/text/text_box_layout.py
index 877bfa5..c13ed32 100644
--- a/pygame_gui/core/text/text_box_layout.py
+++ b/pygame_gui/core/text/text_box_layout.py
@@ -366,6 +366,8 @@ class TextBoxLayout:
         else:
             for row in self.layout_rows:
                 row.finalise(surface)
+                # pygame.draw.rect(surface, pygame.Color("blue"), row, 1)
+                # print("row height:", row.height)
 
         for floating_rect in self.floating_rects:
             floating_rect.finalise(surface, self.view_rect, 0, 0, 0)
diff --git a/pygame_gui/core/text/text_line_chunk.py b/pygame_gui/core/text/text_line_chunk.py
index 3de8f0c..b5a59a8 100644
--- a/pygame_gui/core/text/text_line_chunk.py
+++ b/pygame_gui/core/text/text_line_chunk.py
@@ -37,7 +37,8 @@ class TextLineChunkFTFont(TextLayoutRect):
                  max_dimensions: Optional[Tuple[int, int]] = None,
                  effect_id: Optional[str] = None):
         self.text_shadow_data = text_shadow_data
-        text_height, text_rect, text_width = self._handle_dimensions(font, max_dimensions, text)
+        self.max_dimensions = max_dimensions
+        text_height, text_rect, text_width = self._handle_dimensions(font, text)
         super().__init__((text_width, text_height), can_split=True)
 
         self.text = text
@@ -56,7 +57,6 @@ class TextLineChunkFTFont(TextLayoutRect):
             self.using_default_text_shadow_colour = self.text_shadow_data[4]
             self.shadow_colour = self.text_shadow_data[3]
 
-        self.max_dimensions = max_dimensions
         self.y_origin = text_rect.y
         self.font_y_padding = self._calc_font_padding()
 
@@ -97,7 +97,16 @@ class TextLineChunkFTFont(TextLayoutRect):
     def __repr__(self):
         return "< '" + self.text + "' " + super().__repr__() + " >"
 
-    def _handle_dimensions(self, font, max_dimensions, text):
+    def _clamp_dimensions_to_maximums(self, text_width, text_height):
+        if self.max_dimensions is not None:
+            if not (self.max_dimensions[0] == -1 or self.max_dimensions[1] == -1):
+                # we don't have dynamic maximum dimensions so use maximum dimensions for both
+                text_width = min(self.max_dimensions[0], text_width)
+                text_height = min(self.max_dimensions[1], text_height)
+
+        return text_width, text_height
+
+    def _handle_dimensions(self, font, text):
         if len(text) == 0:
             text_rect = font.get_rect('A')
         else:
@@ -108,11 +117,7 @@ class TextLineChunkFTFont(TextLayoutRect):
             text_shadow_width = self.text_shadow_data[0]
         text_width = self._text_render_width(text, font) + (2 * text_shadow_width)
         text_height = text_rect.height
-        if max_dimensions is not None:
-            if not (max_dimensions[0] == -1 or max_dimensions[1] == -1):
-                # we don't have dynamic maximum dimensions so use maximum dimensions for both
-                text_width = min(max_dimensions[0], text_width)
-                text_height = min(max_dimensions[1], text_height)
+        text_width, text_height = self._clamp_dimensions_to_maximums(text_width, text_height)
         return text_height, text_rect, text_width
 
     def _calc_font_padding(self):
@@ -566,11 +571,7 @@ class TextLineChunkFTFont(TextLayoutRect):
             text_rect = self.font.get_rect(self.text)
         text_width = self._text_render_width(self.text, self.font)
         text_height = text_rect.height
-        if self.max_dimensions is not None:
-            if not (self.max_dimensions[0] == -1 or self.max_dimensions[1] == -1):
-                # we don't have dynamic maximum dimensions so use maximum dimensions for both
-                text_width = min(self.max_dimensions[0], text_width)
-                text_height = min(self.max_dimensions[1], text_height)
+        text_width, text_height = self._clamp_dimensions_to_maximums(text_width, text_height)
 
         self.size = (text_width, text_height) # noqa pylint: disable=attribute-defined-outside-init; pylint getting confused
 
@@ -591,11 +592,7 @@ class TextLineChunkFTFont(TextLayoutRect):
             text_rect = self.font.get_rect(self.text)
         text_width = self._text_render_width(self.text, self.font)
         text_height = text_rect.height
-        if self.max_dimensions is not None:
-            if not (self.max_dimensions[0] == -1 or self.max_dimensions[1] == -1):
-                # we don't have dynamic maximum dimensions so use maximum dimensions for both
-                text_width = min(self.max_dimensions[0], text_width)
-                text_height = min(self.max_dimensions[1], text_height)
+        text_width, text_height = self._clamp_dimensions_to_maximums(text_width, text_height)
 
         self.size = (text_width, text_height)  # noqa pylint: disable=attribute-defined-outside-init; pylint getting confused
 
@@ -616,11 +613,7 @@ class TextLineChunkFTFont(TextLayoutRect):
             text_rect = self.font.get_rect(self.text)
         text_width = self._text_render_width(self.text, self.font)
         text_height = text_rect.height
-        if self.max_dimensions is not None:
-            if self.max_dimensions[0] != -1:
-                text_width = min(self.max_dimensions[0], text_width)
-            if self.max_dimensions[1] != -1:
-                text_height = min(self.max_dimensions[1], text_height)
+        text_width, text_height = self._clamp_dimensions_to_maximums(text_width, text_height)
 
         self.size = (text_width, text_height)  # noqa pylint: disable=attribute-defined-outside-init; pylint getting confused
 
diff --git a/pygame_gui/elements/ui_panel.py b/pygame_gui/elements/ui_panel.py
index 911d22a..dc8a831 100644
--- a/pygame_gui/elements/ui_panel.py
+++ b/pygame_gui/elements/ui_panel.py
@@ -87,8 +87,8 @@ class UIPanel(UIElement, IContainerLikeInterface):
         else:
             self.container_margins = margins
 
-        container_rect = pygame.Rect(self.relative_rect.left,
-                                     self.relative_rect.top,
+        container_rect = pygame.Rect(self.relative_rect.left + self.container_margins['left'],
+                                     self.relative_rect.top + self.container_margins['top'],
                                      self.relative_rect.width - (self.container_margins['left'] +
                                                                  self.container_margins['right']),
                                      self.relative_rect.height - (self.container_margins['top'] +
@@ -178,7 +178,10 @@ class UIPanel(UIElement, IContainerLikeInterface):
                                     self.relative_rect.height - (self.container_margins['top'] +
                                                                  self.container_margins['bottom']))
         if new_container_dimensions != self.get_container().get_size():
+            container_rel_pos = (self.relative_rect.x + self.container_margins['left'],
+                                 self.relative_rect.y + self.container_margins['top'])
             self.get_container().set_dimensions(new_container_dimensions)
+            self.get_container().set_relative_position(container_rel_pos)
 
     def set_relative_position(self, position: Union[pygame.math.Vector2,
                                                     Tuple[int, int],
@@ -190,7 +193,9 @@ class UIPanel(UIElement, IContainerLikeInterface):
 
         """
         super().set_relative_position(position)
-        self.get_container().set_relative_position(self.relative_rect.topleft)
+        container_rel_pos = (self.relative_rect.x + self.container_margins['left'],
+                             self.relative_rect.y + self.container_margins['top'])
+        self.get_container().set_relative_position(container_rel_pos)
 
     def set_position(self, position: Union[pygame.math.Vector2,
                                            Tuple[int, int],
@@ -202,7 +207,9 @@ class UIPanel(UIElement, IContainerLikeInterface):
 
         """
         super().set_position(position)
-        self.get_container().set_relative_position(self.relative_rect.topleft)
+        container_rel_pos = (self.relative_rect.x + self.container_margins['left'],
+                             self.relative_rect.y + self.container_margins['top'])
+        self.get_container().set_relative_position(container_rel_pos)
 
     def rebuild_from_changed_theme_data(self):
         """
diff --git a/pygame_gui/elements/ui_text_entry_box.py b/pygame_gui/elements/ui_text_entry_box.py
index 5012416..9c60804 100644
--- a/pygame_gui/elements/ui_text_entry_box.py
+++ b/pygame_gui/elements/ui_text_entry_box.py
@@ -4,7 +4,7 @@ from typing import Union, Tuple, Dict, Optional
 from pygame_gui.core.utility import clipboard_paste, clipboard_copy
 
 from pygame import Rect, MOUSEBUTTONDOWN, MOUSEBUTTONUP, BUTTON_LEFT, KEYDOWN, TEXTINPUT
-from pygame import KMOD_SHIFT, KMOD_META, KMOD_CTRL, K_a, K_x, K_c, K_v
+from pygame import KMOD_META, KMOD_CTRL, K_a, K_x, K_c, K_v
 from pygame import K_LEFT, K_RIGHT, K_UP, K_DOWN, K_HOME, K_END, K_BACKSPACE, K_DELETE, K_RETURN
 from pygame import key
 from pygame.event import Event, post
@@ -333,140 +333,7 @@ class UITextEntryBox(UITextBox):
 
         """
         consumed_event = False
-        # modded versions of LEFT and RIGHT must go first otherwise the simple
-        # cases will absorb the events
-        if event.key == K_HOME or (event.key == K_LEFT
-            and (event.mod & KMOD_CTRL or event.mod & KMOD_META)
-            ):
-            try:
-                next_pos = self.edit_position - self.html_text[:self.edit_position][::-1].index("\n")
-            except ValueError:
-                next_pos = 0
-            # include case when shift held down to select everything to start
-            # of current line.
-            if abs(self.select_range[0] - self.select_range[1]) > 0:
-                if event.mod & KMOD_SHIFT:
-                    if self.edit_position == self.select_range[1]:
-                        # undo selection to right, create to left
-                        self.select_range = [next_pos, self.select_range[0]]
-                    else:
-                        # extend left
-                        self.select_range = [next_pos, self.select_range[1]]
-                else:
-                    self.select_range = [0, 0]
-            else:
-                if event.mod & KMOD_SHIFT:
-                    self.select_range = [next_pos, self.edit_position]
-                else:
-                    self.select_range = [0, 0]
-            self.edit_position = next_pos
-            self.cursor_has_moved_recently = True
-            consumed_event = True
-        elif event.key == K_END or (event.key == K_RIGHT
-            and (event.mod & KMOD_CTRL or event.mod & KMOD_META)
-            ):
-            try:
-                next_pos = self.edit_position + self.html_text[self.edit_position:].index("\n")
-            except ValueError:
-                next_pos = len(self.html_text)
-            # include case when shift held down to select everything to end
-            # of current line.
-            if abs(self.select_range[0] - self.select_range[1]) > 0:
-                if event.mod & KMOD_SHIFT:
-                    if self.edit_position == self.select_range[0]:
-                        # undo selection to left, create to right
-                        self.select_range = [self.select_range[1], next_pos]
-                    else:
-                        # extend right
-                        self.select_range = [self.select_range[0], next_pos]
-                else:
-                    self.select_range = [0, 0]
-            else:
-                if event.mod & KMOD_SHIFT:
-                    self.select_range = [self.edit_position, next_pos]
-                else:
-                    self.select_range = [0, 0]
-            self.edit_position = next_pos
-            self.cursor_has_moved_recently = True
-            consumed_event = True
-        elif event.key == K_LEFT and event.mod & KMOD_SHIFT:
-            # keyboard-based selection
-            if abs(self.select_range[0] - self.select_range[1]) > 0:
-                # existing selection, so edit_position should correspond to one
-                # end of it
-                if self.edit_position == self.select_range[0]:
-                    # try to extend to the left
-                    self.select_range = [max(0, self.edit_position - 1),
-                                         self.select_range[1]]
-                elif self.edit_position == self.select_range[1]:
-                    # reduce to the left
-                    self.select_range = [self.select_range[0],
-                                         max(0, self.edit_position - 1)]
-            else:
-                self.select_range = [max(0, self.edit_position - 1),
-                                     self.edit_position]
-            if self.edit_position > 0:
-                self.edit_position -= 1
-                self.cursor_has_moved_recently = True
-            consumed_event = True
-        elif event.key == K_RIGHT and event.mod & KMOD_SHIFT:
-            # keyboard-based selection
-            if abs(self.select_range[0] - self.select_range[1]) > 0:
-                if self.edit_position == self.select_range[1]:
-                    # try to extend to the right
-                    self.select_range = [self.select_range[0],
-                                         min(len(self.html_text), self.edit_position + 1)]
-                elif self.edit_position == self.select_range[0]:
-                    # reduce to the right
-                    self.select_range = [min(len(self.html_text), self.edit_position + 1),
-                                         self.select_range[1]]
-            else:
-                self.select_range = [self.edit_position, min(len(self.html_text),
-                                                             self.edit_position + 1)]
-            if self.edit_position < len(self.html_text):
-                self.edit_position += 1
-                self.cursor_has_moved_recently = True
-            consumed_event = True
-        elif event.key == K_UP and event.mod & KMOD_SHIFT:
-            # keyboard-based selection
-            new_pos = self.text_box_layout.get_cursor_pos_move_up_one_row(self.last_horiz_cursor_index)
-            if abs(self.select_range[0] - self.select_range[1]) > 0:
-                # existing selection, so edit_position should correspond to one
-                # end of it
-                if self.edit_position == self.select_range[0]:
-                    # try to extend to the left
-                    self.select_range = [max(0, new_pos),
-                                         self.select_range[1]]
-                elif self.edit_position == self.select_range[1]:
-                    # reduce to the left
-                    self.select_range = [self.select_range[0],
-                                         max(0, new_pos)]
-            else:
-                self.select_range = [max(0, new_pos),
-                                     self.edit_position]
-            if self.edit_position > 0:
-                self.edit_position = new_pos
-                self.cursor_has_moved_recently = True
-        elif event.key == K_DOWN and event.mod & KMOD_SHIFT:
-            # keyboard-based selection
-            new_pos = self.text_box_layout.get_cursor_pos_move_down_one_row(self.last_horiz_cursor_index)
-            if abs(self.select_range[0] - self.select_range[1]) > 0:
-                if self.edit_position == self.select_range[1]:
-                    # try to extend to the right
-                    self.select_range = [self.select_range[0],
-                                                 min(len(self.html_text), new_pos)]
-                elif self.edit_position == self.select_range[0]:
-                    # reduce to the right
-                    self.select_range = [min(len(self.html_text), new_pos),
-                                                 self.select_range[1]]
-            else:
-                self.select_range = [self.edit_position, min(len(self.html_text),
-                                                                     new_pos)]
-            if self.edit_position < len(self.html_text):
-                self.edit_position = new_pos
-                self.cursor_has_moved_recently = True
-            consumed_event = True
-        elif event.key == K_LEFT:
+        if event.key == K_LEFT:
             if abs(self.select_range[0] - self.select_range[1]) > 0:
                 self.edit_position = min(self.select_range[0], self.select_range[1])
                 self.select_range = [0, 0]
@@ -682,9 +549,8 @@ class UITextEntryBox(UITextBox):
                     self.html_text = (self.html_text[:self.edit_position] +
                                       new_text +
                                       self.html_text[self.edit_position:])
-                    original_edit_pos = self.edit_position
                     self.set_text(self.html_text)
-                    self.edit_position = original_edit_pos + len(new_text)
+                    self.edit_position += len(new_text)
                     self.text_box_layout.set_cursor_position(self.edit_position)
                     self.redraw_from_text_block()
                     self.cursor_has_moved_recently = True
@@ -740,3 +606,4 @@ class UITextEntryBox(UITextBox):
     @staticmethod
     def convert_all_line_endings_to_unix(input_str: str):
         return input_str.replace('\r\n', '\n').replace('\r', '\n')
+
diff --git a/pygame_gui/elements/ui_text_entry_line.py b/pygame_gui/elements/ui_text_entry_line.py
index e56255f..01fad4f 100644
--- a/pygame_gui/elements/ui_text_entry_line.py
+++ b/pygame_gui/elements/ui_text_entry_line.py
@@ -579,91 +579,7 @@ class UITextEntryLine(UIElement):
 
         """
         consumed_event = False
-        # modded versions of LEFT and RIGHT must go first otherwise the simple
-        # cases will absorb the events
-        if event.key == pygame.K_HOME or (event.key == pygame.K_LEFT
-            and (event.mod & pygame.KMOD_CTRL or event.mod & pygame.KMOD_META)
-            ):
-            # include case when shift held down to select everything to start
-            # of current line.
-            if abs(self.select_range[0] - self.select_range[1]) > 0:
-                if event.mod & pygame.KMOD_SHIFT:
-                    if self.edit_position == self.select_range[1]:
-                        # undo selection to right, create to left
-                        self.select_range = [0, self.select_range[0]]
-                    else:
-                        # extend left
-                        self.select_range = [0, self.select_range[1]]
-                else:
-                    self.select_range = [0, 0]
-            else:
-                if event.mod & pygame.KMOD_SHIFT:
-                    self.select_range = [0, self.edit_position]
-                else:
-                    self.select_range = [0, 0]
-            self.edit_position = 0
-            self.cursor_has_moved_recently = True
-            consumed_event = True
-        elif event.key == pygame.K_END or (event.key == pygame.K_RIGHT
-            and (event.mod & pygame.KMOD_CTRL or event.mod & pygame.KMOD_META)
-            ):
-            if abs(self.select_range[0] - self.select_range[1]) > 0:
-                if event.mod & pygame.KMOD_SHIFT:
-                    if self.edit_position == self.select_range[0]:
-                        # undo selection to left, create to right
-                        self.select_range = [self.select_range[1], len(self.text)]
-                    else:
-                        # extend right
-                        self.select_range = [self.select_range[0], len(self.text)]
-                else:
-                    self.select_range = [0, 0]
-            else:
-                if event.mod & pygame.KMOD_SHIFT:
-                    self.select_range = [self.edit_position, len(self.text)]
-                else:
-                    self.select_range = [0, 0]
-            self.edit_position = len(self.text)
-            self.cursor_has_moved_recently = True
-            consumed_event = True
-        elif event.key == pygame.K_LEFT and event.mod & pygame.KMOD_SHIFT:
-            # keyboard-based selection
-            if abs(self.select_range[0] - self.select_range[1]) > 0:
-                # existing selection, so edit_position should correspond to one
-                # end of it
-                if self.edit_position == self.select_range[0]:
-                    # try to extend to the left
-                    self.select_range = [max(0, self.edit_position - 1),
-                                         self.select_range[1]]
-                elif self.edit_position == self.select_range[1]:
-                    # reduce to the left
-                    self.select_range = [self.select_range[0], max(0,
-                                                    self.edit_position - 1)]
-            else:
-                self.select_range = [max(0, self.edit_position - 1),
-                                     self.edit_position]
-            if self.edit_position > 0:
-                self.edit_position -= 1
-                self.cursor_has_moved_recently = True
-            consumed_event = True
-        elif event.key == pygame.K_RIGHT and event.mod & pygame.KMOD_SHIFT:
-            # keyboard-based selection
-            if abs(self.select_range[0] - self.select_range[1]) > 0:
-                if self.edit_position == self.select_range[1]:
-                    # try to extend to the right
-                    self.select_range = [self.select_range[0],
-                                         min(len(self.text), self.edit_position + 1)]
-                elif self.edit_position == self.select_range[0]:
-                    # reduce to the right
-                    self.select_range = [min(len(self.text), self.edit_position + 1),
-                                         self.select_range[1]]
-            else:
-                self.select_range = [self.edit_position, min(len(self.text),
-                                                    self.edit_position + 1)]
-            if self.edit_position < len(self.text):
-                self.edit_position += 1
-                self.cursor_has_moved_recently = True
-            consumed_event = True
-        elif event.key == pygame.K_LEFT:
+        if event.key == pygame.K_LEFT:
             if abs(self.select_range[0] - self.select_range[1]) > 0:
                 self.edit_position = min(self.select_range[0], self.select_range[1])
                 self.select_range = [0, 0]
diff --git a/readthedocs.yaml b/readthedocs.yaml
index 8824b0b..4633752 100644
--- a/readthedocs.yaml
+++ b/readthedocs.yaml
@@ -15,6 +15,6 @@ formats:
 
 # Optionally set the version of Python and requirements required to build your docs
 python:
-  version: 3.7
+  version: 3.8
   install:
     - requirements: docs/requirements.txt
\ No newline at end of file
diff --git a/setup.py b/setup.py
index 192b64e..d65e63a 100644
--- a/setup.py
+++ b/setup.py
@@ -3,7 +3,7 @@ from setuptools import setup
 
 setup(
       name='pygame_gui',
-      version='0.6.9',
+      version='0.6.10',
       description='A GUI module for pygame Community Edition',
       long_description="Helps create GUIs for games made using pygame Community Edition. "
                        "Features HTML-style text formatting, localization,"
@@ -11,7 +11,7 @@ setup(
                        " multiple windows of GUI stuff.",
       keywords=["pygame", "gui", "ui"],
       url='https://github.com/MyreMylar/pygame_gui',
-      download_url='https://github.com/MyreMylar/pygame_gui/archive/v_069.tar.gz',
+      download_url='https://github.com/MyreMylar/pygame_gui/archive/v_0610.tar.gz',
       author='Dan Lawrence',
       author_email='danintheshed@gmail.com',
       license='MIT',
@@ -27,22 +27,21 @@ setup(
                 'pygame_gui.data',
                 'pygame_gui.data.translations'],
       zip_safe=False,
-      python_requires='>=3.7',
+      python_requires='>=3.8',
       setup_requires=[],
-      install_requires=['pygame-ce>=2.1.4',
+      install_requires=['pygame-ce>=2.3.2',
                         'python-i18n>=0.3.9',
-                        'importlib_resources>1.3; python_version < "3.9"',
-                        'typing-extensions; python_version < "3.8"'],
+                        'importlib_resources>1.3; python_version < "3.9"'],
       include_package_data=True,
       classifiers=[
           'Development Status :: 3 - Alpha',
           'Intended Audience :: Developers',
           'Topic :: Software Development :: Build Tools',
           'License :: OSI Approved :: MIT License',
-          'Programming Language :: Python :: 3.7',
           'Programming Language :: Python :: 3.8',
           'Programming Language :: Python :: 3.9',
           'Programming Language :: Python :: 3.10',
           'Programming Language :: Python :: 3.11',
+          'Programming Language :: Python :: 3.12',
       ],
       )


Test patch:
diff --git a/.github/workflows/run_tests_ci.yml b/.github/workflows/run_tests_ci.yml
index 498a5e1..f59467c 100644
--- a/.github/workflows/run_tests_ci.yml
+++ b/.github/workflows/run_tests_ci.yml
@@ -8,12 +8,12 @@ jobs:
     strategy:
       max-parallel: 4
       matrix:
-        python-version: ['3.8', '3.9', '3.10', '3.11']
-        pygame-ce-version: ['2.1.4', '2.2.1']
+        python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
+        pygame-ce-version: ['2.3.2']
     steps:
-    - uses: actions/checkout@v3
+    - uses: actions/checkout@v4.1.0
     - name: Set up Python ${{ matrix.python-version }}
-      uses: actions/setup-python@v1
+      uses: actions/setup-python@v4.7.1
       with:
         python-version: ${{ matrix.python-version }}
         pygame-ce-version: ${{ matrix.pygame-ce-version }}
@@ -47,12 +47,12 @@ jobs:
     strategy:
       max-parallel: 4
       matrix:
-        python-version: [ '3.11' ]
-        pygame-ce-version: [ '2.1.4', '2.2.1' ]
+        python-version: [ '3.11','3.12' ]
+        pygame-ce-version: [ '2.3.2' ]
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4.1.0
       - name: Set up Python ${{ matrix.python-version }}
-        uses: actions/setup-python@v1
+        uses: actions/setup-python@v4.7.1
         with:
           python-version: ${{ matrix.python-version }}
           pygame-ce-version: ${{ matrix.pygame-ce-version }}
@@ -83,12 +83,12 @@ jobs:
     strategy:
       max-parallel: 4
       matrix:
-        python-version: [ '3.11' ]
-        pygame-ce-version: [ '2.1.4', '2.2.1' ]
+        python-version: [ '3.11', '3.12' ]
+        pygame-ce-version: [ '2.3.2' ]
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4.1.0
       - name: Set up Python ${{ matrix.python-version }}
-        uses: actions/setup-python@v1
+        uses: actions/setup-python@v4.7.1
         with:
           python-version: ${{ matrix.python-version }}
           pygame-ce-version: ${{ matrix.pygame-ce-version }}
diff --git a/tests/test_elements/test_ui_text_entry_box.py b/tests/test_elements/test_ui_text_entry_box.py
index 254a622..9b1fced 100644
--- a/tests/test_elements/test_ui_text_entry_box.py
+++ b/tests/test_elements/test_ui_text_entry_box.py
@@ -775,7 +775,7 @@ class TestUITextEntryBox:
                                   manager=default_ui_manager)
         assert text_box.image is not None
         assert len(text_box.text_box_layout.layout_rows) == 3
-
+        
     def test_rebuild_select_area_1(self, _init_pygame, default_ui_manager,
                                    _display_surface_return_none):
         text_entry = UITextEntryBox(relative_rect=pygame.Rect(100, 100, 200, 30),
@@ -1148,8 +1148,7 @@ class TestUITextEntryBox:
         text_entry.focus()
 
         processed_key_event = text_entry.process_event(pygame.event.Event(pygame.KEYDOWN,
-                                                                          {'key': pygame.K_RIGHT,
-                                                                           'mod': 0}))
+                                                                          {'key': pygame.K_RIGHT}))
 
         assert processed_key_event
 
@@ -1164,8 +1163,7 @@ class TestUITextEntryBox:
         text_entry.focus()
 
         processed_key_event = text_entry.process_event(pygame.event.Event(pygame.KEYDOWN,
-                                                                          {'key': pygame.K_RIGHT,
-                                                                           'mod': 0}))
+                                                                          {'key': pygame.K_RIGHT}))
 
         assert processed_key_event
 
@@ -1179,8 +1177,7 @@ class TestUITextEntryBox:
         assert text_entry.edit_position == 3
 
         processed_key_event = text_entry.process_event(pygame.event.Event(pygame.KEYDOWN,
-                                                                          {'key': pygame.K_LEFT,
-                                                                           'mod': 0}))
+                                                                          {'key': pygame.K_LEFT}))
 
         assert processed_key_event
         assert text_entry.edit_position == 2
@@ -1195,26 +1192,12 @@ class TestUITextEntryBox:
         text_entry.select_range = [0, 2]
 
         processed_key_event = text_entry.process_event(pygame.event.Event(pygame.KEYDOWN,
-                                                                          {'key': pygame.K_HOME,
-                                                                           'mod': 0}))
+                                                                          {'key': pygame.K_HOME}))
 
         assert processed_key_event
         assert text_entry.select_range == [0, 0]
         assert text_entry.edit_position == 0
 
-        text_entry.set_text('daniel\nmulti-line\ntext')
-        text_entry.edit_position = 3
-        text_entry.focus()
-        text_entry.select_range = [1, 3]
-
-        processed_key_event = text_entry.process_event(pygame.event.Event(pygame.KEYDOWN,
-                                                                          {'key': pygame.K_HOME,
-                                                                           'mod': pygame.KMOD_SHIFT}))
-
-        assert processed_key_event
-        assert text_entry.select_range == [0, 1]
-        assert text_entry.edit_position == 0
-
     def test_process_event_end(self, _init_pygame: None, default_ui_manager: UIManager,
                                _display_surface_return_none: None):
         text_entry = UITextEntryBox(relative_rect=pygame.Rect(100, 100, 200, 30),
@@ -1225,26 +1208,12 @@ class TestUITextEntryBox:
         text_entry.select_range = [0, 2]
 
         processed_key_event = text_entry.process_event(pygame.event.Event(pygame.KEYDOWN,
-                                                                          {'key': pygame.K_END,
-                                                                           'mod': 0}))
+                                                                          {'key': pygame.K_END}))
 
         assert processed_key_event
         assert text_entry.select_range == [0, 0]
         assert text_entry.edit_position == 3
 
-        text_entry.set_text('daniel\nmulti-line\ntext')
-        text_entry.edit_position = 3
-        text_entry.focus()
-        text_entry.select_range = [1, 3]
-
-        processed_key_event = text_entry.process_event(pygame.event.Event(pygame.KEYDOWN,
-                                                                          {'key': pygame.K_END,
-                                                                           'mod': pygame.KMOD_SHIFT}))
-
-        assert processed_key_event
-        assert text_entry.select_range == [1, len("daniel")]
-        assert text_entry.edit_position == len("daniel")
-
     def test_process_event_text_right_select_range(self, _init_pygame: None,
                                                    default_ui_manager: UIManager,
                                                    _display_surface_return_none: None):
@@ -1256,8 +1225,7 @@ class TestUITextEntryBox:
         text_entry.select_range = [0, 2]
 
         processed_key_event = text_entry.process_event(pygame.event.Event(pygame.KEYDOWN,
-                                                                          {'key': pygame.K_RIGHT,
-                                                                           'mod': 0}))
+                                                                          {'key': pygame.K_RIGHT}))
 
         assert processed_key_event
 
@@ -1272,8 +1240,7 @@ class TestUITextEntryBox:
         text_entry.select_range = [0, 2]
 
         processed_key_event = text_entry.process_event(pygame.event.Event(pygame.KEYDOWN,
-                                                                          {'key': pygame.K_LEFT,
-                                                                           'mod': 0}))
+                                                                          {'key': pygame.K_LEFT}))
 
         assert processed_key_event
 
diff --git a/tests/test_elements/test_ui_text_entry_line.py b/tests/test_elements/test_ui_text_entry_line.py
index 3aa3f93..b7fd453 100644
--- a/tests/test_elements/test_ui_text_entry_line.py
+++ b/tests/test_elements/test_ui_text_entry_line.py
@@ -651,22 +651,10 @@ class TestUITextEntryLine:
         text_entry.focus()
 
         processed_key_event = text_entry.process_event(pygame.event.Event(pygame.KEYDOWN,
-                                                                          {'key': pygame.K_RIGHT,
-                                                                           'mod': 0}))
+                                                                          {'key': pygame.K_RIGHT}))
 
         assert processed_key_event
 
-        text_entry.edit_position = 1
-        text_entry.select_range = [1, 3]
-        text_entry.focus()
-
-        processed_key_event = text_entry.process_event(pygame.event.Event(pygame.KEYDOWN,
-                                                                          {'key': pygame.K_RIGHT,
-                                                                           'mod': pygame.KMOD_SHIFT}))
-        assert processed_key_event
-        assert text_entry.select_range == [2, 3]
-        assert text_entry.edit_position == 2
-
     def test_process_event_text_right_actually_move(self, _init_pygame: None,
                                                     default_ui_manager: UIManager,
                                                     _display_surface_return_none: None):
@@ -678,8 +666,7 @@ class TestUITextEntryLine:
         text_entry.focus()
 
         processed_key_event = text_entry.process_event(pygame.event.Event(pygame.KEYDOWN,
-                                                                          {'key': pygame.K_RIGHT,
-                                                                           'mod': 0}))
+                                                                          {'key': pygame.K_RIGHT}))
 
         assert processed_key_event
 
@@ -693,8 +680,7 @@ class TestUITextEntryLine:
         assert text_entry.edit_position == 3
 
         processed_key_event = text_entry.process_event(pygame.event.Event(pygame.KEYDOWN,
-                                                                          {'key': pygame.K_LEFT,
-                                                                           'mod': 0}))
+                                                                          {'key': pygame.K_LEFT}))
 
         assert processed_key_event
         assert text_entry.edit_position == 2
@@ -709,8 +695,7 @@ class TestUITextEntryLine:
         text_entry.select_range = [0, 2]
 
         processed_key_event = text_entry.process_event(pygame.event.Event(pygame.KEYDOWN,
-                                                                          {'key': pygame.K_HOME,
-                                                                           'mod': 0}))
+                                                                          {'key': pygame.K_HOME}))
 
         assert processed_key_event
         assert text_entry.select_range == [0, 0]
@@ -726,25 +711,12 @@ class TestUITextEntryLine:
         text_entry.select_range = [0, 2]
 
         processed_key_event = text_entry.process_event(pygame.event.Event(pygame.KEYDOWN,
-                                                                          {'key': pygame.K_END,
-                                                                           'mod': 0}))
+                                                                          {'key': pygame.K_END}))
 
         assert processed_key_event
         assert text_entry.select_range == [0, 0]
         assert text_entry.edit_position == 3
 
-        text_entry.edit_position = 1
-        text_entry.select_range = [1, 3]
-        text_entry.focus()
-
-        processed_key_event = text_entry.process_event(pygame.event.Event(pygame.KEYDOWN,
-                                                                          {'key': pygame.K_END,
-                                                                           'mod': pygame.KMOD_SHIFT}))
-        assert processed_key_event
-        assert text_entry.select_range == [3, 3]
-        assert text_entry.edit_position == 3
-
-
     def test_process_event_text_right_select_range(self, _init_pygame: None,
                                                    default_ui_manager: UIManager,
                                                    _display_surface_return_none: None):
@@ -756,8 +728,7 @@ class TestUITextEntryLine:
         text_entry.select_range = [0, 2]
 
         processed_key_event = text_entry.process_event(pygame.event.Event(pygame.KEYDOWN,
-                                                                          {'key': pygame.K_RIGHT,
-                                                                           'mod': 0}))
+                                                                          {'key': pygame.K_RIGHT}))
 
         assert processed_key_event
 
@@ -772,8 +743,7 @@ class TestUITextEntryLine:
         text_entry.select_range = [0, 2]
 
         processed_key_event = text_entry.process_event(pygame.event.Event(pygame.KEYDOWN,
-                                                                          {'key': pygame.K_LEFT,
-                                                                           'mod': 0}))
+                                                                          {'key': pygame.K_LEFT}))
 
         assert processed_key_event