Source code for bauiv1lib.playlist.editcontroller

# Released under the MIT License. See LICENSE for details.
#
"""Defines a controller for wrangling playlist edit UIs."""

from __future__ import annotations

import copy
from typing import TYPE_CHECKING

import bascenev1 as bs
import bauiv1 as bui

if TYPE_CHECKING:
    from typing import Any, Callable


[docs] class PlaylistEditController: """Coordinates various UIs involved in playlist editing.""" def __init__( self, sessiontype: type[bs.Session], from_window: bui.MainWindow, *, existing_playlist_name: str | None = None, playlist: list[dict[str, Any]] | None = None, playlist_name: str | None = None, ): from bascenev1 import filter_playlist from bauiv1lib.playlist import PlaylistTypeVars from bauiv1lib.playlist.edit import PlaylistEditWindow appconfig = bui.app.config # Since we may be showing our map list momentarily, # lets go ahead and preload all map preview textures. if bui.app.classic is not None: bui.app.classic.preload_map_preview_media() self._sessiontype = sessiontype self._editing_game = False self._editing_game_type: type[bs.GameActivity] | None = None self._pvars = PlaylistTypeVars(sessiontype) self._existing_playlist_name = existing_playlist_name self._config_name_full = self._pvars.config_name + ' Playlists' self._pre_game_add_state: bui.MainWindowState | None = None self._pre_game_edit_state: bui.MainWindowState | None = None # Make sure config exists. if self._config_name_full not in appconfig: appconfig[self._config_name_full] = {} self._selected_index = 0 if existing_playlist_name: self._name = existing_playlist_name # Filter out invalid games. self._playlist = filter_playlist( appconfig[self._pvars.config_name + ' Playlists'][ existing_playlist_name ], sessiontype=sessiontype, remove_unowned=False, name=existing_playlist_name, ) self._edit_ui_selection = None else: if playlist is not None: self._playlist = playlist else: self._playlist = [] if playlist_name is not None: self._name = playlist_name else: # Find a good unused name. i = 1 while True: self._name = ( self._pvars.default_new_list_name.evaluate() + ((' ' + str(i)) if i > 1 else '') ) if ( self._name not in appconfig[self._pvars.config_name + ' Playlists'] ): break i += 1 # Also we want it to start with 'add' highlighted since its empty # and that's all they can do. self._edit_ui_selection = 'add_button' editwindow = PlaylistEditWindow(editcontroller=self) from_window.main_window_replace(editwindow) # Once we've set our start window, store the back state. We'll # skip back to there once we're fully done. self._back_state = editwindow.main_window_back_state
[docs] def get_config_name(self) -> str: """(internal)""" return self._pvars.config_name
[docs] def get_existing_playlist_name(self) -> str | None: """(internal)""" return self._existing_playlist_name
[docs] def get_edit_ui_selection(self) -> str | None: """(internal)""" return self._edit_ui_selection
[docs] def set_edit_ui_selection(self, selection: str) -> None: """(internal)""" self._edit_ui_selection = selection
[docs] def getname(self) -> str: """(internal)""" return self._name
[docs] def setname(self, name: str) -> None: """(internal)""" self._name = name
[docs] def get_playlist(self) -> list[dict[str, Any]]: """Return the current state of the edited playlist.""" return copy.deepcopy(self._playlist)
[docs] def set_playlist(self, playlist: list[dict[str, Any]]) -> None: """Set the playlist contents.""" self._playlist = copy.deepcopy(playlist)
[docs] def get_session_type(self) -> type[bs.Session]: """Return the bascenev1.Session type for this edit-session.""" return self._sessiontype
[docs] def get_selected_index(self) -> int: """Return the index of the selected playlist.""" return self._selected_index
[docs] def get_default_list_name(self) -> bui.Lstr: """(internal)""" return self._pvars.default_list_name
[docs] def set_selected_index(self, index: int) -> None: """Sets the selected playlist index.""" self._selected_index = index
[docs] def add_game_pressed(self, from_window: bui.MainWindow) -> None: """(internal)""" from bauiv1lib.playlist.addgame import PlaylistAddGameWindow # assert bui.app.classic is not None # No op if we're not in control. if not from_window.main_window_has_control(): return addwindow = PlaylistAddGameWindow(editcontroller=self) from_window.main_window_replace(addwindow) # Once we're there, store the back state. We'll use that to jump # back to our current location once the edit is done. assert self._pre_game_add_state is None self._pre_game_add_state = addwindow.main_window_back_state
[docs] def edit_game_pressed(self, from_window: bui.MainWindow) -> None: """Should be called by supplemental UIs when a game is to be edited.""" if not self._playlist: return self._show_edit_ui( gametype=bui.getclass( self._playlist[self._selected_index]['type'], subclassof=bs.GameActivity, ), settings=self._playlist[self._selected_index], from_window=from_window, )
def _show_edit_ui( self, gametype: type[bs.GameActivity], settings: dict[str, Any] | None, from_window: bui.MainWindow, ) -> None: # pylint: disable=cyclic-import from bauiv1lib.playlist.editgame import PlaylistEditGameWindow if not from_window.main_window_has_control(): return self._editing_game = settings is not None self._editing_game_type = gametype assert self._sessiontype is not None # Jump into an edit window. editwindow = PlaylistEditGameWindow( gametype, self._sessiontype, copy.deepcopy(settings), completion_call=self._edit_game_done, ) from_window.main_window_replace(editwindow) # Once we're there, store the back state. We'll use that to jump # back to our current location once the edit is done. assert self._pre_game_edit_state is None self._pre_game_edit_state = editwindow.main_window_back_state
[docs] def add_game_type_selected( self, gametype: type[bs.GameActivity], from_window: bui.MainWindow ) -> None: """(internal)""" self._show_edit_ui( gametype=gametype, settings=None, from_window=from_window )
def _edit_game_done( self, config: dict[str, Any] | None, from_window: bui.MainWindow ) -> None: # No-op if provided window isn't in charge. if not from_window.main_window_has_control(): return assert bui.app.classic is not None if config is None: bui.getsound('powerdown01').play() else: # Make sure type is in there. assert self._editing_game_type is not None config['type'] = bui.get_type_name(self._editing_game_type) if self._editing_game: self._playlist[self._selected_index] = copy.deepcopy(config) else: # Add a new entry to the playlist. insert_index = min( len(self._playlist), self._selected_index + 1 ) self._playlist.insert(insert_index, copy.deepcopy(config)) self._selected_index = insert_index bui.getsound('gunCocking').play() # If we're adding, jump to before the add started. # Otherwise jump to before the edit started. assert ( self._pre_game_edit_state is not None or self._pre_game_add_state is not None ) if self._pre_game_add_state is not None: from_window.main_window_back_state = self._pre_game_add_state elif self._pre_game_edit_state is not None: from_window.main_window_back_state = self._pre_game_edit_state from_window.main_window_back() self._pre_game_edit_state = None self._pre_game_add_state = None