ui: reduce flicker in buttons, text, and pin dialog

pull/25/head
Jan Pochyla 6 years ago
parent faa665a80b
commit dd5eba8da9

@ -159,6 +159,11 @@ def grid(
class Widget: class Widget:
tainted = True
def taint(self):
self.tainted = True
def render(self): def render(self):
pass pass
@ -173,21 +178,3 @@ 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

@ -1,7 +1,7 @@
from micropython import const from micropython import const
from trezor import io, ui from trezor import io, ui
from trezor.ui import LazyWidget, contains, display, rotate from trezor.ui import Widget, contains, display, rotate
# button events # button events
BTN_CLICKED = const(1) BTN_CLICKED = const(1)
@ -17,7 +17,7 @@ ICON = const(16) # icon size in pixels
BORDER = const(4) # border size in pixels BORDER = const(4) # border size in pixels
class Button(LazyWidget): class Button(Widget):
def __init__(self, area: tuple, content: str, style: dict = ui.BTN_KEY): def __init__(self, area: tuple, content: str, style: dict = ui.BTN_KEY):
self.area = area self.area = area
self.content = content self.content = content
@ -29,14 +29,16 @@ class Button(LazyWidget):
def enable(self): def enable(self):
if self.state == BTN_DISABLED: if self.state == BTN_DISABLED:
self.state = BTN_INITIAL self.state = BTN_INITIAL
self.render_next_frame = True self.tainted = True
def disable(self): def disable(self):
if self.state != BTN_DISABLED: if self.state != BTN_DISABLED:
self.state = BTN_DISABLED self.state = BTN_DISABLED
self.render_next_frame = True self.tainted = True
def render(self): def render(self):
if not self.tainted:
return
state = self.state state = self.state
if state == BTN_DISABLED: if state == BTN_DISABLED:
s = self.disabled_style s = self.disabled_style
@ -47,6 +49,7 @@ class Button(LazyWidget):
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.tainted = False
def render_background(self, s, ax, ay, aw, ah): def render_background(self, s, ax, ay, aw, ah):
radius = s["radius"] radius = s["radius"]
@ -89,20 +92,21 @@ class Button(LazyWidget):
if event == io.TOUCH_START: if event == io.TOUCH_START:
if contains(self.area, pos): if contains(self.area, pos):
self.state = BTN_ACTIVE self.state = BTN_ACTIVE
self.render_next_frame = True self.tainted = True
elif event == io.TOUCH_MOVE: elif event == io.TOUCH_MOVE:
if contains(self.area, pos): if contains(self.area, pos):
if state == BTN_FOCUSED: if state == BTN_FOCUSED:
self.state = BTN_ACTIVE self.state = BTN_ACTIVE
self.render_next_frame = True self.tainted = True
else: else:
if state == BTN_ACTIVE: if state == BTN_ACTIVE:
self.state = BTN_FOCUSED self.state = BTN_FOCUSED
self.render_next_frame = True self.tainted = True
elif event == io.TOUCH_END: elif event == io.TOUCH_END:
if state != BTN_INITIAL:
self.state = BTN_INITIAL self.state = BTN_INITIAL
self.render_next_frame = True self.tainted = True
if state == BTN_ACTIVE and contains(self.area, pos): if state == BTN_ACTIVE and contains(self.area, pos):
return BTN_CLICKED return BTN_CLICKED

@ -79,7 +79,6 @@ class HoldToConfirmDialog(Widget):
self.loader.start() self.loader.start()
return _STARTED return _STARTED
if was_active and not is_active: if was_active and not is_active:
if isinstance(self.content, ui.LazyWidget):
self.content.taint() self.content.taint()
if self.loader.stop(): if self.loader.stop():
return CONFIRMED return CONFIRMED

@ -35,6 +35,13 @@ class PinMatrix(ui.Widget):
self.onchange = None self.onchange = None
def render(self): def render(self):
# pin matrix buttons
for btn in self.pin_buttons:
btn.render()
if not self.tainted:
return
# clear canvas under input line # clear canvas under input line
display.bar(0, 0, ui.WIDTH, 45, ui.BG) display.bar(0, 0, ui.WIDTH, 45, ui.BG)
@ -52,9 +59,7 @@ class PinMatrix(ui.Widget):
# input line with header label # input line with header label
display.text_center(ui.WIDTH // 2, 36, self.label, ui.BOLD, ui.GREY, ui.BG) display.text_center(ui.WIDTH // 2, 36, self.label, ui.BOLD, ui.GREY, ui.BG)
# pin matrix buttons self.tainted = False
for btn in self.pin_buttons:
btn.render()
def touch(self, event, pos): def touch(self, event, pos):
for btn in self.pin_buttons: for btn in self.pin_buttons:
@ -64,6 +69,7 @@ class PinMatrix(ui.Widget):
break break
def change(self, pin): def change(self, pin):
self.tainted = True
self.pin = pin self.pin = pin
for btn in self.pin_buttons: for btn in self.pin_buttons:
if len(self.pin) == self.maxlength: if len(self.pin) == self.maxlength:

@ -106,7 +106,7 @@ def render_text(words: list, new_lines: bool, max_lines: int) -> None:
offset_x += SPACE offset_x += SPACE
class Text(ui.LazyWidget): class Text(ui.Widget):
def __init__( def __init__(
self, self,
header_text: str, header_text: str,
@ -121,6 +121,7 @@ class Text(ui.LazyWidget):
self.max_lines = max_lines self.max_lines = max_lines
self.new_lines = new_lines self.new_lines = new_lines
self.content = [] self.content = []
self.tainted = True
def normal(self, *content): def normal(self, *content):
self.content.append(ui.NORMAL) self.content.append(ui.NORMAL)
@ -142,7 +143,10 @@ class Text(ui.LazyWidget):
self.content.append(BR) self.content.append(BR)
def render(self): def render(self):
if not self.tainted:
return
ui.header( ui.header(
self.header_text, self.header_icon, ui.TITLE_GREY, ui.BG, self.icon_color self.header_text, self.header_icon, ui.TITLE_GREY, ui.BG, self.icon_color
) )
render_text(self.content, self.new_lines, self.max_lines) render_text(self.content, self.new_lines, self.max_lines)
self.tainted = False

Loading…
Cancel
Save