Repository: MyreMylar/pygame_gui

Issue:
UIPanel.set_position() and UIPanel.set_relative_position() incorrectly sets the child container position
```py
class UIPanel:
  def __init__():
        #.....
        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'] +
                                                              self.container_margins['bottom']))
    
        self.panel_container = UIContainer(container_rect, manager,
                                       starting_height=starting_height,
                                       container=container,
                                       parent_element=self,
                                       object_id=ObjectID(object_id='#panel_container',
                                                          class_id=None),
                                       anchors=anchors,
                                       visible=self.visible)

  #.....
  def set_relative_position():
        super().set_relative_position(position)
        self.get_container().set_relative_position(self.relative_rect.topleft) # <- Problem

  def set_position(self, position: Coordinate):
        super().set_position(position)
        self.get_container().set_relative_position(self.relative_rect.topleft) # <- Problem
```

Methods set_relative_position and set_position do not take into margins for child container

Hints from issue comments:

Solution patch:
diff --git a/pygame_gui/elements/ui_panel.py b/pygame_gui/elements/ui_panel.py
index 5901fc7..47d328a 100644
--- a/pygame_gui/elements/ui_panel.py
+++ b/pygame_gui/elements/ui_panel.py
@@ -219,7 +219,13 @@ class UIPanel(UIElement, IContainerLikeInterface):
 
         """
         super().set_relative_position(position)
-        self.get_container().set_relative_position(self.relative_rect.topleft)
+
+        container_top_left = (
+            self.relative_rect.left + self.container_margins["left"],
+            self.relative_rect.top + self.container_margins["top"],
+        )
+
+        self.get_container().set_relative_position(container_top_left)
 
     def set_position(self, position: Coordinate):
         """
@@ -229,7 +235,13 @@ class UIPanel(UIElement, IContainerLikeInterface):
 
         """
         super().set_position(position)
-        self.get_container().set_relative_position(self.relative_rect.topleft)
+
+        container_top_left = (
+            self.relative_rect.left + self.container_margins["left"],
+            self.relative_rect.top + self.container_margins["top"],
+        )
+
+        self.get_container().set_relative_position(container_top_left)
 
     def rebuild_from_changed_theme_data(self):
         """


Test patch:
diff --git a/tests/test_elements/test_ui_panel.py b/tests/test_elements/test_ui_panel.py
index b39a7ed..7b91617 100644
--- a/tests/test_elements/test_ui_panel.py
+++ b/tests/test_elements/test_ui_panel.py
@@ -197,6 +197,42 @@ class TestUIPanel:
         assert element_5.relative_right_margin == 230
         assert element_5.relative_bottom_margin == 230
 
+        # test with margins
+        element_6 = UIPanel(relative_rect=pygame.Rect(0, 0, 50, 50),
+                            manager=default_ui_manager,
+                            container=test_container,
+                            starting_height=5,
+                            margins={'left': 10,
+                                     'right': 10,
+                                     'top': 5,
+                                     'bottom': 5},
+                            anchors={'left': 'left',
+                                     'right': 'right',
+                                     'top': 'top',
+                                     'bottom': 'bottom'})
+
+        assert element_6.rect.topleft == (100, 100)
+        assert element_6.rect.size == (50, 50)
+        assert element_6.rect.bottomright == (150, 150)
+        assert element_6.relative_right_margin == 250
+        assert element_6.relative_bottom_margin == 250
+
+        assert element_6.get_container().rect.topleft == (110, 105)
+        assert element_6.get_container().rect.size == (30, 40)
+        assert element_6.get_container().rect.bottomright == (140, 145)
+
+        element_6.set_relative_position((20, 20))
+
+        assert element_6.rect.topleft == (120, 120)
+        assert element_6.rect.size == (50, 50)
+        assert element_6.rect.bottomright == (170, 170)
+        assert element_6.relative_right_margin == 230
+        assert element_6.relative_bottom_margin == 230
+
+        assert element_6.get_container().rect.topleft == (130, 125)
+        assert element_6.get_container().rect.size == (30, 40)
+        assert element_6.get_container().rect.bottomright == (160, 165)
+
     def test_set_position(self, _init_pygame, _display_surface_return_none, default_ui_manager):
         test_container = UIContainer(relative_rect=pygame.Rect(10, 10, 300, 300),
                                      manager=default_ui_manager)
@@ -284,6 +320,42 @@ class TestUIPanel:
         assert element_5.relative_right_margin == 240
         assert element_5.relative_bottom_margin == 240
 
+        # test with margins
+        element_6 = UIPanel(relative_rect=pygame.Rect(0, 0, 50, 50),
+                            manager=default_ui_manager,
+                            container=test_container,
+                            starting_height=5,
+                            margins={'left': 10,
+                                     'right': 10,
+                                     'top': 5,
+                                     'bottom': 5},
+                            anchors={'left': 'left',
+                                     'right': 'right',
+                                     'top': 'top',
+                                     'bottom': 'bottom'})
+
+        assert element_6.relative_rect.topleft == (0, 0)
+        assert element_6.relative_rect.size == (50, 50)
+        assert element_6.relative_rect.bottomright == (50, 50)
+        assert element_6.relative_right_margin == 250
+        assert element_6.relative_bottom_margin == 250
+
+        assert element_6.get_container().get_relative_rect().topleft == (10, 5)
+        assert element_6.get_container().get_relative_rect().size == (30, 40)
+        assert element_6.get_container().get_relative_rect().bottomright == (40, 45)
+
+        element_6.set_position((20, 20))
+
+        assert element_6.relative_rect.topleft == (10, 10)
+        assert element_6.relative_rect.size == (50, 50)
+        assert element_6.relative_rect.bottomright == (60, 60)
+        assert element_6.relative_right_margin == 240
+        assert element_6.relative_bottom_margin == 240
+
+        assert element_6.get_container().get_relative_rect().topleft == (20, 15)
+        assert element_6.get_container().get_relative_rect().size == (30, 40)
+        assert element_6.get_container().get_relative_rect().bottomright == (50, 55)
+
     def test_set_dimensions(self, _init_pygame, _display_surface_return_none, default_ui_manager):
         test_container = UIContainer(relative_rect=pygame.Rect(10, 10, 300, 300),
                                      manager=default_ui_manager)