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