bauiv1lib.settings.allsettings

UI for top level settings categories.

  1# Released under the MIT License. See LICENSE for details.
  2#
  3"""UI for top level settings categories."""
  4
  5from __future__ import annotations
  6
  7from typing import TYPE_CHECKING, override
  8import logging
  9
 10import bauiv1 as bui
 11
 12if TYPE_CHECKING:
 13    pass
 14
 15
 16class AllSettingsWindow(bui.MainWindow):
 17    """Window for selecting a settings category."""
 18
 19    def __init__(
 20        self,
 21        transition: str | None = 'in_right',
 22        origin_widget: bui.Widget | None = None,
 23    ):
 24        # pylint: disable=too-many-statements
 25        # pylint: disable=too-many-locals
 26
 27        # Preload some modules we use in a background thread so we won't
 28        # have a visual hitch when the user taps them.
 29        bui.app.threadpool_submit_no_wait(self._preload_modules)
 30
 31        bui.set_analytics_screen('Settings Window')
 32        assert bui.app.classic is not None
 33        uiscale = bui.app.ui_v1.uiscale
 34        width = 1000 if uiscale is bui.UIScale.SMALL else 580
 35        x_inset = 125 if uiscale is bui.UIScale.SMALL else 0
 36        height = 435
 37        self._r = 'settingsWindow'
 38        top_extra = 20 if uiscale is bui.UIScale.SMALL else 0
 39
 40        uiscale = bui.app.ui_v1.uiscale
 41        super().__init__(
 42            root_widget=bui.containerwidget(
 43                size=(width, height + top_extra),
 44                toolbar_visibility=(
 45                    'menu_minimal'
 46                    if uiscale is bui.UIScale.SMALL
 47                    else 'menu_full'
 48                ),
 49                scale=(
 50                    1.5
 51                    if uiscale is bui.UIScale.SMALL
 52                    else 1.25 if uiscale is bui.UIScale.MEDIUM else 1.0
 53                ),
 54                stack_offset=(
 55                    (0, 0) if uiscale is bui.UIScale.SMALL else (0, 0)
 56                ),
 57            ),
 58            transition=transition,
 59            origin_widget=origin_widget,
 60        )
 61
 62        if uiscale is bui.UIScale.SMALL:
 63            self._back_button = None
 64            bui.containerwidget(
 65                edit=self._root_widget, on_cancel_call=self.main_window_back
 66            )
 67        else:
 68            self._back_button = btn = bui.buttonwidget(
 69                parent=self._root_widget,
 70                autoselect=True,
 71                position=(40 + x_inset, height - 55),
 72                size=(130, 60),
 73                scale=0.8,
 74                text_scale=1.2,
 75                label=bui.Lstr(resource='backText'),
 76                button_type='back',
 77                on_activate_call=self.main_window_back,
 78            )
 79            bui.containerwidget(edit=self._root_widget, cancel_button=btn)
 80
 81        bui.textwidget(
 82            parent=self._root_widget,
 83            position=(0, height - 44),
 84            size=(width, 25),
 85            text=bui.Lstr(resource=f'{self._r}.titleText'),
 86            color=bui.app.ui_v1.title_color,
 87            h_align='center',
 88            v_align='center',
 89            maxwidth=130,
 90        )
 91
 92        if self._back_button is not None:
 93            bui.buttonwidget(
 94                edit=self._back_button,
 95                button_type='backSmall',
 96                size=(60, 60),
 97                label=bui.charstr(bui.SpecialChar.BACK),
 98            )
 99
100        v = height - 80
101        v -= 145
102
103        basew = 280 if uiscale is bui.UIScale.SMALL else 230
104        baseh = 170
105        x_offs = (
106            x_inset + (105 if uiscale is bui.UIScale.SMALL else 72) - basew
107        )  # now unused
108        x_offs2 = x_offs + basew - 7
109        x_offs3 = x_offs + 2 * (basew - 7)
110        x_offs4 = x_offs2
111        x_offs5 = x_offs3
112
113        def _b_title(
114            x: float, y: float, button: bui.Widget, text: str | bui.Lstr
115        ) -> None:
116            bui.textwidget(
117                parent=self._root_widget,
118                text=text,
119                position=(x + basew * 0.47, y + baseh * 0.22),
120                maxwidth=basew * 0.7,
121                size=(0, 0),
122                h_align='center',
123                v_align='center',
124                draw_controller=button,
125                color=(0.7, 0.9, 0.7, 1.0),
126            )
127
128        ctb = self._controllers_button = bui.buttonwidget(
129            parent=self._root_widget,
130            autoselect=True,
131            position=(x_offs2, v),
132            size=(basew, baseh),
133            button_type='square',
134            label='',
135            on_activate_call=self._do_controllers,
136        )
137        if self._back_button is None:
138            bbtn = bui.get_special_widget('back_button')
139            bui.widget(edit=ctb, left_widget=bbtn)
140        _b_title(
141            x_offs2, v, ctb, bui.Lstr(resource=f'{self._r}.controllersText')
142        )
143        imgw = imgh = 130
144        bui.imagewidget(
145            parent=self._root_widget,
146            position=(x_offs2 + basew * 0.49 - imgw * 0.5, v + 35),
147            size=(imgw, imgh),
148            texture=bui.gettexture('controllerIcon'),
149            draw_controller=ctb,
150        )
151
152        gfxb = self._graphics_button = bui.buttonwidget(
153            parent=self._root_widget,
154            autoselect=True,
155            position=(x_offs3, v),
156            size=(basew, baseh),
157            button_type='square',
158            label='',
159            on_activate_call=self._do_graphics,
160        )
161        pbtn = bui.get_special_widget('squad_button')
162        bui.widget(edit=gfxb, up_widget=pbtn, right_widget=pbtn)
163        _b_title(x_offs3, v, gfxb, bui.Lstr(resource=f'{self._r}.graphicsText'))
164        imgw = imgh = 110
165        bui.imagewidget(
166            parent=self._root_widget,
167            position=(x_offs3 + basew * 0.49 - imgw * 0.5, v + 42),
168            size=(imgw, imgh),
169            texture=bui.gettexture('graphicsIcon'),
170            draw_controller=gfxb,
171        )
172
173        v -= baseh - 5
174
175        abtn = self._audio_button = bui.buttonwidget(
176            parent=self._root_widget,
177            autoselect=True,
178            position=(x_offs4, v),
179            size=(basew, baseh),
180            button_type='square',
181            label='',
182            on_activate_call=self._do_audio,
183        )
184        _b_title(x_offs4, v, abtn, bui.Lstr(resource=f'{self._r}.audioText'))
185        imgw = imgh = 120
186        bui.imagewidget(
187            parent=self._root_widget,
188            position=(x_offs4 + basew * 0.49 - imgw * 0.5 + 5, v + 35),
189            size=(imgw, imgh),
190            color=(1, 1, 0),
191            texture=bui.gettexture('audioIcon'),
192            draw_controller=abtn,
193        )
194
195        avb = self._advanced_button = bui.buttonwidget(
196            parent=self._root_widget,
197            autoselect=True,
198            position=(x_offs5, v),
199            size=(basew, baseh),
200            button_type='square',
201            label='',
202            on_activate_call=self._do_advanced,
203        )
204        _b_title(x_offs5, v, avb, bui.Lstr(resource=f'{self._r}.advancedText'))
205        imgw = imgh = 120
206        bui.imagewidget(
207            parent=self._root_widget,
208            position=(x_offs5 + basew * 0.49 - imgw * 0.5 + 5, v + 35),
209            size=(imgw, imgh),
210            color=(0.8, 0.95, 1),
211            texture=bui.gettexture('advancedIcon'),
212            draw_controller=avb,
213        )
214        self._restore_state()
215
216    @override
217    def get_main_window_state(self) -> bui.MainWindowState:
218        # Support recreating our window for back/refresh purposes.
219        cls = type(self)
220        return bui.BasicMainWindowState(
221            create_call=lambda transition, origin_widget: cls(
222                transition=transition, origin_widget=origin_widget
223            )
224        )
225
226    @override
227    def on_main_window_close(self) -> None:
228        self._save_state()
229
230    @staticmethod
231    def _preload_modules() -> None:
232        """Preload modules we use; avoids hitches (called in bg thread)."""
233        import bauiv1lib.mainmenu as _unused1
234        import bauiv1lib.settings.controls as _unused2
235        import bauiv1lib.settings.graphics as _unused3
236        import bauiv1lib.settings.audio as _unused4
237        import bauiv1lib.settings.advanced as _unused5
238
239    def _do_controllers(self) -> None:
240        # pylint: disable=cyclic-import
241        from bauiv1lib.settings.controls import ControlsSettingsWindow
242
243        # no-op if we're not in control.
244        if not self.main_window_has_control():
245            return
246
247        self.main_window_replace(
248            ControlsSettingsWindow(origin_widget=self._controllers_button)
249        )
250
251    def _do_graphics(self) -> None:
252        # pylint: disable=cyclic-import
253        from bauiv1lib.settings.graphics import GraphicsSettingsWindow
254
255        # no-op if we're not in control.
256        if not self.main_window_has_control():
257            return
258
259        self.main_window_replace(
260            GraphicsSettingsWindow(origin_widget=self._graphics_button)
261        )
262
263    def _do_audio(self) -> None:
264        # pylint: disable=cyclic-import
265        from bauiv1lib.settings.audio import AudioSettingsWindow
266
267        # no-op if we're not in control.
268        if not self.main_window_has_control():
269            return
270
271        self.main_window_replace(
272            AudioSettingsWindow(origin_widget=self._audio_button)
273        )
274
275    def _do_advanced(self) -> None:
276        # pylint: disable=cyclic-import
277        from bauiv1lib.settings.advanced import AdvancedSettingsWindow
278
279        # no-op if we're not in control.
280        if not self.main_window_has_control():
281            return
282
283        self.main_window_replace(
284            AdvancedSettingsWindow(origin_widget=self._advanced_button)
285        )
286
287    def _save_state(self) -> None:
288        try:
289            sel = self._root_widget.get_selected_child()
290            if sel == self._controllers_button:
291                sel_name = 'Controllers'
292            elif sel == self._graphics_button:
293                sel_name = 'Graphics'
294            elif sel == self._audio_button:
295                sel_name = 'Audio'
296            elif sel == self._advanced_button:
297                sel_name = 'Advanced'
298            elif sel == self._back_button:
299                sel_name = 'Back'
300            else:
301                raise ValueError(f'unrecognized selection \'{sel}\'')
302            assert bui.app.classic is not None
303            bui.app.ui_v1.window_states[type(self)] = {'sel_name': sel_name}
304        except Exception:
305            logging.exception('Error saving state for %s.', self)
306
307    def _restore_state(self) -> None:
308        try:
309            assert bui.app.classic is not None
310            sel_name = bui.app.ui_v1.window_states.get(type(self), {}).get(
311                'sel_name'
312            )
313            sel: bui.Widget | None
314            if sel_name == 'Controllers':
315                sel = self._controllers_button
316            elif sel_name == 'Graphics':
317                sel = self._graphics_button
318            elif sel_name == 'Audio':
319                sel = self._audio_button
320            elif sel_name == 'Advanced':
321                sel = self._advanced_button
322            elif sel_name == 'Back':
323                sel = self._back_button
324            else:
325                sel = self._controllers_button
326            if sel is not None:
327                bui.containerwidget(edit=self._root_widget, selected_child=sel)
328        except Exception:
329            logging.exception('Error restoring state for %s.', self)
class AllSettingsWindow(bauiv1._uitypes.MainWindow):
 17class AllSettingsWindow(bui.MainWindow):
 18    """Window for selecting a settings category."""
 19
 20    def __init__(
 21        self,
 22        transition: str | None = 'in_right',
 23        origin_widget: bui.Widget | None = None,
 24    ):
 25        # pylint: disable=too-many-statements
 26        # pylint: disable=too-many-locals
 27
 28        # Preload some modules we use in a background thread so we won't
 29        # have a visual hitch when the user taps them.
 30        bui.app.threadpool_submit_no_wait(self._preload_modules)
 31
 32        bui.set_analytics_screen('Settings Window')
 33        assert bui.app.classic is not None
 34        uiscale = bui.app.ui_v1.uiscale
 35        width = 1000 if uiscale is bui.UIScale.SMALL else 580
 36        x_inset = 125 if uiscale is bui.UIScale.SMALL else 0
 37        height = 435
 38        self._r = 'settingsWindow'
 39        top_extra = 20 if uiscale is bui.UIScale.SMALL else 0
 40
 41        uiscale = bui.app.ui_v1.uiscale
 42        super().__init__(
 43            root_widget=bui.containerwidget(
 44                size=(width, height + top_extra),
 45                toolbar_visibility=(
 46                    'menu_minimal'
 47                    if uiscale is bui.UIScale.SMALL
 48                    else 'menu_full'
 49                ),
 50                scale=(
 51                    1.5
 52                    if uiscale is bui.UIScale.SMALL
 53                    else 1.25 if uiscale is bui.UIScale.MEDIUM else 1.0
 54                ),
 55                stack_offset=(
 56                    (0, 0) if uiscale is bui.UIScale.SMALL else (0, 0)
 57                ),
 58            ),
 59            transition=transition,
 60            origin_widget=origin_widget,
 61        )
 62
 63        if uiscale is bui.UIScale.SMALL:
 64            self._back_button = None
 65            bui.containerwidget(
 66                edit=self._root_widget, on_cancel_call=self.main_window_back
 67            )
 68        else:
 69            self._back_button = btn = bui.buttonwidget(
 70                parent=self._root_widget,
 71                autoselect=True,
 72                position=(40 + x_inset, height - 55),
 73                size=(130, 60),
 74                scale=0.8,
 75                text_scale=1.2,
 76                label=bui.Lstr(resource='backText'),
 77                button_type='back',
 78                on_activate_call=self.main_window_back,
 79            )
 80            bui.containerwidget(edit=self._root_widget, cancel_button=btn)
 81
 82        bui.textwidget(
 83            parent=self._root_widget,
 84            position=(0, height - 44),
 85            size=(width, 25),
 86            text=bui.Lstr(resource=f'{self._r}.titleText'),
 87            color=bui.app.ui_v1.title_color,
 88            h_align='center',
 89            v_align='center',
 90            maxwidth=130,
 91        )
 92
 93        if self._back_button is not None:
 94            bui.buttonwidget(
 95                edit=self._back_button,
 96                button_type='backSmall',
 97                size=(60, 60),
 98                label=bui.charstr(bui.SpecialChar.BACK),
 99            )
100
101        v = height - 80
102        v -= 145
103
104        basew = 280 if uiscale is bui.UIScale.SMALL else 230
105        baseh = 170
106        x_offs = (
107            x_inset + (105 if uiscale is bui.UIScale.SMALL else 72) - basew
108        )  # now unused
109        x_offs2 = x_offs + basew - 7
110        x_offs3 = x_offs + 2 * (basew - 7)
111        x_offs4 = x_offs2
112        x_offs5 = x_offs3
113
114        def _b_title(
115            x: float, y: float, button: bui.Widget, text: str | bui.Lstr
116        ) -> None:
117            bui.textwidget(
118                parent=self._root_widget,
119                text=text,
120                position=(x + basew * 0.47, y + baseh * 0.22),
121                maxwidth=basew * 0.7,
122                size=(0, 0),
123                h_align='center',
124                v_align='center',
125                draw_controller=button,
126                color=(0.7, 0.9, 0.7, 1.0),
127            )
128
129        ctb = self._controllers_button = bui.buttonwidget(
130            parent=self._root_widget,
131            autoselect=True,
132            position=(x_offs2, v),
133            size=(basew, baseh),
134            button_type='square',
135            label='',
136            on_activate_call=self._do_controllers,
137        )
138        if self._back_button is None:
139            bbtn = bui.get_special_widget('back_button')
140            bui.widget(edit=ctb, left_widget=bbtn)
141        _b_title(
142            x_offs2, v, ctb, bui.Lstr(resource=f'{self._r}.controllersText')
143        )
144        imgw = imgh = 130
145        bui.imagewidget(
146            parent=self._root_widget,
147            position=(x_offs2 + basew * 0.49 - imgw * 0.5, v + 35),
148            size=(imgw, imgh),
149            texture=bui.gettexture('controllerIcon'),
150            draw_controller=ctb,
151        )
152
153        gfxb = self._graphics_button = bui.buttonwidget(
154            parent=self._root_widget,
155            autoselect=True,
156            position=(x_offs3, v),
157            size=(basew, baseh),
158            button_type='square',
159            label='',
160            on_activate_call=self._do_graphics,
161        )
162        pbtn = bui.get_special_widget('squad_button')
163        bui.widget(edit=gfxb, up_widget=pbtn, right_widget=pbtn)
164        _b_title(x_offs3, v, gfxb, bui.Lstr(resource=f'{self._r}.graphicsText'))
165        imgw = imgh = 110
166        bui.imagewidget(
167            parent=self._root_widget,
168            position=(x_offs3 + basew * 0.49 - imgw * 0.5, v + 42),
169            size=(imgw, imgh),
170            texture=bui.gettexture('graphicsIcon'),
171            draw_controller=gfxb,
172        )
173
174        v -= baseh - 5
175
176        abtn = self._audio_button = bui.buttonwidget(
177            parent=self._root_widget,
178            autoselect=True,
179            position=(x_offs4, v),
180            size=(basew, baseh),
181            button_type='square',
182            label='',
183            on_activate_call=self._do_audio,
184        )
185        _b_title(x_offs4, v, abtn, bui.Lstr(resource=f'{self._r}.audioText'))
186        imgw = imgh = 120
187        bui.imagewidget(
188            parent=self._root_widget,
189            position=(x_offs4 + basew * 0.49 - imgw * 0.5 + 5, v + 35),
190            size=(imgw, imgh),
191            color=(1, 1, 0),
192            texture=bui.gettexture('audioIcon'),
193            draw_controller=abtn,
194        )
195
196        avb = self._advanced_button = bui.buttonwidget(
197            parent=self._root_widget,
198            autoselect=True,
199            position=(x_offs5, v),
200            size=(basew, baseh),
201            button_type='square',
202            label='',
203            on_activate_call=self._do_advanced,
204        )
205        _b_title(x_offs5, v, avb, bui.Lstr(resource=f'{self._r}.advancedText'))
206        imgw = imgh = 120
207        bui.imagewidget(
208            parent=self._root_widget,
209            position=(x_offs5 + basew * 0.49 - imgw * 0.5 + 5, v + 35),
210            size=(imgw, imgh),
211            color=(0.8, 0.95, 1),
212            texture=bui.gettexture('advancedIcon'),
213            draw_controller=avb,
214        )
215        self._restore_state()
216
217    @override
218    def get_main_window_state(self) -> bui.MainWindowState:
219        # Support recreating our window for back/refresh purposes.
220        cls = type(self)
221        return bui.BasicMainWindowState(
222            create_call=lambda transition, origin_widget: cls(
223                transition=transition, origin_widget=origin_widget
224            )
225        )
226
227    @override
228    def on_main_window_close(self) -> None:
229        self._save_state()
230
231    @staticmethod
232    def _preload_modules() -> None:
233        """Preload modules we use; avoids hitches (called in bg thread)."""
234        import bauiv1lib.mainmenu as _unused1
235        import bauiv1lib.settings.controls as _unused2
236        import bauiv1lib.settings.graphics as _unused3
237        import bauiv1lib.settings.audio as _unused4
238        import bauiv1lib.settings.advanced as _unused5
239
240    def _do_controllers(self) -> None:
241        # pylint: disable=cyclic-import
242        from bauiv1lib.settings.controls import ControlsSettingsWindow
243
244        # no-op if we're not in control.
245        if not self.main_window_has_control():
246            return
247
248        self.main_window_replace(
249            ControlsSettingsWindow(origin_widget=self._controllers_button)
250        )
251
252    def _do_graphics(self) -> None:
253        # pylint: disable=cyclic-import
254        from bauiv1lib.settings.graphics import GraphicsSettingsWindow
255
256        # no-op if we're not in control.
257        if not self.main_window_has_control():
258            return
259
260        self.main_window_replace(
261            GraphicsSettingsWindow(origin_widget=self._graphics_button)
262        )
263
264    def _do_audio(self) -> None:
265        # pylint: disable=cyclic-import
266        from bauiv1lib.settings.audio import AudioSettingsWindow
267
268        # no-op if we're not in control.
269        if not self.main_window_has_control():
270            return
271
272        self.main_window_replace(
273            AudioSettingsWindow(origin_widget=self._audio_button)
274        )
275
276    def _do_advanced(self) -> None:
277        # pylint: disable=cyclic-import
278        from bauiv1lib.settings.advanced import AdvancedSettingsWindow
279
280        # no-op if we're not in control.
281        if not self.main_window_has_control():
282            return
283
284        self.main_window_replace(
285            AdvancedSettingsWindow(origin_widget=self._advanced_button)
286        )
287
288    def _save_state(self) -> None:
289        try:
290            sel = self._root_widget.get_selected_child()
291            if sel == self._controllers_button:
292                sel_name = 'Controllers'
293            elif sel == self._graphics_button:
294                sel_name = 'Graphics'
295            elif sel == self._audio_button:
296                sel_name = 'Audio'
297            elif sel == self._advanced_button:
298                sel_name = 'Advanced'
299            elif sel == self._back_button:
300                sel_name = 'Back'
301            else:
302                raise ValueError(f'unrecognized selection \'{sel}\'')
303            assert bui.app.classic is not None
304            bui.app.ui_v1.window_states[type(self)] = {'sel_name': sel_name}
305        except Exception:
306            logging.exception('Error saving state for %s.', self)
307
308    def _restore_state(self) -> None:
309        try:
310            assert bui.app.classic is not None
311            sel_name = bui.app.ui_v1.window_states.get(type(self), {}).get(
312                'sel_name'
313            )
314            sel: bui.Widget | None
315            if sel_name == 'Controllers':
316                sel = self._controllers_button
317            elif sel_name == 'Graphics':
318                sel = self._graphics_button
319            elif sel_name == 'Audio':
320                sel = self._audio_button
321            elif sel_name == 'Advanced':
322                sel = self._advanced_button
323            elif sel_name == 'Back':
324                sel = self._back_button
325            else:
326                sel = self._controllers_button
327            if sel is not None:
328                bui.containerwidget(edit=self._root_widget, selected_child=sel)
329        except Exception:
330            logging.exception('Error restoring state for %s.', self)

Window for selecting a settings category.

AllSettingsWindow( transition: str | None = 'in_right', origin_widget: _bauiv1.Widget | None = None)
 20    def __init__(
 21        self,
 22        transition: str | None = 'in_right',
 23        origin_widget: bui.Widget | None = None,
 24    ):
 25        # pylint: disable=too-many-statements
 26        # pylint: disable=too-many-locals
 27
 28        # Preload some modules we use in a background thread so we won't
 29        # have a visual hitch when the user taps them.
 30        bui.app.threadpool_submit_no_wait(self._preload_modules)
 31
 32        bui.set_analytics_screen('Settings Window')
 33        assert bui.app.classic is not None
 34        uiscale = bui.app.ui_v1.uiscale
 35        width = 1000 if uiscale is bui.UIScale.SMALL else 580
 36        x_inset = 125 if uiscale is bui.UIScale.SMALL else 0
 37        height = 435
 38        self._r = 'settingsWindow'
 39        top_extra = 20 if uiscale is bui.UIScale.SMALL else 0
 40
 41        uiscale = bui.app.ui_v1.uiscale
 42        super().__init__(
 43            root_widget=bui.containerwidget(
 44                size=(width, height + top_extra),
 45                toolbar_visibility=(
 46                    'menu_minimal'
 47                    if uiscale is bui.UIScale.SMALL
 48                    else 'menu_full'
 49                ),
 50                scale=(
 51                    1.5
 52                    if uiscale is bui.UIScale.SMALL
 53                    else 1.25 if uiscale is bui.UIScale.MEDIUM else 1.0
 54                ),
 55                stack_offset=(
 56                    (0, 0) if uiscale is bui.UIScale.SMALL else (0, 0)
 57                ),
 58            ),
 59            transition=transition,
 60            origin_widget=origin_widget,
 61        )
 62
 63        if uiscale is bui.UIScale.SMALL:
 64            self._back_button = None
 65            bui.containerwidget(
 66                edit=self._root_widget, on_cancel_call=self.main_window_back
 67            )
 68        else:
 69            self._back_button = btn = bui.buttonwidget(
 70                parent=self._root_widget,
 71                autoselect=True,
 72                position=(40 + x_inset, height - 55),
 73                size=(130, 60),
 74                scale=0.8,
 75                text_scale=1.2,
 76                label=bui.Lstr(resource='backText'),
 77                button_type='back',
 78                on_activate_call=self.main_window_back,
 79            )
 80            bui.containerwidget(edit=self._root_widget, cancel_button=btn)
 81
 82        bui.textwidget(
 83            parent=self._root_widget,
 84            position=(0, height - 44),
 85            size=(width, 25),
 86            text=bui.Lstr(resource=f'{self._r}.titleText'),
 87            color=bui.app.ui_v1.title_color,
 88            h_align='center',
 89            v_align='center',
 90            maxwidth=130,
 91        )
 92
 93        if self._back_button is not None:
 94            bui.buttonwidget(
 95                edit=self._back_button,
 96                button_type='backSmall',
 97                size=(60, 60),
 98                label=bui.charstr(bui.SpecialChar.BACK),
 99            )
100
101        v = height - 80
102        v -= 145
103
104        basew = 280 if uiscale is bui.UIScale.SMALL else 230
105        baseh = 170
106        x_offs = (
107            x_inset + (105 if uiscale is bui.UIScale.SMALL else 72) - basew
108        )  # now unused
109        x_offs2 = x_offs + basew - 7
110        x_offs3 = x_offs + 2 * (basew - 7)
111        x_offs4 = x_offs2
112        x_offs5 = x_offs3
113
114        def _b_title(
115            x: float, y: float, button: bui.Widget, text: str | bui.Lstr
116        ) -> None:
117            bui.textwidget(
118                parent=self._root_widget,
119                text=text,
120                position=(x + basew * 0.47, y + baseh * 0.22),
121                maxwidth=basew * 0.7,
122                size=(0, 0),
123                h_align='center',
124                v_align='center',
125                draw_controller=button,
126                color=(0.7, 0.9, 0.7, 1.0),
127            )
128
129        ctb = self._controllers_button = bui.buttonwidget(
130            parent=self._root_widget,
131            autoselect=True,
132            position=(x_offs2, v),
133            size=(basew, baseh),
134            button_type='square',
135            label='',
136            on_activate_call=self._do_controllers,
137        )
138        if self._back_button is None:
139            bbtn = bui.get_special_widget('back_button')
140            bui.widget(edit=ctb, left_widget=bbtn)
141        _b_title(
142            x_offs2, v, ctb, bui.Lstr(resource=f'{self._r}.controllersText')
143        )
144        imgw = imgh = 130
145        bui.imagewidget(
146            parent=self._root_widget,
147            position=(x_offs2 + basew * 0.49 - imgw * 0.5, v + 35),
148            size=(imgw, imgh),
149            texture=bui.gettexture('controllerIcon'),
150            draw_controller=ctb,
151        )
152
153        gfxb = self._graphics_button = bui.buttonwidget(
154            parent=self._root_widget,
155            autoselect=True,
156            position=(x_offs3, v),
157            size=(basew, baseh),
158            button_type='square',
159            label='',
160            on_activate_call=self._do_graphics,
161        )
162        pbtn = bui.get_special_widget('squad_button')
163        bui.widget(edit=gfxb, up_widget=pbtn, right_widget=pbtn)
164        _b_title(x_offs3, v, gfxb, bui.Lstr(resource=f'{self._r}.graphicsText'))
165        imgw = imgh = 110
166        bui.imagewidget(
167            parent=self._root_widget,
168            position=(x_offs3 + basew * 0.49 - imgw * 0.5, v + 42),
169            size=(imgw, imgh),
170            texture=bui.gettexture('graphicsIcon'),
171            draw_controller=gfxb,
172        )
173
174        v -= baseh - 5
175
176        abtn = self._audio_button = bui.buttonwidget(
177            parent=self._root_widget,
178            autoselect=True,
179            position=(x_offs4, v),
180            size=(basew, baseh),
181            button_type='square',
182            label='',
183            on_activate_call=self._do_audio,
184        )
185        _b_title(x_offs4, v, abtn, bui.Lstr(resource=f'{self._r}.audioText'))
186        imgw = imgh = 120
187        bui.imagewidget(
188            parent=self._root_widget,
189            position=(x_offs4 + basew * 0.49 - imgw * 0.5 + 5, v + 35),
190            size=(imgw, imgh),
191            color=(1, 1, 0),
192            texture=bui.gettexture('audioIcon'),
193            draw_controller=abtn,
194        )
195
196        avb = self._advanced_button = bui.buttonwidget(
197            parent=self._root_widget,
198            autoselect=True,
199            position=(x_offs5, v),
200            size=(basew, baseh),
201            button_type='square',
202            label='',
203            on_activate_call=self._do_advanced,
204        )
205        _b_title(x_offs5, v, avb, bui.Lstr(resource=f'{self._r}.advancedText'))
206        imgw = imgh = 120
207        bui.imagewidget(
208            parent=self._root_widget,
209            position=(x_offs5 + basew * 0.49 - imgw * 0.5 + 5, v + 35),
210            size=(imgw, imgh),
211            color=(0.8, 0.95, 1),
212            texture=bui.gettexture('advancedIcon'),
213            draw_controller=avb,
214        )
215        self._restore_state()

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:
217    @override
218    def get_main_window_state(self) -> bui.MainWindowState:
219        # Support recreating our window for back/refresh purposes.
220        cls = type(self)
221        return bui.BasicMainWindowState(
222            create_call=lambda transition, origin_widget: cls(
223                transition=transition, origin_widget=origin_widget
224            )
225        )

Return a WindowState to recreate this window, if supported.

@override
def on_main_window_close(self) -> None:
227    @override
228    def on_main_window_close(self) -> None:
229        self._save_state()

Called before transitioning out a main window.

A good opportunity to save window state/etc.

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
bauiv1._uitypes.Window
get_root_widget