1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-06-08 17:18:46 +00:00

ui: introduce LazyWidget

Used in Button and Text.
This commit is contained in:
Jan Pochyla 2018-06-28 14:05:38 +02:00
parent f9d77479d4
commit 6e13a1475b
4 changed files with 62 additions and 42 deletions

View File

@ -175,3 +175,21 @@ class Widget:
event, *pos = yield touch event, *pos = yield touch
result = self.touch(event, pos) result = self.touch(event, pos)
return result return result
class LazyWidget(Widget):
render_next_frame = True
def taint(self):
self.render_next_frame = True
def __iter__(self):
touch = loop.wait(io.TOUCH)
result = None
while result is None:
if self.render_next_frame:
self.render()
self.render_next_frame = False
event, *pos = yield touch
result = self.touch(event, pos)
return result

View File

@ -6,57 +6,53 @@ from trezor import ui
from trezor.ui import contains from trezor.ui import contains
from trezor.ui import display from trezor.ui import display
from trezor.ui import rotate from trezor.ui import rotate
from trezor.ui import Widget from trezor.ui import LazyWidget
# button events
BTN_CLICKED = const(1) BTN_CLICKED = const(1)
BTN_STARTED = const(1) # button states
BTN_ACTIVE = const(2) BTN_INITIAL = const(0)
BTN_DIRTY = const(4) BTN_DISABLED = const(1)
BTN_DISABLED = const(8) BTN_FOCUSED = const(2)
BTN_ACTIVE = const(3)
# constants
ICON = const(16) # icon size in pixels ICON = const(16) # icon size in pixels
BORDER = const(4) # border size in pixels BORDER = const(4) # border size in pixels
class Button(Widget): class Button(LazyWidget):
def __init__(self, area, content, style=ui.BTN_KEY, absolute=False): def __init__(self, area: tuple, content: str, style: dict = ui.BTN_KEY):
self.area = area self.area = area
self.content = content self.content = content
self.normal_style = style['normal'] or ui.BTN_KEY['normal'] self.normal_style = style['normal'] or ui.BTN_KEY['normal']
self.active_style = style['active'] or ui.BTN_KEY['active'] self.active_style = style['active'] or ui.BTN_KEY['active']
self.disabled_style = style['disabled'] or ui.BTN_KEY['disabled'] self.disabled_style = style['disabled'] or ui.BTN_KEY['disabled']
self.absolute = absolute self.state = BTN_INITIAL
self.state = BTN_DIRTY
def enable(self): def enable(self):
if self.state & BTN_DISABLED: if self.state == BTN_DISABLED:
self.state &= ~BTN_DISABLED self.state = BTN_INITIAL
self.state |= BTN_DIRTY self.render_next_frame = True
def disable(self): def disable(self):
if not self.state & BTN_DISABLED: if self.state != BTN_DISABLED:
self.state |= BTN_DISABLED | BTN_DIRTY self.state = BTN_DISABLED
self.render_next_frame = True
def taint(self):
self.state |= BTN_DIRTY
def render(self): def render(self):
if not self.state & BTN_DIRTY: state = self.state
return if state == BTN_DISABLED:
state = self.state & ~BTN_DIRTY
if state & BTN_DISABLED:
s = self.disabled_style s = self.disabled_style
elif state & BTN_ACTIVE: elif state == BTN_ACTIVE:
s = self.active_style s = self.active_style
else: else:
s = self.normal_style s = self.normal_style
ax, ay, aw, ah = self.area ax, ay, aw, ah = self.area
self.render_background(s, ax, ay, aw, ah) self.render_background(s, ax, ay, aw, ah)
self.render_content(s, ax, ay, aw, ah) self.render_content(s, ax, ay, aw, ah)
self.state = state
def render_background(self, s, ax, ay, aw, ah): def render_background(self, s, ax, ay, aw, ah):
radius = s['radius'] radius = s['radius']
@ -94,25 +90,29 @@ class Button(Widget):
tx - ICON // 2, ty - ICON, c, s['fg-color'], s['bg-color']) tx - ICON // 2, ty - ICON, c, s['fg-color'], s['bg-color'])
def touch(self, event, pos): def touch(self, event, pos):
pos = rotate(pos)
state = self.state state = self.state
if state & BTN_DISABLED: if state == BTN_DISABLED:
return return
if not self.absolute:
pos = rotate(pos)
if event == io.TOUCH_START: if event == io.TOUCH_START:
if contains(self.area, pos): if contains(self.area, pos):
self.state = BTN_STARTED | BTN_DIRTY | BTN_ACTIVE self.state = BTN_ACTIVE
self.render_next_frame = True
elif event == io.TOUCH_MOVE and state & BTN_STARTED: elif event == io.TOUCH_MOVE:
if contains(self.area, pos): if contains(self.area, pos):
if not state & BTN_ACTIVE: if state == BTN_FOCUSED:
self.state = BTN_STARTED | BTN_DIRTY | BTN_ACTIVE self.state = BTN_ACTIVE
self.render_next_frame = True
else: else:
if state & BTN_ACTIVE: if state == BTN_ACTIVE:
self.state = BTN_STARTED | BTN_DIRTY self.state = BTN_FOCUSED
self.render_next_frame = True
elif event == io.TOUCH_END and state & BTN_STARTED: elif event == io.TOUCH_END:
self.state = BTN_DIRTY self.state = BTN_INITIAL
if contains(self.area, pos): self.render_next_frame = True
if state == BTN_ACTIVE and contains(self.area, pos):
return BTN_CLICKED return BTN_CLICKED

View File

@ -1,7 +1,7 @@
from micropython import const from micropython import const
from trezor import loop, res, ui from trezor import loop, res, ui
from trezor.ui import Widget from trezor.ui import Widget
from trezor.ui.button import BTN_ACTIVE, BTN_CLICKED, BTN_STARTED, Button from trezor.ui.button import BTN_ACTIVE, BTN_CLICKED, Button
from trezor.ui.loader import Loader from trezor.ui.loader import Loader
if __debug__: if __debug__:
@ -70,14 +70,16 @@ class HoldToConfirmDialog(Widget):
def touch(self, event, pos): def touch(self, event, pos):
button = self.button button = self.button
was_started = button.state & BTN_STARTED and button.state & BTN_ACTIVE was_active = button.state == BTN_ACTIVE
button.touch(event, pos) button.touch(event, pos)
is_started = button.state & BTN_STARTED and button.state & BTN_ACTIVE is_active = button.state == BTN_ACTIVE
if is_started and not was_started: if is_active and not was_active:
ui.display.clear() ui.display.clear()
self.loader.start() self.loader.start()
return _STARTED return _STARTED
if was_started and not is_started: if was_active and not is_active:
if isinstance(self.content, ui.LazyWidget):
self.content.taint()
if self.loader.stop(): if self.loader.stop():
return CONFIRMED return CONFIRMED
else: else:

View File

@ -98,7 +98,7 @@ def render_words(words: list, new_lines: bool, max_lines: int) -> None:
offset_x += SPACE offset_x += SPACE
class Text(ui.Widget): class Text(ui.LazyWidget):
def __init__(self, def __init__(self,
header_text: str, header_text: str,
header_icon: bytes, header_icon: bytes,