bastd.ui.playlist.edit
Provides a window for editing individual game playlists.
1# Released under the MIT License. See LICENSE for details. 2# 3"""Provides a window for editing individual game playlists.""" 4 5from __future__ import annotations 6 7from typing import TYPE_CHECKING, cast 8 9import ba 10import ba.internal 11 12if TYPE_CHECKING: 13 from bastd.ui.playlist.editcontroller import PlaylistEditController 14 15 16class PlaylistEditWindow(ba.Window): 17 """Window for editing an individual game playlist.""" 18 19 def __init__( 20 self, 21 editcontroller: PlaylistEditController, 22 transition: str = 'in_right', 23 ): 24 # pylint: disable=too-many-statements 25 # pylint: disable=too-many-locals 26 prev_selection: str | None 27 self._editcontroller = editcontroller 28 self._r = 'editGameListWindow' 29 prev_selection = self._editcontroller.get_edit_ui_selection() 30 31 uiscale = ba.app.ui.uiscale 32 self._width = 770 if uiscale is ba.UIScale.SMALL else 670 33 x_inset = 50 if uiscale is ba.UIScale.SMALL else 0 34 self._height = ( 35 400 36 if uiscale is ba.UIScale.SMALL 37 else 470 38 if uiscale is ba.UIScale.MEDIUM 39 else 540 40 ) 41 42 top_extra = 20 if uiscale is ba.UIScale.SMALL else 0 43 super().__init__( 44 root_widget=ba.containerwidget( 45 size=(self._width, self._height + top_extra), 46 transition=transition, 47 scale=( 48 2.0 49 if uiscale is ba.UIScale.SMALL 50 else 1.3 51 if uiscale is ba.UIScale.MEDIUM 52 else 1.0 53 ), 54 stack_offset=(0, -16) 55 if uiscale is ba.UIScale.SMALL 56 else (0, 0), 57 ) 58 ) 59 cancel_button = ba.buttonwidget( 60 parent=self._root_widget, 61 position=(35 + x_inset, self._height - 60), 62 scale=0.8, 63 size=(175, 60), 64 autoselect=True, 65 label=ba.Lstr(resource='cancelText'), 66 text_scale=1.2, 67 ) 68 save_button = btn = ba.buttonwidget( 69 parent=self._root_widget, 70 position=(self._width - (195 + x_inset), self._height - 60), 71 scale=0.8, 72 size=(190, 60), 73 autoselect=True, 74 left_widget=cancel_button, 75 label=ba.Lstr(resource='saveText'), 76 text_scale=1.2, 77 ) 78 79 if ba.app.ui.use_toolbars: 80 ba.widget( 81 edit=btn, 82 right_widget=ba.internal.get_special_widget('party_button'), 83 ) 84 85 ba.widget( 86 edit=cancel_button, 87 left_widget=cancel_button, 88 right_widget=save_button, 89 ) 90 91 ba.textwidget( 92 parent=self._root_widget, 93 position=(-10, self._height - 50), 94 size=(self._width, 25), 95 text=ba.Lstr(resource=self._r + '.titleText'), 96 color=ba.app.ui.title_color, 97 scale=1.05, 98 h_align='center', 99 v_align='center', 100 maxwidth=270, 101 ) 102 103 v = self._height - 115.0 104 105 self._scroll_width = self._width - (205 + 2 * x_inset) 106 107 ba.textwidget( 108 parent=self._root_widget, 109 text=ba.Lstr(resource=self._r + '.listNameText'), 110 position=(196 + x_inset, v + 31), 111 maxwidth=150, 112 color=(0.8, 0.8, 0.8, 0.5), 113 size=(0, 0), 114 scale=0.75, 115 h_align='right', 116 v_align='center', 117 ) 118 119 self._text_field = ba.textwidget( 120 parent=self._root_widget, 121 position=(210 + x_inset, v + 7), 122 size=(self._scroll_width - 53, 43), 123 text=self._editcontroller.getname(), 124 h_align='left', 125 v_align='center', 126 max_chars=40, 127 autoselect=True, 128 color=(0.9, 0.9, 0.9, 1.0), 129 description=ba.Lstr(resource=self._r + '.listNameText'), 130 editable=True, 131 padding=4, 132 on_return_press_call=self._save_press_with_sound, 133 ) 134 ba.widget(edit=cancel_button, down_widget=self._text_field) 135 136 self._list_widgets: list[ba.Widget] = [] 137 138 h = 40 + x_inset 139 v = self._height - 172.0 140 141 b_color = (0.6, 0.53, 0.63) 142 b_textcolor = (0.75, 0.7, 0.8) 143 144 v -= 2.0 145 v += 63 146 147 scl = ( 148 1.03 149 if uiscale is ba.UIScale.SMALL 150 else 1.36 151 if uiscale is ba.UIScale.MEDIUM 152 else 1.74 153 ) 154 v -= 63.0 * scl 155 156 add_game_button = ba.buttonwidget( 157 parent=self._root_widget, 158 position=(h, v), 159 size=(110, 61.0 * scl), 160 on_activate_call=self._add, 161 on_select_call=ba.Call(self._set_ui_selection, 'add_button'), 162 autoselect=True, 163 button_type='square', 164 color=b_color, 165 textcolor=b_textcolor, 166 text_scale=0.8, 167 label=ba.Lstr(resource=self._r + '.addGameText'), 168 ) 169 ba.widget(edit=add_game_button, up_widget=self._text_field) 170 v -= 63.0 * scl 171 172 self._edit_button = edit_game_button = ba.buttonwidget( 173 parent=self._root_widget, 174 position=(h, v), 175 size=(110, 61.0 * scl), 176 on_activate_call=self._edit, 177 on_select_call=ba.Call(self._set_ui_selection, 'editButton'), 178 autoselect=True, 179 button_type='square', 180 color=b_color, 181 textcolor=b_textcolor, 182 text_scale=0.8, 183 label=ba.Lstr(resource=self._r + '.editGameText'), 184 ) 185 v -= 63.0 * scl 186 187 remove_game_button = ba.buttonwidget( 188 parent=self._root_widget, 189 position=(h, v), 190 size=(110, 61.0 * scl), 191 text_scale=0.8, 192 on_activate_call=self._remove, 193 autoselect=True, 194 button_type='square', 195 color=b_color, 196 textcolor=b_textcolor, 197 label=ba.Lstr(resource=self._r + '.removeGameText'), 198 ) 199 v -= 40 200 h += 9 201 ba.buttonwidget( 202 parent=self._root_widget, 203 position=(h, v), 204 size=(42, 35), 205 on_activate_call=self._move_up, 206 label=ba.charstr(ba.SpecialChar.UP_ARROW), 207 button_type='square', 208 color=b_color, 209 textcolor=b_textcolor, 210 autoselect=True, 211 repeat=True, 212 ) 213 h += 52 214 ba.buttonwidget( 215 parent=self._root_widget, 216 position=(h, v), 217 size=(42, 35), 218 on_activate_call=self._move_down, 219 autoselect=True, 220 button_type='square', 221 color=b_color, 222 textcolor=b_textcolor, 223 label=ba.charstr(ba.SpecialChar.DOWN_ARROW), 224 repeat=True, 225 ) 226 227 v = self._height - 100 228 scroll_height = self._height - 155 229 scrollwidget = ba.scrollwidget( 230 parent=self._root_widget, 231 position=(160 + x_inset, v - scroll_height), 232 highlight=False, 233 on_select_call=ba.Call(self._set_ui_selection, 'gameList'), 234 size=(self._scroll_width, (scroll_height - 15)), 235 ) 236 ba.widget( 237 edit=scrollwidget, 238 left_widget=add_game_button, 239 right_widget=scrollwidget, 240 ) 241 self._columnwidget = ba.columnwidget( 242 parent=scrollwidget, border=2, margin=0 243 ) 244 ba.widget(edit=self._columnwidget, up_widget=self._text_field) 245 246 for button in [add_game_button, edit_game_button, remove_game_button]: 247 ba.widget( 248 edit=button, left_widget=button, right_widget=scrollwidget 249 ) 250 251 self._refresh() 252 253 ba.buttonwidget(edit=cancel_button, on_activate_call=self._cancel) 254 ba.containerwidget( 255 edit=self._root_widget, 256 cancel_button=cancel_button, 257 selected_child=scrollwidget, 258 ) 259 260 ba.buttonwidget(edit=save_button, on_activate_call=self._save_press) 261 ba.containerwidget(edit=self._root_widget, start_button=save_button) 262 263 if prev_selection == 'add_button': 264 ba.containerwidget( 265 edit=self._root_widget, selected_child=add_game_button 266 ) 267 elif prev_selection == 'editButton': 268 ba.containerwidget( 269 edit=self._root_widget, selected_child=edit_game_button 270 ) 271 elif prev_selection == 'gameList': 272 ba.containerwidget( 273 edit=self._root_widget, selected_child=scrollwidget 274 ) 275 276 def _set_ui_selection(self, selection: str) -> None: 277 self._editcontroller.set_edit_ui_selection(selection) 278 279 def _cancel(self) -> None: 280 from bastd.ui.playlist.customizebrowser import ( 281 PlaylistCustomizeBrowserWindow, 282 ) 283 284 ba.playsound(ba.getsound('powerdown01')) 285 ba.containerwidget(edit=self._root_widget, transition='out_right') 286 ba.app.ui.set_main_menu_window( 287 PlaylistCustomizeBrowserWindow( 288 transition='in_left', 289 sessiontype=self._editcontroller.get_session_type(), 290 select_playlist=( 291 self._editcontroller.get_existing_playlist_name() 292 ), 293 ).get_root_widget() 294 ) 295 296 def _add(self) -> None: 297 # Store list name then tell the session to perform an add. 298 self._editcontroller.setname( 299 cast(str, ba.textwidget(query=self._text_field)) 300 ) 301 self._editcontroller.add_game_pressed() 302 303 def _edit(self) -> None: 304 # Store list name then tell the session to perform an add. 305 self._editcontroller.setname( 306 cast(str, ba.textwidget(query=self._text_field)) 307 ) 308 self._editcontroller.edit_game_pressed() 309 310 def _save_press(self) -> None: 311 from bastd.ui.playlist.customizebrowser import ( 312 PlaylistCustomizeBrowserWindow, 313 ) 314 315 new_name = cast(str, ba.textwidget(query=self._text_field)) 316 if ( 317 new_name != self._editcontroller.get_existing_playlist_name() 318 and new_name 319 in ba.app.config[ 320 self._editcontroller.get_config_name() + ' Playlists' 321 ] 322 ): 323 ba.screenmessage( 324 ba.Lstr(resource=self._r + '.cantSaveAlreadyExistsText') 325 ) 326 ba.playsound(ba.getsound('error')) 327 return 328 if not new_name: 329 ba.playsound(ba.getsound('error')) 330 return 331 if not self._editcontroller.get_playlist(): 332 ba.screenmessage( 333 ba.Lstr(resource=self._r + '.cantSaveEmptyListText') 334 ) 335 ba.playsound(ba.getsound('error')) 336 return 337 338 # We couldn't actually replace the default list anyway, but disallow 339 # using its exact name to avoid confusion. 340 if new_name == self._editcontroller.get_default_list_name().evaluate(): 341 ba.screenmessage( 342 ba.Lstr(resource=self._r + '.cantOverwriteDefaultText') 343 ) 344 ba.playsound(ba.getsound('error')) 345 return 346 347 # If we had an old one, delete it. 348 if self._editcontroller.get_existing_playlist_name() is not None: 349 ba.internal.add_transaction( 350 { 351 'type': 'REMOVE_PLAYLIST', 352 'playlistType': self._editcontroller.get_config_name(), 353 'playlistName': ( 354 self._editcontroller.get_existing_playlist_name() 355 ), 356 } 357 ) 358 359 ba.internal.add_transaction( 360 { 361 'type': 'ADD_PLAYLIST', 362 'playlistType': self._editcontroller.get_config_name(), 363 'playlistName': new_name, 364 'playlist': self._editcontroller.get_playlist(), 365 } 366 ) 367 ba.internal.run_transactions() 368 369 ba.containerwidget(edit=self._root_widget, transition='out_right') 370 ba.playsound(ba.getsound('gunCocking')) 371 ba.app.ui.set_main_menu_window( 372 PlaylistCustomizeBrowserWindow( 373 transition='in_left', 374 sessiontype=self._editcontroller.get_session_type(), 375 select_playlist=new_name, 376 ).get_root_widget() 377 ) 378 379 def _save_press_with_sound(self) -> None: 380 ba.playsound(ba.getsound('swish')) 381 self._save_press() 382 383 def _select(self, index: int) -> None: 384 self._editcontroller.set_selected_index(index) 385 386 def _refresh(self) -> None: 387 from ba.internal import getclass 388 389 # Need to grab this here as rebuilding the list will 390 # change it otherwise. 391 old_selection_index = self._editcontroller.get_selected_index() 392 393 while self._list_widgets: 394 self._list_widgets.pop().delete() 395 for index, pentry in enumerate(self._editcontroller.get_playlist()): 396 397 try: 398 cls = getclass(pentry['type'], subclassof=ba.GameActivity) 399 desc = cls.get_settings_display_string(pentry) 400 except Exception: 401 ba.print_exception() 402 desc = "(invalid: '" + pentry['type'] + "')" 403 404 txtw = ba.textwidget( 405 parent=self._columnwidget, 406 size=(self._width - 80, 30), 407 on_select_call=ba.Call(self._select, index), 408 always_highlight=True, 409 color=(0.8, 0.8, 0.8, 1.0), 410 padding=0, 411 maxwidth=self._scroll_width * 0.93, 412 text=desc, 413 on_activate_call=self._edit_button.activate, 414 v_align='center', 415 selectable=True, 416 ) 417 ba.widget(edit=txtw, show_buffer_top=50, show_buffer_bottom=50) 418 419 # Wanna be able to jump up to the text field from the top one. 420 if index == 0: 421 ba.widget(edit=txtw, up_widget=self._text_field) 422 self._list_widgets.append(txtw) 423 if old_selection_index == index: 424 ba.columnwidget( 425 edit=self._columnwidget, 426 selected_child=txtw, 427 visible_child=txtw, 428 ) 429 430 def _move_down(self) -> None: 431 playlist = self._editcontroller.get_playlist() 432 index = self._editcontroller.get_selected_index() 433 if index >= len(playlist) - 1: 434 return 435 tmp = playlist[index] 436 playlist[index] = playlist[index + 1] 437 playlist[index + 1] = tmp 438 index += 1 439 self._editcontroller.set_playlist(playlist) 440 self._editcontroller.set_selected_index(index) 441 self._refresh() 442 443 def _move_up(self) -> None: 444 playlist = self._editcontroller.get_playlist() 445 index = self._editcontroller.get_selected_index() 446 if index < 1: 447 return 448 tmp = playlist[index] 449 playlist[index] = playlist[index - 1] 450 playlist[index - 1] = tmp 451 index -= 1 452 self._editcontroller.set_playlist(playlist) 453 self._editcontroller.set_selected_index(index) 454 self._refresh() 455 456 def _remove(self) -> None: 457 playlist = self._editcontroller.get_playlist() 458 index = self._editcontroller.get_selected_index() 459 if not playlist: 460 return 461 del playlist[index] 462 if index >= len(playlist): 463 index = len(playlist) - 1 464 self._editcontroller.set_playlist(playlist) 465 self._editcontroller.set_selected_index(index) 466 ba.playsound(ba.getsound('shieldDown')) 467 self._refresh()
class
PlaylistEditWindow(ba.ui.Window):
17class PlaylistEditWindow(ba.Window): 18 """Window for editing an individual game playlist.""" 19 20 def __init__( 21 self, 22 editcontroller: PlaylistEditController, 23 transition: str = 'in_right', 24 ): 25 # pylint: disable=too-many-statements 26 # pylint: disable=too-many-locals 27 prev_selection: str | None 28 self._editcontroller = editcontroller 29 self._r = 'editGameListWindow' 30 prev_selection = self._editcontroller.get_edit_ui_selection() 31 32 uiscale = ba.app.ui.uiscale 33 self._width = 770 if uiscale is ba.UIScale.SMALL else 670 34 x_inset = 50 if uiscale is ba.UIScale.SMALL else 0 35 self._height = ( 36 400 37 if uiscale is ba.UIScale.SMALL 38 else 470 39 if uiscale is ba.UIScale.MEDIUM 40 else 540 41 ) 42 43 top_extra = 20 if uiscale is ba.UIScale.SMALL else 0 44 super().__init__( 45 root_widget=ba.containerwidget( 46 size=(self._width, self._height + top_extra), 47 transition=transition, 48 scale=( 49 2.0 50 if uiscale is ba.UIScale.SMALL 51 else 1.3 52 if uiscale is ba.UIScale.MEDIUM 53 else 1.0 54 ), 55 stack_offset=(0, -16) 56 if uiscale is ba.UIScale.SMALL 57 else (0, 0), 58 ) 59 ) 60 cancel_button = ba.buttonwidget( 61 parent=self._root_widget, 62 position=(35 + x_inset, self._height - 60), 63 scale=0.8, 64 size=(175, 60), 65 autoselect=True, 66 label=ba.Lstr(resource='cancelText'), 67 text_scale=1.2, 68 ) 69 save_button = btn = ba.buttonwidget( 70 parent=self._root_widget, 71 position=(self._width - (195 + x_inset), self._height - 60), 72 scale=0.8, 73 size=(190, 60), 74 autoselect=True, 75 left_widget=cancel_button, 76 label=ba.Lstr(resource='saveText'), 77 text_scale=1.2, 78 ) 79 80 if ba.app.ui.use_toolbars: 81 ba.widget( 82 edit=btn, 83 right_widget=ba.internal.get_special_widget('party_button'), 84 ) 85 86 ba.widget( 87 edit=cancel_button, 88 left_widget=cancel_button, 89 right_widget=save_button, 90 ) 91 92 ba.textwidget( 93 parent=self._root_widget, 94 position=(-10, self._height - 50), 95 size=(self._width, 25), 96 text=ba.Lstr(resource=self._r + '.titleText'), 97 color=ba.app.ui.title_color, 98 scale=1.05, 99 h_align='center', 100 v_align='center', 101 maxwidth=270, 102 ) 103 104 v = self._height - 115.0 105 106 self._scroll_width = self._width - (205 + 2 * x_inset) 107 108 ba.textwidget( 109 parent=self._root_widget, 110 text=ba.Lstr(resource=self._r + '.listNameText'), 111 position=(196 + x_inset, v + 31), 112 maxwidth=150, 113 color=(0.8, 0.8, 0.8, 0.5), 114 size=(0, 0), 115 scale=0.75, 116 h_align='right', 117 v_align='center', 118 ) 119 120 self._text_field = ba.textwidget( 121 parent=self._root_widget, 122 position=(210 + x_inset, v + 7), 123 size=(self._scroll_width - 53, 43), 124 text=self._editcontroller.getname(), 125 h_align='left', 126 v_align='center', 127 max_chars=40, 128 autoselect=True, 129 color=(0.9, 0.9, 0.9, 1.0), 130 description=ba.Lstr(resource=self._r + '.listNameText'), 131 editable=True, 132 padding=4, 133 on_return_press_call=self._save_press_with_sound, 134 ) 135 ba.widget(edit=cancel_button, down_widget=self._text_field) 136 137 self._list_widgets: list[ba.Widget] = [] 138 139 h = 40 + x_inset 140 v = self._height - 172.0 141 142 b_color = (0.6, 0.53, 0.63) 143 b_textcolor = (0.75, 0.7, 0.8) 144 145 v -= 2.0 146 v += 63 147 148 scl = ( 149 1.03 150 if uiscale is ba.UIScale.SMALL 151 else 1.36 152 if uiscale is ba.UIScale.MEDIUM 153 else 1.74 154 ) 155 v -= 63.0 * scl 156 157 add_game_button = ba.buttonwidget( 158 parent=self._root_widget, 159 position=(h, v), 160 size=(110, 61.0 * scl), 161 on_activate_call=self._add, 162 on_select_call=ba.Call(self._set_ui_selection, 'add_button'), 163 autoselect=True, 164 button_type='square', 165 color=b_color, 166 textcolor=b_textcolor, 167 text_scale=0.8, 168 label=ba.Lstr(resource=self._r + '.addGameText'), 169 ) 170 ba.widget(edit=add_game_button, up_widget=self._text_field) 171 v -= 63.0 * scl 172 173 self._edit_button = edit_game_button = ba.buttonwidget( 174 parent=self._root_widget, 175 position=(h, v), 176 size=(110, 61.0 * scl), 177 on_activate_call=self._edit, 178 on_select_call=ba.Call(self._set_ui_selection, 'editButton'), 179 autoselect=True, 180 button_type='square', 181 color=b_color, 182 textcolor=b_textcolor, 183 text_scale=0.8, 184 label=ba.Lstr(resource=self._r + '.editGameText'), 185 ) 186 v -= 63.0 * scl 187 188 remove_game_button = ba.buttonwidget( 189 parent=self._root_widget, 190 position=(h, v), 191 size=(110, 61.0 * scl), 192 text_scale=0.8, 193 on_activate_call=self._remove, 194 autoselect=True, 195 button_type='square', 196 color=b_color, 197 textcolor=b_textcolor, 198 label=ba.Lstr(resource=self._r + '.removeGameText'), 199 ) 200 v -= 40 201 h += 9 202 ba.buttonwidget( 203 parent=self._root_widget, 204 position=(h, v), 205 size=(42, 35), 206 on_activate_call=self._move_up, 207 label=ba.charstr(ba.SpecialChar.UP_ARROW), 208 button_type='square', 209 color=b_color, 210 textcolor=b_textcolor, 211 autoselect=True, 212 repeat=True, 213 ) 214 h += 52 215 ba.buttonwidget( 216 parent=self._root_widget, 217 position=(h, v), 218 size=(42, 35), 219 on_activate_call=self._move_down, 220 autoselect=True, 221 button_type='square', 222 color=b_color, 223 textcolor=b_textcolor, 224 label=ba.charstr(ba.SpecialChar.DOWN_ARROW), 225 repeat=True, 226 ) 227 228 v = self._height - 100 229 scroll_height = self._height - 155 230 scrollwidget = ba.scrollwidget( 231 parent=self._root_widget, 232 position=(160 + x_inset, v - scroll_height), 233 highlight=False, 234 on_select_call=ba.Call(self._set_ui_selection, 'gameList'), 235 size=(self._scroll_width, (scroll_height - 15)), 236 ) 237 ba.widget( 238 edit=scrollwidget, 239 left_widget=add_game_button, 240 right_widget=scrollwidget, 241 ) 242 self._columnwidget = ba.columnwidget( 243 parent=scrollwidget, border=2, margin=0 244 ) 245 ba.widget(edit=self._columnwidget, up_widget=self._text_field) 246 247 for button in [add_game_button, edit_game_button, remove_game_button]: 248 ba.widget( 249 edit=button, left_widget=button, right_widget=scrollwidget 250 ) 251 252 self._refresh() 253 254 ba.buttonwidget(edit=cancel_button, on_activate_call=self._cancel) 255 ba.containerwidget( 256 edit=self._root_widget, 257 cancel_button=cancel_button, 258 selected_child=scrollwidget, 259 ) 260 261 ba.buttonwidget(edit=save_button, on_activate_call=self._save_press) 262 ba.containerwidget(edit=self._root_widget, start_button=save_button) 263 264 if prev_selection == 'add_button': 265 ba.containerwidget( 266 edit=self._root_widget, selected_child=add_game_button 267 ) 268 elif prev_selection == 'editButton': 269 ba.containerwidget( 270 edit=self._root_widget, selected_child=edit_game_button 271 ) 272 elif prev_selection == 'gameList': 273 ba.containerwidget( 274 edit=self._root_widget, selected_child=scrollwidget 275 ) 276 277 def _set_ui_selection(self, selection: str) -> None: 278 self._editcontroller.set_edit_ui_selection(selection) 279 280 def _cancel(self) -> None: 281 from bastd.ui.playlist.customizebrowser import ( 282 PlaylistCustomizeBrowserWindow, 283 ) 284 285 ba.playsound(ba.getsound('powerdown01')) 286 ba.containerwidget(edit=self._root_widget, transition='out_right') 287 ba.app.ui.set_main_menu_window( 288 PlaylistCustomizeBrowserWindow( 289 transition='in_left', 290 sessiontype=self._editcontroller.get_session_type(), 291 select_playlist=( 292 self._editcontroller.get_existing_playlist_name() 293 ), 294 ).get_root_widget() 295 ) 296 297 def _add(self) -> None: 298 # Store list name then tell the session to perform an add. 299 self._editcontroller.setname( 300 cast(str, ba.textwidget(query=self._text_field)) 301 ) 302 self._editcontroller.add_game_pressed() 303 304 def _edit(self) -> None: 305 # Store list name then tell the session to perform an add. 306 self._editcontroller.setname( 307 cast(str, ba.textwidget(query=self._text_field)) 308 ) 309 self._editcontroller.edit_game_pressed() 310 311 def _save_press(self) -> None: 312 from bastd.ui.playlist.customizebrowser import ( 313 PlaylistCustomizeBrowserWindow, 314 ) 315 316 new_name = cast(str, ba.textwidget(query=self._text_field)) 317 if ( 318 new_name != self._editcontroller.get_existing_playlist_name() 319 and new_name 320 in ba.app.config[ 321 self._editcontroller.get_config_name() + ' Playlists' 322 ] 323 ): 324 ba.screenmessage( 325 ba.Lstr(resource=self._r + '.cantSaveAlreadyExistsText') 326 ) 327 ba.playsound(ba.getsound('error')) 328 return 329 if not new_name: 330 ba.playsound(ba.getsound('error')) 331 return 332 if not self._editcontroller.get_playlist(): 333 ba.screenmessage( 334 ba.Lstr(resource=self._r + '.cantSaveEmptyListText') 335 ) 336 ba.playsound(ba.getsound('error')) 337 return 338 339 # We couldn't actually replace the default list anyway, but disallow 340 # using its exact name to avoid confusion. 341 if new_name == self._editcontroller.get_default_list_name().evaluate(): 342 ba.screenmessage( 343 ba.Lstr(resource=self._r + '.cantOverwriteDefaultText') 344 ) 345 ba.playsound(ba.getsound('error')) 346 return 347 348 # If we had an old one, delete it. 349 if self._editcontroller.get_existing_playlist_name() is not None: 350 ba.internal.add_transaction( 351 { 352 'type': 'REMOVE_PLAYLIST', 353 'playlistType': self._editcontroller.get_config_name(), 354 'playlistName': ( 355 self._editcontroller.get_existing_playlist_name() 356 ), 357 } 358 ) 359 360 ba.internal.add_transaction( 361 { 362 'type': 'ADD_PLAYLIST', 363 'playlistType': self._editcontroller.get_config_name(), 364 'playlistName': new_name, 365 'playlist': self._editcontroller.get_playlist(), 366 } 367 ) 368 ba.internal.run_transactions() 369 370 ba.containerwidget(edit=self._root_widget, transition='out_right') 371 ba.playsound(ba.getsound('gunCocking')) 372 ba.app.ui.set_main_menu_window( 373 PlaylistCustomizeBrowserWindow( 374 transition='in_left', 375 sessiontype=self._editcontroller.get_session_type(), 376 select_playlist=new_name, 377 ).get_root_widget() 378 ) 379 380 def _save_press_with_sound(self) -> None: 381 ba.playsound(ba.getsound('swish')) 382 self._save_press() 383 384 def _select(self, index: int) -> None: 385 self._editcontroller.set_selected_index(index) 386 387 def _refresh(self) -> None: 388 from ba.internal import getclass 389 390 # Need to grab this here as rebuilding the list will 391 # change it otherwise. 392 old_selection_index = self._editcontroller.get_selected_index() 393 394 while self._list_widgets: 395 self._list_widgets.pop().delete() 396 for index, pentry in enumerate(self._editcontroller.get_playlist()): 397 398 try: 399 cls = getclass(pentry['type'], subclassof=ba.GameActivity) 400 desc = cls.get_settings_display_string(pentry) 401 except Exception: 402 ba.print_exception() 403 desc = "(invalid: '" + pentry['type'] + "')" 404 405 txtw = ba.textwidget( 406 parent=self._columnwidget, 407 size=(self._width - 80, 30), 408 on_select_call=ba.Call(self._select, index), 409 always_highlight=True, 410 color=(0.8, 0.8, 0.8, 1.0), 411 padding=0, 412 maxwidth=self._scroll_width * 0.93, 413 text=desc, 414 on_activate_call=self._edit_button.activate, 415 v_align='center', 416 selectable=True, 417 ) 418 ba.widget(edit=txtw, show_buffer_top=50, show_buffer_bottom=50) 419 420 # Wanna be able to jump up to the text field from the top one. 421 if index == 0: 422 ba.widget(edit=txtw, up_widget=self._text_field) 423 self._list_widgets.append(txtw) 424 if old_selection_index == index: 425 ba.columnwidget( 426 edit=self._columnwidget, 427 selected_child=txtw, 428 visible_child=txtw, 429 ) 430 431 def _move_down(self) -> None: 432 playlist = self._editcontroller.get_playlist() 433 index = self._editcontroller.get_selected_index() 434 if index >= len(playlist) - 1: 435 return 436 tmp = playlist[index] 437 playlist[index] = playlist[index + 1] 438 playlist[index + 1] = tmp 439 index += 1 440 self._editcontroller.set_playlist(playlist) 441 self._editcontroller.set_selected_index(index) 442 self._refresh() 443 444 def _move_up(self) -> None: 445 playlist = self._editcontroller.get_playlist() 446 index = self._editcontroller.get_selected_index() 447 if index < 1: 448 return 449 tmp = playlist[index] 450 playlist[index] = playlist[index - 1] 451 playlist[index - 1] = tmp 452 index -= 1 453 self._editcontroller.set_playlist(playlist) 454 self._editcontroller.set_selected_index(index) 455 self._refresh() 456 457 def _remove(self) -> None: 458 playlist = self._editcontroller.get_playlist() 459 index = self._editcontroller.get_selected_index() 460 if not playlist: 461 return 462 del playlist[index] 463 if index >= len(playlist): 464 index = len(playlist) - 1 465 self._editcontroller.set_playlist(playlist) 466 self._editcontroller.set_selected_index(index) 467 ba.playsound(ba.getsound('shieldDown')) 468 self._refresh()
Window for editing an individual game playlist.
PlaylistEditWindow( editcontroller: bastd.ui.playlist.editcontroller.PlaylistEditController, transition: str = 'in_right')
20 def __init__( 21 self, 22 editcontroller: PlaylistEditController, 23 transition: str = 'in_right', 24 ): 25 # pylint: disable=too-many-statements 26 # pylint: disable=too-many-locals 27 prev_selection: str | None 28 self._editcontroller = editcontroller 29 self._r = 'editGameListWindow' 30 prev_selection = self._editcontroller.get_edit_ui_selection() 31 32 uiscale = ba.app.ui.uiscale 33 self._width = 770 if uiscale is ba.UIScale.SMALL else 670 34 x_inset = 50 if uiscale is ba.UIScale.SMALL else 0 35 self._height = ( 36 400 37 if uiscale is ba.UIScale.SMALL 38 else 470 39 if uiscale is ba.UIScale.MEDIUM 40 else 540 41 ) 42 43 top_extra = 20 if uiscale is ba.UIScale.SMALL else 0 44 super().__init__( 45 root_widget=ba.containerwidget( 46 size=(self._width, self._height + top_extra), 47 transition=transition, 48 scale=( 49 2.0 50 if uiscale is ba.UIScale.SMALL 51 else 1.3 52 if uiscale is ba.UIScale.MEDIUM 53 else 1.0 54 ), 55 stack_offset=(0, -16) 56 if uiscale is ba.UIScale.SMALL 57 else (0, 0), 58 ) 59 ) 60 cancel_button = ba.buttonwidget( 61 parent=self._root_widget, 62 position=(35 + x_inset, self._height - 60), 63 scale=0.8, 64 size=(175, 60), 65 autoselect=True, 66 label=ba.Lstr(resource='cancelText'), 67 text_scale=1.2, 68 ) 69 save_button = btn = ba.buttonwidget( 70 parent=self._root_widget, 71 position=(self._width - (195 + x_inset), self._height - 60), 72 scale=0.8, 73 size=(190, 60), 74 autoselect=True, 75 left_widget=cancel_button, 76 label=ba.Lstr(resource='saveText'), 77 text_scale=1.2, 78 ) 79 80 if ba.app.ui.use_toolbars: 81 ba.widget( 82 edit=btn, 83 right_widget=ba.internal.get_special_widget('party_button'), 84 ) 85 86 ba.widget( 87 edit=cancel_button, 88 left_widget=cancel_button, 89 right_widget=save_button, 90 ) 91 92 ba.textwidget( 93 parent=self._root_widget, 94 position=(-10, self._height - 50), 95 size=(self._width, 25), 96 text=ba.Lstr(resource=self._r + '.titleText'), 97 color=ba.app.ui.title_color, 98 scale=1.05, 99 h_align='center', 100 v_align='center', 101 maxwidth=270, 102 ) 103 104 v = self._height - 115.0 105 106 self._scroll_width = self._width - (205 + 2 * x_inset) 107 108 ba.textwidget( 109 parent=self._root_widget, 110 text=ba.Lstr(resource=self._r + '.listNameText'), 111 position=(196 + x_inset, v + 31), 112 maxwidth=150, 113 color=(0.8, 0.8, 0.8, 0.5), 114 size=(0, 0), 115 scale=0.75, 116 h_align='right', 117 v_align='center', 118 ) 119 120 self._text_field = ba.textwidget( 121 parent=self._root_widget, 122 position=(210 + x_inset, v + 7), 123 size=(self._scroll_width - 53, 43), 124 text=self._editcontroller.getname(), 125 h_align='left', 126 v_align='center', 127 max_chars=40, 128 autoselect=True, 129 color=(0.9, 0.9, 0.9, 1.0), 130 description=ba.Lstr(resource=self._r + '.listNameText'), 131 editable=True, 132 padding=4, 133 on_return_press_call=self._save_press_with_sound, 134 ) 135 ba.widget(edit=cancel_button, down_widget=self._text_field) 136 137 self._list_widgets: list[ba.Widget] = [] 138 139 h = 40 + x_inset 140 v = self._height - 172.0 141 142 b_color = (0.6, 0.53, 0.63) 143 b_textcolor = (0.75, 0.7, 0.8) 144 145 v -= 2.0 146 v += 63 147 148 scl = ( 149 1.03 150 if uiscale is ba.UIScale.SMALL 151 else 1.36 152 if uiscale is ba.UIScale.MEDIUM 153 else 1.74 154 ) 155 v -= 63.0 * scl 156 157 add_game_button = ba.buttonwidget( 158 parent=self._root_widget, 159 position=(h, v), 160 size=(110, 61.0 * scl), 161 on_activate_call=self._add, 162 on_select_call=ba.Call(self._set_ui_selection, 'add_button'), 163 autoselect=True, 164 button_type='square', 165 color=b_color, 166 textcolor=b_textcolor, 167 text_scale=0.8, 168 label=ba.Lstr(resource=self._r + '.addGameText'), 169 ) 170 ba.widget(edit=add_game_button, up_widget=self._text_field) 171 v -= 63.0 * scl 172 173 self._edit_button = edit_game_button = ba.buttonwidget( 174 parent=self._root_widget, 175 position=(h, v), 176 size=(110, 61.0 * scl), 177 on_activate_call=self._edit, 178 on_select_call=ba.Call(self._set_ui_selection, 'editButton'), 179 autoselect=True, 180 button_type='square', 181 color=b_color, 182 textcolor=b_textcolor, 183 text_scale=0.8, 184 label=ba.Lstr(resource=self._r + '.editGameText'), 185 ) 186 v -= 63.0 * scl 187 188 remove_game_button = ba.buttonwidget( 189 parent=self._root_widget, 190 position=(h, v), 191 size=(110, 61.0 * scl), 192 text_scale=0.8, 193 on_activate_call=self._remove, 194 autoselect=True, 195 button_type='square', 196 color=b_color, 197 textcolor=b_textcolor, 198 label=ba.Lstr(resource=self._r + '.removeGameText'), 199 ) 200 v -= 40 201 h += 9 202 ba.buttonwidget( 203 parent=self._root_widget, 204 position=(h, v), 205 size=(42, 35), 206 on_activate_call=self._move_up, 207 label=ba.charstr(ba.SpecialChar.UP_ARROW), 208 button_type='square', 209 color=b_color, 210 textcolor=b_textcolor, 211 autoselect=True, 212 repeat=True, 213 ) 214 h += 52 215 ba.buttonwidget( 216 parent=self._root_widget, 217 position=(h, v), 218 size=(42, 35), 219 on_activate_call=self._move_down, 220 autoselect=True, 221 button_type='square', 222 color=b_color, 223 textcolor=b_textcolor, 224 label=ba.charstr(ba.SpecialChar.DOWN_ARROW), 225 repeat=True, 226 ) 227 228 v = self._height - 100 229 scroll_height = self._height - 155 230 scrollwidget = ba.scrollwidget( 231 parent=self._root_widget, 232 position=(160 + x_inset, v - scroll_height), 233 highlight=False, 234 on_select_call=ba.Call(self._set_ui_selection, 'gameList'), 235 size=(self._scroll_width, (scroll_height - 15)), 236 ) 237 ba.widget( 238 edit=scrollwidget, 239 left_widget=add_game_button, 240 right_widget=scrollwidget, 241 ) 242 self._columnwidget = ba.columnwidget( 243 parent=scrollwidget, border=2, margin=0 244 ) 245 ba.widget(edit=self._columnwidget, up_widget=self._text_field) 246 247 for button in [add_game_button, edit_game_button, remove_game_button]: 248 ba.widget( 249 edit=button, left_widget=button, right_widget=scrollwidget 250 ) 251 252 self._refresh() 253 254 ba.buttonwidget(edit=cancel_button, on_activate_call=self._cancel) 255 ba.containerwidget( 256 edit=self._root_widget, 257 cancel_button=cancel_button, 258 selected_child=scrollwidget, 259 ) 260 261 ba.buttonwidget(edit=save_button, on_activate_call=self._save_press) 262 ba.containerwidget(edit=self._root_widget, start_button=save_button) 263 264 if prev_selection == 'add_button': 265 ba.containerwidget( 266 edit=self._root_widget, selected_child=add_game_button 267 ) 268 elif prev_selection == 'editButton': 269 ba.containerwidget( 270 edit=self._root_widget, selected_child=edit_game_button 271 ) 272 elif prev_selection == 'gameList': 273 ba.containerwidget( 274 edit=self._root_widget, selected_child=scrollwidget 275 )
Inherited Members
- ba.ui.Window
- get_root_widget