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