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 our underlying widget is dead or on its way out.
244        if not self._root_widget or self._root_widget.transitioning_out:
245            return
246
247        self._save_state()
248        bui.containerwidget(edit=self._root_widget, transition='out_left')
249        assert bui.app.classic is not None
250        bui.app.ui_v1.set_main_window(
251            ControlsSettingsWindow(origin_widget=self._controllers_button),
252            from_window=self,
253        )
254
255    def _do_graphics(self) -> None:
256        # pylint: disable=cyclic-import
257        from bauiv1lib.settings.graphics import GraphicsSettingsWindow
258
259        # no-op if our underlying widget is dead or on its way out.
260        if not self._root_widget or self._root_widget.transitioning_out:
261            return
262
263        self._save_state()
264        bui.containerwidget(edit=self._root_widget, transition='out_left')
265        assert bui.app.classic is not None
266        bui.app.ui_v1.set_main_window(
267            GraphicsSettingsWindow(origin_widget=self._graphics_button),
268            from_window=self,
269        )
270
271    def _do_audio(self) -> None:
272        # pylint: disable=cyclic-import
273        from bauiv1lib.settings.audio import AudioSettingsWindow
274
275        # no-op if our underlying widget is dead or on its way out.
276        if not self._root_widget or self._root_widget.transitioning_out:
277            return
278
279        self._save_state()
280        bui.containerwidget(edit=self._root_widget, transition='out_left')
281        assert bui.app.classic is not None
282        bui.app.ui_v1.set_main_window(
283            AudioSettingsWindow(origin_widget=self._audio_button),
284            from_window=self,
285        )
286
287    def _do_advanced(self) -> None:
288        # pylint: disable=cyclic-import
289        from bauiv1lib.settings.advanced import AdvancedSettingsWindow
290
291        # no-op if our underlying widget is dead or on its way out.
292        if not self._root_widget or self._root_widget.transitioning_out:
293            return
294
295        self._save_state()
296        bui.containerwidget(edit=self._root_widget, transition='out_left')
297        assert bui.app.classic is not None
298        bui.app.ui_v1.set_main_window(
299            AdvancedSettingsWindow(origin_widget=self._advanced_button),
300            from_window=self,
301        )
302
303    def _save_state(self) -> None:
304        try:
305            sel = self._root_widget.get_selected_child()
306            if sel == self._controllers_button:
307                sel_name = 'Controllers'
308            elif sel == self._graphics_button:
309                sel_name = 'Graphics'
310            elif sel == self._audio_button:
311                sel_name = 'Audio'
312            elif sel == self._advanced_button:
313                sel_name = 'Advanced'
314            elif sel == self._back_button:
315                sel_name = 'Back'
316            else:
317                raise ValueError(f'unrecognized selection \'{sel}\'')
318            assert bui.app.classic is not None
319            bui.app.ui_v1.window_states[type(self)] = {'sel_name': sel_name}
320        except Exception:
321            logging.exception('Error saving state for %s.', self)
322
323    def _restore_state(self) -> None:
324        try:
325            assert bui.app.classic is not None
326            sel_name = bui.app.ui_v1.window_states.get(type(self), {}).get(
327                'sel_name'
328            )
329            sel: bui.Widget | None
330            if sel_name == 'Controllers':
331                sel = self._controllers_button
332            elif sel_name == 'Graphics':
333                sel = self._graphics_button
334            elif sel_name == 'Audio':
335                sel = self._audio_button
336            elif sel_name == 'Advanced':
337                sel = self._advanced_button
338            elif sel_name == 'Back':
339                sel = self._back_button
340            else:
341                sel = self._controllers_button
342            if sel is not None:
343                bui.containerwidget(edit=self._root_widget, selected_child=sel)
344        except Exception:
345            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 our underlying widget is dead or on its way out.
245        if not self._root_widget or self._root_widget.transitioning_out:
246            return
247
248        self._save_state()
249        bui.containerwidget(edit=self._root_widget, transition='out_left')
250        assert bui.app.classic is not None
251        bui.app.ui_v1.set_main_window(
252            ControlsSettingsWindow(origin_widget=self._controllers_button),
253            from_window=self,
254        )
255
256    def _do_graphics(self) -> None:
257        # pylint: disable=cyclic-import
258        from bauiv1lib.settings.graphics import GraphicsSettingsWindow
259
260        # no-op if our underlying widget is dead or on its way out.
261        if not self._root_widget or self._root_widget.transitioning_out:
262            return
263
264        self._save_state()
265        bui.containerwidget(edit=self._root_widget, transition='out_left')
266        assert bui.app.classic is not None
267        bui.app.ui_v1.set_main_window(
268            GraphicsSettingsWindow(origin_widget=self._graphics_button),
269            from_window=self,
270        )
271
272    def _do_audio(self) -> None:
273        # pylint: disable=cyclic-import
274        from bauiv1lib.settings.audio import AudioSettingsWindow
275
276        # no-op if our underlying widget is dead or on its way out.
277        if not self._root_widget or self._root_widget.transitioning_out:
278            return
279
280        self._save_state()
281        bui.containerwidget(edit=self._root_widget, transition='out_left')
282        assert bui.app.classic is not None
283        bui.app.ui_v1.set_main_window(
284            AudioSettingsWindow(origin_widget=self._audio_button),
285            from_window=self,
286        )
287
288    def _do_advanced(self) -> None:
289        # pylint: disable=cyclic-import
290        from bauiv1lib.settings.advanced import AdvancedSettingsWindow
291
292        # no-op if our underlying widget is dead or on its way out.
293        if not self._root_widget or self._root_widget.transitioning_out:
294            return
295
296        self._save_state()
297        bui.containerwidget(edit=self._root_widget, transition='out_left')
298        assert bui.app.classic is not None
299        bui.app.ui_v1.set_main_window(
300            AdvancedSettingsWindow(origin_widget=self._advanced_button),
301            from_window=self,
302        )
303
304    def _save_state(self) -> None:
305        try:
306            sel = self._root_widget.get_selected_child()
307            if sel == self._controllers_button:
308                sel_name = 'Controllers'
309            elif sel == self._graphics_button:
310                sel_name = 'Graphics'
311            elif sel == self._audio_button:
312                sel_name = 'Audio'
313            elif sel == self._advanced_button:
314                sel_name = 'Advanced'
315            elif sel == self._back_button:
316                sel_name = 'Back'
317            else:
318                raise ValueError(f'unrecognized selection \'{sel}\'')
319            assert bui.app.classic is not None
320            bui.app.ui_v1.window_states[type(self)] = {'sel_name': sel_name}
321        except Exception:
322            logging.exception('Error saving state for %s.', self)
323
324    def _restore_state(self) -> None:
325        try:
326            assert bui.app.classic is not None
327            sel_name = bui.app.ui_v1.window_states.get(type(self), {}).get(
328                'sel_name'
329            )
330            sel: bui.Widget | None
331            if sel_name == 'Controllers':
332                sel = self._controllers_button
333            elif sel_name == 'Graphics':
334                sel = self._graphics_button
335            elif sel_name == 'Audio':
336                sel = self._audio_button
337            elif sel_name == 'Advanced':
338                sel = self._advanced_button
339            elif sel_name == 'Back':
340                sel = self._back_button
341            else:
342                sel = self._controllers_button
343            if sel is not None:
344                bui.containerwidget(edit=self._root_widget, selected_child=sel)
345        except Exception:
346            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_close
can_change_main_window
main_window_back
main_window_replace
bauiv1._uitypes.Window
get_root_widget