bauiv1lib.soundtrack.entrytypeselect
Provides UI for selecting soundtrack entry types.
1# Released under the MIT License. See LICENSE for details. 2# 3"""Provides UI for selecting soundtrack entry types.""" 4from __future__ import annotations 5 6import copy 7from typing import TYPE_CHECKING, override 8 9import bauiv1 as bui 10 11if TYPE_CHECKING: 12 from typing import Any, Callable 13 14 15class SoundtrackEntryTypeSelectWindow(bui.MainWindow): 16 """Window for selecting a soundtrack entry type.""" 17 18 def __init__( 19 self, 20 callback: Callable[[Any], Any], 21 current_entry: Any, 22 selection_target_name: str, 23 *, 24 transition: str | None = 'in_right', 25 origin_widget: bui.Widget | None = None, 26 ): 27 # pylint: disable=too-many-locals 28 assert bui.app.classic is not None 29 music = bui.app.classic.music 30 self._r = 'editSoundtrackWindow' 31 32 self._selection_target_name = selection_target_name 33 self._callback = callback 34 self._current_entry = copy.deepcopy(current_entry) 35 36 self._width = 580 37 self._height = 220 38 spacing = 80 39 40 # FIXME: Generalize this so new custom soundtrack types can add 41 # themselves here. 42 do_default = True 43 do_mac_music_app_playlist = music.supports_soundtrack_entry_type( 44 'iTunesPlaylist' 45 ) 46 do_music_file = music.supports_soundtrack_entry_type('musicFile') 47 do_music_folder = music.supports_soundtrack_entry_type('musicFolder') 48 49 if do_mac_music_app_playlist: 50 self._height += spacing 51 if do_music_file: 52 self._height += spacing 53 if do_music_folder: 54 self._height += spacing 55 56 uiscale = bui.app.ui_v1.uiscale 57 58 # NOTE: When something is selected, we close our UI and kick off 59 # another window which then calls us back when its done, so the 60 # standard UI-cleanup-check complains that something is holding 61 # on to our instance after its ui is gone. Should restructure in 62 # a cleaner way, but just disabling that check for now. 63 super().__init__( 64 root_widget=bui.containerwidget( 65 size=(self._width, self._height), 66 scale=( 67 1.7 68 if uiscale is bui.UIScale.SMALL 69 else 1.4 if uiscale is bui.UIScale.MEDIUM else 1.0 70 ), 71 ), 72 cleanupcheck=False, 73 transition=transition, 74 origin_widget=origin_widget, 75 ) 76 btn = bui.buttonwidget( 77 parent=self._root_widget, 78 position=(35, self._height - 65), 79 size=(160, 60), 80 scale=0.8, 81 text_scale=1.2, 82 label=bui.Lstr(resource='cancelText'), 83 on_activate_call=self._on_cancel_press, 84 ) 85 bui.containerwidget(edit=self._root_widget, cancel_button=btn) 86 bui.textwidget( 87 parent=self._root_widget, 88 position=(self._width * 0.5, self._height - 32), 89 size=(0, 0), 90 text=bui.Lstr(resource=f'{self._r}.selectASourceText'), 91 color=bui.app.ui_v1.title_color, 92 maxwidth=230, 93 h_align='center', 94 v_align='center', 95 ) 96 97 bui.textwidget( 98 parent=self._root_widget, 99 position=(self._width * 0.5, self._height - 56), 100 size=(0, 0), 101 text=selection_target_name, 102 color=bui.app.ui_v1.infotextcolor, 103 scale=0.7, 104 maxwidth=230, 105 h_align='center', 106 v_align='center', 107 ) 108 109 v = self._height - 155 110 111 current_entry_type = music.get_soundtrack_entry_type(current_entry) 112 113 if do_default: 114 btn = bui.buttonwidget( 115 parent=self._root_widget, 116 size=(self._width - 100, 60), 117 position=(50, v), 118 label=bui.Lstr(resource=f'{self._r}.useDefaultGameMusicText'), 119 on_activate_call=self._on_default_press, 120 ) 121 if current_entry_type == 'default': 122 bui.containerwidget(edit=self._root_widget, selected_child=btn) 123 v -= spacing 124 125 if do_mac_music_app_playlist: 126 btn = bui.buttonwidget( 127 parent=self._root_widget, 128 size=(self._width - 100, 60), 129 position=(50, v), 130 label=bui.Lstr(resource=f'{self._r}.useITunesPlaylistText'), 131 on_activate_call=self._on_mac_music_app_playlist_press, 132 icon=None, 133 ) 134 if current_entry_type == 'iTunesPlaylist': 135 bui.containerwidget(edit=self._root_widget, selected_child=btn) 136 v -= spacing 137 138 if do_music_file: 139 btn = bui.buttonwidget( 140 parent=self._root_widget, 141 size=(self._width - 100, 60), 142 position=(50, v), 143 label=bui.Lstr(resource=f'{self._r}.useMusicFileText'), 144 on_activate_call=self._on_music_file_press, 145 icon=bui.gettexture('file'), 146 ) 147 if current_entry_type == 'musicFile': 148 bui.containerwidget(edit=self._root_widget, selected_child=btn) 149 v -= spacing 150 151 if do_music_folder: 152 btn = bui.buttonwidget( 153 parent=self._root_widget, 154 size=(self._width - 100, 60), 155 position=(50, v), 156 label=bui.Lstr(resource=f'{self._r}.useMusicFolderText'), 157 on_activate_call=self._on_music_folder_press, 158 icon=bui.gettexture('folder'), 159 icon_color=(1.1, 0.8, 0.2), 160 ) 161 if current_entry_type == 'musicFolder': 162 bui.containerwidget(edit=self._root_widget, selected_child=btn) 163 v -= spacing 164 165 @override 166 def get_main_window_state(self) -> bui.MainWindowState: 167 # Support recreating our window for back/refresh purposes. 168 cls = type(self) 169 170 # Pull these out of self here; if we reference self in the 171 # lambda we'll keep our window alive which is bad. 172 current_entry = self._current_entry 173 callback = self._callback 174 selection_target_name = self._selection_target_name 175 176 return bui.BasicMainWindowState( 177 create_call=lambda transition, origin_widget: cls( 178 transition=transition, 179 origin_widget=origin_widget, 180 current_entry=current_entry, 181 callback=callback, 182 selection_target_name=selection_target_name, 183 ) 184 ) 185 186 def _on_mac_music_app_playlist_press(self) -> None: 187 assert bui.app.classic is not None 188 music = bui.app.classic.music 189 from bauiv1lib.soundtrack.macmusicapp import ( 190 MacMusicAppPlaylistSelectWindow, 191 ) 192 193 # no-op if we're not in control. 194 if not self.main_window_has_control(): 195 return 196 197 current_playlist_entry: str | None 198 if ( 199 music.get_soundtrack_entry_type(self._current_entry) 200 == 'iTunesPlaylist' 201 ): 202 current_playlist_entry = music.get_soundtrack_entry_name( 203 self._current_entry 204 ) 205 else: 206 current_playlist_entry = None 207 208 self.main_window_replace( 209 MacMusicAppPlaylistSelectWindow( 210 self._callback, current_playlist_entry, self._current_entry 211 ) 212 ) 213 214 def _on_music_file_press(self) -> None: 215 from babase import android_get_external_files_dir 216 from baclassic.osmusic import OSMusicPlayer 217 from bauiv1lib.fileselector import FileSelectorWindow 218 219 # no-op if we're not in control. 220 if not self.main_window_has_control(): 221 return 222 223 base_path = android_get_external_files_dir() 224 assert bui.app.classic is not None 225 226 self.main_window_replace( 227 FileSelectorWindow( 228 base_path, 229 callback=self._music_file_selector_cb, 230 show_base_path=False, 231 valid_file_extensions=( 232 OSMusicPlayer.get_valid_music_file_extensions() 233 ), 234 allow_folders=False, 235 ), 236 ) 237 238 def _on_music_folder_press(self) -> None: 239 from bauiv1lib.fileselector import FileSelectorWindow 240 from babase import android_get_external_files_dir 241 242 # no-op if we're not in control. 243 if not self.main_window_has_control(): 244 return 245 246 base_path = android_get_external_files_dir() 247 assert bui.app.classic is not None 248 249 self.main_window_replace( 250 FileSelectorWindow( 251 base_path, 252 callback=self._music_folder_selector_cb, 253 show_base_path=False, 254 valid_file_extensions=[], 255 allow_folders=True, 256 ), 257 ) 258 259 def _music_file_selector_cb(self, result: str | None) -> None: 260 if result is None: 261 self._callback(self._current_entry) 262 else: 263 self._callback({'type': 'musicFile', 'name': result}) 264 265 def _music_folder_selector_cb(self, result: str | None) -> None: 266 if result is None: 267 self._callback(self._current_entry) 268 else: 269 self._callback({'type': 'musicFolder', 'name': result}) 270 271 def _on_default_press(self) -> None: 272 self.main_window_back() 273 self._callback(None) 274 275 def _on_cancel_press(self) -> None: 276 self.main_window_back() 277 self._callback(self._current_entry)
class
SoundtrackEntryTypeSelectWindow(bauiv1._uitypes.MainWindow):
16class SoundtrackEntryTypeSelectWindow(bui.MainWindow): 17 """Window for selecting a soundtrack entry type.""" 18 19 def __init__( 20 self, 21 callback: Callable[[Any], Any], 22 current_entry: Any, 23 selection_target_name: str, 24 *, 25 transition: str | None = 'in_right', 26 origin_widget: bui.Widget | None = None, 27 ): 28 # pylint: disable=too-many-locals 29 assert bui.app.classic is not None 30 music = bui.app.classic.music 31 self._r = 'editSoundtrackWindow' 32 33 self._selection_target_name = selection_target_name 34 self._callback = callback 35 self._current_entry = copy.deepcopy(current_entry) 36 37 self._width = 580 38 self._height = 220 39 spacing = 80 40 41 # FIXME: Generalize this so new custom soundtrack types can add 42 # themselves here. 43 do_default = True 44 do_mac_music_app_playlist = music.supports_soundtrack_entry_type( 45 'iTunesPlaylist' 46 ) 47 do_music_file = music.supports_soundtrack_entry_type('musicFile') 48 do_music_folder = music.supports_soundtrack_entry_type('musicFolder') 49 50 if do_mac_music_app_playlist: 51 self._height += spacing 52 if do_music_file: 53 self._height += spacing 54 if do_music_folder: 55 self._height += spacing 56 57 uiscale = bui.app.ui_v1.uiscale 58 59 # NOTE: When something is selected, we close our UI and kick off 60 # another window which then calls us back when its done, so the 61 # standard UI-cleanup-check complains that something is holding 62 # on to our instance after its ui is gone. Should restructure in 63 # a cleaner way, but just disabling that check for now. 64 super().__init__( 65 root_widget=bui.containerwidget( 66 size=(self._width, self._height), 67 scale=( 68 1.7 69 if uiscale is bui.UIScale.SMALL 70 else 1.4 if uiscale is bui.UIScale.MEDIUM else 1.0 71 ), 72 ), 73 cleanupcheck=False, 74 transition=transition, 75 origin_widget=origin_widget, 76 ) 77 btn = bui.buttonwidget( 78 parent=self._root_widget, 79 position=(35, self._height - 65), 80 size=(160, 60), 81 scale=0.8, 82 text_scale=1.2, 83 label=bui.Lstr(resource='cancelText'), 84 on_activate_call=self._on_cancel_press, 85 ) 86 bui.containerwidget(edit=self._root_widget, cancel_button=btn) 87 bui.textwidget( 88 parent=self._root_widget, 89 position=(self._width * 0.5, self._height - 32), 90 size=(0, 0), 91 text=bui.Lstr(resource=f'{self._r}.selectASourceText'), 92 color=bui.app.ui_v1.title_color, 93 maxwidth=230, 94 h_align='center', 95 v_align='center', 96 ) 97 98 bui.textwidget( 99 parent=self._root_widget, 100 position=(self._width * 0.5, self._height - 56), 101 size=(0, 0), 102 text=selection_target_name, 103 color=bui.app.ui_v1.infotextcolor, 104 scale=0.7, 105 maxwidth=230, 106 h_align='center', 107 v_align='center', 108 ) 109 110 v = self._height - 155 111 112 current_entry_type = music.get_soundtrack_entry_type(current_entry) 113 114 if do_default: 115 btn = bui.buttonwidget( 116 parent=self._root_widget, 117 size=(self._width - 100, 60), 118 position=(50, v), 119 label=bui.Lstr(resource=f'{self._r}.useDefaultGameMusicText'), 120 on_activate_call=self._on_default_press, 121 ) 122 if current_entry_type == 'default': 123 bui.containerwidget(edit=self._root_widget, selected_child=btn) 124 v -= spacing 125 126 if do_mac_music_app_playlist: 127 btn = bui.buttonwidget( 128 parent=self._root_widget, 129 size=(self._width - 100, 60), 130 position=(50, v), 131 label=bui.Lstr(resource=f'{self._r}.useITunesPlaylistText'), 132 on_activate_call=self._on_mac_music_app_playlist_press, 133 icon=None, 134 ) 135 if current_entry_type == 'iTunesPlaylist': 136 bui.containerwidget(edit=self._root_widget, selected_child=btn) 137 v -= spacing 138 139 if do_music_file: 140 btn = bui.buttonwidget( 141 parent=self._root_widget, 142 size=(self._width - 100, 60), 143 position=(50, v), 144 label=bui.Lstr(resource=f'{self._r}.useMusicFileText'), 145 on_activate_call=self._on_music_file_press, 146 icon=bui.gettexture('file'), 147 ) 148 if current_entry_type == 'musicFile': 149 bui.containerwidget(edit=self._root_widget, selected_child=btn) 150 v -= spacing 151 152 if do_music_folder: 153 btn = bui.buttonwidget( 154 parent=self._root_widget, 155 size=(self._width - 100, 60), 156 position=(50, v), 157 label=bui.Lstr(resource=f'{self._r}.useMusicFolderText'), 158 on_activate_call=self._on_music_folder_press, 159 icon=bui.gettexture('folder'), 160 icon_color=(1.1, 0.8, 0.2), 161 ) 162 if current_entry_type == 'musicFolder': 163 bui.containerwidget(edit=self._root_widget, selected_child=btn) 164 v -= spacing 165 166 @override 167 def get_main_window_state(self) -> bui.MainWindowState: 168 # Support recreating our window for back/refresh purposes. 169 cls = type(self) 170 171 # Pull these out of self here; if we reference self in the 172 # lambda we'll keep our window alive which is bad. 173 current_entry = self._current_entry 174 callback = self._callback 175 selection_target_name = self._selection_target_name 176 177 return bui.BasicMainWindowState( 178 create_call=lambda transition, origin_widget: cls( 179 transition=transition, 180 origin_widget=origin_widget, 181 current_entry=current_entry, 182 callback=callback, 183 selection_target_name=selection_target_name, 184 ) 185 ) 186 187 def _on_mac_music_app_playlist_press(self) -> None: 188 assert bui.app.classic is not None 189 music = bui.app.classic.music 190 from bauiv1lib.soundtrack.macmusicapp import ( 191 MacMusicAppPlaylistSelectWindow, 192 ) 193 194 # no-op if we're not in control. 195 if not self.main_window_has_control(): 196 return 197 198 current_playlist_entry: str | None 199 if ( 200 music.get_soundtrack_entry_type(self._current_entry) 201 == 'iTunesPlaylist' 202 ): 203 current_playlist_entry = music.get_soundtrack_entry_name( 204 self._current_entry 205 ) 206 else: 207 current_playlist_entry = None 208 209 self.main_window_replace( 210 MacMusicAppPlaylistSelectWindow( 211 self._callback, current_playlist_entry, self._current_entry 212 ) 213 ) 214 215 def _on_music_file_press(self) -> None: 216 from babase import android_get_external_files_dir 217 from baclassic.osmusic import OSMusicPlayer 218 from bauiv1lib.fileselector import FileSelectorWindow 219 220 # no-op if we're not in control. 221 if not self.main_window_has_control(): 222 return 223 224 base_path = android_get_external_files_dir() 225 assert bui.app.classic is not None 226 227 self.main_window_replace( 228 FileSelectorWindow( 229 base_path, 230 callback=self._music_file_selector_cb, 231 show_base_path=False, 232 valid_file_extensions=( 233 OSMusicPlayer.get_valid_music_file_extensions() 234 ), 235 allow_folders=False, 236 ), 237 ) 238 239 def _on_music_folder_press(self) -> None: 240 from bauiv1lib.fileselector import FileSelectorWindow 241 from babase import android_get_external_files_dir 242 243 # no-op if we're not in control. 244 if not self.main_window_has_control(): 245 return 246 247 base_path = android_get_external_files_dir() 248 assert bui.app.classic is not None 249 250 self.main_window_replace( 251 FileSelectorWindow( 252 base_path, 253 callback=self._music_folder_selector_cb, 254 show_base_path=False, 255 valid_file_extensions=[], 256 allow_folders=True, 257 ), 258 ) 259 260 def _music_file_selector_cb(self, result: str | None) -> None: 261 if result is None: 262 self._callback(self._current_entry) 263 else: 264 self._callback({'type': 'musicFile', 'name': result}) 265 266 def _music_folder_selector_cb(self, result: str | None) -> None: 267 if result is None: 268 self._callback(self._current_entry) 269 else: 270 self._callback({'type': 'musicFolder', 'name': result}) 271 272 def _on_default_press(self) -> None: 273 self.main_window_back() 274 self._callback(None) 275 276 def _on_cancel_press(self) -> None: 277 self.main_window_back() 278 self._callback(self._current_entry)
Window for selecting a soundtrack entry type.
SoundtrackEntryTypeSelectWindow( callback: Callable[[Any], Any], current_entry: Any, selection_target_name: str, *, transition: str | None = 'in_right', origin_widget: _bauiv1.Widget | None = None)
19 def __init__( 20 self, 21 callback: Callable[[Any], Any], 22 current_entry: Any, 23 selection_target_name: str, 24 *, 25 transition: str | None = 'in_right', 26 origin_widget: bui.Widget | None = None, 27 ): 28 # pylint: disable=too-many-locals 29 assert bui.app.classic is not None 30 music = bui.app.classic.music 31 self._r = 'editSoundtrackWindow' 32 33 self._selection_target_name = selection_target_name 34 self._callback = callback 35 self._current_entry = copy.deepcopy(current_entry) 36 37 self._width = 580 38 self._height = 220 39 spacing = 80 40 41 # FIXME: Generalize this so new custom soundtrack types can add 42 # themselves here. 43 do_default = True 44 do_mac_music_app_playlist = music.supports_soundtrack_entry_type( 45 'iTunesPlaylist' 46 ) 47 do_music_file = music.supports_soundtrack_entry_type('musicFile') 48 do_music_folder = music.supports_soundtrack_entry_type('musicFolder') 49 50 if do_mac_music_app_playlist: 51 self._height += spacing 52 if do_music_file: 53 self._height += spacing 54 if do_music_folder: 55 self._height += spacing 56 57 uiscale = bui.app.ui_v1.uiscale 58 59 # NOTE: When something is selected, we close our UI and kick off 60 # another window which then calls us back when its done, so the 61 # standard UI-cleanup-check complains that something is holding 62 # on to our instance after its ui is gone. Should restructure in 63 # a cleaner way, but just disabling that check for now. 64 super().__init__( 65 root_widget=bui.containerwidget( 66 size=(self._width, self._height), 67 scale=( 68 1.7 69 if uiscale is bui.UIScale.SMALL 70 else 1.4 if uiscale is bui.UIScale.MEDIUM else 1.0 71 ), 72 ), 73 cleanupcheck=False, 74 transition=transition, 75 origin_widget=origin_widget, 76 ) 77 btn = bui.buttonwidget( 78 parent=self._root_widget, 79 position=(35, self._height - 65), 80 size=(160, 60), 81 scale=0.8, 82 text_scale=1.2, 83 label=bui.Lstr(resource='cancelText'), 84 on_activate_call=self._on_cancel_press, 85 ) 86 bui.containerwidget(edit=self._root_widget, cancel_button=btn) 87 bui.textwidget( 88 parent=self._root_widget, 89 position=(self._width * 0.5, self._height - 32), 90 size=(0, 0), 91 text=bui.Lstr(resource=f'{self._r}.selectASourceText'), 92 color=bui.app.ui_v1.title_color, 93 maxwidth=230, 94 h_align='center', 95 v_align='center', 96 ) 97 98 bui.textwidget( 99 parent=self._root_widget, 100 position=(self._width * 0.5, self._height - 56), 101 size=(0, 0), 102 text=selection_target_name, 103 color=bui.app.ui_v1.infotextcolor, 104 scale=0.7, 105 maxwidth=230, 106 h_align='center', 107 v_align='center', 108 ) 109 110 v = self._height - 155 111 112 current_entry_type = music.get_soundtrack_entry_type(current_entry) 113 114 if do_default: 115 btn = bui.buttonwidget( 116 parent=self._root_widget, 117 size=(self._width - 100, 60), 118 position=(50, v), 119 label=bui.Lstr(resource=f'{self._r}.useDefaultGameMusicText'), 120 on_activate_call=self._on_default_press, 121 ) 122 if current_entry_type == 'default': 123 bui.containerwidget(edit=self._root_widget, selected_child=btn) 124 v -= spacing 125 126 if do_mac_music_app_playlist: 127 btn = bui.buttonwidget( 128 parent=self._root_widget, 129 size=(self._width - 100, 60), 130 position=(50, v), 131 label=bui.Lstr(resource=f'{self._r}.useITunesPlaylistText'), 132 on_activate_call=self._on_mac_music_app_playlist_press, 133 icon=None, 134 ) 135 if current_entry_type == 'iTunesPlaylist': 136 bui.containerwidget(edit=self._root_widget, selected_child=btn) 137 v -= spacing 138 139 if do_music_file: 140 btn = bui.buttonwidget( 141 parent=self._root_widget, 142 size=(self._width - 100, 60), 143 position=(50, v), 144 label=bui.Lstr(resource=f'{self._r}.useMusicFileText'), 145 on_activate_call=self._on_music_file_press, 146 icon=bui.gettexture('file'), 147 ) 148 if current_entry_type == 'musicFile': 149 bui.containerwidget(edit=self._root_widget, selected_child=btn) 150 v -= spacing 151 152 if do_music_folder: 153 btn = bui.buttonwidget( 154 parent=self._root_widget, 155 size=(self._width - 100, 60), 156 position=(50, v), 157 label=bui.Lstr(resource=f'{self._r}.useMusicFolderText'), 158 on_activate_call=self._on_music_folder_press, 159 icon=bui.gettexture('folder'), 160 icon_color=(1.1, 0.8, 0.2), 161 ) 162 if current_entry_type == 'musicFolder': 163 bui.containerwidget(edit=self._root_widget, selected_child=btn) 164 v -= spacing
Create a MainWindow given a root widget and transition info.
Automatically handles in and out transitions on the provided widget, so there is no need to set transitions when creating it.
166 @override 167 def get_main_window_state(self) -> bui.MainWindowState: 168 # Support recreating our window for back/refresh purposes. 169 cls = type(self) 170 171 # Pull these out of self here; if we reference self in the 172 # lambda we'll keep our window alive which is bad. 173 current_entry = self._current_entry 174 callback = self._callback 175 selection_target_name = self._selection_target_name 176 177 return bui.BasicMainWindowState( 178 create_call=lambda transition, origin_widget: cls( 179 transition=transition, 180 origin_widget=origin_widget, 181 current_entry=current_entry, 182 callback=callback, 183 selection_target_name=selection_target_name, 184 ) 185 )
Return a WindowState to recreate this window, if supported.