bauiv1lib.playlist.mapselect

Provides UI for selecting maps in playlists.

  1# Released under the MIT License. See LICENSE for details.
  2#
  3"""Provides UI for selecting maps in playlists."""
  4
  5from __future__ import annotations
  6
  7import math
  8from typing import TYPE_CHECKING, override
  9
 10import bauiv1 as bui
 11
 12if TYPE_CHECKING:
 13    from typing import Any, Callable
 14
 15    import bascenev1 as bs
 16
 17
 18class PlaylistMapSelectWindow(bui.MainWindow):
 19    """Window to select a map."""
 20
 21    def __init__(
 22        self,
 23        gametype: type[bs.GameActivity],
 24        sessiontype: type[bs.Session],
 25        config: dict[str, Any],
 26        edit_info: dict[str, Any],
 27        completion_call: Callable[[dict[str, Any] | None, bui.MainWindow], Any],
 28        transition: str | None = 'in_right',
 29        origin_widget: bui.Widget | None = None,
 30        select_get_more_maps_button: bool = False,
 31    ):
 32        # pylint: disable=too-many-locals
 33
 34        from bascenev1 import get_filtered_map_name
 35
 36        self._gametype = gametype
 37        self._sessiontype = sessiontype
 38        self._config = config
 39        self._completion_call = completion_call
 40        self._edit_info = edit_info
 41        self._maps: list[tuple[str, bui.Texture]] = []
 42        self._selected_get_more_maps = False
 43        try:
 44            self._previous_map = get_filtered_map_name(
 45                config['settings']['map']
 46            )
 47        except Exception:
 48            self._previous_map = ''
 49
 50        assert bui.app.classic is not None
 51        uiscale = bui.app.ui_v1.uiscale
 52        width = 815 if uiscale is bui.UIScale.SMALL else 615
 53        x_inset = 100 if uiscale is bui.UIScale.SMALL else 0
 54        height = (
 55            400
 56            if uiscale is bui.UIScale.SMALL
 57            else 480 if uiscale is bui.UIScale.MEDIUM else 600
 58        )
 59
 60        top_extra = 20 if uiscale is bui.UIScale.SMALL else 0
 61        super().__init__(
 62            root_widget=bui.containerwidget(
 63                size=(width, height + top_extra),
 64                scale=(
 65                    1.95
 66                    if uiscale is bui.UIScale.SMALL
 67                    else 1.3 if uiscale is bui.UIScale.MEDIUM else 1.0
 68                ),
 69                stack_offset=(
 70                    (0, -27) if uiscale is bui.UIScale.SMALL else (0, 0)
 71                ),
 72            ),
 73            transition=transition,
 74            origin_widget=origin_widget,
 75        )
 76
 77        self._cancel_button = btn = bui.buttonwidget(
 78            parent=self._root_widget,
 79            position=(38 + x_inset, height - 67),
 80            size=(140, 50),
 81            scale=0.9,
 82            text_scale=1.0,
 83            autoselect=True,
 84            label=bui.Lstr(resource='cancelText'),
 85            on_activate_call=self.main_window_back,
 86        )
 87
 88        bui.containerwidget(edit=self._root_widget, cancel_button=btn)
 89        bui.textwidget(
 90            parent=self._root_widget,
 91            position=(width * 0.5, height - 46),
 92            size=(0, 0),
 93            maxwidth=260,
 94            scale=1.1,
 95            text=bui.Lstr(
 96                resource='mapSelectTitleText',
 97                subs=[('${GAME}', self._gametype.get_display_string())],
 98            ),
 99            color=bui.app.ui_v1.title_color,
100            h_align='center',
101            v_align='center',
102        )
103        v = height - 70
104        self._scroll_width = width - (80 + 2 * x_inset)
105        self._scroll_height = height - 140
106
107        self._scrollwidget = bui.scrollwidget(
108            parent=self._root_widget,
109            position=(40 + x_inset, v - self._scroll_height),
110            size=(self._scroll_width, self._scroll_height),
111        )
112        bui.containerwidget(
113            edit=self._root_widget, selected_child=self._scrollwidget
114        )
115        bui.containerwidget(edit=self._scrollwidget, claims_left_right=True)
116
117        self._subcontainer: bui.Widget | None = None
118        self._refresh(select_get_more_maps_button=select_get_more_maps_button)
119
120    @override
121    def get_main_window_state(self) -> bui.MainWindowState:
122        # Support recreating our window for back/refresh purposes.
123        cls = type(self)
124
125        # Pull things out of self here; if we do it in the lambda we'll
126        # keep ourself alive.
127        gametype = self._gametype
128        sessiontype = self._sessiontype
129        config = self._config
130        edit_info = self._edit_info
131        completion_call = self._completion_call
132        select_get_more_maps = self._selected_get_more_maps
133
134        return bui.BasicMainWindowState(
135            create_call=lambda transition, origin_widget: cls(
136                transition=transition,
137                origin_widget=origin_widget,
138                gametype=gametype,
139                sessiontype=sessiontype,
140                config=config,
141                edit_info=edit_info,
142                completion_call=completion_call,
143                select_get_more_maps_button=select_get_more_maps,
144            )
145        )
146
147    def _refresh(self, select_get_more_maps_button: bool = False) -> None:
148        # pylint: disable=too-many-statements
149        # pylint: disable=too-many-branches
150        # pylint: disable=too-many-locals
151        from bascenev1 import (
152            get_map_class,
153            get_map_display_string,
154        )
155
156        assert bui.app.classic is not None
157        store = bui.app.classic.store
158        # Kill old.
159        if self._subcontainer is not None:
160            self._subcontainer.delete()
161
162        mesh_opaque = bui.getmesh('level_select_button_opaque')
163        mesh_transparent = bui.getmesh('level_select_button_transparent')
164
165        self._maps = []
166        map_list = self._gametype.get_supported_maps(self._sessiontype)
167        map_list_sorted = list(map_list)
168        map_list_sorted.sort()
169        unowned_maps = store.get_unowned_maps()
170
171        for mapname in map_list_sorted:
172            # Disallow ones we don't own.
173            if mapname in unowned_maps:
174                continue
175            map_tex_name = get_map_class(mapname).get_preview_texture_name()
176            if map_tex_name is not None:
177                try:
178                    map_tex = bui.gettexture(map_tex_name)
179                    self._maps.append((mapname, map_tex))
180                except Exception:
181                    print(f'Invalid map preview texture: "{map_tex_name}".')
182            else:
183                print('Error: no map preview texture for map:', mapname)
184
185        count = len(self._maps)
186        columns = 2
187        rows = int(math.ceil(float(count) / columns))
188        button_width = 220
189        button_height = button_width * 0.5
190        button_buffer_h = 16
191        button_buffer_v = 19
192        self._sub_width = self._scroll_width * 0.95
193        self._sub_height = (
194            5 + rows * (button_height + 2 * button_buffer_v) + 100
195        )
196        self._subcontainer = bui.containerwidget(
197            parent=self._scrollwidget,
198            size=(self._sub_width, self._sub_height),
199            background=False,
200        )
201        index = 0
202        mask_texture = bui.gettexture('mapPreviewMask')
203        h_offs = 130 if len(self._maps) == 1 else 0
204        for y in range(rows):
205            for x in range(columns):
206                pos = (
207                    x * (button_width + 2 * button_buffer_h)
208                    + button_buffer_h
209                    + h_offs,
210                    self._sub_height
211                    - (y + 1) * (button_height + 2 * button_buffer_v)
212                    + 12,
213                )
214                btn = bui.buttonwidget(
215                    parent=self._subcontainer,
216                    button_type='square',
217                    size=(button_width, button_height),
218                    autoselect=True,
219                    texture=self._maps[index][1],
220                    mask_texture=mask_texture,
221                    mesh_opaque=mesh_opaque,
222                    mesh_transparent=mesh_transparent,
223                    label='',
224                    color=(1, 1, 1),
225                    on_activate_call=bui.Call(
226                        self._select_with_delay, self._maps[index][0]
227                    ),
228                    position=pos,
229                )
230                if x == 0:
231                    bui.widget(edit=btn, left_widget=self._cancel_button)
232                if y == 0:
233                    bui.widget(edit=btn, up_widget=self._cancel_button)
234                if x == columns - 1:
235                    bui.widget(
236                        edit=btn,
237                        right_widget=bui.get_special_widget('squad_button'),
238                    )
239
240                bui.widget(edit=btn, show_buffer_top=60, show_buffer_bottom=60)
241                if self._maps[index][0] == self._previous_map:
242                    bui.containerwidget(
243                        edit=self._subcontainer,
244                        selected_child=btn,
245                        visible_child=btn,
246                    )
247                name = get_map_display_string(self._maps[index][0])
248                bui.textwidget(
249                    parent=self._subcontainer,
250                    text=name,
251                    position=(pos[0] + button_width * 0.5, pos[1] - 12),
252                    size=(0, 0),
253                    scale=0.5,
254                    maxwidth=button_width,
255                    draw_controller=btn,
256                    h_align='center',
257                    v_align='center',
258                    color=(0.8, 0.8, 0.8, 0.8),
259                )
260                index += 1
261
262                if index >= count:
263                    break
264            if index >= count:
265                break
266        self._get_more_maps_button = btn = bui.buttonwidget(
267            parent=self._subcontainer,
268            size=(self._sub_width * 0.8, 60),
269            position=(self._sub_width * 0.1, 30),
270            label=bui.Lstr(resource='mapSelectGetMoreMapsText'),
271            on_activate_call=self._on_store_press,
272            color=(0.6, 0.53, 0.63),
273            textcolor=(0.75, 0.7, 0.8),
274            autoselect=True,
275        )
276        bui.widget(edit=btn, show_buffer_top=30, show_buffer_bottom=30)
277        if select_get_more_maps_button:
278            bui.containerwidget(
279                edit=self._subcontainer, selected_child=btn, visible_child=btn
280            )
281
282    def _on_store_press(self) -> None:
283        from bauiv1lib import account
284        from bauiv1lib.store.browser import StoreBrowserWindow
285
286        # No-op if we're not in control.
287        if not self.main_window_has_control():
288            return
289
290        plus = bui.app.plus
291        assert plus is not None
292
293        if plus.get_v1_account_state() != 'signed_in':
294            account.show_sign_in_prompt()
295            return
296
297        self._selected_get_more_maps = True
298
299        self.main_window_replace(
300            StoreBrowserWindow(
301                show_tab=StoreBrowserWindow.TabID.MAPS,
302                origin_widget=self._get_more_maps_button,
303                minimal_toolbars=True,
304            )
305        )
306
307    def _select(self, map_name: str) -> None:
308
309        # no-op if our underlying widget is dead or on its way out.
310        if not self.main_window_has_control():
311            return
312
313        self._config['settings']['map'] = map_name
314        self.main_window_back()
315
316    def _select_with_delay(self, map_name: str) -> None:
317        bui.lock_all_input()
318        bui.apptimer(0.1, bui.unlock_all_input)
319        bui.apptimer(0.1, bui.WeakCall(self._select, map_name))
class PlaylistMapSelectWindow(bauiv1._uitypes.MainWindow):
 19class PlaylistMapSelectWindow(bui.MainWindow):
 20    """Window to select a map."""
 21
 22    def __init__(
 23        self,
 24        gametype: type[bs.GameActivity],
 25        sessiontype: type[bs.Session],
 26        config: dict[str, Any],
 27        edit_info: dict[str, Any],
 28        completion_call: Callable[[dict[str, Any] | None, bui.MainWindow], Any],
 29        transition: str | None = 'in_right',
 30        origin_widget: bui.Widget | None = None,
 31        select_get_more_maps_button: bool = False,
 32    ):
 33        # pylint: disable=too-many-locals
 34
 35        from bascenev1 import get_filtered_map_name
 36
 37        self._gametype = gametype
 38        self._sessiontype = sessiontype
 39        self._config = config
 40        self._completion_call = completion_call
 41        self._edit_info = edit_info
 42        self._maps: list[tuple[str, bui.Texture]] = []
 43        self._selected_get_more_maps = False
 44        try:
 45            self._previous_map = get_filtered_map_name(
 46                config['settings']['map']
 47            )
 48        except Exception:
 49            self._previous_map = ''
 50
 51        assert bui.app.classic is not None
 52        uiscale = bui.app.ui_v1.uiscale
 53        width = 815 if uiscale is bui.UIScale.SMALL else 615
 54        x_inset = 100 if uiscale is bui.UIScale.SMALL else 0
 55        height = (
 56            400
 57            if uiscale is bui.UIScale.SMALL
 58            else 480 if uiscale is bui.UIScale.MEDIUM else 600
 59        )
 60
 61        top_extra = 20 if uiscale is bui.UIScale.SMALL else 0
 62        super().__init__(
 63            root_widget=bui.containerwidget(
 64                size=(width, height + top_extra),
 65                scale=(
 66                    1.95
 67                    if uiscale is bui.UIScale.SMALL
 68                    else 1.3 if uiscale is bui.UIScale.MEDIUM else 1.0
 69                ),
 70                stack_offset=(
 71                    (0, -27) if uiscale is bui.UIScale.SMALL else (0, 0)
 72                ),
 73            ),
 74            transition=transition,
 75            origin_widget=origin_widget,
 76        )
 77
 78        self._cancel_button = btn = bui.buttonwidget(
 79            parent=self._root_widget,
 80            position=(38 + x_inset, height - 67),
 81            size=(140, 50),
 82            scale=0.9,
 83            text_scale=1.0,
 84            autoselect=True,
 85            label=bui.Lstr(resource='cancelText'),
 86            on_activate_call=self.main_window_back,
 87        )
 88
 89        bui.containerwidget(edit=self._root_widget, cancel_button=btn)
 90        bui.textwidget(
 91            parent=self._root_widget,
 92            position=(width * 0.5, height - 46),
 93            size=(0, 0),
 94            maxwidth=260,
 95            scale=1.1,
 96            text=bui.Lstr(
 97                resource='mapSelectTitleText',
 98                subs=[('${GAME}', self._gametype.get_display_string())],
 99            ),
100            color=bui.app.ui_v1.title_color,
101            h_align='center',
102            v_align='center',
103        )
104        v = height - 70
105        self._scroll_width = width - (80 + 2 * x_inset)
106        self._scroll_height = height - 140
107
108        self._scrollwidget = bui.scrollwidget(
109            parent=self._root_widget,
110            position=(40 + x_inset, v - self._scroll_height),
111            size=(self._scroll_width, self._scroll_height),
112        )
113        bui.containerwidget(
114            edit=self._root_widget, selected_child=self._scrollwidget
115        )
116        bui.containerwidget(edit=self._scrollwidget, claims_left_right=True)
117
118        self._subcontainer: bui.Widget | None = None
119        self._refresh(select_get_more_maps_button=select_get_more_maps_button)
120
121    @override
122    def get_main_window_state(self) -> bui.MainWindowState:
123        # Support recreating our window for back/refresh purposes.
124        cls = type(self)
125
126        # Pull things out of self here; if we do it in the lambda we'll
127        # keep ourself alive.
128        gametype = self._gametype
129        sessiontype = self._sessiontype
130        config = self._config
131        edit_info = self._edit_info
132        completion_call = self._completion_call
133        select_get_more_maps = self._selected_get_more_maps
134
135        return bui.BasicMainWindowState(
136            create_call=lambda transition, origin_widget: cls(
137                transition=transition,
138                origin_widget=origin_widget,
139                gametype=gametype,
140                sessiontype=sessiontype,
141                config=config,
142                edit_info=edit_info,
143                completion_call=completion_call,
144                select_get_more_maps_button=select_get_more_maps,
145            )
146        )
147
148    def _refresh(self, select_get_more_maps_button: bool = False) -> None:
149        # pylint: disable=too-many-statements
150        # pylint: disable=too-many-branches
151        # pylint: disable=too-many-locals
152        from bascenev1 import (
153            get_map_class,
154            get_map_display_string,
155        )
156
157        assert bui.app.classic is not None
158        store = bui.app.classic.store
159        # Kill old.
160        if self._subcontainer is not None:
161            self._subcontainer.delete()
162
163        mesh_opaque = bui.getmesh('level_select_button_opaque')
164        mesh_transparent = bui.getmesh('level_select_button_transparent')
165
166        self._maps = []
167        map_list = self._gametype.get_supported_maps(self._sessiontype)
168        map_list_sorted = list(map_list)
169        map_list_sorted.sort()
170        unowned_maps = store.get_unowned_maps()
171
172        for mapname in map_list_sorted:
173            # Disallow ones we don't own.
174            if mapname in unowned_maps:
175                continue
176            map_tex_name = get_map_class(mapname).get_preview_texture_name()
177            if map_tex_name is not None:
178                try:
179                    map_tex = bui.gettexture(map_tex_name)
180                    self._maps.append((mapname, map_tex))
181                except Exception:
182                    print(f'Invalid map preview texture: "{map_tex_name}".')
183            else:
184                print('Error: no map preview texture for map:', mapname)
185
186        count = len(self._maps)
187        columns = 2
188        rows = int(math.ceil(float(count) / columns))
189        button_width = 220
190        button_height = button_width * 0.5
191        button_buffer_h = 16
192        button_buffer_v = 19
193        self._sub_width = self._scroll_width * 0.95
194        self._sub_height = (
195            5 + rows * (button_height + 2 * button_buffer_v) + 100
196        )
197        self._subcontainer = bui.containerwidget(
198            parent=self._scrollwidget,
199            size=(self._sub_width, self._sub_height),
200            background=False,
201        )
202        index = 0
203        mask_texture = bui.gettexture('mapPreviewMask')
204        h_offs = 130 if len(self._maps) == 1 else 0
205        for y in range(rows):
206            for x in range(columns):
207                pos = (
208                    x * (button_width + 2 * button_buffer_h)
209                    + button_buffer_h
210                    + h_offs,
211                    self._sub_height
212                    - (y + 1) * (button_height + 2 * button_buffer_v)
213                    + 12,
214                )
215                btn = bui.buttonwidget(
216                    parent=self._subcontainer,
217                    button_type='square',
218                    size=(button_width, button_height),
219                    autoselect=True,
220                    texture=self._maps[index][1],
221                    mask_texture=mask_texture,
222                    mesh_opaque=mesh_opaque,
223                    mesh_transparent=mesh_transparent,
224                    label='',
225                    color=(1, 1, 1),
226                    on_activate_call=bui.Call(
227                        self._select_with_delay, self._maps[index][0]
228                    ),
229                    position=pos,
230                )
231                if x == 0:
232                    bui.widget(edit=btn, left_widget=self._cancel_button)
233                if y == 0:
234                    bui.widget(edit=btn, up_widget=self._cancel_button)
235                if x == columns - 1:
236                    bui.widget(
237                        edit=btn,
238                        right_widget=bui.get_special_widget('squad_button'),
239                    )
240
241                bui.widget(edit=btn, show_buffer_top=60, show_buffer_bottom=60)
242                if self._maps[index][0] == self._previous_map:
243                    bui.containerwidget(
244                        edit=self._subcontainer,
245                        selected_child=btn,
246                        visible_child=btn,
247                    )
248                name = get_map_display_string(self._maps[index][0])
249                bui.textwidget(
250                    parent=self._subcontainer,
251                    text=name,
252                    position=(pos[0] + button_width * 0.5, pos[1] - 12),
253                    size=(0, 0),
254                    scale=0.5,
255                    maxwidth=button_width,
256                    draw_controller=btn,
257                    h_align='center',
258                    v_align='center',
259                    color=(0.8, 0.8, 0.8, 0.8),
260                )
261                index += 1
262
263                if index >= count:
264                    break
265            if index >= count:
266                break
267        self._get_more_maps_button = btn = bui.buttonwidget(
268            parent=self._subcontainer,
269            size=(self._sub_width * 0.8, 60),
270            position=(self._sub_width * 0.1, 30),
271            label=bui.Lstr(resource='mapSelectGetMoreMapsText'),
272            on_activate_call=self._on_store_press,
273            color=(0.6, 0.53, 0.63),
274            textcolor=(0.75, 0.7, 0.8),
275            autoselect=True,
276        )
277        bui.widget(edit=btn, show_buffer_top=30, show_buffer_bottom=30)
278        if select_get_more_maps_button:
279            bui.containerwidget(
280                edit=self._subcontainer, selected_child=btn, visible_child=btn
281            )
282
283    def _on_store_press(self) -> None:
284        from bauiv1lib import account
285        from bauiv1lib.store.browser import StoreBrowserWindow
286
287        # No-op if we're not in control.
288        if not self.main_window_has_control():
289            return
290
291        plus = bui.app.plus
292        assert plus is not None
293
294        if plus.get_v1_account_state() != 'signed_in':
295            account.show_sign_in_prompt()
296            return
297
298        self._selected_get_more_maps = True
299
300        self.main_window_replace(
301            StoreBrowserWindow(
302                show_tab=StoreBrowserWindow.TabID.MAPS,
303                origin_widget=self._get_more_maps_button,
304                minimal_toolbars=True,
305            )
306        )
307
308    def _select(self, map_name: str) -> None:
309
310        # no-op if our underlying widget is dead or on its way out.
311        if not self.main_window_has_control():
312            return
313
314        self._config['settings']['map'] = map_name
315        self.main_window_back()
316
317    def _select_with_delay(self, map_name: str) -> None:
318        bui.lock_all_input()
319        bui.apptimer(0.1, bui.unlock_all_input)
320        bui.apptimer(0.1, bui.WeakCall(self._select, map_name))

Window to select a map.

PlaylistMapSelectWindow( gametype: type[bascenev1.GameActivity], sessiontype: type[bascenev1.Session], config: dict[str, typing.Any], edit_info: dict[str, typing.Any], completion_call: Callable[[dict[str, Any] | None, bauiv1.MainWindow], Any], transition: str | None = 'in_right', origin_widget: _bauiv1.Widget | None = None, select_get_more_maps_button: bool = False)
 22    def __init__(
 23        self,
 24        gametype: type[bs.GameActivity],
 25        sessiontype: type[bs.Session],
 26        config: dict[str, Any],
 27        edit_info: dict[str, Any],
 28        completion_call: Callable[[dict[str, Any] | None, bui.MainWindow], Any],
 29        transition: str | None = 'in_right',
 30        origin_widget: bui.Widget | None = None,
 31        select_get_more_maps_button: bool = False,
 32    ):
 33        # pylint: disable=too-many-locals
 34
 35        from bascenev1 import get_filtered_map_name
 36
 37        self._gametype = gametype
 38        self._sessiontype = sessiontype
 39        self._config = config
 40        self._completion_call = completion_call
 41        self._edit_info = edit_info
 42        self._maps: list[tuple[str, bui.Texture]] = []
 43        self._selected_get_more_maps = False
 44        try:
 45            self._previous_map = get_filtered_map_name(
 46                config['settings']['map']
 47            )
 48        except Exception:
 49            self._previous_map = ''
 50
 51        assert bui.app.classic is not None
 52        uiscale = bui.app.ui_v1.uiscale
 53        width = 815 if uiscale is bui.UIScale.SMALL else 615
 54        x_inset = 100 if uiscale is bui.UIScale.SMALL else 0
 55        height = (
 56            400
 57            if uiscale is bui.UIScale.SMALL
 58            else 480 if uiscale is bui.UIScale.MEDIUM else 600
 59        )
 60
 61        top_extra = 20 if uiscale is bui.UIScale.SMALL else 0
 62        super().__init__(
 63            root_widget=bui.containerwidget(
 64                size=(width, height + top_extra),
 65                scale=(
 66                    1.95
 67                    if uiscale is bui.UIScale.SMALL
 68                    else 1.3 if uiscale is bui.UIScale.MEDIUM else 1.0
 69                ),
 70                stack_offset=(
 71                    (0, -27) if uiscale is bui.UIScale.SMALL else (0, 0)
 72                ),
 73            ),
 74            transition=transition,
 75            origin_widget=origin_widget,
 76        )
 77
 78        self._cancel_button = btn = bui.buttonwidget(
 79            parent=self._root_widget,
 80            position=(38 + x_inset, height - 67),
 81            size=(140, 50),
 82            scale=0.9,
 83            text_scale=1.0,
 84            autoselect=True,
 85            label=bui.Lstr(resource='cancelText'),
 86            on_activate_call=self.main_window_back,
 87        )
 88
 89        bui.containerwidget(edit=self._root_widget, cancel_button=btn)
 90        bui.textwidget(
 91            parent=self._root_widget,
 92            position=(width * 0.5, height - 46),
 93            size=(0, 0),
 94            maxwidth=260,
 95            scale=1.1,
 96            text=bui.Lstr(
 97                resource='mapSelectTitleText',
 98                subs=[('${GAME}', self._gametype.get_display_string())],
 99            ),
100            color=bui.app.ui_v1.title_color,
101            h_align='center',
102            v_align='center',
103        )
104        v = height - 70
105        self._scroll_width = width - (80 + 2 * x_inset)
106        self._scroll_height = height - 140
107
108        self._scrollwidget = bui.scrollwidget(
109            parent=self._root_widget,
110            position=(40 + x_inset, v - self._scroll_height),
111            size=(self._scroll_width, self._scroll_height),
112        )
113        bui.containerwidget(
114            edit=self._root_widget, selected_child=self._scrollwidget
115        )
116        bui.containerwidget(edit=self._scrollwidget, claims_left_right=True)
117
118        self._subcontainer: bui.Widget | None = None
119        self._refresh(select_get_more_maps_button=select_get_more_maps_button)

Create a MainWindow given a root widget and transition info.

Automatically handles in and out transitions on the provided widget, so there is no need to set transitions when creating it.

@override
def get_main_window_state(self) -> bauiv1.MainWindowState:
121    @override
122    def get_main_window_state(self) -> bui.MainWindowState:
123        # Support recreating our window for back/refresh purposes.
124        cls = type(self)
125
126        # Pull things out of self here; if we do it in the lambda we'll
127        # keep ourself alive.
128        gametype = self._gametype
129        sessiontype = self._sessiontype
130        config = self._config
131        edit_info = self._edit_info
132        completion_call = self._completion_call
133        select_get_more_maps = self._selected_get_more_maps
134
135        return bui.BasicMainWindowState(
136            create_call=lambda transition, origin_widget: cls(
137                transition=transition,
138                origin_widget=origin_widget,
139                gametype=gametype,
140                sessiontype=sessiontype,
141                config=config,
142                edit_info=edit_info,
143                completion_call=completion_call,
144                select_get_more_maps_button=select_get_more_maps,
145            )
146        )

Return a WindowState to recreate this window, if supported.

Inherited Members
bauiv1._uitypes.MainWindow
main_window_back_state
main_window_is_top_level
main_window_close
main_window_has_control
main_window_back
main_window_replace
on_main_window_close
bauiv1._uitypes.Window
get_root_widget