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

Window for selecting a settings category.

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