bauiv1lib.playlist.editcontroller

Defines a controller for wrangling playlist edit UIs.

  1# Released under the MIT License. See LICENSE for details.
  2#
  3"""Defines a controller for wrangling playlist edit UIs."""
  4
  5from __future__ import annotations
  6
  7import copy
  8from typing import TYPE_CHECKING
  9
 10import bascenev1 as bs
 11import bauiv1 as bui
 12
 13if TYPE_CHECKING:
 14    from typing import Any
 15
 16
 17class PlaylistEditController:
 18    """Coordinates various UIs involved in playlist editing."""
 19
 20    def __init__(
 21        self,
 22        sessiontype: type[bs.Session],
 23        existing_playlist_name: str | None = None,
 24        transition: str = 'in_right',
 25        playlist: list[dict[str, Any]] | None = None,
 26        playlist_name: str | None = None,
 27    ):
 28        from bascenev1 import filter_playlist
 29        from bauiv1lib.playlist import PlaylistTypeVars
 30        from bauiv1lib.playlist.edit import PlaylistEditWindow
 31
 32        appconfig = bui.app.config
 33
 34        # Since we may be showing our map list momentarily,
 35        # lets go ahead and preload all map preview textures.
 36        if bui.app.classic is not None:
 37            bui.app.classic.preload_map_preview_media()
 38
 39        self._sessiontype = sessiontype
 40
 41        self._editing_game = False
 42        self._editing_game_type: type[bs.GameActivity] | None = None
 43        self._pvars = PlaylistTypeVars(sessiontype)
 44        self._existing_playlist_name = existing_playlist_name
 45        self._config_name_full = self._pvars.config_name + ' Playlists'
 46
 47        # Make sure config exists.
 48        if self._config_name_full not in appconfig:
 49            appconfig[self._config_name_full] = {}
 50
 51        self._selected_index = 0
 52        if existing_playlist_name:
 53            self._name = existing_playlist_name
 54
 55            # Filter out invalid games.
 56            self._playlist = filter_playlist(
 57                appconfig[self._pvars.config_name + ' Playlists'][
 58                    existing_playlist_name
 59                ],
 60                sessiontype=sessiontype,
 61                remove_unowned=False,
 62                name=existing_playlist_name,
 63            )
 64            self._edit_ui_selection = None
 65        else:
 66            if playlist is not None:
 67                self._playlist = playlist
 68            else:
 69                self._playlist = []
 70            if playlist_name is not None:
 71                self._name = playlist_name
 72            else:
 73                # Find a good unused name.
 74                i = 1
 75                while True:
 76                    self._name = (
 77                        self._pvars.default_new_list_name.evaluate()
 78                        + ((' ' + str(i)) if i > 1 else '')
 79                    )
 80                    if (
 81                        self._name
 82                        not in appconfig[self._pvars.config_name + ' Playlists']
 83                    ):
 84                        break
 85                    i += 1
 86
 87            # Also we want it to start with 'add' highlighted since its empty
 88            # and that's all they can do.
 89            self._edit_ui_selection = 'add_button'
 90
 91        assert bui.app.classic is not None
 92        bui.app.ui_v1.set_main_menu_window(
 93            PlaylistEditWindow(
 94                editcontroller=self, transition=transition
 95            ).get_root_widget(),
 96            from_window=False,  # Disable this check.
 97        )
 98
 99    def get_config_name(self) -> str:
100        """(internal)"""
101        return self._pvars.config_name
102
103    def get_existing_playlist_name(self) -> str | None:
104        """(internal)"""
105        return self._existing_playlist_name
106
107    def get_edit_ui_selection(self) -> str | None:
108        """(internal)"""
109        return self._edit_ui_selection
110
111    def set_edit_ui_selection(self, selection: str) -> None:
112        """(internal)"""
113        self._edit_ui_selection = selection
114
115    def getname(self) -> str:
116        """(internal)"""
117        return self._name
118
119    def setname(self, name: str) -> None:
120        """(internal)"""
121        self._name = name
122
123    def get_playlist(self) -> list[dict[str, Any]]:
124        """Return the current state of the edited playlist."""
125        return copy.deepcopy(self._playlist)
126
127    def set_playlist(self, playlist: list[dict[str, Any]]) -> None:
128        """Set the playlist contents."""
129        self._playlist = copy.deepcopy(playlist)
130
131    def get_session_type(self) -> type[bs.Session]:
132        """Return the bascenev1.Session type for this edit-session."""
133        return self._sessiontype
134
135    def get_selected_index(self) -> int:
136        """Return the index of the selected playlist."""
137        return self._selected_index
138
139    def get_default_list_name(self) -> bui.Lstr:
140        """(internal)"""
141        return self._pvars.default_list_name
142
143    def set_selected_index(self, index: int) -> None:
144        """Sets the selected playlist index."""
145        self._selected_index = index
146
147    def add_game_pressed(self) -> None:
148        """(internal)"""
149        from bauiv1lib.playlist.addgame import PlaylistAddGameWindow
150
151        assert bui.app.classic is not None
152        bui.app.ui_v1.clear_main_menu_window(transition='out_left')
153        bui.app.ui_v1.set_main_menu_window(
154            PlaylistAddGameWindow(editcontroller=self).get_root_widget(),
155            from_window=None,
156        )
157
158    def edit_game_pressed(self) -> None:
159        """Should be called by supplemental UIs when a game is to be edited."""
160
161        if not self._playlist:
162            return
163        self._show_edit_ui(
164            gametype=bui.getclass(
165                self._playlist[self._selected_index]['type'],
166                subclassof=bs.GameActivity,
167            ),
168            settings=self._playlist[self._selected_index],
169        )
170
171    def add_game_cancelled(self) -> None:
172        """(internal)"""
173        from bauiv1lib.playlist.edit import PlaylistEditWindow
174
175        assert bui.app.classic is not None
176        bui.app.ui_v1.clear_main_menu_window(transition='out_right')
177        bui.app.ui_v1.set_main_menu_window(
178            PlaylistEditWindow(
179                editcontroller=self, transition='in_left'
180            ).get_root_widget(),
181            from_window=None,
182        )
183
184    def _show_edit_ui(
185        self, gametype: type[bs.GameActivity], settings: dict[str, Any] | None
186    ) -> None:
187        self._editing_game = settings is not None
188        self._editing_game_type = gametype
189        assert self._sessiontype is not None
190        gametype.create_settings_ui(
191            self._sessiontype, copy.deepcopy(settings), self._edit_game_done
192        )
193
194    def add_game_type_selected(self, gametype: type[bs.GameActivity]) -> None:
195        """(internal)"""
196        self._show_edit_ui(gametype=gametype, settings=None)
197
198    def _edit_game_done(self, config: dict[str, Any] | None) -> None:
199        from bauiv1lib.playlist.edit import PlaylistEditWindow
200        from bauiv1lib.playlist.addgame import PlaylistAddGameWindow
201
202        assert bui.app.classic is not None
203        if config is None:
204            # If we were editing, go back to our list.
205            if self._editing_game:
206                bui.getsound('powerdown01').play()
207                bui.app.ui_v1.clear_main_menu_window(transition='out_right')
208                bui.app.ui_v1.set_main_menu_window(
209                    PlaylistEditWindow(
210                        editcontroller=self, transition='in_left'
211                    ).get_root_widget(),
212                    from_window=None,
213                )
214
215            # Otherwise we were adding; go back to the add type choice list.
216            else:
217                bui.app.ui_v1.clear_main_menu_window(transition='out_right')
218                bui.app.ui_v1.set_main_menu_window(
219                    PlaylistAddGameWindow(
220                        editcontroller=self, transition='in_left'
221                    ).get_root_widget(),
222                    from_window=None,
223                )
224        else:
225            # Make sure type is in there.
226            assert self._editing_game_type is not None
227            config['type'] = bui.get_type_name(self._editing_game_type)
228
229            if self._editing_game:
230                self._playlist[self._selected_index] = copy.deepcopy(config)
231            else:
232                # Add a new entry to the playlist.
233                insert_index = min(
234                    len(self._playlist), self._selected_index + 1
235                )
236                self._playlist.insert(insert_index, copy.deepcopy(config))
237                self._selected_index = insert_index
238
239            bui.getsound('gunCocking').play()
240            bui.app.ui_v1.clear_main_menu_window(transition='out_right')
241            bui.app.ui_v1.set_main_menu_window(
242                PlaylistEditWindow(
243                    editcontroller=self, transition='in_left'
244                ).get_root_widget(),
245                from_window=None,
246            )
class PlaylistEditController:
 18class PlaylistEditController:
 19    """Coordinates various UIs involved in playlist editing."""
 20
 21    def __init__(
 22        self,
 23        sessiontype: type[bs.Session],
 24        existing_playlist_name: str | None = None,
 25        transition: str = 'in_right',
 26        playlist: list[dict[str, Any]] | None = None,
 27        playlist_name: str | None = None,
 28    ):
 29        from bascenev1 import filter_playlist
 30        from bauiv1lib.playlist import PlaylistTypeVars
 31        from bauiv1lib.playlist.edit import PlaylistEditWindow
 32
 33        appconfig = bui.app.config
 34
 35        # Since we may be showing our map list momentarily,
 36        # lets go ahead and preload all map preview textures.
 37        if bui.app.classic is not None:
 38            bui.app.classic.preload_map_preview_media()
 39
 40        self._sessiontype = sessiontype
 41
 42        self._editing_game = False
 43        self._editing_game_type: type[bs.GameActivity] | None = None
 44        self._pvars = PlaylistTypeVars(sessiontype)
 45        self._existing_playlist_name = existing_playlist_name
 46        self._config_name_full = self._pvars.config_name + ' Playlists'
 47
 48        # Make sure config exists.
 49        if self._config_name_full not in appconfig:
 50            appconfig[self._config_name_full] = {}
 51
 52        self._selected_index = 0
 53        if existing_playlist_name:
 54            self._name = existing_playlist_name
 55
 56            # Filter out invalid games.
 57            self._playlist = filter_playlist(
 58                appconfig[self._pvars.config_name + ' Playlists'][
 59                    existing_playlist_name
 60                ],
 61                sessiontype=sessiontype,
 62                remove_unowned=False,
 63                name=existing_playlist_name,
 64            )
 65            self._edit_ui_selection = None
 66        else:
 67            if playlist is not None:
 68                self._playlist = playlist
 69            else:
 70                self._playlist = []
 71            if playlist_name is not None:
 72                self._name = playlist_name
 73            else:
 74                # Find a good unused name.
 75                i = 1
 76                while True:
 77                    self._name = (
 78                        self._pvars.default_new_list_name.evaluate()
 79                        + ((' ' + str(i)) if i > 1 else '')
 80                    )
 81                    if (
 82                        self._name
 83                        not in appconfig[self._pvars.config_name + ' Playlists']
 84                    ):
 85                        break
 86                    i += 1
 87
 88            # Also we want it to start with 'add' highlighted since its empty
 89            # and that's all they can do.
 90            self._edit_ui_selection = 'add_button'
 91
 92        assert bui.app.classic is not None
 93        bui.app.ui_v1.set_main_menu_window(
 94            PlaylistEditWindow(
 95                editcontroller=self, transition=transition
 96            ).get_root_widget(),
 97            from_window=False,  # Disable this check.
 98        )
 99
100    def get_config_name(self) -> str:
101        """(internal)"""
102        return self._pvars.config_name
103
104    def get_existing_playlist_name(self) -> str | None:
105        """(internal)"""
106        return self._existing_playlist_name
107
108    def get_edit_ui_selection(self) -> str | None:
109        """(internal)"""
110        return self._edit_ui_selection
111
112    def set_edit_ui_selection(self, selection: str) -> None:
113        """(internal)"""
114        self._edit_ui_selection = selection
115
116    def getname(self) -> str:
117        """(internal)"""
118        return self._name
119
120    def setname(self, name: str) -> None:
121        """(internal)"""
122        self._name = name
123
124    def get_playlist(self) -> list[dict[str, Any]]:
125        """Return the current state of the edited playlist."""
126        return copy.deepcopy(self._playlist)
127
128    def set_playlist(self, playlist: list[dict[str, Any]]) -> None:
129        """Set the playlist contents."""
130        self._playlist = copy.deepcopy(playlist)
131
132    def get_session_type(self) -> type[bs.Session]:
133        """Return the bascenev1.Session type for this edit-session."""
134        return self._sessiontype
135
136    def get_selected_index(self) -> int:
137        """Return the index of the selected playlist."""
138        return self._selected_index
139
140    def get_default_list_name(self) -> bui.Lstr:
141        """(internal)"""
142        return self._pvars.default_list_name
143
144    def set_selected_index(self, index: int) -> None:
145        """Sets the selected playlist index."""
146        self._selected_index = index
147
148    def add_game_pressed(self) -> None:
149        """(internal)"""
150        from bauiv1lib.playlist.addgame import PlaylistAddGameWindow
151
152        assert bui.app.classic is not None
153        bui.app.ui_v1.clear_main_menu_window(transition='out_left')
154        bui.app.ui_v1.set_main_menu_window(
155            PlaylistAddGameWindow(editcontroller=self).get_root_widget(),
156            from_window=None,
157        )
158
159    def edit_game_pressed(self) -> None:
160        """Should be called by supplemental UIs when a game is to be edited."""
161
162        if not self._playlist:
163            return
164        self._show_edit_ui(
165            gametype=bui.getclass(
166                self._playlist[self._selected_index]['type'],
167                subclassof=bs.GameActivity,
168            ),
169            settings=self._playlist[self._selected_index],
170        )
171
172    def add_game_cancelled(self) -> None:
173        """(internal)"""
174        from bauiv1lib.playlist.edit import PlaylistEditWindow
175
176        assert bui.app.classic is not None
177        bui.app.ui_v1.clear_main_menu_window(transition='out_right')
178        bui.app.ui_v1.set_main_menu_window(
179            PlaylistEditWindow(
180                editcontroller=self, transition='in_left'
181            ).get_root_widget(),
182            from_window=None,
183        )
184
185    def _show_edit_ui(
186        self, gametype: type[bs.GameActivity], settings: dict[str, Any] | None
187    ) -> None:
188        self._editing_game = settings is not None
189        self._editing_game_type = gametype
190        assert self._sessiontype is not None
191        gametype.create_settings_ui(
192            self._sessiontype, copy.deepcopy(settings), self._edit_game_done
193        )
194
195    def add_game_type_selected(self, gametype: type[bs.GameActivity]) -> None:
196        """(internal)"""
197        self._show_edit_ui(gametype=gametype, settings=None)
198
199    def _edit_game_done(self, config: dict[str, Any] | None) -> None:
200        from bauiv1lib.playlist.edit import PlaylistEditWindow
201        from bauiv1lib.playlist.addgame import PlaylistAddGameWindow
202
203        assert bui.app.classic is not None
204        if config is None:
205            # If we were editing, go back to our list.
206            if self._editing_game:
207                bui.getsound('powerdown01').play()
208                bui.app.ui_v1.clear_main_menu_window(transition='out_right')
209                bui.app.ui_v1.set_main_menu_window(
210                    PlaylistEditWindow(
211                        editcontroller=self, transition='in_left'
212                    ).get_root_widget(),
213                    from_window=None,
214                )
215
216            # Otherwise we were adding; go back to the add type choice list.
217            else:
218                bui.app.ui_v1.clear_main_menu_window(transition='out_right')
219                bui.app.ui_v1.set_main_menu_window(
220                    PlaylistAddGameWindow(
221                        editcontroller=self, transition='in_left'
222                    ).get_root_widget(),
223                    from_window=None,
224                )
225        else:
226            # Make sure type is in there.
227            assert self._editing_game_type is not None
228            config['type'] = bui.get_type_name(self._editing_game_type)
229
230            if self._editing_game:
231                self._playlist[self._selected_index] = copy.deepcopy(config)
232            else:
233                # Add a new entry to the playlist.
234                insert_index = min(
235                    len(self._playlist), self._selected_index + 1
236                )
237                self._playlist.insert(insert_index, copy.deepcopy(config))
238                self._selected_index = insert_index
239
240            bui.getsound('gunCocking').play()
241            bui.app.ui_v1.clear_main_menu_window(transition='out_right')
242            bui.app.ui_v1.set_main_menu_window(
243                PlaylistEditWindow(
244                    editcontroller=self, transition='in_left'
245                ).get_root_widget(),
246                from_window=None,
247            )

Coordinates various UIs involved in playlist editing.

PlaylistEditController( sessiontype: type[bascenev1._session.Session], existing_playlist_name: str | None = None, transition: str = 'in_right', playlist: list[dict[str, typing.Any]] | None = None, playlist_name: str | None = None)
21    def __init__(
22        self,
23        sessiontype: type[bs.Session],
24        existing_playlist_name: str | None = None,
25        transition: str = 'in_right',
26        playlist: list[dict[str, Any]] | None = None,
27        playlist_name: str | None = None,
28    ):
29        from bascenev1 import filter_playlist
30        from bauiv1lib.playlist import PlaylistTypeVars
31        from bauiv1lib.playlist.edit import PlaylistEditWindow
32
33        appconfig = bui.app.config
34
35        # Since we may be showing our map list momentarily,
36        # lets go ahead and preload all map preview textures.
37        if bui.app.classic is not None:
38            bui.app.classic.preload_map_preview_media()
39
40        self._sessiontype = sessiontype
41
42        self._editing_game = False
43        self._editing_game_type: type[bs.GameActivity] | None = None
44        self._pvars = PlaylistTypeVars(sessiontype)
45        self._existing_playlist_name = existing_playlist_name
46        self._config_name_full = self._pvars.config_name + ' Playlists'
47
48        # Make sure config exists.
49        if self._config_name_full not in appconfig:
50            appconfig[self._config_name_full] = {}
51
52        self._selected_index = 0
53        if existing_playlist_name:
54            self._name = existing_playlist_name
55
56            # Filter out invalid games.
57            self._playlist = filter_playlist(
58                appconfig[self._pvars.config_name + ' Playlists'][
59                    existing_playlist_name
60                ],
61                sessiontype=sessiontype,
62                remove_unowned=False,
63                name=existing_playlist_name,
64            )
65            self._edit_ui_selection = None
66        else:
67            if playlist is not None:
68                self._playlist = playlist
69            else:
70                self._playlist = []
71            if playlist_name is not None:
72                self._name = playlist_name
73            else:
74                # Find a good unused name.
75                i = 1
76                while True:
77                    self._name = (
78                        self._pvars.default_new_list_name.evaluate()
79                        + ((' ' + str(i)) if i > 1 else '')
80                    )
81                    if (
82                        self._name
83                        not in appconfig[self._pvars.config_name + ' Playlists']
84                    ):
85                        break
86                    i += 1
87
88            # Also we want it to start with 'add' highlighted since its empty
89            # and that's all they can do.
90            self._edit_ui_selection = 'add_button'
91
92        assert bui.app.classic is not None
93        bui.app.ui_v1.set_main_menu_window(
94            PlaylistEditWindow(
95                editcontroller=self, transition=transition
96            ).get_root_widget(),
97            from_window=False,  # Disable this check.
98        )
def get_playlist(self) -> list[dict[str, typing.Any]]:
124    def get_playlist(self) -> list[dict[str, Any]]:
125        """Return the current state of the edited playlist."""
126        return copy.deepcopy(self._playlist)

Return the current state of the edited playlist.

def set_playlist(self, playlist: list[dict[str, typing.Any]]) -> None:
128    def set_playlist(self, playlist: list[dict[str, Any]]) -> None:
129        """Set the playlist contents."""
130        self._playlist = copy.deepcopy(playlist)

Set the playlist contents.

def get_session_type(self) -> type[bascenev1._session.Session]:
132    def get_session_type(self) -> type[bs.Session]:
133        """Return the bascenev1.Session type for this edit-session."""
134        return self._sessiontype

Return the bascenev1.Session type for this edit-session.

def get_selected_index(self) -> int:
136    def get_selected_index(self) -> int:
137        """Return the index of the selected playlist."""
138        return self._selected_index

Return the index of the selected playlist.

def set_selected_index(self, index: int) -> None:
144    def set_selected_index(self, index: int) -> None:
145        """Sets the selected playlist index."""
146        self._selected_index = index

Sets the selected playlist index.

def edit_game_pressed(self) -> None:
159    def edit_game_pressed(self) -> None:
160        """Should be called by supplemental UIs when a game is to be edited."""
161
162        if not self._playlist:
163            return
164        self._show_edit_ui(
165            gametype=bui.getclass(
166                self._playlist[self._selected_index]['type'],
167                subclassof=bs.GameActivity,
168            ),
169            settings=self._playlist[self._selected_index],
170        )

Should be called by supplemental UIs when a game is to be edited.