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        )
 97
 98    def get_config_name(self) -> str:
 99        """(internal)"""
100        return self._pvars.config_name
101
102    def get_existing_playlist_name(self) -> str | None:
103        """(internal)"""
104        return self._existing_playlist_name
105
106    def get_edit_ui_selection(self) -> str | None:
107        """(internal)"""
108        return self._edit_ui_selection
109
110    def set_edit_ui_selection(self, selection: str) -> None:
111        """(internal)"""
112        self._edit_ui_selection = selection
113
114    def getname(self) -> str:
115        """(internal)"""
116        return self._name
117
118    def setname(self, name: str) -> None:
119        """(internal)"""
120        self._name = name
121
122    def get_playlist(self) -> list[dict[str, Any]]:
123        """Return the current state of the edited playlist."""
124        return copy.deepcopy(self._playlist)
125
126    def set_playlist(self, playlist: list[dict[str, Any]]) -> None:
127        """Set the playlist contents."""
128        self._playlist = copy.deepcopy(playlist)
129
130    def get_session_type(self) -> type[bs.Session]:
131        """Return the bascenev1.Session type for this edit-session."""
132        return self._sessiontype
133
134    def get_selected_index(self) -> int:
135        """Return the index of the selected playlist."""
136        return self._selected_index
137
138    def get_default_list_name(self) -> bui.Lstr:
139        """(internal)"""
140        return self._pvars.default_list_name
141
142    def set_selected_index(self, index: int) -> None:
143        """Sets the selected playlist index."""
144        self._selected_index = index
145
146    def add_game_pressed(self) -> None:
147        """(internal)"""
148        from bauiv1lib.playlist.addgame import PlaylistAddGameWindow
149
150        assert bui.app.classic is not None
151        bui.app.ui_v1.clear_main_menu_window(transition='out_left')
152        bui.app.ui_v1.set_main_menu_window(
153            PlaylistAddGameWindow(editcontroller=self).get_root_widget()
154        )
155
156    def edit_game_pressed(self) -> None:
157        """Should be called by supplemental UIs when a game is to be edited."""
158
159        if not self._playlist:
160            return
161        self._show_edit_ui(
162            gametype=bui.getclass(
163                self._playlist[self._selected_index]['type'],
164                subclassof=bs.GameActivity,
165            ),
166            settings=self._playlist[self._selected_index],
167        )
168
169    def add_game_cancelled(self) -> None:
170        """(internal)"""
171        from bauiv1lib.playlist.edit import PlaylistEditWindow
172
173        assert bui.app.classic is not None
174        bui.app.ui_v1.clear_main_menu_window(transition='out_right')
175        bui.app.ui_v1.set_main_menu_window(
176            PlaylistEditWindow(
177                editcontroller=self, transition='in_left'
178            ).get_root_widget()
179        )
180
181    def _show_edit_ui(
182        self, gametype: type[bs.GameActivity], settings: dict[str, Any] | None
183    ) -> None:
184        self._editing_game = settings is not None
185        self._editing_game_type = gametype
186        assert self._sessiontype is not None
187        gametype.create_settings_ui(
188            self._sessiontype, copy.deepcopy(settings), self._edit_game_done
189        )
190
191    def add_game_type_selected(self, gametype: type[bs.GameActivity]) -> None:
192        """(internal)"""
193        self._show_edit_ui(gametype=gametype, settings=None)
194
195    def _edit_game_done(self, config: dict[str, Any] | None) -> None:
196        from bauiv1lib.playlist.edit import PlaylistEditWindow
197        from bauiv1lib.playlist.addgame import PlaylistAddGameWindow
198
199        assert bui.app.classic is not None
200        if config is None:
201            # If we were editing, go back to our list.
202            if self._editing_game:
203                bui.getsound('powerdown01').play()
204                bui.app.ui_v1.clear_main_menu_window(transition='out_right')
205                bui.app.ui_v1.set_main_menu_window(
206                    PlaylistEditWindow(
207                        editcontroller=self, transition='in_left'
208                    ).get_root_widget()
209                )
210
211            # Otherwise we were adding; go back to the add type choice list.
212            else:
213                bui.app.ui_v1.clear_main_menu_window(transition='out_right')
214                bui.app.ui_v1.set_main_menu_window(
215                    PlaylistAddGameWindow(
216                        editcontroller=self, transition='in_left'
217                    ).get_root_widget()
218                )
219        else:
220            # Make sure type is in there.
221            assert self._editing_game_type is not None
222            config['type'] = bui.get_type_name(self._editing_game_type)
223
224            if self._editing_game:
225                self._playlist[self._selected_index] = copy.deepcopy(config)
226            else:
227                # Add a new entry to the playlist.
228                insert_index = min(
229                    len(self._playlist), self._selected_index + 1
230                )
231                self._playlist.insert(insert_index, copy.deepcopy(config))
232                self._selected_index = insert_index
233
234            bui.getsound('gunCocking').play()
235            bui.app.ui_v1.clear_main_menu_window(transition='out_right')
236            bui.app.ui_v1.set_main_menu_window(
237                PlaylistEditWindow(
238                    editcontroller=self, transition='in_left'
239                ).get_root_widget()
240            )
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        )
 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        )
156
157    def edit_game_pressed(self) -> None:
158        """Should be called by supplemental UIs when a game is to be edited."""
159
160        if not self._playlist:
161            return
162        self._show_edit_ui(
163            gametype=bui.getclass(
164                self._playlist[self._selected_index]['type'],
165                subclassof=bs.GameActivity,
166            ),
167            settings=self._playlist[self._selected_index],
168        )
169
170    def add_game_cancelled(self) -> None:
171        """(internal)"""
172        from bauiv1lib.playlist.edit import PlaylistEditWindow
173
174        assert bui.app.classic is not None
175        bui.app.ui_v1.clear_main_menu_window(transition='out_right')
176        bui.app.ui_v1.set_main_menu_window(
177            PlaylistEditWindow(
178                editcontroller=self, transition='in_left'
179            ).get_root_widget()
180        )
181
182    def _show_edit_ui(
183        self, gametype: type[bs.GameActivity], settings: dict[str, Any] | None
184    ) -> None:
185        self._editing_game = settings is not None
186        self._editing_game_type = gametype
187        assert self._sessiontype is not None
188        gametype.create_settings_ui(
189            self._sessiontype, copy.deepcopy(settings), self._edit_game_done
190        )
191
192    def add_game_type_selected(self, gametype: type[bs.GameActivity]) -> None:
193        """(internal)"""
194        self._show_edit_ui(gametype=gametype, settings=None)
195
196    def _edit_game_done(self, config: dict[str, Any] | None) -> None:
197        from bauiv1lib.playlist.edit import PlaylistEditWindow
198        from bauiv1lib.playlist.addgame import PlaylistAddGameWindow
199
200        assert bui.app.classic is not None
201        if config is None:
202            # If we were editing, go back to our list.
203            if self._editing_game:
204                bui.getsound('powerdown01').play()
205                bui.app.ui_v1.clear_main_menu_window(transition='out_right')
206                bui.app.ui_v1.set_main_menu_window(
207                    PlaylistEditWindow(
208                        editcontroller=self, transition='in_left'
209                    ).get_root_widget()
210                )
211
212            # Otherwise we were adding; go back to the add type choice list.
213            else:
214                bui.app.ui_v1.clear_main_menu_window(transition='out_right')
215                bui.app.ui_v1.set_main_menu_window(
216                    PlaylistAddGameWindow(
217                        editcontroller=self, transition='in_left'
218                    ).get_root_widget()
219                )
220        else:
221            # Make sure type is in there.
222            assert self._editing_game_type is not None
223            config['type'] = bui.get_type_name(self._editing_game_type)
224
225            if self._editing_game:
226                self._playlist[self._selected_index] = copy.deepcopy(config)
227            else:
228                # Add a new entry to the playlist.
229                insert_index = min(
230                    len(self._playlist), self._selected_index + 1
231                )
232                self._playlist.insert(insert_index, copy.deepcopy(config))
233                self._selected_index = insert_index
234
235            bui.getsound('gunCocking').play()
236            bui.app.ui_v1.clear_main_menu_window(transition='out_right')
237            bui.app.ui_v1.set_main_menu_window(
238                PlaylistEditWindow(
239                    editcontroller=self, transition='in_left'
240                ).get_root_widget()
241            )

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        )
def get_playlist(self) -> list[dict[str, typing.Any]]:
123    def get_playlist(self) -> list[dict[str, Any]]:
124        """Return the current state of the edited playlist."""
125        return copy.deepcopy(self._playlist)

Return the current state of the edited playlist.

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

Set the playlist contents.

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

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

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

Return the index of the selected playlist.

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

Sets the selected playlist index.

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

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