Bombsquad-Ballistica-Modded.../dist/ba_data/python/bauiv1lib/docuitest.py
2026-02-15 14:00:00 +05:30

1092 lines
41 KiB
Python

# Released under the MIT License. See LICENSE for details.
#
"""Examples/tests for using DocUI to build UIs."""
# pylint: disable=too-many-lines
from __future__ import annotations
import time
import copy
from typing import TYPE_CHECKING, override
from efro.error import CleanError
import bauiv1 as bui
from bauiv1lib.docui import DocUIWindow, DocUIController
if TYPE_CHECKING:
from bacommon.docui import DocUIRequest, DocUIResponse
import bacommon.docui.v1
from bauiv1lib.docui import DocUILocalAction
def show_test_doc_ui_window() -> None:
"""Bust out a doc-ui window."""
import bacommon.docui.v1 as dui1
# Pop up an auxiliary window wherever we are in the nav stack.
bui.app.ui_v1.auxiliary_window_activate(
win_type=DocUIWindow,
win_create_call=bui.CallStrict(
TestDocUIController().create_window, dui1.Request('/')
),
win_extra_type_id=TestDocUIController.get_window_extra_type_id(),
)
class TestDocUIController(DocUIController):
"""Provides various tests/demonstrations of docui functionality."""
@override
def fulfill_request(self, request: DocUIRequest) -> DocUIResponse:
"""Fulfill a request.
Will be called in a background thread.
"""
# pylint: disable=too-many-return-statements
import bacommon.docui.v1 as dui1
# We currently support v1 requests only.
if not isinstance(request, dui1.Request):
raise CleanError('Invalid request version.')
# Handle some pages purely locally.
if request.path == '/':
return _test_page_root(request)
if request.path == '/test2':
return _test_page_2(request)
if request.path == '/slow':
return _test_page_long(request)
if request.path == '/timedactions':
return _test_page_timed_actions(request)
if request.path == '/displayitems':
return _test_page_display_items(request)
if request.path == '/emptypage':
return _test_page_empty(request)
if request.path == '/boundstests':
return _test_bounds(request)
# Ship '/webtest/*' off to some webserver to handle.
if request.path.startswith('/webtest/'):
return self.fulfill_request_web(
request, 'https://www.ballistica.net/docuitest'
)
# Ship '/cloudmsgtest/*' through our cloud connection to handle.
if request.path.startswith('/cloudmsgtest/'):
return self.fulfill_request_cloud(request, 'test')
raise CleanError('Invalid request path.')
@override
def local_action(self, action: DocUILocalAction) -> None:
bui.screenmessage(
f'Would do {action.name!r} with args {action.args!r}.'
)
def _test_page_long(
request: bacommon.docui.v1.Request,
) -> bacommon.docui.v1.Response:
"""Testing a page that takes a bit of time to load."""
import bacommon.docui.v1 as dui1
del request # Unused.
# Simulate a slow connection or whatnot.
time.sleep(3.0)
return dui1.Response(
page=dui1.Page(
title='Test',
center_vertically=True,
rows=[
dui1.ButtonRow(
title='That took a while',
center_title=True,
center_content=True,
buttons=[
dui1.Button(
'Sure Did',
size=(120, 80),
action=dui1.Browse(dui1.Request('/')),
),
],
),
],
)
)
def _test_page_timed_actions(
request: bacommon.docui.v1.Request,
) -> bacommon.docui.v1.Response:
"""Testing a page that takes a bit of time to load."""
import bacommon.docui.v1 as dui1
val = request.args.get('val')
if not isinstance(val, int):
val = 5
return dui1.Response(
page=dui1.Page(
title='Test',
center_vertically=True,
rows=[
dui1.ButtonRow(
title=f'Hello there {val}',
subtitle='Each change here is a new request/response.',
center_title=True,
center_content=True,
buttons=[
dui1.Button(
'Done',
size=(120, 80),
action=dui1.Local(close_window=True),
default=True,
),
],
),
],
),
# Refresh this page with a countdown until we hit zero and then
# close the window.
timed_action=(
dui1.Replace(dui1.Request('/timedactions', args={'val': val - 1}))
if (val - 1) > 0
else dui1.Local(close_window=True)
),
timed_action_delay=1.0,
)
def _test_page_effects() -> bacommon.docui.v1.Page:
"""Testing effects after a page load."""
import bacommon.docui.v1 as dui1
return dui1.Page(
title='Effects',
center_vertically=True,
rows=[
dui1.ButtonRow(
title='Have some lovely effects',
center_title=True,
center_content=True,
buttons=[
dui1.Button(
'Nice!',
size=(120, 80),
action=dui1.Local(close_window=True),
),
],
),
],
)
def _test_page_2(
request: bacommon.docui.v1.Request,
) -> bacommon.docui.v1.Response:
"""More testing."""
import bacommon.docui.v1 as dui1
del request # Unused.
return dui1.Response(
page=dui1.Page(
title='Test 2',
rows=[
dui1.ButtonRow(
title='More Tests',
buttons=[
dui1.Button(
'Browse',
size=(120, 80),
action=dui1.Browse(dui1.Request('/')),
),
dui1.Button(
'Replace',
size=(120, 80),
action=dui1.Replace(dui1.Request('/')),
),
dui1.Button(
'Close',
size=(120, 80),
action=dui1.Local(close_window=True),
selected=True, # Testing this
),
],
),
],
)
)
def _test_page_root(
request: bacommon.docui.v1.Request,
) -> bacommon.docui.v1.Response:
"""Return test page."""
import bacommon.clienteffect as clfx
import bacommon.docui.v1 as dui1
# Show some specific debug bits if they ask us to.
debug = bool(request.args.get('debug', False))
response = dui1.Response(
page=dui1.Page(
title='Test Root',
rows=[
dui1.ButtonRow(
debug=debug,
header_height=100,
header_decorations_left=[
dui1.Text(
'HeaderLeft',
position=(0, 10 + 20),
color=(1, 1, 1, 0.3),
size=(150, 30),
h_align=dui1.HAlign.LEFT,
debug=debug,
),
],
header_decorations_center=[
dui1.Text(
'Hello From DocUI!',
position=(0, 10 + 20),
size=(300, 30),
debug=debug,
),
dui1.Text(
(
'Use this as reference for building'
' UIs with DocUI.'
' Its code lives at bauiv1lib.docuitest'
),
scale=0.5,
position=(0, -18 + 20),
size=(600, 23),
debug=debug,
),
dui1.Image(
'nub', position=(0, -58 + 20), size=(60, 60)
),
],
header_decorations_right=[
dui1.Text(
'HeaderRight',
position=(0, 10 + 20),
color=(1, 1, 1, 0.3),
size=(150, 30),
h_align=dui1.HAlign.RIGHT,
debug=debug,
),
],
title='Some Tests',
buttons=[
dui1.Button(
'Browse',
size=(120, 80),
action=dui1.Browse(dui1.Request('/test2')),
),
dui1.Button(
'Replace',
size=(120, 80),
action=dui1.Replace(dui1.Request('/test2')),
),
dui1.Button(
'Close',
size=(120, 80),
action=dui1.Local(close_window=True),
),
dui1.Button(
'Invalid\nRequest',
size=(120, 80),
action=dui1.Browse(dui1.Request('/invalidrequest')),
),
dui1.Button(
'Immediate\nClientEffects',
size=(120, 80),
action=dui1.Local(
immediate_client_effects=[
clfx.ScreenMessage(
'Hello From Immediate Client Effects',
color=(0, 1, 0),
),
clfx.PlaySound(clfx.Sound.CASH_REGISTER),
clfx.Delay(1.0),
clfx.ScreenMessage(
'{"r":"successText"}',
is_lstr=True,
color=(0, 1, 0),
),
clfx.PlaySound(clfx.Sound.CASH_REGISTER),
]
),
),
dui1.Button(
'Response\nClientEffects',
size=(120, 80),
action=dui1.Browse(
dui1.Request('/', args={'test_effects': True})
),
),
dui1.Button(
'Immediate\nLocalAction',
size=(120, 80),
action=dui1.Local(
immediate_local_action='testaction',
immediate_local_action_args={'testparam': 123},
),
),
dui1.Button(
'Response\nLocalAction',
size=(120, 80),
action=dui1.Browse(
dui1.Request('/', args={'test_action': True})
),
),
],
),
dui1.ButtonRow(
title='A Few More Tests',
buttons=[
dui1.Button(
'Hide\nDebug' if debug else 'Show\nDebug',
size=(120, 80),
action=dui1.Replace(
dui1.Request('/', args={'debug': not debug})
),
),
dui1.Button(
'Slow\nBrowse',
size=(120, 80),
action=dui1.Browse(dui1.Request('/slow')),
),
dui1.Button(
'Slow\nReplace',
size=(120, 80),
action=dui1.Replace(dui1.Request('/slow')),
),
dui1.Button(
'Timed\nActions',
size=(120, 80),
action=dui1.Browse(dui1.Request('/timedactions')),
),
dui1.Button(
'Web\nGET',
size=(120, 80),
action=dui1.Browse(dui1.Request('/webtest/get')),
),
dui1.Button(
'Web\nPOST',
size=(120, 80),
action=dui1.Browse(
dui1.Request(
'/webtest/post',
method=dui1.RequestMethod.POST,
)
),
),
dui1.Button(
'DisplayItems',
size=(120, 80),
action=dui1.Browse(dui1.Request('/displayitems')),
),
dui1.Button(
'Empty\nPage',
size=(120, 80),
action=dui1.Browse(dui1.Request('/emptypage')),
),
],
),
dui1.ButtonRow(
title='Even More Tests',
buttons=[
dui1.Button(
'Cloud-Msg\nGET',
size=(120, 80),
action=dui1.Browse(
dui1.Request('/cloudmsgtest/get')
),
),
dui1.Button(
'Cloud-Msg\nPOST',
size=(120, 80),
action=dui1.Browse(
dui1.Request(
'/cloudmsgtest/post',
method=dui1.RequestMethod.POST,
)
),
),
dui1.Button(
'Bounds\nTests',
size=(120, 80),
action=dui1.Browse(dui1.Request('/boundstests')),
),
],
),
dui1.ButtonRow(title='Empty Row', buttons=[]),
dui1.ButtonRow(
title='Layout Tests',
debug=debug,
padding_left=5.0,
buttons=[
dui1.Button(
label='Test',
size=(180, 200),
decorations=[
dui1.Image(
'powerupPunch',
position=(-70, 0),
size=(40, 40),
h_align=dui1.HAlign.LEFT,
),
dui1.Image(
'powerupSpeed',
position=(0, 75),
size=(35, 35),
v_align=dui1.VAlign.TOP,
),
dui1.Text(
'TL',
position=(-70, 75),
size=(50, 50),
h_align=dui1.HAlign.LEFT,
v_align=dui1.VAlign.TOP,
debug=debug,
),
dui1.Text(
'TR',
position=(70, 75),
size=(50, 50),
h_align=dui1.HAlign.RIGHT,
v_align=dui1.VAlign.TOP,
debug=debug,
),
dui1.Text(
'BL',
position=(-70, -75),
size=(50, 50),
h_align=dui1.HAlign.LEFT,
v_align=dui1.VAlign.BOTTOM,
debug=debug,
),
dui1.Text(
'BR',
position=(70, -75),
size=(50, 50),
h_align=dui1.HAlign.RIGHT,
v_align=dui1.VAlign.BOTTOM,
debug=debug,
),
],
),
dui1.Button(
label='Test2',
size=(100, 100),
color=(1, 0, 0, 1),
label_color=(1, 1, 1, 1),
padding_right=4,
),
# Should look like the first button but
# scaled down.
dui1.Button(
label='Test',
size=(180, 200),
scale=0.6,
padding_bottom=30, # Should nudge us up.
debug=debug, # Show bounds.
decorations=[
dui1.Image(
'powerupPunch',
position=(-70, 0),
size=(40, 40),
h_align=dui1.HAlign.LEFT,
),
dui1.Image(
'powerupSpeed',
position=(0, 75),
size=(35, 35),
v_align=dui1.VAlign.TOP,
),
dui1.Text(
'TL',
position=(-70, 75),
size=(50, 50),
h_align=dui1.HAlign.LEFT,
v_align=dui1.VAlign.TOP,
debug=debug,
),
dui1.Text(
'TR',
position=(70, 75),
size=(50, 50),
h_align=dui1.HAlign.RIGHT,
v_align=dui1.VAlign.TOP,
debug=debug,
),
dui1.Text(
'BL',
position=(-70, -75),
size=(50, 50),
h_align=dui1.HAlign.LEFT,
v_align=dui1.VAlign.BOTTOM,
debug=debug,
),
dui1.Text(
'BR',
position=(70, -75),
size=(50, 50),
h_align=dui1.HAlign.RIGHT,
v_align=dui1.VAlign.BOTTOM,
debug=debug,
),
],
),
# Testing custom button images and opacity.
dui1.Button(
label='Test3',
texture='buttonSquareWide',
padding_left=10.0,
padding_right=10.0,
color=(1, 1, 1, 0.3),
size=(200, 100),
),
# Testing image drawing vs bounds
dui1.Button(
label='BoundsTest',
texture='white',
color=(1, 1, 1, 0.3),
size=(150, 100),
debug=debug,
),
],
),
dui1.ButtonRow(
title='Long Row Test',
subtitle='Look - a subtitle!',
buttons=[
dui1.Button(
size=(150, 100),
decorations=[
dui1.Text(
'MaxWidthTest',
position=(0, 25),
size=(150 * 0.8, 32.0),
flatness=1.0,
shadow=0.0,
debug=debug,
),
dui1.Text(
'MaxHeightTest\nSecondLine',
position=(0, -20),
size=(150 * 0.8, 40),
flatness=1.0,
shadow=0.0,
debug=debug,
),
],
),
dui1.Button(
size=(150, 100),
decorations=[
dui1.Image(
'zoeIcon',
position=(0, 0),
size=(70, 70),
tint_texture='zoeIconColorMask',
tint_color=(1, 0, 0),
tint2_color=(0, 1, 0),
mask_texture='characterIconMask',
),
],
),
dui1.Button(
size=(150, 100),
decorations=[
dui1.Image(
'bridgitPreview',
position=(0, 10),
size=(120, 60),
mask_texture='mapPreviewMask',
mesh_opaque='level_select_button_opaque',
mesh_transparent=(
'level_select_button_transparent'
),
),
],
),
dui1.Button(size=(150, 100)),
dui1.Button(size=(150, 100)),
dui1.Button(size=(150, 100)),
dui1.Button(size=(150, 100)),
dui1.Button(size=(150, 100)),
dui1.Button(size=(150, 100)),
dui1.Button(size=(150, 100)),
dui1.Button(size=(150, 100)),
dui1.Button(
'foo',
size=(150, 100),
scale=0.4,
padding_left=100,
padding_right=200,
),
dui1.Button(size=(150, 100)),
dui1.Button(size=(150, 100)),
dui1.Button(size=(150, 100)),
dui1.Button(size=(150, 100)),
dui1.Button(size=(150, 100)),
dui1.Button(size=(150, 100)),
dui1.Button(size=(150, 100)),
dui1.Button(size=(150, 100)),
],
),
dui1.ButtonRow(
spacing_top=-15,
subtitle='Subtitle only!',
buttons=[
dui1.Button(size=(200, 120)),
],
),
dui1.ButtonRow(
buttons=[
dui1.Button(
'Row-With-No-Title Test',
size=(300, 80),
style=dui1.ButtonStyle.MEDIUM,
color=(0.8, 0.8, 0.8, 1),
icon='buttonPunch',
icon_color=(0.5, 0.3, 1.0, 1.0),
icon_scale=1.2,
),
],
),
dui1.ButtonRow(
title='Centered Content / Faded Title',
title_color=(0.6, 0.6, 1.0, 0.3),
title_flatness=1.0,
title_shadow=1.0,
subtitle='Testing Centered Title/Content',
subtitle_color=(1.0, 0.5, 1.0, 0.5),
subtitle_flatness=1.0,
subtitle_shadow=0.0,
center_content=True,
center_title=True,
buttons=[
dui1.Button(
'Hello There!',
size=(200, 120),
color=(0.7, 0.7, 0.9, 1),
),
],
),
],
),
)
# Include some client effects if they ask.
if request.args.get('test_effects', False):
response.client_effects = [
clfx.ScreenMessage(
'Hello From Response Client Effects', color=(0, 1, 0)
),
clfx.PlaySound(clfx.Sound.CASH_REGISTER),
clfx.Delay(1.0),
clfx.ScreenMessage(
'{"r":"successText"}', is_lstr=True, color=(0, 1, 0)
),
clfx.PlaySound(clfx.Sound.CASH_REGISTER),
]
# Include a local-action if they ask.
if request.args.get('test_action', False):
response.local_action = 'testaction'
response.local_action_args = {'testparam': 234}
return response
def _test_page_empty(
request: bacommon.docui.v1.Request,
) -> bacommon.docui.v1.Response:
import bacommon.docui.v1 as dui1
del request # Unused.
return dui1.Response(page=dui1.Page(title='EmptyPage', rows=[]))
def _test_page_display_items(
request: bacommon.docui.v1.Request,
) -> bacommon.docui.v1.Response:
"""Testing display-items."""
from bacommon.classic import ClassicChestAppearance, ClassicChestDisplayItem
import bacommon.docui.v1 as dui1
import bacommon.displayitem as ditm
# Show some specific debug bits if they ask us to.
debug = bool(request.args.get('debug', False))
def _make_test_button(
scale: float,
wrapper: ditm.Wrapper,
) -> dui1.Button:
# See how this looks when unrecognized (relying on wrapper info
# only).
uwrapper = copy.deepcopy(wrapper)
uwrapper.item = ditm.Unknown()
return dui1.Button(
size=(300, 400),
scale=scale,
decorations=[
dui1.DisplayItem(
wrapper=wrapper,
style=dui1.DisplayItemStyle.FULL,
position=(-62, 100),
size=(120, 120),
debug=debug,
),
dui1.DisplayItem(
wrapper=uwrapper,
style=dui1.DisplayItemStyle.FULL,
position=(62, 100),
size=(120, 120),
debug=debug,
),
dui1.DisplayItem(
wrapper=wrapper,
style=dui1.DisplayItemStyle.COMPACT,
position=(-55, -20),
size=(80, 80),
debug=debug,
),
dui1.DisplayItem(
wrapper=uwrapper,
style=dui1.DisplayItemStyle.COMPACT,
position=(55, -20),
size=(80, 80),
debug=debug,
),
dui1.DisplayItem(
wrapper=wrapper,
style=dui1.DisplayItemStyle.ICON,
position=(-55, -120),
size=(100, 80),
debug=debug,
),
dui1.DisplayItem(
wrapper=uwrapper,
style=dui1.DisplayItemStyle.ICON,
position=(55, -120),
size=(100, 80),
debug=debug,
),
],
)
return dui1.Response(
page=dui1.Page(
padding_left=20,
padding_right=20,
title='DisplayItems',
rows=[
dui1.ButtonRow(
debug=debug,
padding_left=-10,
title='Display Item Tests',
subtitle=(
'top=FULL, center=COMPACT, bottom=ICON;'
' left=regular, right=unknown'
),
buttons=[
_make_test_button(
1.0,
ditm.Wrapper.for_item(ditm.Tickets(count=213)),
),
_make_test_button(
0.47,
ditm.Wrapper.for_item(ditm.Tickets(count=213)),
),
_make_test_button(
1.0,
ditm.Wrapper.for_item(
ClassicChestDisplayItem(
appearance=ClassicChestAppearance.L3
)
),
),
_make_test_button(
1.0,
ditm.Wrapper.for_item(ditm.Tokens(count=3)),
),
_make_test_button(
1.0,
ditm.Wrapper.for_item(ditm.Tokens(count=1414287)),
),
_make_test_button(
1.0,
ditm.Wrapper.for_item(ditm.Test()),
),
],
),
dui1.ButtonRow(
buttons=[
dui1.Button(
'Hide Debug' if debug else 'Show Debug',
style=dui1.ButtonStyle.MEDIUM,
size=(240, 60),
color=(0.6, 0.4, 0.8, 1.0),
action=dui1.Replace(
dui1.Request(
request.path, args={'debug': not debug}
)
),
)
],
),
],
)
)
def _test_bounds(
request: bacommon.docui.v1.Request,
) -> bacommon.docui.v1.Response:
import bacommon.docui.v1 as dui1
del request # Unused.
def _nm(style: dui1.ButtonStyle) -> str:
return f'{type(style).__name__}.{style.name}'
return dui1.Response(
page=dui1.Page(
title='BoundsTests',
rows=[
dui1.ButtonRow(
title=_nm(dui1.ButtonStyle.SQUARE),
buttons=[
dui1.Button('Hello', size=(300, 300), debug=True),
dui1.Button('Hello', size=(200, 200), debug=True),
dui1.Button('Hello', size=(100, 100), debug=True),
],
),
dui1.ButtonRow(
title=_nm(dui1.ButtonStyle.SQUARE_WIDE),
buttons=[
dui1.Button(
'Hello',
size=(400, 200),
style=dui1.ButtonStyle.SQUARE_WIDE,
debug=True,
),
dui1.Button(
'Hello',
size=(200, 250),
style=dui1.ButtonStyle.SQUARE_WIDE,
debug=True,
),
dui1.Button(
'Hello',
size=(60, 100),
style=dui1.ButtonStyle.SQUARE_WIDE,
debug=True,
),
],
),
dui1.ButtonRow(
title='(background texture)',
buttons=[
dui1.Button(
'Hello',
size=(300, 300),
texture='white',
color=(1, 0, 0, 0.3),
debug=True,
),
dui1.Button(
'Hello',
size=(200, 200),
texture='white',
color=(1, 0, 0, 0.3),
debug=True,
),
dui1.Button(
'Hello',
size=(100, 100),
texture='white',
color=(1, 0, 0, 0.3),
debug=True,
),
],
),
dui1.ButtonRow(
title=_nm(dui1.ButtonStyle.TAB),
buttons=[
dui1.Button(
'Hello',
size=(400, 100),
style=dui1.ButtonStyle.TAB,
debug=True,
),
dui1.Button(
'Hello',
size=(200, 50),
style=dui1.ButtonStyle.TAB,
debug=True,
),
dui1.Button(
'Hello',
size=(100, 60),
style=dui1.ButtonStyle.TAB,
debug=True,
),
],
),
dui1.ButtonRow(
title=_nm(dui1.ButtonStyle.LARGER),
buttons=[
dui1.Button(
'Hello',
size=(500, 100),
style=dui1.ButtonStyle.LARGER,
debug=True,
),
dui1.Button(
'Hello',
size=(200, 50),
style=dui1.ButtonStyle.LARGER,
debug=True,
),
dui1.Button(
'Hello',
size=(100, 60),
style=dui1.ButtonStyle.LARGER,
debug=True,
),
],
),
dui1.ButtonRow(
title=_nm(dui1.ButtonStyle.LARGE),
buttons=[
dui1.Button(
'Hello',
size=(400, 100),
style=dui1.ButtonStyle.LARGE,
debug=True,
),
dui1.Button(
'Hello',
size=(200, 50),
style=dui1.ButtonStyle.LARGE,
debug=True,
),
dui1.Button(
'Hello',
size=(100, 60),
style=dui1.ButtonStyle.LARGE,
debug=True,
),
],
),
dui1.ButtonRow(
title=_nm(dui1.ButtonStyle.MEDIUM),
buttons=[
dui1.Button(
'Hello',
size=(300, 100),
style=dui1.ButtonStyle.MEDIUM,
debug=True,
),
dui1.Button(
'Hello',
size=(200, 50),
style=dui1.ButtonStyle.MEDIUM,
debug=True,
),
dui1.Button(
'Hello',
size=(100, 60),
style=dui1.ButtonStyle.MEDIUM,
debug=True,
),
],
),
dui1.ButtonRow(
title=_nm(dui1.ButtonStyle.SMALL),
buttons=[
dui1.Button(
'Hello',
size=(200, 100),
style=dui1.ButtonStyle.SMALL,
debug=True,
),
dui1.Button(
'Hello',
size=(200, 50),
style=dui1.ButtonStyle.SMALL,
debug=True,
),
dui1.Button(
'Hello',
size=(100, 60),
style=dui1.ButtonStyle.SMALL,
debug=True,
),
],
),
dui1.ButtonRow(
title=_nm(dui1.ButtonStyle.BACK),
buttons=[
dui1.Button(
'Hello',
size=(200, 100),
style=dui1.ButtonStyle.BACK,
debug=True,
),
dui1.Button(
'Hello',
size=(200, 50),
style=dui1.ButtonStyle.BACK,
debug=True,
),
dui1.Button(
'Hello',
size=(100, 60),
style=dui1.ButtonStyle.BACK,
debug=True,
),
],
),
dui1.ButtonRow(
title=_nm(dui1.ButtonStyle.BACK_SMALL),
buttons=[
dui1.Button(
'Hello',
size=(200, 100),
style=dui1.ButtonStyle.BACK_SMALL,
debug=True,
),
dui1.Button(
'Hello',
size=(200, 50),
style=dui1.ButtonStyle.BACK_SMALL,
debug=True,
),
dui1.Button(
'Hello',
size=(100, 60),
style=dui1.ButtonStyle.BACK_SMALL,
debug=True,
),
],
),
],
)
)