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