bauiv1lib.playlist.addgame

Provides a window for selecting a game type to add to a playlist.

  1# Released under the MIT License. See LICENSE for details.
  2#
  3"""Provides a window for selecting a game type to add to a playlist."""
  4
  5from __future__ import annotations
  6
  7from typing import TYPE_CHECKING
  8
  9import bascenev1 as bs
 10import bauiv1 as bui
 11
 12if TYPE_CHECKING:
 13    from bauiv1lib.playlist.editcontroller import PlaylistEditController
 14
 15
 16class PlaylistAddGameWindow(bui.Window):
 17    """Window for selecting a game type to add to a playlist."""
 18
 19    def __init__(
 20        self,
 21        editcontroller: PlaylistEditController,
 22        transition: str = 'in_right',
 23    ):
 24        self._editcontroller = editcontroller
 25        self._r = 'addGameWindow'
 26        assert bui.app.classic is not None
 27        uiscale = bui.app.ui_v1.uiscale
 28        self._width = 750 if uiscale is bui.UIScale.SMALL else 650
 29        x_inset = 50 if uiscale is bui.UIScale.SMALL else 0
 30        self._height = (
 31            346
 32            if uiscale is bui.UIScale.SMALL
 33            else 380
 34            if uiscale is bui.UIScale.MEDIUM
 35            else 440
 36        )
 37        top_extra = 30 if uiscale is bui.UIScale.SMALL else 20
 38        self._scroll_width = 210
 39
 40        super().__init__(
 41            root_widget=bui.containerwidget(
 42                size=(self._width, self._height + top_extra),
 43                transition=transition,
 44                scale=(
 45                    2.17
 46                    if uiscale is bui.UIScale.SMALL
 47                    else 1.5
 48                    if uiscale is bui.UIScale.MEDIUM
 49                    else 1.0
 50                ),
 51                stack_offset=(0, 1) if uiscale is bui.UIScale.SMALL else (0, 0),
 52            )
 53        )
 54
 55        self._back_button = bui.buttonwidget(
 56            parent=self._root_widget,
 57            position=(58 + x_inset, self._height - 53),
 58            size=(165, 70),
 59            scale=0.75,
 60            text_scale=1.2,
 61            label=bui.Lstr(resource='backText'),
 62            autoselect=True,
 63            button_type='back',
 64            on_activate_call=self._back,
 65        )
 66        self._select_button = select_button = bui.buttonwidget(
 67            parent=self._root_widget,
 68            position=(self._width - (172 + x_inset), self._height - 50),
 69            autoselect=True,
 70            size=(160, 60),
 71            scale=0.75,
 72            text_scale=1.2,
 73            label=bui.Lstr(resource='selectText'),
 74            on_activate_call=self._add,
 75        )
 76
 77        if bui.app.ui_v1.use_toolbars:
 78            bui.widget(
 79                edit=select_button,
 80                right_widget=bui.get_special_widget('party_button'),
 81            )
 82
 83        bui.textwidget(
 84            parent=self._root_widget,
 85            position=(self._width * 0.5, self._height - 28),
 86            size=(0, 0),
 87            scale=1.0,
 88            text=bui.Lstr(resource=self._r + '.titleText'),
 89            h_align='center',
 90            color=bui.app.ui_v1.title_color,
 91            maxwidth=250,
 92            v_align='center',
 93        )
 94        v = self._height - 64
 95
 96        self._selected_title_text = bui.textwidget(
 97            parent=self._root_widget,
 98            position=(x_inset + self._scroll_width + 50 + 30, v - 15),
 99            size=(0, 0),
100            scale=1.0,
101            color=(0.7, 1.0, 0.7, 1.0),
102            maxwidth=self._width - self._scroll_width - 150 - x_inset * 2,
103            h_align='left',
104            v_align='center',
105        )
106        v -= 30
107
108        self._selected_description_text = bui.textwidget(
109            parent=self._root_widget,
110            position=(x_inset + self._scroll_width + 50 + 30, v),
111            size=(0, 0),
112            scale=0.7,
113            color=(0.5, 0.8, 0.5, 1.0),
114            maxwidth=self._width - self._scroll_width - 150 - x_inset * 2,
115            h_align='left',
116        )
117
118        scroll_height = self._height - 100
119
120        v = self._height - 60
121
122        self._scrollwidget = bui.scrollwidget(
123            parent=self._root_widget,
124            position=(x_inset + 61, v - scroll_height),
125            size=(self._scroll_width, scroll_height),
126            highlight=False,
127        )
128        bui.widget(
129            edit=self._scrollwidget,
130            up_widget=self._back_button,
131            left_widget=self._back_button,
132            right_widget=select_button,
133        )
134        self._column: bui.Widget | None = None
135
136        v -= 35
137        bui.containerwidget(
138            edit=self._root_widget,
139            cancel_button=self._back_button,
140            start_button=select_button,
141        )
142        self._selected_game_type: type[bs.GameActivity] | None = None
143
144        bui.containerwidget(
145            edit=self._root_widget, selected_child=self._scrollwidget
146        )
147
148        self._game_types: list[type[bs.GameActivity]] = []
149
150        # Get actual games loading in the bg.
151        bui.app.meta.load_exported_classes(
152            bs.GameActivity,
153            self._on_game_types_loaded,
154            completion_cb_in_bg_thread=True,
155        )
156
157        # Refresh with our initial empty list. We'll refresh again once
158        # game loading is complete.
159        self._refresh()
160
161    def _on_game_types_loaded(
162        self, gametypes: list[type[bs.GameActivity]]
163    ) -> None:
164        assert bui.app.classic is not None
165        store = bui.app.classic.store
166
167        # We asked for a bg thread completion cb so we can do some
168        # filtering here in the bg thread where its not gonna cause hitches.
169        assert not bui.in_logic_thread()
170        sessiontype = self._editcontroller.get_session_type()
171        unowned = store.get_unowned_game_types()
172        self._game_types = [
173            gt
174            for gt in gametypes
175            if gt not in unowned and gt.supports_session_type(sessiontype)
176        ]
177
178        # Sort in the current language.
179        self._game_types.sort(key=lambda g: g.get_display_string().evaluate())
180
181        # Tell ourself to refresh back in the logic thread.
182        bui.pushcall(self._refresh, from_other_thread=True)
183
184    def _refresh(self, select_get_more_games_button: bool = False) -> None:
185        if self._column is not None:
186            self._column.delete()
187
188        self._column = bui.columnwidget(
189            parent=self._scrollwidget, border=2, margin=0
190        )
191
192        for i, gametype in enumerate(self._game_types):
193
194            def _doit() -> None:
195                if self._select_button:
196                    bui.apptimer(0.1, self._select_button.activate)
197
198            txt = bui.textwidget(
199                parent=self._column,
200                position=(0, 0),
201                size=(self._scroll_width * 1.1, 24),
202                text=gametype.get_display_string(),
203                h_align='left',
204                v_align='center',
205                color=(0.8, 0.8, 0.8, 1.0),
206                maxwidth=self._scroll_width * 0.8,
207                on_select_call=bui.Call(self._set_selected_game_type, gametype),
208                always_highlight=True,
209                selectable=True,
210                on_activate_call=_doit,
211            )
212            if i == 0:
213                bui.widget(edit=txt, up_widget=self._back_button)
214
215        self._get_more_games_button = bui.buttonwidget(
216            parent=self._column,
217            autoselect=True,
218            label=bui.Lstr(resource=self._r + '.getMoreGamesText'),
219            color=(0.54, 0.52, 0.67),
220            textcolor=(0.7, 0.65, 0.7),
221            on_activate_call=self._on_get_more_games_press,
222            size=(178, 50),
223        )
224        if select_get_more_games_button:
225            bui.containerwidget(
226                edit=self._column,
227                selected_child=self._get_more_games_button,
228                visible_child=self._get_more_games_button,
229            )
230
231    def _on_get_more_games_press(self) -> None:
232        from bauiv1lib.account import show_sign_in_prompt
233        from bauiv1lib.store.browser import StoreBrowserWindow
234
235        plus = bui.app.plus
236        assert plus is not None
237
238        if plus.get_v1_account_state() != 'signed_in':
239            show_sign_in_prompt()
240            return
241        StoreBrowserWindow(
242            modal=True,
243            show_tab=StoreBrowserWindow.TabID.MINIGAMES,
244            on_close_call=self._on_store_close,
245            origin_widget=self._get_more_games_button,
246        )
247
248    def _on_store_close(self) -> None:
249        self._refresh(select_get_more_games_button=True)
250
251    def _add(self) -> None:
252        bui.lock_all_input()  # Make sure no more commands happen.
253        bui.apptimer(0.1, bui.unlock_all_input)
254        assert self._selected_game_type is not None
255        self._editcontroller.add_game_type_selected(self._selected_game_type)
256
257    def _set_selected_game_type(self, gametype: type[bs.GameActivity]) -> None:
258        self._selected_game_type = gametype
259        bui.textwidget(
260            edit=self._selected_title_text, text=gametype.get_display_string()
261        )
262        bui.textwidget(
263            edit=self._selected_description_text,
264            text=gametype.get_description_display_string(
265                self._editcontroller.get_session_type()
266            ),
267        )
268
269    def _back(self) -> None:
270        self._editcontroller.add_game_cancelled()
class PlaylistAddGameWindow(bauiv1._uitypes.Window):
 17class PlaylistAddGameWindow(bui.Window):
 18    """Window for selecting a game type to add to a playlist."""
 19
 20    def __init__(
 21        self,
 22        editcontroller: PlaylistEditController,
 23        transition: str = 'in_right',
 24    ):
 25        self._editcontroller = editcontroller
 26        self._r = 'addGameWindow'
 27        assert bui.app.classic is not None
 28        uiscale = bui.app.ui_v1.uiscale
 29        self._width = 750 if uiscale is bui.UIScale.SMALL else 650
 30        x_inset = 50 if uiscale is bui.UIScale.SMALL else 0
 31        self._height = (
 32            346
 33            if uiscale is bui.UIScale.SMALL
 34            else 380
 35            if uiscale is bui.UIScale.MEDIUM
 36            else 440
 37        )
 38        top_extra = 30 if uiscale is bui.UIScale.SMALL else 20
 39        self._scroll_width = 210
 40
 41        super().__init__(
 42            root_widget=bui.containerwidget(
 43                size=(self._width, self._height + top_extra),
 44                transition=transition,
 45                scale=(
 46                    2.17
 47                    if uiscale is bui.UIScale.SMALL
 48                    else 1.5
 49                    if uiscale is bui.UIScale.MEDIUM
 50                    else 1.0
 51                ),
 52                stack_offset=(0, 1) if uiscale is bui.UIScale.SMALL else (0, 0),
 53            )
 54        )
 55
 56        self._back_button = bui.buttonwidget(
 57            parent=self._root_widget,
 58            position=(58 + x_inset, self._height - 53),
 59            size=(165, 70),
 60            scale=0.75,
 61            text_scale=1.2,
 62            label=bui.Lstr(resource='backText'),
 63            autoselect=True,
 64            button_type='back',
 65            on_activate_call=self._back,
 66        )
 67        self._select_button = select_button = bui.buttonwidget(
 68            parent=self._root_widget,
 69            position=(self._width - (172 + x_inset), self._height - 50),
 70            autoselect=True,
 71            size=(160, 60),
 72            scale=0.75,
 73            text_scale=1.2,
 74            label=bui.Lstr(resource='selectText'),
 75            on_activate_call=self._add,
 76        )
 77
 78        if bui.app.ui_v1.use_toolbars:
 79            bui.widget(
 80                edit=select_button,
 81                right_widget=bui.get_special_widget('party_button'),
 82            )
 83
 84        bui.textwidget(
 85            parent=self._root_widget,
 86            position=(self._width * 0.5, self._height - 28),
 87            size=(0, 0),
 88            scale=1.0,
 89            text=bui.Lstr(resource=self._r + '.titleText'),
 90            h_align='center',
 91            color=bui.app.ui_v1.title_color,
 92            maxwidth=250,
 93            v_align='center',
 94        )
 95        v = self._height - 64
 96
 97        self._selected_title_text = bui.textwidget(
 98            parent=self._root_widget,
 99            position=(x_inset + self._scroll_width + 50 + 30, v - 15),
100            size=(0, 0),
101            scale=1.0,
102            color=(0.7, 1.0, 0.7, 1.0),
103            maxwidth=self._width - self._scroll_width - 150 - x_inset * 2,
104            h_align='left',
105            v_align='center',
106        )
107        v -= 30
108
109        self._selected_description_text = bui.textwidget(
110            parent=self._root_widget,
111            position=(x_inset + self._scroll_width + 50 + 30, v),
112            size=(0, 0),
113            scale=0.7,
114            color=(0.5, 0.8, 0.5, 1.0),
115            maxwidth=self._width - self._scroll_width - 150 - x_inset * 2,
116            h_align='left',
117        )
118
119        scroll_height = self._height - 100
120
121        v = self._height - 60
122
123        self._scrollwidget = bui.scrollwidget(
124            parent=self._root_widget,
125            position=(x_inset + 61, v - scroll_height),
126            size=(self._scroll_width, scroll_height),
127            highlight=False,
128        )
129        bui.widget(
130            edit=self._scrollwidget,
131            up_widget=self._back_button,
132            left_widget=self._back_button,
133            right_widget=select_button,
134        )
135        self._column: bui.Widget | None = None
136
137        v -= 35
138        bui.containerwidget(
139            edit=self._root_widget,
140            cancel_button=self._back_button,
141            start_button=select_button,
142        )
143        self._selected_game_type: type[bs.GameActivity] | None = None
144
145        bui.containerwidget(
146            edit=self._root_widget, selected_child=self._scrollwidget
147        )
148
149        self._game_types: list[type[bs.GameActivity]] = []
150
151        # Get actual games loading in the bg.
152        bui.app.meta.load_exported_classes(
153            bs.GameActivity,
154            self._on_game_types_loaded,
155            completion_cb_in_bg_thread=True,
156        )
157
158        # Refresh with our initial empty list. We'll refresh again once
159        # game loading is complete.
160        self._refresh()
161
162    def _on_game_types_loaded(
163        self, gametypes: list[type[bs.GameActivity]]
164    ) -> None:
165        assert bui.app.classic is not None
166        store = bui.app.classic.store
167
168        # We asked for a bg thread completion cb so we can do some
169        # filtering here in the bg thread where its not gonna cause hitches.
170        assert not bui.in_logic_thread()
171        sessiontype = self._editcontroller.get_session_type()
172        unowned = store.get_unowned_game_types()
173        self._game_types = [
174            gt
175            for gt in gametypes
176            if gt not in unowned and gt.supports_session_type(sessiontype)
177        ]
178
179        # Sort in the current language.
180        self._game_types.sort(key=lambda g: g.get_display_string().evaluate())
181
182        # Tell ourself to refresh back in the logic thread.
183        bui.pushcall(self._refresh, from_other_thread=True)
184
185    def _refresh(self, select_get_more_games_button: bool = False) -> None:
186        if self._column is not None:
187            self._column.delete()
188
189        self._column = bui.columnwidget(
190            parent=self._scrollwidget, border=2, margin=0
191        )
192
193        for i, gametype in enumerate(self._game_types):
194
195            def _doit() -> None:
196                if self._select_button:
197                    bui.apptimer(0.1, self._select_button.activate)
198
199            txt = bui.textwidget(
200                parent=self._column,
201                position=(0, 0),
202                size=(self._scroll_width * 1.1, 24),
203                text=gametype.get_display_string(),
204                h_align='left',
205                v_align='center',
206                color=(0.8, 0.8, 0.8, 1.0),
207                maxwidth=self._scroll_width * 0.8,
208                on_select_call=bui.Call(self._set_selected_game_type, gametype),
209                always_highlight=True,
210                selectable=True,
211                on_activate_call=_doit,
212            )
213            if i == 0:
214                bui.widget(edit=txt, up_widget=self._back_button)
215
216        self._get_more_games_button = bui.buttonwidget(
217            parent=self._column,
218            autoselect=True,
219            label=bui.Lstr(resource=self._r + '.getMoreGamesText'),
220            color=(0.54, 0.52, 0.67),
221            textcolor=(0.7, 0.65, 0.7),
222            on_activate_call=self._on_get_more_games_press,
223            size=(178, 50),
224        )
225        if select_get_more_games_button:
226            bui.containerwidget(
227                edit=self._column,
228                selected_child=self._get_more_games_button,
229                visible_child=self._get_more_games_button,
230            )
231
232    def _on_get_more_games_press(self) -> None:
233        from bauiv1lib.account import show_sign_in_prompt
234        from bauiv1lib.store.browser import StoreBrowserWindow
235
236        plus = bui.app.plus
237        assert plus is not None
238
239        if plus.get_v1_account_state() != 'signed_in':
240            show_sign_in_prompt()
241            return
242        StoreBrowserWindow(
243            modal=True,
244            show_tab=StoreBrowserWindow.TabID.MINIGAMES,
245            on_close_call=self._on_store_close,
246            origin_widget=self._get_more_games_button,
247        )
248
249    def _on_store_close(self) -> None:
250        self._refresh(select_get_more_games_button=True)
251
252    def _add(self) -> None:
253        bui.lock_all_input()  # Make sure no more commands happen.
254        bui.apptimer(0.1, bui.unlock_all_input)
255        assert self._selected_game_type is not None
256        self._editcontroller.add_game_type_selected(self._selected_game_type)
257
258    def _set_selected_game_type(self, gametype: type[bs.GameActivity]) -> None:
259        self._selected_game_type = gametype
260        bui.textwidget(
261            edit=self._selected_title_text, text=gametype.get_display_string()
262        )
263        bui.textwidget(
264            edit=self._selected_description_text,
265            text=gametype.get_description_display_string(
266                self._editcontroller.get_session_type()
267            ),
268        )
269
270    def _back(self) -> None:
271        self._editcontroller.add_game_cancelled()

Window for selecting a game type to add to a playlist.

PlaylistAddGameWindow( editcontroller: bauiv1lib.playlist.editcontroller.PlaylistEditController, transition: str = 'in_right')
 20    def __init__(
 21        self,
 22        editcontroller: PlaylistEditController,
 23        transition: str = 'in_right',
 24    ):
 25        self._editcontroller = editcontroller
 26        self._r = 'addGameWindow'
 27        assert bui.app.classic is not None
 28        uiscale = bui.app.ui_v1.uiscale
 29        self._width = 750 if uiscale is bui.UIScale.SMALL else 650
 30        x_inset = 50 if uiscale is bui.UIScale.SMALL else 0
 31        self._height = (
 32            346
 33            if uiscale is bui.UIScale.SMALL
 34            else 380
 35            if uiscale is bui.UIScale.MEDIUM
 36            else 440
 37        )
 38        top_extra = 30 if uiscale is bui.UIScale.SMALL else 20
 39        self._scroll_width = 210
 40
 41        super().__init__(
 42            root_widget=bui.containerwidget(
 43                size=(self._width, self._height + top_extra),
 44                transition=transition,
 45                scale=(
 46                    2.17
 47                    if uiscale is bui.UIScale.SMALL
 48                    else 1.5
 49                    if uiscale is bui.UIScale.MEDIUM
 50                    else 1.0
 51                ),
 52                stack_offset=(0, 1) if uiscale is bui.UIScale.SMALL else (0, 0),
 53            )
 54        )
 55
 56        self._back_button = bui.buttonwidget(
 57            parent=self._root_widget,
 58            position=(58 + x_inset, self._height - 53),
 59            size=(165, 70),
 60            scale=0.75,
 61            text_scale=1.2,
 62            label=bui.Lstr(resource='backText'),
 63            autoselect=True,
 64            button_type='back',
 65            on_activate_call=self._back,
 66        )
 67        self._select_button = select_button = bui.buttonwidget(
 68            parent=self._root_widget,
 69            position=(self._width - (172 + x_inset), self._height - 50),
 70            autoselect=True,
 71            size=(160, 60),
 72            scale=0.75,
 73            text_scale=1.2,
 74            label=bui.Lstr(resource='selectText'),
 75            on_activate_call=self._add,
 76        )
 77
 78        if bui.app.ui_v1.use_toolbars:
 79            bui.widget(
 80                edit=select_button,
 81                right_widget=bui.get_special_widget('party_button'),
 82            )
 83
 84        bui.textwidget(
 85            parent=self._root_widget,
 86            position=(self._width * 0.5, self._height - 28),
 87            size=(0, 0),
 88            scale=1.0,
 89            text=bui.Lstr(resource=self._r + '.titleText'),
 90            h_align='center',
 91            color=bui.app.ui_v1.title_color,
 92            maxwidth=250,
 93            v_align='center',
 94        )
 95        v = self._height - 64
 96
 97        self._selected_title_text = bui.textwidget(
 98            parent=self._root_widget,
 99            position=(x_inset + self._scroll_width + 50 + 30, v - 15),
100            size=(0, 0),
101            scale=1.0,
102            color=(0.7, 1.0, 0.7, 1.0),
103            maxwidth=self._width - self._scroll_width - 150 - x_inset * 2,
104            h_align='left',
105            v_align='center',
106        )
107        v -= 30
108
109        self._selected_description_text = bui.textwidget(
110            parent=self._root_widget,
111            position=(x_inset + self._scroll_width + 50 + 30, v),
112            size=(0, 0),
113            scale=0.7,
114            color=(0.5, 0.8, 0.5, 1.0),
115            maxwidth=self._width - self._scroll_width - 150 - x_inset * 2,
116            h_align='left',
117        )
118
119        scroll_height = self._height - 100
120
121        v = self._height - 60
122
123        self._scrollwidget = bui.scrollwidget(
124            parent=self._root_widget,
125            position=(x_inset + 61, v - scroll_height),
126            size=(self._scroll_width, scroll_height),
127            highlight=False,
128        )
129        bui.widget(
130            edit=self._scrollwidget,
131            up_widget=self._back_button,
132            left_widget=self._back_button,
133            right_widget=select_button,
134        )
135        self._column: bui.Widget | None = None
136
137        v -= 35
138        bui.containerwidget(
139            edit=self._root_widget,
140            cancel_button=self._back_button,
141            start_button=select_button,
142        )
143        self._selected_game_type: type[bs.GameActivity] | None = None
144
145        bui.containerwidget(
146            edit=self._root_widget, selected_child=self._scrollwidget
147        )
148
149        self._game_types: list[type[bs.GameActivity]] = []
150
151        # Get actual games loading in the bg.
152        bui.app.meta.load_exported_classes(
153            bs.GameActivity,
154            self._on_game_types_loaded,
155            completion_cb_in_bg_thread=True,
156        )
157
158        # Refresh with our initial empty list. We'll refresh again once
159        # game loading is complete.
160        self._refresh()
Inherited Members
bauiv1._uitypes.Window
get_root_widget