Repository: kivy/kivy

Issue:
ScreenManager doesn't recognize itself
I tried defining a screen manager, but when I try to switch to another screen it complains that the screen is already managed by another screen manager. Of course this is a lie as there is only one screen manager:

```
In [1]: from main import Game; Game().run()
[INFO              ] Kivy v1.8.0

......

/Users/sinclair/repos/project/main.kv in <module>()
     26             scale:       1.0
     27             border:      (0, 0, 0, 0)
---> 28             on_touch_up: root.manager.switch_to(root.manager.get_screen('new_game_screen'), direction = 'left')
     29
     30         Button:

/Users/sinclair/Library/Python/2.7/lib/python/site-packages/kivy/uix/screenmanager.pyc in switch_to(self, screen, **options)
    956
    957         # add and leave if we are set as the current screen
--> 958         self.add_widget(screen)
    959         if self.current_screen is screen:
    960             return

/Users/sinclair/Library/Python/2.7/lib/python/site-packages/kivy/uix/screenmanager.pyc in add_widget(self, screen)
    803         if screen.manager:
    804             raise ScreenManagerException(
--> 805                 'Screen already managed by another ScreenManager.')
    806         screen.manager = self
    807         screen.bind(name=self._screen_name_changed)

ScreenManagerException: Screen already managed by another ScreenManager.

In [2]: debug
> /Users/sinclair/Library/Python/2.7/lib/python/site-packages/kivy/uix/screenmanager.py(805)add_widget()
    804             raise ScreenManagerException(
--> 805                 'Screen already managed by another ScreenManager.')
    806         screen.manager = self

ipdb> self
<kivy.uix.screenmanager.ScreenManager object at 0x109017db8>
ipdb> screen.manager
<kivy.uix.screenmanager.ScreenManager object at 0x109017db8>
ipdb>
```



Discussion:
The switch_to method adds the `Screen` to the `ScreenManager`, so this fails when you have already added the `Screen` to it - just like any other case where you attempt to add a `Widget` which already has a parent. You can just update the value of the `current` property to change screens:

```
on_press: self.manager.current = 'new_game_screen'
```

You can change the transition direction at the same time (for supported transition types):

```
on_press: self.manager.transition.direction = 'left'; self.manager.current = 'new_game_screen'
```

OK, yes I get it now. I probably was too quick at opening an issue. Still the error message is misleading, The screen isn't already being managed by _another_ ScreenManager, but by the same, current ScreenManager.

I'm reopening this because, indeed, the error message is misleading. Also, we could implement a helper function which works like `switch_to` for screens already added to the `ScreenManager`, or modify `switch_to` to only add the screen if it has not been added to the current SM yet.

If anyone finds this because he is having the same problem, my solution was to create a dictionary of all screens, that gets populated after the screens themselves are created, so that the screens can all hold a reference to the dictionary that will be filled afterwards:

```
# Dictionary of all screens #
all_screens = {}

# Manager #
from kivy.uix.screenmanager import ScreenManager
screen_manager = ScreenManager()

# Import #
from my_game.screens.splash    import splash_screen
from my_game.screens.new_game  import new_game_screen
from my_game.screens.load_game import load_game_screen

# Populate all screens #
all_screens.update({
    'splash':     splash_screen,
    'new_game':   new_game_screen,
    'load_game':  load_game_screen,
})

# Go to first screen #
screen_manager.switch_to(all_screens['splash'])
```

And in one of the screen files:

```
# Kivy modules #
from kivy.uix.screenmanager import Screen
from kivy.lang import Builder
from kivy.uix.button import Button

# Internal modules #
from my_game.screens import screen_manager, all_screens

# Kivy language #
Builder.load_string("""
<NewGameScreen>:
    BoxLayout:
        ToSplashFromNew:
            text: 'Back to splash'
""")

###############################################################################
class NewGameScreen(Screen):
    def on_release(self):
        pass

class ToSplashFromNew(Button):
    def on_release(self):
        screen_manager.switch_to(all_screens['splash'], direction='right', duration=0.8)
        Button.on_release(self)

###############################################################################
new_game_screen = NewGameScreen(name='new_game')
```

I don't really know if it was intended to be used like that, but that's my take on it ^^


Resolving patch:
diff --git a/kivy/uix/screenmanager.py b/kivy/uix/screenmanager.py
--- a/kivy/uix/screenmanager.py
+++ b/kivy/uix/screenmanager.py
@@ -859,6 +859,11 @@ def add_widget(self, screen):
             raise ScreenManagerException(
                 'ScreenManager accepts only Screen widget.')
         if screen.manager:
+            if screen.manager is self:
+                raise ScreenManagerException(
+                    'Screen already managed by this ScreenManager (are you '
+                    'calling `switch_to` when you should be setting '
+                    '`current`?)')
             raise ScreenManagerException(
                 'Screen already managed by another ScreenManager.')
         screen.manager = self


Test patch: