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