WIP on plugin system

This commit is contained in:
Eric Froemling 2020-07-16 12:28:32 -07:00
parent e752a7dbb3
commit d09ecae712
9 changed files with 206 additions and 26 deletions

View File

@ -420,36 +420,36 @@
"assets/build/ba_data/audio/zoeOw.ogg": "https://files.ballistica.net/cache/ba1/75/1d/868bb04cf691736035c917d02762",
"assets/build/ba_data/audio/zoePickup01.ogg": "https://files.ballistica.net/cache/ba1/44/2a/8535b446284235cb503947ece074",
"assets/build/ba_data/audio/zoeScream01.ogg": "https://files.ballistica.net/cache/ba1/f5/d3/8e941851c4310465646c4167afc1",
"assets/build/ba_data/data/langdata.json": "https://files.ballistica.net/cache/ba1/78/70/98c37db0c28354adfe8fa03676a5",
"assets/build/ba_data/data/langdata.json": "https://files.ballistica.net/cache/ba1/ad/82/41fe495cb2c7431379171fc5778e",
"assets/build/ba_data/data/languages/arabic.json": "https://files.ballistica.net/cache/ba1/30/8e/38c5f21b9251ea1111bed554035f",
"assets/build/ba_data/data/languages/belarussian.json": "https://files.ballistica.net/cache/ba1/49/5f/b29bb65369040892fe6601801637",
"assets/build/ba_data/data/languages/chinese.json": "https://files.ballistica.net/cache/ba1/97/4e/48ae80fb711a22559a311c49b358",
"assets/build/ba_data/data/languages/chinesetraditional.json": "https://files.ballistica.net/cache/ba1/21/38/7e50214f79088f55c6e059fd33d2",
"assets/build/ba_data/data/languages/chinesetraditional.json": "https://files.ballistica.net/cache/ba1/a0/ca/b4e3c4ea2c76e462b7e657b2b1c2",
"assets/build/ba_data/data/languages/croatian.json": "https://files.ballistica.net/cache/ba1/bb/9c/360fc084e6254a087096993af219",
"assets/build/ba_data/data/languages/czech.json": "https://files.ballistica.net/cache/ba1/dd/5a/14ca3ebb92a802315921e2b2b215",
"assets/build/ba_data/data/languages/danish.json": "https://files.ballistica.net/cache/ba1/3f/46/e4da3c1d2b0ebf916df55c608b28",
"assets/build/ba_data/data/languages/dutch.json": "https://files.ballistica.net/cache/ba1/5b/a3/a46a77f0cc498e1f1e369d772414",
"assets/build/ba_data/data/languages/english.json": "https://files.ballistica.net/cache/ba1/e7/8e/3553965def02a0b2362a0ed8aebe",
"assets/build/ba_data/data/languages/dutch.json": "https://files.ballistica.net/cache/ba1/bb/99/cf7307a78b9635cb0bf93e1647c9",
"assets/build/ba_data/data/languages/english.json": "https://files.ballistica.net/cache/ba1/8b/c6/3fbabe88f18df228f6f2984201a5",
"assets/build/ba_data/data/languages/esperanto.json": "https://files.ballistica.net/cache/ba1/6e/fd/685a4e1da031474d47a1d9eb2731",
"assets/build/ba_data/data/languages/french.json": "https://files.ballistica.net/cache/ba1/eb/94/449eceecc6b0a6c7e4a548ea3607",
"assets/build/ba_data/data/languages/german.json": "https://files.ballistica.net/cache/ba1/ef/92/4a602f11f6dd3d0310ce98cd5538",
"assets/build/ba_data/data/languages/gibberish.json": "https://files.ballistica.net/cache/ba1/43/ee/42cf5ad52de3d4f567ec04018655",
"assets/build/ba_data/data/languages/gibberish.json": "https://files.ballistica.net/cache/ba1/cb/10/5d94df639e3e0cb405711e1b907f",
"assets/build/ba_data/data/languages/greek.json": "https://files.ballistica.net/cache/ba1/17/78/3fd0dca40e632ce53d03a944e7fa",
"assets/build/ba_data/data/languages/hindi.json": "https://files.ballistica.net/cache/ba1/11/56/ed2b07866104596338f7ce582d64",
"assets/build/ba_data/data/languages/hungarian.json": "https://files.ballistica.net/cache/ba1/4d/4b/0790110201c9adb1b521e9a55e63",
"assets/build/ba_data/data/languages/indonesian.json": "https://files.ballistica.net/cache/ba1/e3/6f/df2600b658a163f80077bd6c8d78",
"assets/build/ba_data/data/languages/italian.json": "https://files.ballistica.net/cache/ba1/70/d0/36b0d655839c60c2a763bbe52332",
"assets/build/ba_data/data/languages/indonesian.json": "https://files.ballistica.net/cache/ba1/7f/52/3d0b7e1955af24a1158a36c9a272",
"assets/build/ba_data/data/languages/italian.json": "https://files.ballistica.net/cache/ba1/ff/3f/f1c11e1f22454ceceb7b4d277a2a",
"assets/build/ba_data/data/languages/korean.json": "https://files.ballistica.net/cache/ba1/0a/84/bbb6ed2abf66509406f534cbbb52",
"assets/build/ba_data/data/languages/persian.json": "https://files.ballistica.net/cache/ba1/8e/3f/41e12b96fc07a623d89153b10c38",
"assets/build/ba_data/data/languages/persian.json": "https://files.ballistica.net/cache/ba1/bd/45/ffb2d9d9ce9578ae11de9bb5123d",
"assets/build/ba_data/data/languages/polish.json": "https://files.ballistica.net/cache/ba1/8f/e6/675e5e41b5aea12d34b152f0f705",
"assets/build/ba_data/data/languages/portuguese.json": "https://files.ballistica.net/cache/ba1/9c/e3/834faf6869f5cd175edd4a0244b9",
"assets/build/ba_data/data/languages/romanian.json": "https://files.ballistica.net/cache/ba1/44/3c/7cc06ca8d5475e1687d0ed05bdbf",
"assets/build/ba_data/data/languages/russian.json": "https://files.ballistica.net/cache/ba1/33/82/be19758f3563ba6617db4736de74",
"assets/build/ba_data/data/languages/serbian.json": "https://files.ballistica.net/cache/ba1/e7/d8/ace32888249fc8b8cca0e2edb48b",
"assets/build/ba_data/data/languages/slovak.json": "https://files.ballistica.net/cache/ba1/b7/0a/fab820b96e7aa587ee56427ecdc2",
"assets/build/ba_data/data/languages/spanish.json": "https://files.ballistica.net/cache/ba1/a0/89/d377dea2c8b1ec5f4cb47e4e61ae",
"assets/build/ba_data/data/languages/spanish.json": "https://files.ballistica.net/cache/ba1/c9/6b/dadd4329de69d0b7bfe1aa5f31d6",
"assets/build/ba_data/data/languages/swedish.json": "https://files.ballistica.net/cache/ba1/50/9f/be006ba19be6a69a57837eb6dca0",
"assets/build/ba_data/data/languages/turkish.json": "https://files.ballistica.net/cache/ba1/d7/bc/0d6cf14910b9cdec808e0accf5c7",
"assets/build/ba_data/data/languages/turkish.json": "https://files.ballistica.net/cache/ba1/82/7c/5363de81ac6823935098df95dc66",
"assets/build/ba_data/data/languages/ukrainian.json": "https://files.ballistica.net/cache/ba1/9d/fb/6c2feb78bdabbec049a71ba40d78",
"assets/build/ba_data/data/languages/vietnamese.json": "https://files.ballistica.net/cache/ba1/f1/00/c4ccd5969084505359e07f927b3a",
"assets/build/ba_data/data/maps/big_g.json": "https://files.ballistica.net/cache/ba1/47/0a/a617cc85d927b576c4e6fc1091ed",
@ -4135,16 +4135,16 @@
"assets/build/windows/x64/vc_redist.x64.exe": "https://files.ballistica.net/cache/ba1/ea/19/8b8787d81abcdce158ba608cd24f",
"assets/build/windows/x64/vcruntime140_1d.dll": "https://files.ballistica.net/cache/ba1/11/d8/ff6344b429b00c24d9a1930d4338",
"assets/build/windows/x64/vcruntime140d.dll": "https://files.ballistica.net/cache/ba1/20/33/0825e11e6518f87ece3009309933",
"build/prefab/linux-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/44/c5/099debe438f2bca2c3dc8d9f048e",
"build/prefab/linux-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/c4/7a/f92d78baa6d8137a8150e37c40a8",
"build/prefab/linux/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/35/8b/1d44da11d466aa8e49390048bd3c",
"build/prefab/linux/release/ballisticacore": "https://files.ballistica.net/cache/ba1/13/b2/6f0da477dd7d4f54fe48647ce44b",
"build/prefab/mac-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/d9/11/e50c98eb60cfbe1c5268e33af8b8",
"build/prefab/mac-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/3b/e5/ce291661086203e424dce2dcd692",
"build/prefab/mac/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/70/09/d12993418eade4f88e8290d92f2e",
"build/prefab/mac/release/ballisticacore": "https://files.ballistica.net/cache/ba1/93/8c/8d7097c9b662b6583a145ad34f56",
"build/prefab/windows-server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/52/d4/96f341a77b48a1f4adcbc5ca1e40",
"build/prefab/windows-server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/af/79/c1be9d5908663f693dc67a24fd5e",
"build/prefab/windows/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/9e/e6/2cc3bc3fe700d8750387032bf43d",
"build/prefab/windows/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/92/8f/99cddfd2549fadedbb6f483bb174"
"build/prefab/linux-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/2f/d2/729e7d4c7e884bcdc6749a52c069",
"build/prefab/linux-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/b8/45/60a8069130b52e85422236921806",
"build/prefab/linux/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/80/84/06b8fd82adb7a10dfc2c5a6b622b",
"build/prefab/linux/release/ballisticacore": "https://files.ballistica.net/cache/ba1/54/fa/b6d33c93285c9d686bf455374ce3",
"build/prefab/mac-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/bf/db/d010f67fb908315d89e7a0e38fb7",
"build/prefab/mac-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/6a/34/66068c15c8e349743d82be4b0e98",
"build/prefab/mac/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/e2/03/89949b43cdf17f571e549a85e439",
"build/prefab/mac/release/ballisticacore": "https://files.ballistica.net/cache/ba1/d1/a0/5ffc17a4b0c4c93ee3de59a1597b",
"build/prefab/windows-server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/87/17/e01ce11e3c4869da04e0a8824ee8",
"build/prefab/windows-server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/8f/30/dc9361159cb9b1c735e8957a0a66",
"build/prefab/windows/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/07/c2/fbed8e21c1b973f9b30267b49386",
"build/prefab/windows/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/a3/2f/04346dd3c73a959eef8d59c43991"
}

View File

@ -414,6 +414,7 @@
"ba_data/python/bastd/ui/settings/__pycache__/graphics.cpython-37.opt-1.pyc",
"ba_data/python/bastd/ui/settings/__pycache__/keyboard.cpython-37.opt-1.pyc",
"ba_data/python/bastd/ui/settings/__pycache__/nettesting.cpython-37.opt-1.pyc",
"ba_data/python/bastd/ui/settings/__pycache__/plugins.cpython-37.opt-1.pyc",
"ba_data/python/bastd/ui/settings/__pycache__/ps3controller.cpython-37.opt-1.pyc",
"ba_data/python/bastd/ui/settings/__pycache__/remoteapp.cpython-37.opt-1.pyc",
"ba_data/python/bastd/ui/settings/__pycache__/testing.cpython-37.opt-1.pyc",
@ -431,6 +432,7 @@
"ba_data/python/bastd/ui/settings/graphics.py",
"ba_data/python/bastd/ui/settings/keyboard.py",
"ba_data/python/bastd/ui/settings/nettesting.py",
"ba_data/python/bastd/ui/settings/plugins.py",
"ba_data/python/bastd/ui/settings/ps3controller.py",
"ba_data/python/bastd/ui/settings/remoteapp.py",
"ba_data/python/bastd/ui/settings/testing.py",

View File

@ -353,6 +353,7 @@ SCRIPT_TARGETS_PY_PUBLIC = \
build/ba_data/python/bastd/ui/settings/graphics.py \
build/ba_data/python/bastd/ui/settings/keyboard.py \
build/ba_data/python/bastd/ui/settings/nettesting.py \
build/ba_data/python/bastd/ui/settings/plugins.py \
build/ba_data/python/bastd/ui/settings/ps3controller.py \
build/ba_data/python/bastd/ui/settings/remoteapp.py \
build/ba_data/python/bastd/ui/settings/testing.py \
@ -585,6 +586,7 @@ SCRIPT_TARGETS_PYC_PUBLIC = \
build/ba_data/python/bastd/ui/settings/__pycache__/graphics.cpython-37.opt-1.pyc \
build/ba_data/python/bastd/ui/settings/__pycache__/keyboard.cpython-37.opt-1.pyc \
build/ba_data/python/bastd/ui/settings/__pycache__/nettesting.cpython-37.opt-1.pyc \
build/ba_data/python/bastd/ui/settings/__pycache__/plugins.cpython-37.opt-1.pyc \
build/ba_data/python/bastd/ui/settings/__pycache__/ps3controller.cpython-37.opt-1.pyc \
build/ba_data/python/bastd/ui/settings/__pycache__/remoteapp.cpython-37.opt-1.pyc \
build/ba_data/python/bastd/ui/settings/__pycache__/testing.cpython-37.opt-1.pyc \

View File

@ -286,7 +286,7 @@ class CoopBrowserWindow(ba.Window):
@staticmethod
def _preload_modules() -> None:
"""For preloading modules we use in a bg thread to prevent hitches."""
"""Preload modules we use (called in bg thread)."""
import bastd.ui.purchase as _unused1
import bastd.ui.coop.gamebutton as _unused2
import bastd.ui.confirm as _unused3

View File

@ -91,7 +91,7 @@ class MainMenuWindow(ba.Window):
@staticmethod
def _preload_modules() -> None:
"""For preloading modules we use in a bg thread to prevent hitches."""
"""Preload modules we use (called in bg thread)."""
import bastd.ui.getremote as _unused
import bastd.ui.confirm as _unused2
import bastd.ui.store.button as _unused3

View File

@ -420,7 +420,7 @@ class PlayWindow(ba.Window):
@staticmethod
def _preload_modules() -> None:
"""For preloading modules we use in a bg thread to prevent hitches."""
"""Preload modules we use (called in bg thread)."""
import bastd.ui.mainmenu as _unused1
import bastd.ui.account as _unused2
import bastd.ui.coop.browser as _unused3

View File

@ -41,6 +41,12 @@ class AdvancedSettingsWindow(ba.Window):
# 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.
@ -99,6 +105,7 @@ class AdvancedSettingsWindow(ba.Window):
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'
@ -160,6 +167,19 @@ class AdvancedSettingsWindow(ba.Window):
master_server_get('bsLangGetCompleted', {'b': app.build_number},
callback=ba.WeakCall(self._completed_langs_cb))
@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.language in self._complete_langs_list)
@ -452,6 +472,17 @@ class AdvancedSettingsWindow(ba.Window):
ba.open_url,
'http://www.froemling.net/docs/bombsquad-modding-guide'))
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: Optional[ba.Widget]
@ -539,6 +570,14 @@ class AdvancedSettingsWindow(ba.Window):
return
appinvite.handle_app_invites_press()
def _on_plugins_button_press(self) -> None:
from bastd.ui.settings.plugins import PluginSettingsWindow
self._save_state()
ba.containerwidget(edit=self._root_widget, transition='out_left')
ba.app.ui.set_main_menu_window(
PluginSettingsWindow(
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
@ -592,6 +631,8 @@ class AdvancedSettingsWindow(ba.Window):
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:
@ -644,6 +685,8 @@ class AdvancedSettingsWindow(ba.Window):
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':

View File

@ -207,7 +207,7 @@ class AllSettingsWindow(ba.Window):
@staticmethod
def _preload_modules() -> None:
"""For preloading modules we use in a bg thread to prevent hitches."""
"""Preload modules we use (called in bg thread)."""
import bastd.ui.mainmenu as _unused1
import bastd.ui.settings.controls as _unused2
import bastd.ui.settings.graphics as _unused3

View File

@ -0,0 +1,133 @@
# Copyright (c) 2011-2020 Eric Froemling
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# -----------------------------------------------------------------------------
"""Plugin settings UI."""
from __future__ import annotations
from typing import TYPE_CHECKING
import ba
if TYPE_CHECKING:
from typing import Tuple, Optional
class PluginSettingsWindow(ba.Window):
"""Window for configuring plugins."""
def __init__(self,
transition: str = 'in_right',
origin_widget: ba.Widget = None):
app = ba.app
# If they provided an origin-widget, scale up from that.
scale_origin: Optional[Tuple[float, float]]
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.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)
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._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 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='pluginsText'),
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))
ba.containerwidget(edit=self._scrollwidget,
selection_loop_to_parent=True)
self._subcontainer = ba.containerwidget(parent=self._scrollwidget,
size=(self._sub_width,
self._sub_height),
background=False,
selection_loop_to_parent=True)
ba.screenmessage('Work in progress...')
self._restore_state()
def _save_state(self) -> None:
print('would save state')
def _restore_state(self) -> None:
print('would restore state')
def _do_back(self) -> None:
# pylint: disable=cyclic-import
from bastd.ui.settings.advanced import AdvancedSettingsWindow
self._save_state()
ba.containerwidget(edit=self._root_widget,
transition=self._transition_out)
ba.app.ui.set_main_menu_window(
AdvancedSettingsWindow(transition='in_left').get_root_widget())