vh-bombsquad-modded-server-.../dist/ba_data/python/bastd/ui/settings/advanced.py
2024-06-06 19:50:58 +05:30

865 lines
31 KiB
Python

# Released under the MIT License. See LICENSE for details.
#
"""UI functionality for advanced settings."""
from __future__ import annotations
from typing import TYPE_CHECKING
import ba
import ba.internal
from bastd.ui import popup as popup_ui
if TYPE_CHECKING:
from typing import Any
class AdvancedSettingsWindow(ba.Window):
"""Window for editing advanced game settings."""
def __init__(
self,
transition: str = 'in_right',
origin_widget: ba.Widget | None = None,
):
# pylint: disable=too-many-statements
from ba.internal import master_server_get
import threading
# Preload some modules we use in a background thread so we won't
# have a visual hitch when the user taps them.
threading.Thread(target=self._preload_modules).start()
app = ba.app
# If they provided an origin-widget, scale up from that.
scale_origin: tuple[float, float] | None
if origin_widget is not None:
self._transition_out = 'out_scale'
scale_origin = origin_widget.get_screen_space_center()
transition = 'in_scale'
else:
self._transition_out = 'out_right'
scale_origin = None
uiscale = ba.app.ui.uiscale
self._width = 870.0 if uiscale is ba.UIScale.SMALL else 670.0
x_inset = 100 if uiscale is ba.UIScale.SMALL else 0
self._height = (
390.0
if uiscale is ba.UIScale.SMALL
else 450.0
if uiscale is ba.UIScale.MEDIUM
else 520.0
)
self._spacing = 32
self._menu_open = False
top_extra = 10 if uiscale is ba.UIScale.SMALL else 0
super().__init__(
root_widget=ba.containerwidget(
size=(self._width, self._height + top_extra),
transition=transition,
toolbar_visibility='menu_minimal',
scale_origin_stack_offset=scale_origin,
scale=(
2.06
if uiscale is ba.UIScale.SMALL
else 1.4
if uiscale is ba.UIScale.MEDIUM
else 1.0
),
stack_offset=(0, -25)
if uiscale is ba.UIScale.SMALL
else (0, 0),
)
)
self._prev_lang = ''
self._prev_lang_list: list[str] = []
self._complete_langs_list: list | None = None
self._complete_langs_error = False
self._language_popup: popup_ui.PopupMenu | None = None
# In vr-mode, the internal keyboard is currently the *only* option,
# so no need to show this.
self._show_always_use_internal_keyboard = (
not app.vr_mode and not app.iircade_mode
)
self._scroll_width = self._width - (100 + 2 * x_inset)
self._scroll_height = self._height - 115.0
self._sub_width = self._scroll_width * 0.95
self._sub_height = 724.0
if self._show_always_use_internal_keyboard:
self._sub_height += 62
self._show_disable_gyro = app.platform in {'ios', 'android'}
if self._show_disable_gyro:
self._sub_height += 42
self._do_vr_test_button = app.vr_mode
self._do_net_test_button = True
self._extra_button_spacing = self._spacing * 2.5
if self._do_vr_test_button:
self._sub_height += self._extra_button_spacing
if self._do_net_test_button:
self._sub_height += self._extra_button_spacing
self._sub_height += self._spacing * 2.0 # plugins
self._r = 'settingsWindowAdvanced'
if app.ui.use_toolbars and uiscale is ba.UIScale.SMALL:
ba.containerwidget(
edit=self._root_widget, on_cancel_call=self._do_back
)
self._back_button = None
else:
self._back_button = ba.buttonwidget(
parent=self._root_widget,
position=(53 + x_inset, self._height - 60),
size=(140, 60),
scale=0.8,
autoselect=True,
label=ba.Lstr(resource='backText'),
button_type='back',
on_activate_call=self._do_back,
)
ba.containerwidget(
edit=self._root_widget, cancel_button=self._back_button
)
self._title_text = ba.textwidget(
parent=self._root_widget,
position=(0, self._height - 52),
size=(self._width, 25),
text=ba.Lstr(resource=f'{self._r}.titleText'),
color=app.ui.title_color,
h_align='center',
v_align='top',
)
if self._back_button is not None:
ba.buttonwidget(
edit=self._back_button,
button_type='backSmall',
size=(60, 60),
label=ba.charstr(ba.SpecialChar.BACK),
)
self._scrollwidget = ba.scrollwidget(
parent=self._root_widget,
position=(50 + x_inset, 50),
simple_culling_v=20.0,
highlight=False,
size=(self._scroll_width, self._scroll_height),
selection_loops_to_parent=True,
)
ba.widget(edit=self._scrollwidget, right_widget=self._scrollwidget)
self._subcontainer = ba.containerwidget(
parent=self._scrollwidget,
size=(self._sub_width, self._sub_height),
background=False,
selection_loops_to_parent=True,
)
self._rebuild()
# Rebuild periodically to pick up language changes/additions/etc.
self._rebuild_timer = ba.Timer(
1.0,
ba.WeakCall(self._rebuild),
repeat=True,
timetype=ba.TimeType.REAL,
)
# Fetch the list of completed languages.
master_server_get(
'bsLangGetCompleted',
{'b': app.build_number},
callback=ba.WeakCall(self._completed_langs_cb),
)
# noinspection PyUnresolvedReferences
@staticmethod
def _preload_modules() -> None:
"""Preload modules we use (called in bg thread)."""
from bastd.ui import config as _unused1
from ba import modutils as _unused2
from bastd.ui.settings import vrtesting as _unused3
from bastd.ui.settings import nettesting as _unused4
from bastd.ui import appinvite as _unused5
from bastd.ui import account as _unused6
from bastd.ui import promocode as _unused7
from bastd.ui import debug as _unused8
from bastd.ui.settings import plugins as _unused9
def _update_lang_status(self) -> None:
if self._complete_langs_list is not None:
up_to_date = ba.app.lang.language in self._complete_langs_list
ba.textwidget(
edit=self._lang_status_text,
text=''
if ba.app.lang.language == 'Test'
else ba.Lstr(
resource=f'{self._r}.translationNoUpdateNeededText'
)
if up_to_date
else ba.Lstr(resource=f'{self._r}.translationUpdateNeededText'),
color=(0.2, 1.0, 0.2, 0.8)
if up_to_date
else (1.0, 0.2, 0.2, 0.8),
)
else:
ba.textwidget(
edit=self._lang_status_text,
text=ba.Lstr(resource=f'{self._r}.translationFetchErrorText')
if self._complete_langs_error
else ba.Lstr(
resource=f'{self._r}.translationFetchingStatusText'
),
color=(1.0, 0.5, 0.2)
if self._complete_langs_error
else (0.7, 0.7, 0.7),
)
def _rebuild(self) -> None:
# pylint: disable=too-many-statements
# pylint: disable=too-many-branches
# pylint: disable=too-many-locals
from bastd.ui.config import ConfigCheckBox
from ba.modutils import show_user_scripts
available_languages = ba.app.lang.available_languages
# Don't rebuild if the menu is open or if our language and
# language-list hasn't changed.
# NOTE - although we now support widgets updating their own
# translations, we still change the label formatting on the language
# menu based on the language so still need this. ...however we could
# make this more limited to it only rebuilds that one menu instead
# of everything.
if self._menu_open or (
self._prev_lang == ba.app.config.get('Lang', None)
and self._prev_lang_list == available_languages
):
return
self._prev_lang = ba.app.config.get('Lang', None)
self._prev_lang_list = available_languages
# Clear out our sub-container.
children = self._subcontainer.get_children()
for child in children:
child.delete()
v = self._sub_height - 35
v -= self._spacing * 1.2
# Update our existing back button and title.
if self._back_button is not None:
ba.buttonwidget(
edit=self._back_button, label=ba.Lstr(resource='backText')
)
ba.buttonwidget(
edit=self._back_button, label=ba.charstr(ba.SpecialChar.BACK)
)
ba.textwidget(
edit=self._title_text, text=ba.Lstr(resource=f'{self._r}.titleText')
)
this_button_width = 410
self._promo_code_button = ba.buttonwidget(
parent=self._subcontainer,
position=(self._sub_width / 2 - this_button_width / 2, v - 14),
size=(this_button_width, 60),
autoselect=True,
label=ba.Lstr(resource=f'{self._r}.enterPromoCodeText'),
text_scale=1.0,
on_activate_call=self._on_promo_code_press,
)
if self._back_button is not None:
ba.widget(
edit=self._promo_code_button,
up_widget=self._back_button,
left_widget=self._back_button,
)
v -= self._extra_button_spacing * 0.8
ba.textwidget(
parent=self._subcontainer,
position=(200, v + 10),
size=(0, 0),
text=ba.Lstr(resource=f'{self._r}.languageText'),
maxwidth=150,
scale=0.95,
color=ba.app.ui.title_color,
h_align='right',
v_align='center',
)
languages = ba.app.lang.available_languages
cur_lang = ba.app.config.get('Lang', None)
if cur_lang is None:
cur_lang = 'Auto'
# We have a special dict of language names in that language
# so we don't have to go digging through each full language.
try:
import json
with open('ba_data/data/langdata.json', encoding='utf-8') as infile:
lang_names_translated = json.loads(infile.read())[
'lang_names_translated'
]
except Exception:
ba.print_exception('Error reading lang data.')
lang_names_translated = {}
langs_translated = {}
for lang in languages:
langs_translated[lang] = lang_names_translated.get(lang, lang)
langs_full = {}
for lang in languages:
lang_translated = ba.Lstr(translate=('languages', lang)).evaluate()
if langs_translated[lang] == lang_translated:
langs_full[lang] = lang_translated
else:
langs_full[lang] = (
langs_translated[lang] + ' (' + lang_translated + ')'
)
self._language_popup = popup_ui.PopupMenu(
parent=self._subcontainer,
position=(210, v - 19),
width=150,
opening_call=ba.WeakCall(self._on_menu_open),
closing_call=ba.WeakCall(self._on_menu_close),
autoselect=False,
on_value_change_call=ba.WeakCall(self._on_menu_choice),
choices=['Auto'] + languages,
button_size=(250, 60),
choices_display=(
[
ba.Lstr(
value=(
ba.Lstr(resource='autoText').evaluate()
+ ' ('
+ ba.Lstr(
translate=(
'languages',
ba.app.lang.default_language,
)
).evaluate()
+ ')'
)
)
]
+ [ba.Lstr(value=langs_full[l]) for l in languages]
),
current_choice=cur_lang,
)
v -= self._spacing * 1.8
ba.textwidget(
parent=self._subcontainer,
position=(self._sub_width * 0.5, v + 10),
size=(0, 0),
text=ba.Lstr(
resource=f'{self._r}.helpTranslateText',
subs=[('${APP_NAME}', ba.Lstr(resource='titleText'))],
),
maxwidth=self._sub_width * 0.9,
max_height=55,
flatness=1.0,
scale=0.65,
color=(0.4, 0.9, 0.4, 0.8),
h_align='center',
v_align='center',
)
v -= self._spacing * 1.9
this_button_width = 410
self._translation_editor_button = ba.buttonwidget(
parent=self._subcontainer,
position=(self._sub_width / 2 - this_button_width / 2, v - 24),
size=(this_button_width, 60),
label=ba.Lstr(
resource=f'{self._r}.translationEditorButtonText',
subs=[('${APP_NAME}', ba.Lstr(resource='titleText'))],
),
autoselect=True,
on_activate_call=ba.Call(
ba.open_url, 'https://legacy.ballistica.net/translate'
),
)
self._lang_status_text = ba.textwidget(
parent=self._subcontainer,
position=(self._sub_width * 0.5, v - 40),
size=(0, 0),
text='',
flatness=1.0,
scale=0.63,
h_align='center',
v_align='center',
maxwidth=400.0,
)
self._update_lang_status()
v -= 40
lang_inform = ba.internal.get_v1_account_misc_val('langInform', False)
self._language_inform_checkbox = cbw = ba.checkboxwidget(
parent=self._subcontainer,
position=(50, v - 50),
size=(self._sub_width - 100, 30),
autoselect=True,
maxwidth=430,
textcolor=(0.8, 0.8, 0.8),
value=lang_inform,
text=ba.Lstr(resource=f'{self._r}.translationInformMe'),
on_value_change_call=ba.WeakCall(self._on_lang_inform_value_change),
)
ba.widget(
edit=self._translation_editor_button,
down_widget=cbw,
up_widget=self._language_popup.get_button(),
)
v -= self._spacing * 3.0
self._kick_idle_players_check_box = ConfigCheckBox(
parent=self._subcontainer,
position=(50, v),
size=(self._sub_width - 100, 30),
configkey='Kick Idle Players',
displayname=ba.Lstr(resource=f'{self._r}.kickIdlePlayersText'),
scale=1.0,
maxwidth=430,
)
v -= 42
self._show_game_ping_check_box = ConfigCheckBox(
parent=self._subcontainer,
position=(50, v),
size=(self._sub_width - 100, 30),
configkey='Show Ping',
displayname=ba.Lstr(resource=f'{self._r}.showInGamePingText'),
scale=1.0,
maxwidth=430,
)
v -= 42
self._disable_camera_shake_check_box = ConfigCheckBox(
parent=self._subcontainer,
position=(50, v),
size=(self._sub_width - 100, 30),
configkey='Disable Camera Shake',
displayname=ba.Lstr(resource=f'{self._r}.disableCameraShakeText'),
scale=1.0,
maxwidth=430,
)
self._disable_gyro_check_box: ConfigCheckBox | None = None
if self._show_disable_gyro:
v -= 42
self._disable_gyro_check_box = ConfigCheckBox(
parent=self._subcontainer,
position=(50, v),
size=(self._sub_width - 100, 30),
configkey='Disable Camera Gyro',
displayname=ba.Lstr(
resource=f'{self._r}.disableCameraGyroscopeMotionText'
),
scale=1.0,
maxwidth=430,
)
self._always_use_internal_keyboard_check_box: ConfigCheckBox | None
if self._show_always_use_internal_keyboard:
v -= 42
self._always_use_internal_keyboard_check_box = ConfigCheckBox(
parent=self._subcontainer,
position=(50, v),
size=(self._sub_width - 100, 30),
configkey='Always Use Internal Keyboard',
autoselect=True,
displayname=ba.Lstr(
resource=f'{self._r}.alwaysUseInternalKeyboardText'
),
scale=1.0,
maxwidth=430,
)
ba.textwidget(
parent=self._subcontainer,
position=(90, v - 10),
size=(0, 0),
text=ba.Lstr(
resource=(
f'{self._r}.alwaysUseInternalKeyboardDescriptionText'
)
),
maxwidth=400,
flatness=1.0,
scale=0.65,
color=(0.4, 0.9, 0.4, 0.8),
h_align='left',
v_align='center',
)
v -= 20
else:
self._always_use_internal_keyboard_check_box = None
v -= self._spacing * 2.1
this_button_width = 410
self._modding_guide_button = ba.buttonwidget(
parent=self._subcontainer,
position=(self._sub_width / 2 - this_button_width / 2, v - 10),
size=(this_button_width, 60),
autoselect=True,
label=ba.Lstr(resource=f'{self._r}.moddingGuideText'),
text_scale=1.0,
on_activate_call=ba.Call(
ba.open_url, 'https://ballistica.net/wiki/modding-guide'
),
)
if self._show_always_use_internal_keyboard:
assert self._always_use_internal_keyboard_check_box is not None
ba.widget(
edit=self._always_use_internal_keyboard_check_box.widget,
down_widget=self._modding_guide_button,
)
ba.widget(
edit=self._modding_guide_button,
up_widget=self._always_use_internal_keyboard_check_box.widget,
)
else:
ba.widget(
edit=self._modding_guide_button,
up_widget=self._kick_idle_players_check_box.widget,
)
ba.widget(
edit=self._kick_idle_players_check_box.widget,
down_widget=self._modding_guide_button,
)
v -= self._spacing * 2.0
self._show_user_mods_button = ba.buttonwidget(
parent=self._subcontainer,
position=(self._sub_width / 2 - this_button_width / 2, v - 10),
size=(this_button_width, 60),
autoselect=True,
label=ba.Lstr(resource=f'{self._r}.showUserModsText'),
text_scale=1.0,
on_activate_call=show_user_scripts,
)
v -= self._spacing * 2.0
self._plugins_button = ba.buttonwidget(
parent=self._subcontainer,
position=(self._sub_width / 2 - this_button_width / 2, v - 10),
size=(this_button_width, 60),
autoselect=True,
label=ba.Lstr(resource='pluginsText'),
text_scale=1.0,
on_activate_call=self._on_plugins_button_press,
)
v -= self._spacing * 0.6
self._vr_test_button: ba.Widget | None
if self._do_vr_test_button:
v -= self._extra_button_spacing
self._vr_test_button = ba.buttonwidget(
parent=self._subcontainer,
position=(self._sub_width / 2 - this_button_width / 2, v - 14),
size=(this_button_width, 60),
autoselect=True,
label=ba.Lstr(resource=f'{self._r}.vrTestingText'),
text_scale=1.0,
on_activate_call=self._on_vr_test_press,
)
else:
self._vr_test_button = None
self._net_test_button: ba.Widget | None
if self._do_net_test_button:
v -= self._extra_button_spacing
self._net_test_button = ba.buttonwidget(
parent=self._subcontainer,
position=(self._sub_width / 2 - this_button_width / 2, v - 14),
size=(this_button_width, 60),
autoselect=True,
label=ba.Lstr(resource=f'{self._r}.netTestingText'),
text_scale=1.0,
on_activate_call=self._on_net_test_press,
)
else:
self._net_test_button = None
v -= 70
self._benchmarks_button = ba.buttonwidget(
parent=self._subcontainer,
position=(self._sub_width / 2 - this_button_width / 2, v - 14),
size=(this_button_width, 60),
autoselect=True,
label=ba.Lstr(resource=f'{self._r}.benchmarksText'),
text_scale=1.0,
on_activate_call=self._on_benchmark_press,
)
for child in self._subcontainer.get_children():
ba.widget(edit=child, show_buffer_bottom=30, show_buffer_top=20)
if ba.app.ui.use_toolbars:
pbtn = ba.internal.get_special_widget('party_button')
ba.widget(edit=self._scrollwidget, right_widget=pbtn)
if self._back_button is None:
ba.widget(
edit=self._scrollwidget,
left_widget=ba.internal.get_special_widget('back_button'),
)
self._restore_state()
def _show_restart_needed(self, value: Any) -> None:
del value # Unused.
ba.screenmessage(
ba.Lstr(resource=f'{self._r}.mustRestartText'), color=(1, 1, 0)
)
def _on_lang_inform_value_change(self, val: bool) -> None:
ba.internal.add_transaction(
{'type': 'SET_MISC_VAL', 'name': 'langInform', 'value': val}
)
ba.internal.run_transactions()
def _on_vr_test_press(self) -> None:
from bastd.ui.settings.vrtesting import VRTestingWindow
self._save_state()
ba.containerwidget(edit=self._root_widget, transition='out_left')
ba.app.ui.set_main_menu_window(
VRTestingWindow(transition='in_right').get_root_widget()
)
def _on_net_test_press(self) -> None:
from bastd.ui.settings.nettesting import NetTestingWindow
# Net-testing requires a signed in v1 account.
if ba.internal.get_v1_account_state() != 'signed_in':
ba.screenmessage(
ba.Lstr(resource='notSignedInErrorText'), color=(1, 0, 0)
)
ba.playsound(ba.getsound('error'))
return
self._save_state()
ba.containerwidget(edit=self._root_widget, transition='out_left')
ba.app.ui.set_main_menu_window(
NetTestingWindow(transition='in_right').get_root_widget()
)
def _on_friend_promo_code_press(self) -> None:
from bastd.ui import appinvite
from bastd.ui import account
if ba.internal.get_v1_account_state() != 'signed_in':
account.show_sign_in_prompt()
return
appinvite.handle_app_invites_press()
def _on_plugins_button_press(self) -> None:
from bastd.ui.settings.plugins import PluginWindow
self._save_state()
ba.containerwidget(edit=self._root_widget, transition='out_left')
ba.app.ui.set_main_menu_window(
PluginWindow(origin_widget=self._plugins_button).get_root_widget()
)
def _on_promo_code_press(self) -> None:
from bastd.ui.promocode import PromoCodeWindow
from bastd.ui.account import show_sign_in_prompt
# We have to be logged in for promo-codes to work.
if ba.internal.get_v1_account_state() != 'signed_in':
show_sign_in_prompt()
return
self._save_state()
ba.containerwidget(edit=self._root_widget, transition='out_left')
ba.app.ui.set_main_menu_window(
PromoCodeWindow(
origin_widget=self._promo_code_button
).get_root_widget()
)
def _on_benchmark_press(self) -> None:
from bastd.ui.debug import DebugWindow
self._save_state()
ba.containerwidget(edit=self._root_widget, transition='out_left')
ba.app.ui.set_main_menu_window(
DebugWindow(transition='in_right').get_root_widget()
)
def _save_state(self) -> None:
# pylint: disable=too-many-branches
try:
sel = self._root_widget.get_selected_child()
if sel == self._scrollwidget:
sel = self._subcontainer.get_selected_child()
if sel == self._vr_test_button:
sel_name = 'VRTest'
elif sel == self._net_test_button:
sel_name = 'NetTest'
elif sel == self._promo_code_button:
sel_name = 'PromoCode'
elif sel == self._benchmarks_button:
sel_name = 'Benchmarks'
elif sel == self._kick_idle_players_check_box.widget:
sel_name = 'KickIdlePlayers'
elif sel == self._show_game_ping_check_box.widget:
sel_name = 'ShowPing'
elif sel == self._disable_camera_shake_check_box.widget:
sel_name = 'DisableCameraShake'
elif (
self._always_use_internal_keyboard_check_box is not None
and sel
== self._always_use_internal_keyboard_check_box.widget
):
sel_name = 'AlwaysUseInternalKeyboard'
elif (
self._disable_gyro_check_box is not None
and sel == self._disable_gyro_check_box.widget
):
sel_name = 'DisableGyro'
elif (
self._language_popup is not None
and sel == self._language_popup.get_button()
):
sel_name = 'Languages'
elif sel == self._translation_editor_button:
sel_name = 'TranslationEditor'
elif sel == self._show_user_mods_button:
sel_name = 'ShowUserMods'
elif sel == self._plugins_button:
sel_name = 'Plugins'
elif sel == self._modding_guide_button:
sel_name = 'ModdingGuide'
elif sel == self._language_inform_checkbox:
sel_name = 'LangInform'
else:
raise ValueError(f'unrecognized selection \'{sel}\'')
elif sel == self._back_button:
sel_name = 'Back'
else:
raise ValueError(f'unrecognized selection \'{sel}\'')
ba.app.ui.window_states[type(self)] = {'sel_name': sel_name}
except Exception:
ba.print_exception(f'Error saving state for {self.__class__}')
def _restore_state(self) -> None:
# pylint: disable=too-many-branches
try:
sel_name = ba.app.ui.window_states.get(type(self), {}).get(
'sel_name'
)
if sel_name == 'Back':
sel = self._back_button
else:
ba.containerwidget(
edit=self._root_widget, selected_child=self._scrollwidget
)
if sel_name == 'VRTest':
sel = self._vr_test_button
elif sel_name == 'NetTest':
sel = self._net_test_button
elif sel_name == 'PromoCode':
sel = self._promo_code_button
elif sel_name == 'Benchmarks':
sel = self._benchmarks_button
elif sel_name == 'KickIdlePlayers':
sel = self._kick_idle_players_check_box.widget
elif sel_name == 'ShowPing':
sel = self._show_game_ping_check_box.widget
elif sel_name == 'DisableCameraShake':
sel = self._disable_camera_shake_check_box.widget
elif (
sel_name == 'AlwaysUseInternalKeyboard'
and self._always_use_internal_keyboard_check_box is not None
):
sel = self._always_use_internal_keyboard_check_box.widget
elif (
sel_name == 'DisableGyro'
and self._disable_gyro_check_box is not None
):
sel = self._disable_gyro_check_box.widget
elif (
sel_name == 'Languages' and self._language_popup is not None
):
sel = self._language_popup.get_button()
elif sel_name == 'TranslationEditor':
sel = self._translation_editor_button
elif sel_name == 'ShowUserMods':
sel = self._show_user_mods_button
elif sel_name == 'Plugins':
sel = self._plugins_button
elif sel_name == 'ModdingGuide':
sel = self._modding_guide_button
elif sel_name == 'LangInform':
sel = self._language_inform_checkbox
else:
sel = None
if sel is not None:
ba.containerwidget(
edit=self._subcontainer,
selected_child=sel,
visible_child=sel,
)
except Exception:
ba.print_exception(f'Error restoring state for {self.__class__}')
def _on_menu_open(self) -> None:
self._menu_open = True
def _on_menu_close(self) -> None:
self._menu_open = False
def _on_menu_choice(self, choice: str) -> None:
ba.app.lang.setlanguage(None if choice == 'Auto' else choice)
self._save_state()
ba.timer(0.1, ba.WeakCall(self._rebuild), timetype=ba.TimeType.REAL)
def _completed_langs_cb(self, results: dict[str, Any] | None) -> None:
if results is not None and results['langs'] is not None:
self._complete_langs_list = results['langs']
self._complete_langs_error = False
else:
self._complete_langs_list = None
self._complete_langs_error = True
ba.timer(
0.001,
ba.WeakCall(self._update_lang_status),
timetype=ba.TimeType.REAL,
)
def _do_back(self) -> None:
from bastd.ui.settings.allsettings import AllSettingsWindow
self._save_state()
ba.containerwidget(
edit=self._root_widget, transition=self._transition_out
)
ba.app.ui.set_main_menu_window(
AllSettingsWindow(transition='in_left').get_root_widget()
)