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

Window for selecting a settings category.

AllSettingsWindow( transition: str = 'in_right', origin_widget: _ba.Widget | None = None)
 20    def __init__(
 21        self,
 22        transition: str = 'in_right',
 23        origin_widget: ba.Widget | None = None,
 24    ):
 25        # pylint: disable=too-many-statements
 26        # pylint: disable=too-many-locals
 27        import threading
 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        threading.Thread(target=self._preload_modules).start()
 32
 33        ba.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        uiscale = ba.app.ui.uiscale
 43        width = 900 if uiscale is ba.UIScale.SMALL else 580
 44        x_inset = 75 if uiscale is ba.UIScale.SMALL else 0
 45        height = 435
 46        self._r = 'settingsWindow'
 47        top_extra = 20 if uiscale is ba.UIScale.SMALL else 0
 48
 49        uiscale = ba.app.ui.uiscale
 50        super().__init__(
 51            root_widget=ba.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 ba.UIScale.SMALL
 59                    else 1.35
 60                    if uiscale is ba.UIScale.MEDIUM
 61                    else 1.0
 62                ),
 63                stack_offset=(0, -8) if uiscale is ba.UIScale.SMALL else (0, 0),
 64            )
 65        )
 66
 67        if ba.app.ui.use_toolbars and uiscale is ba.UIScale.SMALL:
 68            self._back_button = None
 69            ba.containerwidget(
 70                edit=self._root_widget, on_cancel_call=self._do_back
 71            )
 72        else:
 73            self._back_button = btn = ba.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=ba.Lstr(resource='backText'),
 81                button_type='back',
 82                on_activate_call=self._do_back,
 83            )
 84            ba.containerwidget(edit=self._root_widget, cancel_button=btn)
 85
 86        ba.textwidget(
 87            parent=self._root_widget,
 88            position=(0, height - 44),
 89            size=(width, 25),
 90            text=ba.Lstr(resource=self._r + '.titleText'),
 91            color=ba.app.ui.title_color,
 92            h_align='center',
 93            v_align='center',
 94            maxwidth=130,
 95        )
 96
 97        if self._back_button is not None:
 98            ba.buttonwidget(
 99                edit=self._back_button,
100                button_type='backSmall',
101                size=(60, 60),
102                label=ba.charstr(ba.SpecialChar.BACK),
103            )
104
105        v = height - 80
106        v -= 145
107
108        basew = 280 if uiscale is ba.UIScale.SMALL else 230
109        baseh = 170
110        x_offs = (
111            x_inset + (105 if uiscale is ba.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: ba.Widget, text: str | ba.Lstr
120        ) -> None:
121            ba.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 = ba.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 ba.app.ui.use_toolbars and self._back_button is None:
143            bbtn = ba.internal.get_special_widget('back_button')
144            ba.widget(edit=ctb, left_widget=bbtn)
145        _b_title(
146            x_offs2, v, ctb, ba.Lstr(resource=self._r + '.controllersText')
147        )
148        imgw = imgh = 130
149        ba.imagewidget(
150            parent=self._root_widget,
151            position=(x_offs2 + basew * 0.49 - imgw * 0.5, v + 35),
152            size=(imgw, imgh),
153            texture=ba.gettexture('controllerIcon'),
154            draw_controller=ctb,
155        )
156
157        gfxb = self._graphics_button = ba.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 ba.app.ui.use_toolbars:
167            pbtn = ba.internal.get_special_widget('party_button')
168            ba.widget(edit=gfxb, up_widget=pbtn, right_widget=pbtn)
169        _b_title(x_offs3, v, gfxb, ba.Lstr(resource=self._r + '.graphicsText'))
170        imgw = imgh = 110
171        ba.imagewidget(
172            parent=self._root_widget,
173            position=(x_offs3 + basew * 0.49 - imgw * 0.5, v + 42),
174            size=(imgw, imgh),
175            texture=ba.gettexture('graphicsIcon'),
176            draw_controller=gfxb,
177        )
178
179        v -= baseh - 5
180
181        abtn = self._audio_button = ba.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, ba.Lstr(resource=self._r + '.audioText'))
191        imgw = imgh = 120
192        ba.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=ba.gettexture('audioIcon'),
198            draw_controller=abtn,
199        )
200
201        avb = self._advanced_button = ba.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, ba.Lstr(resource=self._r + '.advancedText'))
211        imgw = imgh = 120
212        ba.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=ba.gettexture('advancedIcon'),
218            draw_controller=avb,
219        )
220        self._restore_state()
Inherited Members
ba.ui.Window
get_root_widget