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

Window for editing an individual game playlist.

PlaylistEditWindow( editcontroller: bastd.ui.playlist.editcontroller.PlaylistEditController, transition: str = 'in_right')
 20    def __init__(self,
 21                 editcontroller: PlaylistEditController,
 22                 transition: str = 'in_right'):
 23        # pylint: disable=too-many-statements
 24        # pylint: disable=too-many-locals
 25        prev_selection: str | None
 26        self._editcontroller = editcontroller
 27        self._r = 'editGameListWindow'
 28        prev_selection = self._editcontroller.get_edit_ui_selection()
 29
 30        uiscale = ba.app.ui.uiscale
 31        self._width = 770 if uiscale is ba.UIScale.SMALL else 670
 32        x_inset = 50 if uiscale is ba.UIScale.SMALL else 0
 33        self._height = (400 if uiscale is ba.UIScale.SMALL else
 34                        470 if uiscale is ba.UIScale.MEDIUM else 540)
 35
 36        top_extra = 20 if uiscale is ba.UIScale.SMALL else 0
 37        super().__init__(root_widget=ba.containerwidget(
 38            size=(self._width, self._height + top_extra),
 39            transition=transition,
 40            scale=(2.0 if uiscale is ba.UIScale.SMALL else
 41                   1.3 if uiscale is ba.UIScale.MEDIUM else 1.0),
 42            stack_offset=(0, -16) if uiscale is ba.UIScale.SMALL else (0, 0)))
 43        cancel_button = ba.buttonwidget(parent=self._root_widget,
 44                                        position=(35 + x_inset,
 45                                                  self._height - 60),
 46                                        scale=0.8,
 47                                        size=(175, 60),
 48                                        autoselect=True,
 49                                        label=ba.Lstr(resource='cancelText'),
 50                                        text_scale=1.2)
 51        save_button = btn = ba.buttonwidget(
 52            parent=self._root_widget,
 53            position=(self._width - (195 + x_inset), self._height - 60),
 54            scale=0.8,
 55            size=(190, 60),
 56            autoselect=True,
 57            left_widget=cancel_button,
 58            label=ba.Lstr(resource='saveText'),
 59            text_scale=1.2)
 60
 61        if ba.app.ui.use_toolbars:
 62            ba.widget(edit=btn,
 63                      right_widget=_ba.get_special_widget('party_button'))
 64
 65        ba.widget(edit=cancel_button,
 66                  left_widget=cancel_button,
 67                  right_widget=save_button)
 68
 69        ba.textwidget(parent=self._root_widget,
 70                      position=(-10, self._height - 50),
 71                      size=(self._width, 25),
 72                      text=ba.Lstr(resource=self._r + '.titleText'),
 73                      color=ba.app.ui.title_color,
 74                      scale=1.05,
 75                      h_align='center',
 76                      v_align='center',
 77                      maxwidth=270)
 78
 79        v = self._height - 115.0
 80
 81        self._scroll_width = self._width - (205 + 2 * x_inset)
 82
 83        ba.textwidget(parent=self._root_widget,
 84                      text=ba.Lstr(resource=self._r + '.listNameText'),
 85                      position=(196 + x_inset, v + 31),
 86                      maxwidth=150,
 87                      color=(0.8, 0.8, 0.8, 0.5),
 88                      size=(0, 0),
 89                      scale=0.75,
 90                      h_align='right',
 91                      v_align='center')
 92
 93        self._text_field = ba.textwidget(
 94            parent=self._root_widget,
 95            position=(210 + x_inset, v + 7),
 96            size=(self._scroll_width - 53, 43),
 97            text=self._editcontroller.getname(),
 98            h_align='left',
 99            v_align='center',
100            max_chars=40,
101            autoselect=True,
102            color=(0.9, 0.9, 0.9, 1.0),
103            description=ba.Lstr(resource=self._r + '.listNameText'),
104            editable=True,
105            padding=4,
106            on_return_press_call=self._save_press_with_sound)
107        ba.widget(edit=cancel_button, down_widget=self._text_field)
108
109        self._list_widgets: list[ba.Widget] = []
110
111        h = 40 + x_inset
112        v = self._height - 172.0
113
114        b_color = (0.6, 0.53, 0.63)
115        b_textcolor = (0.75, 0.7, 0.8)
116
117        v -= 2.0
118        v += 63
119
120        scl = (1.03 if uiscale is ba.UIScale.SMALL else
121               1.36 if uiscale is ba.UIScale.MEDIUM else 1.74)
122        v -= 63.0 * scl
123
124        add_game_button = ba.buttonwidget(
125            parent=self._root_widget,
126            position=(h, v),
127            size=(110, 61.0 * scl),
128            on_activate_call=self._add,
129            on_select_call=ba.Call(self._set_ui_selection, 'add_button'),
130            autoselect=True,
131            button_type='square',
132            color=b_color,
133            textcolor=b_textcolor,
134            text_scale=0.8,
135            label=ba.Lstr(resource=self._r + '.addGameText'))
136        ba.widget(edit=add_game_button, up_widget=self._text_field)
137        v -= 63.0 * scl
138
139        self._edit_button = edit_game_button = ba.buttonwidget(
140            parent=self._root_widget,
141            position=(h, v),
142            size=(110, 61.0 * scl),
143            on_activate_call=self._edit,
144            on_select_call=ba.Call(self._set_ui_selection, 'editButton'),
145            autoselect=True,
146            button_type='square',
147            color=b_color,
148            textcolor=b_textcolor,
149            text_scale=0.8,
150            label=ba.Lstr(resource=self._r + '.editGameText'))
151        v -= 63.0 * scl
152
153        remove_game_button = ba.buttonwidget(parent=self._root_widget,
154                                             position=(h, v),
155                                             size=(110, 61.0 * scl),
156                                             text_scale=0.8,
157                                             on_activate_call=self._remove,
158                                             autoselect=True,
159                                             button_type='square',
160                                             color=b_color,
161                                             textcolor=b_textcolor,
162                                             label=ba.Lstr(resource=self._r +
163                                                           '.removeGameText'))
164        v -= 40
165        h += 9
166        ba.buttonwidget(parent=self._root_widget,
167                        position=(h, v),
168                        size=(42, 35),
169                        on_activate_call=self._move_up,
170                        label=ba.charstr(ba.SpecialChar.UP_ARROW),
171                        button_type='square',
172                        color=b_color,
173                        textcolor=b_textcolor,
174                        autoselect=True,
175                        repeat=True)
176        h += 52
177        ba.buttonwidget(parent=self._root_widget,
178                        position=(h, v),
179                        size=(42, 35),
180                        on_activate_call=self._move_down,
181                        autoselect=True,
182                        button_type='square',
183                        color=b_color,
184                        textcolor=b_textcolor,
185                        label=ba.charstr(ba.SpecialChar.DOWN_ARROW),
186                        repeat=True)
187
188        v = self._height - 100
189        scroll_height = self._height - 155
190        scrollwidget = ba.scrollwidget(
191            parent=self._root_widget,
192            position=(160 + x_inset, v - scroll_height),
193            highlight=False,
194            on_select_call=ba.Call(self._set_ui_selection, 'gameList'),
195            size=(self._scroll_width, (scroll_height - 15)))
196        ba.widget(edit=scrollwidget,
197                  left_widget=add_game_button,
198                  right_widget=scrollwidget)
199        self._columnwidget = ba.columnwidget(parent=scrollwidget,
200                                             border=2,
201                                             margin=0)
202        ba.widget(edit=self._columnwidget, up_widget=self._text_field)
203
204        for button in [add_game_button, edit_game_button, remove_game_button]:
205            ba.widget(edit=button,
206                      left_widget=button,
207                      right_widget=scrollwidget)
208
209        self._refresh()
210
211        ba.buttonwidget(edit=cancel_button, on_activate_call=self._cancel)
212        ba.containerwidget(edit=self._root_widget,
213                           cancel_button=cancel_button,
214                           selected_child=scrollwidget)
215
216        ba.buttonwidget(edit=save_button, on_activate_call=self._save_press)
217        ba.containerwidget(edit=self._root_widget, start_button=save_button)
218
219        if prev_selection == 'add_button':
220            ba.containerwidget(edit=self._root_widget,
221                               selected_child=add_game_button)
222        elif prev_selection == 'editButton':
223            ba.containerwidget(edit=self._root_widget,
224                               selected_child=edit_game_button)
225        elif prev_selection == 'gameList':
226            ba.containerwidget(edit=self._root_widget,
227                               selected_child=scrollwidget)
Inherited Members
ba.ui.Window
get_root_widget