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

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

Return the current state of the edited playlist.

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

Set the playlist contents.

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

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

def get_selected_index(self) -> int:
122    def get_selected_index(self) -> int:
123        """Return the index of the selected playlist."""
124        return self._selected_index

Return the index of the selected playlist.

def set_selected_index(self, index: int) -> None:
130    def set_selected_index(self, index: int) -> None:
131        """Sets the selected playlist index."""
132        self._selected_index = index

Sets the selected playlist index.

def edit_game_pressed(self) -> None:
141    def edit_game_pressed(self) -> None:
142        """Should be called by supplemental UIs when a game is to be edited."""
143        from ba.internal import getclass
144        if not self._playlist:
145            return
146        self._show_edit_ui(gametype=getclass(
147            self._playlist[self._selected_index]['type'],
148            subclassof=ba.GameActivity),
149                           settings=self._playlist[self._selected_index])

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