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

Coordinates various UIs involved in playlist editing.

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

Return the current state of the edited playlist.

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

Set the playlist contents.

def get_session_type(self) -> type[ba._session.Session]:
128    def get_session_type(self) -> type[ba.Session]:
129        """Return the ba.Session type for this edit-session."""
130        return self._sessiontype

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

def get_selected_index(self) -> int:
132    def get_selected_index(self) -> int:
133        """Return the index of the selected playlist."""
134        return self._selected_index

Return the index of the selected playlist.

def set_selected_index(self, index: int) -> None:
140    def set_selected_index(self, index: int) -> None:
141        """Sets the selected playlist index."""
142        self._selected_index = index

Sets the selected playlist index.

def edit_game_pressed(self) -> None:
153    def edit_game_pressed(self) -> None:
154        """Should be called by supplemental UIs when a game is to be edited."""
155        from ba.internal import getclass
156
157        if not self._playlist:
158            return
159        self._show_edit_ui(
160            gametype=getclass(
161                self._playlist[self._selected_index]['type'],
162                subclassof=ba.GameActivity,
163            ),
164            settings=self._playlist[self._selected_index],
165        )

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