ui: request_words, keyboard ui
BIN
assets/5390-200.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.1 KiB |
BIN
assets/left.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
assets/recovery-old.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.3 KiB |
BIN
assets/send-old.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
assets/send.png
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.3 KiB |
30
src/apps/common/request_words.py
Normal file
@ -0,0 +1,30 @@
|
||||
from trezor import wire, ui, loop
|
||||
from trezor.utils import unimport
|
||||
|
||||
# used to confirm/cancel the dialogs from outside of this module (i.e.
|
||||
# through debug link)
|
||||
if __debug__:
|
||||
signal = loop.signal()
|
||||
|
||||
|
||||
@ui.layout
|
||||
@unimport
|
||||
async def request_words(ctx, content, code=None, *args, **kwargs):
|
||||
from trezor.ui.word_select import WordSelector
|
||||
from trezor.messages.ButtonRequest import ButtonRequest
|
||||
from trezor.messages.ButtonRequestType import Other
|
||||
from trezor.messages.wire_types import ButtonAck
|
||||
|
||||
ui.display.clear()
|
||||
dialog = WordSelector(content, *args, **kwargs)
|
||||
dialog.render()
|
||||
|
||||
if code is None:
|
||||
code = Other
|
||||
await ctx.call(ButtonRequest(code=code), ButtonAck)
|
||||
|
||||
if __debug__:
|
||||
waiter = loop.wait(signal, dialog)
|
||||
else:
|
||||
waiter = dialog
|
||||
return await waiter
|
@ -11,15 +11,20 @@ async def layout_recovery_device(ctx, msg):
|
||||
from trezor.ui.text import Text
|
||||
from apps.common import storage
|
||||
from apps.common.confirm import require_confirm
|
||||
from apps.common.request_words import request_words
|
||||
|
||||
if storage.is_initialized():
|
||||
raise wire.FailureError(UnexpectedMessage, 'Already initialized')
|
||||
|
||||
words = []
|
||||
|
||||
wc = await request_words(ctx, Text(
|
||||
'Device recovery', ui.ICON_RECOVERY, 'Number of words?'))
|
||||
msg.word_count = int(wc)
|
||||
ui.display.clear()
|
||||
kbd = KeyboardMultiTap()
|
||||
for i in range(0, msg.word_count):
|
||||
kbd.prompt = '%s. ' % (i + 1)
|
||||
kbd.prompt = 'Type %s. word' % (i + 1)
|
||||
word = await kbd
|
||||
words.append(word)
|
||||
|
||||
|
BIN
src/trezor/res/click.toig
Normal file
BIN
src/trezor/res/confirm2.toig
Normal file
BIN
src/trezor/res/cross2.toig
Normal file
BIN
src/trezor/res/left.toig
Normal file
BIN
src/trezor/res/recovery.toig
Normal file
BIN
src/trezor/res/send2.toig
Normal file
@ -106,11 +106,10 @@ def layout(f):
|
||||
return inner
|
||||
|
||||
|
||||
def header(title: str, icon: bytes=ICON_RESET, fg: int=BG, bg: int=BG):
|
||||
display.bar(0, 0, 240, 32, bg)
|
||||
def header(title: str, icon: bytes=ICON_RESET, fg: int=BG, bg: int=BG, ifg: int=BG):
|
||||
if icon is not None:
|
||||
display.icon(8, 4, res.load(icon), fg, bg)
|
||||
display.text(8 + 24 + 2, 24, title, BOLD, fg, bg)
|
||||
display.icon(14, 14, res.load(icon), ifg, bg)
|
||||
display.text(44, 35, title, BOLD, fg, bg)
|
||||
|
||||
|
||||
class Widget:
|
||||
|
@ -32,11 +32,13 @@ class Button(Widget):
|
||||
self.state = BTN_DIRTY
|
||||
|
||||
def enable(self):
|
||||
self.state &= ~BTN_DISABLED
|
||||
self.state |= BTN_DIRTY
|
||||
if self.state & BTN_DISABLED:
|
||||
self.state &= ~BTN_DISABLED
|
||||
self.state |= BTN_DIRTY
|
||||
|
||||
def disable(self):
|
||||
self.state |= BTN_DISABLED | BTN_DIRTY
|
||||
if not self.state & BTN_DISABLED:
|
||||
self.state |= BTN_DISABLED | BTN_DIRTY
|
||||
|
||||
def taint(self):
|
||||
self.state |= BTN_DIRTY
|
||||
@ -54,6 +56,7 @@ class Button(Widget):
|
||||
ax, ay, aw, ah = self.area
|
||||
tx = ax + aw // 2
|
||||
ty = ay + ah // 2 + 8
|
||||
|
||||
display.bar_radius(ax, ay, aw, ah,
|
||||
s['border-color'],
|
||||
ui.BG,
|
||||
@ -70,7 +73,7 @@ class Button(Widget):
|
||||
s['bg-color'])
|
||||
|
||||
else:
|
||||
display.icon(tx - 15, ty - 20, self.content,
|
||||
display.icon(tx - 8, ty - 16, self.content,
|
||||
s['fg-color'],
|
||||
s['bg-color'])
|
||||
|
||||
|
@ -4,7 +4,7 @@ from trezor.ui import display
|
||||
from trezor.ui.button import Button, BTN_CLICKED
|
||||
|
||||
|
||||
def cell_area(i, n_x=3, n_y=3, start_x=0, start_y=40, end_x=240, end_y=240, spacing=0):
|
||||
def cell_area(i, n_x=3, n_y=3, start_x=6, start_y=66, end_x=234, end_y=237, spacing=0):
|
||||
w = (end_x - start_x) // n_x
|
||||
h = (end_y - start_y) // n_y
|
||||
x = (i % n_x) * w
|
||||
@ -17,7 +17,8 @@ def key_buttons():
|
||||
# keys = [' ', 'abc', 'def', 'ghi', 'jkl', 'mno', 'pqrs', 'tuv', 'wxyz']
|
||||
return [Button(cell_area(i), k,
|
||||
normal_style=ui.BTN_KEY,
|
||||
active_style=ui.BTN_KEY_ACTIVE) for i, k in enumerate(keys)]
|
||||
active_style=ui.BTN_KEY_ACTIVE,
|
||||
disabled_style=ui.BTN_KEY_DISABLED) for i, k in enumerate(keys)]
|
||||
|
||||
|
||||
def compute_mask(text):
|
||||
@ -41,38 +42,52 @@ class KeyboardMultiTap(ui.Widget):
|
||||
self.pending_index = 0
|
||||
|
||||
self.key_buttons = key_buttons()
|
||||
self.sugg_button = Button((5, 5, 240 - 35, 30), '')
|
||||
self.bs_button = Button((240 - 35, 5, 30, 30),
|
||||
res.load('trezor/res/pin_close.toig'),
|
||||
self.sugg_button = Button((63, 0, 240 - 65, 57), '')
|
||||
self.bs_button = Button((6, 5, 57, 60),
|
||||
res.load('trezor/res/left.toig'),
|
||||
normal_style=ui.BTN_CLEAR,
|
||||
active_style=ui.BTN_CLEAR_ACTIVE)
|
||||
|
||||
def render(self):
|
||||
|
||||
# clear canvas under input line
|
||||
display.bar(0, 0, 205, 40, ui.BG)
|
||||
|
||||
# input line
|
||||
content_width = display.text_width(self.prompt + self.content, ui.BOLD)
|
||||
display.text(20, 30, self.prompt + self.content, ui.BOLD, ui.FG, ui.BG)
|
||||
|
||||
# pending marker
|
||||
if self.pending_button is not None:
|
||||
pending_width = display.text_width(self.content[-1:], ui.BOLD)
|
||||
pending_x = 20 + content_width - pending_width
|
||||
display.bar(pending_x, 33, pending_width + 2, 3, ui.FG)
|
||||
|
||||
# auto-suggest
|
||||
if self.sugg_word is not None:
|
||||
sugg_rest = self.sugg_word[len(self.content):]
|
||||
sugg_x = 20 + content_width
|
||||
display.text(sugg_x, 30, sugg_rest, ui.BOLD, ui.GREY, ui.BG)
|
||||
|
||||
# render backspace button
|
||||
if self.content:
|
||||
display.bar(62, 8, 168, 54, ui.BG)
|
||||
content_width = display.text_width(self.content, ui.BOLD)
|
||||
offset_x = 78
|
||||
if self.content == self.sugg_word:
|
||||
# confirm button + content
|
||||
display.bar_radius(67, 8, 164, 54, ui.GREEN, ui.BG, ui.RADIUS)
|
||||
type_icon = res.load(ui.ICON_CONFIRM2)
|
||||
display.icon(228 - 30, 28, type_icon, ui.WHITE, ui.GREEN)
|
||||
display.text(offset_x, 40, self.content, ui.BOLD, ui.WHITE, ui.GREEN)
|
||||
|
||||
elif self.sugg_word is not None:
|
||||
# auto-suggest button + content + suggestion
|
||||
display.bar_radius(67, 8, 164, 54, ui.BLACKISH, ui.BG, ui.RADIUS)
|
||||
display.text(offset_x, 40, self.content, ui.BOLD, ui.FG, ui.BLACKISH)
|
||||
sugg_text = self.sugg_word[len(self.content):]
|
||||
sugg_x = offset_x + content_width
|
||||
type_icon = res.load(ui.ICON_CLICK)
|
||||
display.icon(228 - 30, 24, type_icon, ui.GREY, ui.BLACKISH)
|
||||
display.text(sugg_x, 40, sugg_text, ui.BOLD, ui.GREY, ui.BLACKISH)
|
||||
|
||||
else:
|
||||
# content
|
||||
display.bar(63, 8, 168, 54, ui.BG)
|
||||
display.text(offset_x, 40, self.content, ui.BOLD, ui.FG, ui.BG)
|
||||
|
||||
# backspace button
|
||||
self.bs_button.render()
|
||||
|
||||
# pending marker
|
||||
if self.pending_button is not None:
|
||||
pending_width = display.text_width(self.content[-1:], ui.BOLD)
|
||||
pending_x = offset_x + content_width - pending_width
|
||||
display.bar(pending_x, 42, pending_width + 2, 3, ui.FG)
|
||||
|
||||
else:
|
||||
display.bar(240 - 48, 0, 48, 42, ui.BG)
|
||||
# prompt
|
||||
display.bar(0, 8, 240, 60, ui.BG)
|
||||
display.text(20, 40, self.prompt, ui.BOLD, ui.GREY, ui.BG)
|
||||
|
||||
# key buttons
|
||||
for btn in self.key_buttons:
|
||||
@ -87,10 +102,12 @@ class KeyboardMultiTap(ui.Widget):
|
||||
self._update_buttons()
|
||||
return
|
||||
if self.sugg_button.touch(event, pos) == BTN_CLICKED:
|
||||
if self.content == bip39.find_word(self.content):
|
||||
if not self.content or self.sugg_word is None:
|
||||
return None
|
||||
if self.content == self.sugg_word:
|
||||
result = self.content
|
||||
self.content = ''
|
||||
elif self.sugg_word is not None:
|
||||
else:
|
||||
result = None
|
||||
self.content = self.sugg_word
|
||||
self.pending_button = None
|
||||
@ -128,19 +145,22 @@ class KeyboardMultiTap(ui.Widget):
|
||||
else:
|
||||
btn.disable()
|
||||
|
||||
def __iter__(self):
|
||||
async def __iter__(self):
|
||||
timeout = loop.sleep(1000 * 1000 * 1)
|
||||
touch = loop.select(io.TOUCH)
|
||||
wait_timeout = loop.wait(touch, timeout)
|
||||
wait_touch = loop.wait(touch)
|
||||
content = None
|
||||
|
||||
self.bs_button.taint()
|
||||
|
||||
while content is None:
|
||||
self.render()
|
||||
if self.pending_button is not None:
|
||||
wait = wait_timeout
|
||||
else:
|
||||
wait = wait_touch
|
||||
result = yield wait
|
||||
result = await wait
|
||||
if touch in wait.finished:
|
||||
event, *pos = result
|
||||
content = self.touch(event, pos)
|
||||
@ -154,90 +174,90 @@ class KeyboardMultiTap(ui.Widget):
|
||||
return content
|
||||
|
||||
|
||||
def zoom_buttons(keys, upper=False):
|
||||
n_x = len(keys)
|
||||
if upper:
|
||||
keys = keys + keys.upper()
|
||||
n_y = 2
|
||||
else:
|
||||
n_y = 1
|
||||
return [Button(cell_area(i, n_x, n_y), key) for i, key in enumerate(keys)]
|
||||
# def zoom_buttons(keys, upper=False):
|
||||
# n_x = len(keys)
|
||||
# if upper:
|
||||
# keys = keys + keys.upper()
|
||||
# n_y = 2
|
||||
# else:
|
||||
# n_y = 1
|
||||
# return [Button(cell_area(i, n_x, n_y), key) for i, key in enumerate(keys)]
|
||||
|
||||
|
||||
class KeyboardZooming(ui.Widget):
|
||||
# class KeyboardZooming(ui.Widget):
|
||||
|
||||
def __init__(self, content='', uppercase=True):
|
||||
self.content = content
|
||||
self.uppercase = uppercase
|
||||
# def __init__(self, content='', uppercase=True):
|
||||
# self.content = content
|
||||
# self.uppercase = uppercase
|
||||
|
||||
self.zoom_buttons = None
|
||||
self.key_buttons = key_buttons()
|
||||
self.bs_button = Button((240 - 35, 5, 30, 30),
|
||||
res.load('trezor/res/pin_close.toig'),
|
||||
normal_style=ui.BTN_CLEAR,
|
||||
active_style=ui.BTN_CLEAR_ACTIVE)
|
||||
# self.zoom_buttons = None
|
||||
# self.key_buttons = key_buttons()
|
||||
# self.bs_button = Button((240 - 35, 5, 30, 30),
|
||||
# res.load('trezor/res/pin_close.toig'),
|
||||
# normal_style=ui.BTN_CLEAR,
|
||||
# active_style=ui.BTN_CLEAR_ACTIVE)
|
||||
|
||||
def render(self):
|
||||
self.render_input()
|
||||
if self.zoom_buttons:
|
||||
for btn in self.zoom_buttons:
|
||||
btn.render()
|
||||
else:
|
||||
for btn in self.key_buttons:
|
||||
btn.render()
|
||||
# def render(self):
|
||||
# self.render_input()
|
||||
# if self.zoom_buttons:
|
||||
# for btn in self.zoom_buttons:
|
||||
# btn.render()
|
||||
# else:
|
||||
# for btn in self.key_buttons:
|
||||
# btn.render()
|
||||
|
||||
def render_input(self):
|
||||
if self.content:
|
||||
display.bar(0, 0, 200, 40, ui.BG)
|
||||
else:
|
||||
display.bar(0, 0, 240, 40, ui.BG)
|
||||
display.text(20, 30, self.content, ui.BOLD, ui.GREY, ui.BG)
|
||||
if self.content:
|
||||
self.bs_button.render()
|
||||
# def render_input(self):
|
||||
# if self.content:
|
||||
# display.bar(0, 0, 200, 40, ui.BG)
|
||||
# else:
|
||||
# display.bar(0, 0, 240, 40, ui.BG)
|
||||
# display.text(20, 30, self.content, ui.BOLD, ui.GREY, ui.BG)
|
||||
# if self.content:
|
||||
# self.bs_button.render()
|
||||
|
||||
def touch(self, event, pos):
|
||||
if self.bs_button.touch(event, pos) == BTN_CLICKED:
|
||||
self.content = self.content[:-1]
|
||||
self.bs_button.taint()
|
||||
return
|
||||
if self.zoom_buttons:
|
||||
return self.touch_zoom(event, pos)
|
||||
else:
|
||||
return self.touch_keyboard(event, pos)
|
||||
# def touch(self, event, pos):
|
||||
# if self.bs_button.touch(event, pos) == BTN_CLICKED:
|
||||
# self.content = self.content[:-1]
|
||||
# self.bs_button.taint()
|
||||
# return
|
||||
# if self.zoom_buttons:
|
||||
# return self.touch_zoom(event, pos)
|
||||
# else:
|
||||
# return self.touch_keyboard(event, pos)
|
||||
|
||||
def touch_zoom(self, event, pos):
|
||||
for btn in self.zoom_buttons:
|
||||
if btn.touch(event, pos) == BTN_CLICKED:
|
||||
self.content += btn.content
|
||||
self.zoom_buttons = None
|
||||
for b in self.key_buttons:
|
||||
b.taint()
|
||||
self.bs_button.taint()
|
||||
break
|
||||
# def touch_zoom(self, event, pos):
|
||||
# for btn in self.zoom_buttons:
|
||||
# if btn.touch(event, pos) == BTN_CLICKED:
|
||||
# self.content += btn.content
|
||||
# self.zoom_buttons = None
|
||||
# for b in self.key_buttons:
|
||||
# b.taint()
|
||||
# self.bs_button.taint()
|
||||
# break
|
||||
|
||||
def touch_keyboard(self, event, pos):
|
||||
for btn in self.key_buttons:
|
||||
if btn.touch(event, pos) == BTN_CLICKED:
|
||||
self.zoom_buttons = zoom_buttons(btn.content, self.uppercase)
|
||||
for b in self.zoom_buttons:
|
||||
b.taint()
|
||||
self.bs_button.taint()
|
||||
break
|
||||
# def touch_keyboard(self, event, pos):
|
||||
# for btn in self.key_buttons:
|
||||
# if btn.touch(event, pos) == BTN_CLICKED:
|
||||
# self.zoom_buttons = zoom_buttons(btn.content, self.uppercase)
|
||||
# for b in self.zoom_buttons:
|
||||
# b.taint()
|
||||
# self.bs_button.taint()
|
||||
# break
|
||||
|
||||
def __iter__(self):
|
||||
timeout = loop.sleep(1000 * 1000 * 1)
|
||||
touch = loop.select(io.TOUCH)
|
||||
wait = loop.wait(touch, timeout)
|
||||
while True:
|
||||
self.render()
|
||||
result = yield wait
|
||||
if touch in wait.finished:
|
||||
event, *pos = result
|
||||
self.touch(event, pos)
|
||||
elif self.zoom_buttons:
|
||||
self.zoom_buttons = None
|
||||
for btn in self.key_buttons:
|
||||
btn.taint()
|
||||
# def __iter__(self):
|
||||
# timeout = loop.sleep(1000 * 1000 * 1)
|
||||
# touch = loop.select(io.TOUCH)
|
||||
# wait = loop.wait(touch, timeout)
|
||||
# while True:
|
||||
# self.render()
|
||||
# result = yield wait
|
||||
# if touch in wait.finished:
|
||||
# event, *pos = result
|
||||
# self.touch(event, pos)
|
||||
# elif self.zoom_buttons:
|
||||
# self.zoom_buttons = None
|
||||
# for btn in self.key_buttons:
|
||||
# btn.taint()
|
||||
|
||||
|
||||
Keyboard = KeyboardMultiTap
|
||||
|
@ -38,7 +38,10 @@ DARK_GREY = rgb(0x3E, 0x3E, 0x3E)
|
||||
BLUE_GRAY = rgb(0x60, 0x7D, 0x8B)
|
||||
BLACK = rgb(0x00, 0x00, 0x00)
|
||||
WHITE = rgb(0xFA, 0xFA, 0xFA)
|
||||
BLACKISH = rgb(0x20, 0x20, 0x20)
|
||||
BLACKISH = rgb(0x30, 0x30, 0x30)
|
||||
|
||||
TITLE_GREY = rgb(0x9B, 0x9B, 0x9B)
|
||||
ORANGE_ICON = rgb(0xF5, 0xA6, 0x23)
|
||||
|
||||
# common color styles
|
||||
BG = BLACK
|
||||
@ -47,11 +50,13 @@ FG = WHITE
|
||||
# icons
|
||||
ICON_RESET = 'trezor/res/header_icons/reset.toig'
|
||||
ICON_WIPE = 'trezor/res/header_icons/wipe.toig'
|
||||
ICON_RECOVERY = 'trezor/res/header_icons/recovery.toig'
|
||||
ICON_RECOVERY = 'trezor/res/header_icons/reset.toig'
|
||||
ICON_CLEAR = 'trezor/res/clear.toig'
|
||||
ICON_CONFIRM = 'trezor/res/confirm.toig'
|
||||
ICON_CONFIRM2 = 'trezor/res/confirm2.toig'
|
||||
ICON_LOCK = 'trezor/res/lock.toig'
|
||||
ICON_SEND = 'trezor/res/send.toig'
|
||||
ICON_CLICK = 'trezor/res/click.toig'
|
||||
|
||||
# buttons
|
||||
BTN_DEFAULT = {
|
||||
@ -104,7 +109,7 @@ BTN_CONFIRM_ACTIVE = {
|
||||
'radius': RADIUS,
|
||||
}
|
||||
BTN_CLEAR = {
|
||||
'bg-color': BG,
|
||||
'bg-color': ORANGE,
|
||||
'fg-color': FG,
|
||||
'text-style': NORMAL,
|
||||
'border-color': BG,
|
||||
@ -131,6 +136,13 @@ BTN_KEY_ACTIVE = {
|
||||
'border-color': FG,
|
||||
'radius': RADIUS,
|
||||
}
|
||||
BTN_KEY_DISABLED = {
|
||||
'bg-color': BG,
|
||||
'fg-color': GREY,
|
||||
'text-style': MONO,
|
||||
'border-color': BG,
|
||||
'radius': RADIUS,
|
||||
}
|
||||
|
||||
# loader
|
||||
LDR_DEFAULT = {
|
||||
|
@ -1,9 +1,9 @@
|
||||
from micropython import const
|
||||
from trezor import ui
|
||||
|
||||
TEXT_HEADER_HEIGHT = const(32)
|
||||
TEXT_HEADER_HEIGHT = const(51)
|
||||
TEXT_LINE_HEIGHT = const(23)
|
||||
TEXT_MARGIN_LEFT = const(10)
|
||||
TEXT_MARGIN_LEFT = const(14)
|
||||
|
||||
|
||||
class Text(ui.Widget):
|
||||
@ -19,7 +19,7 @@ class Text(ui.Widget):
|
||||
style = ui.NORMAL
|
||||
fg = ui.FG
|
||||
bg = ui.BG
|
||||
ui.header(self.header_text, self.header_icon, ui.GREEN, ui.BG)
|
||||
ui.header(self.header_text, self.header_icon, ui.TITLE_GREY, ui.BG, ui.ORANGE_ICON)
|
||||
|
||||
for item in self.content:
|
||||
if isinstance(item, str):
|
||||
|
53
src/trezor/ui/word_select.py
Normal file
@ -0,0 +1,53 @@
|
||||
from micropython import const
|
||||
from trezor import loop
|
||||
from trezor import ui, res
|
||||
from trezor.ui import Widget
|
||||
from trezor.ui.button import Button, BTN_CLICKED, BTN_STARTED, BTN_ACTIVE
|
||||
|
||||
W12 = '12'
|
||||
W15 = '15'
|
||||
W18 = '18'
|
||||
W24 = '24'
|
||||
|
||||
class WordSelector(Widget):
|
||||
|
||||
def __init__(self, content):
|
||||
self.content = content
|
||||
self.w12 = Button((6, 135, 114, 51), W12,
|
||||
normal_style=ui.BTN_KEY,
|
||||
active_style=ui.BTN_KEY_ACTIVE)
|
||||
self.w15 = Button((120, 135, 114, 51), W15,
|
||||
normal_style=ui.BTN_KEY,
|
||||
active_style=ui.BTN_KEY_ACTIVE)
|
||||
self.w18 = Button((6, 186, 114, 51), W18,
|
||||
normal_style=ui.BTN_KEY,
|
||||
active_style=ui.BTN_KEY_ACTIVE)
|
||||
self.w24 = Button((120, 186, 114, 51), W24,
|
||||
normal_style=ui.BTN_KEY,
|
||||
active_style=ui.BTN_KEY_ACTIVE)
|
||||
|
||||
def render(self):
|
||||
self.w12.render()
|
||||
self.w15.render()
|
||||
self.w18.render()
|
||||
self.w24.render()
|
||||
|
||||
def touch(self, event, pos):
|
||||
if self.w12.touch(event, pos) == BTN_CLICKED:
|
||||
return W12
|
||||
if self.w15.touch(event, pos) == BTN_CLICKED:
|
||||
return W15
|
||||
if self.w18.touch(event, pos) == BTN_CLICKED:
|
||||
return W18
|
||||
if self.w24.touch(event, pos) == BTN_CLICKED:
|
||||
return W24
|
||||
|
||||
async def __iter__(self):
|
||||
return await loop.wait(super().__iter__(), self.content)
|
||||
|
||||
|
||||
_STARTED = const(-1)
|
||||
_STOPPED = const(-2)
|
||||
|
||||
|
||||
|