Repository: ppizarror/pygame-menu

Issue:
Copy theme and modify attributes
**Environment information**
Describe your environment information, such as:
- SO: OSX
- python version: v3.7.7
- pygame version: v2.0.1
- pygame-menu version: v4.0.2

**Describe the bug**
Creating theme by copy, then modifying `selection_color` is not taken into account.

**To Reproduce**
```
THEME_WHITE = pgm.themes.Theme(
    background_color=(255, 255, 255),
    scrollbar_thick=14,
    scrollbar_slider_pad=2,
    scrollbar_slider_color=(35, 149, 135),
    selection_color=(29, 120, 107),
    title_background_color=(35, 149, 135),
    title_font=fonts.get_filename("Monoid-Regular"),
    title_font_size=33,
    title_font_color=(255, 255, 255),
    widget_margin=(0, 20),
    widget_font=fonts.get_filename("Monoid-Retina"),
    widget_font_size=30,
    widget_font_color=(0, 0, 0),
)

SUBTHEME1_WHITE = THEME_WHITE.copy()
SUBTHEME1_WHITE.background_color = (255, 255, 255)
SUBTHEME1_WHITE.scrollbar_slider_color = (252, 151, 0)
SUBTHEME1_WHITE.selection_color = (241, 125, 1)
SUBTHEME1_WHITE.title_background_color = (252, 151, 0)
SUBTHEME1_WHITE.widget_alignment = pgm.locals.ALIGN_LEFT
SUBTHEME1_WHITE.widget_margin = (40, 10)
SUBTHEME1_WHITE.widget_font_size = 18
```

**Expected behavior**
Menu using the theme SUBTHEME1_WHITE should have selection color of (241, 125, 1), but have (29, 120, 107)


Discussion:

Patch:
diff --git a/pygame_menu/_widgetmanager.py b/pygame_menu/_widgetmanager.py
index 28af48e8..c962106b 100644
--- a/pygame_menu/_widgetmanager.py
+++ b/pygame_menu/_widgetmanager.py
@@ -235,6 +235,8 @@ class WidgetManager(Base):
         else:
             selection_effect = selection_effect.copy()
         assert isinstance(selection_effect, pygame_menu.widgets.core.Selection)
+
+        selection_effect.set_color(attributes['selection_color'])
         attributes['selection_effect'] = selection_effect
 
         # tab_size
diff --git a/pygame_menu/themes.py b/pygame_menu/themes.py
index e5069ed9..b084af95 100644
--- a/pygame_menu/themes.py
+++ b/pygame_menu/themes.py
@@ -137,7 +137,7 @@ class Theme(object):
     :type scrollbar_slider_pad: int, float
     :param scrollbar_thick: Scrollbar thickness in px
     :type scrollbar_thick: int
-    :param selection_color: Color of the selected widget
+    :param selection_color: Color of the selected widget. It updates both selected font and ``widget_selection_effect`` color
     :type selection_color: tuple, list, str, int, :py:class:`pygame.Color`
     :param surface_clear_color: Surface clear color before applying background function
     :type surface_clear_color: tuple, list, str, int, :py:class:`pygame.Color`
@@ -376,10 +376,6 @@ class Theme(object):
         self.scrollbar_thick = self._get(kwargs, 'scrollbar_thick', int, 20)
 
         # Generic widget themes
-        default_selection_effect = HighlightSelection(margin_x=0, margin_y=0).set_color(self.selection_color)
-        self.widget_selection_effect = self._get(kwargs, 'widget_selection_effect', Selection,
-                                                 default_selection_effect)
-
         self.widget_alignment = self._get(kwargs, 'widget_alignment', 'alignment', ALIGN_CENTER)
         self.widget_background_color = self._get(kwargs, 'widget_background_color', 'color_image_none')
         self.widget_background_inflate = self._get(kwargs, 'background_inflate', 'tuple2int', (0, 0))
@@ -412,6 +408,8 @@ class Theme(object):
         self.widget_margin = self._get(kwargs, 'widget_margin', 'tuple2', (0, 0))
         self.widget_offset = self._get(kwargs, 'widget_offset', 'tuple2', (0, 0))
         self.widget_padding = self._get(kwargs, 'widget_padding', PaddingInstance, (4, 8))
+        self.widget_selection_effect = self._get(kwargs, 'widget_selection_effect', Selection,
+                                                 HighlightSelection(margin_x=0, margin_y=0))
         self.widget_tab_size = self._get(kwargs, 'widget_tab_size', int, 4)
         self.widget_url_color = self._get(kwargs, 'widget_url_color', 'color', (6, 69, 173))
 
@@ -618,6 +616,7 @@ class Theme(object):
 
         :return: Copied theme
         """
+        self.validate()
         return copy.deepcopy(self)
 
     def __copy__(self) -> 'Theme':
diff --git a/pygame_menu/version.py b/pygame_menu/version.py
index 61f92826..c6d43cb1 100644
--- a/pygame_menu/version.py
+++ b/pygame_menu/version.py
@@ -57,6 +57,6 @@ class Version(tuple):
     patch = property(lambda self: self[2])
 
 
-vernum = Version(4, 0, 3)
+vernum = Version(4, 0, 4)
 ver = str(vernum)
 rev = ''


Test patch:
diff --git a/test/test_themes.py b/test/test_themes.py
index a3f5f5e0..72d8ebed 100644
--- a/test/test_themes.py
+++ b/test/test_themes.py
@@ -31,6 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 __all__ = ['ThemeTest']
 
+from test._utils import MenuUtils
 from pathlib import Path
 import unittest
 
@@ -90,6 +91,23 @@ class ThemeTest(unittest.TestCase):
         self.assertEqual(theme_white.selection_color, color_main)
         self.assertEqual(sub_theme_white.selection_color, color_copy)
 
+        self.assertNotEqual(theme_white.selection_color, sub_theme_white.selection_color)
+        self.assertNotEqual(theme_white.widget_selection_effect, sub_theme_white.widget_selection_effect)
+
+        # Test the widget effect color is different in both objects
+        m1 = MenuUtils.generic_menu(theme=theme_white)
+        m2 = MenuUtils.generic_menu(theme=sub_theme_white)
+        b1 = m1.add.button('1')
+        b2 = m2.add.button('2')
+
+        self.assertEqual(b1._selection_effect.color, b1.get_menu().get_theme().selection_color)
+        self.assertEqual(b2._selection_effect.color, b2.get_menu().get_theme().selection_color)
+        self.assertNotEqual(b1._selection_effect.color, b2._selection_effect.color)
+
+        # Main Theme selection effect class should not be modified
+        self.assertEqual(b1.get_menu().get_theme(), theme_white)
+        self.assertEqual(theme_white.widget_selection_effect.color, (0, 0, 0))
+
     def test_methods(self) -> None:
         """
         Test theme method.