You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
trezor-firmware/src/trezor/ui/button.py

114 lines
3.6 KiB

from micropython import const
from trezor import io, ui
from trezor.ui import LazyWidget, contains, display, rotate
# button events
BTN_CLICKED = const(1)
# button states
BTN_INITIAL = const(0)
BTN_DISABLED = const(1)
BTN_FOCUSED = const(2)
BTN_ACTIVE = const(3)
# constants
ICON = const(16) # icon size in pixels
BORDER = const(4) # border size in pixels
class Button(LazyWidget):
def __init__(self, area: tuple, content: str, style: dict = ui.BTN_KEY):
self.area = area
self.content = content
self.normal_style = style['normal'] or ui.BTN_KEY['normal']
self.active_style = style['active'] or ui.BTN_KEY['active']
self.disabled_style = style['disabled'] or ui.BTN_KEY['disabled']
self.state = BTN_INITIAL
def enable(self):
if self.state == BTN_DISABLED:
self.state = BTN_INITIAL
self.render_next_frame = True
def disable(self):
if self.state != BTN_DISABLED:
self.state = BTN_DISABLED
self.render_next_frame = True
def render(self):
state = self.state
if state == BTN_DISABLED:
s = self.disabled_style
elif state == BTN_ACTIVE:
s = self.active_style
else:
s = self.normal_style
ax, ay, aw, ah = self.area
self.render_background(s, ax, ay, aw, ah)
self.render_content(s, ax, ay, aw, ah)
def render_background(self, s, ax, ay, aw, ah):
radius = s['radius']
bg_color = s['bg-color']
border_color = s['border-color']
if border_color != bg_color:
# render border and background on top of it
display.bar_radius(ax, ay,
aw, ah,
border_color,
ui.BG,
radius)
display.bar_radius(ax + BORDER, ay + BORDER,
aw - BORDER * 2, ah - BORDER * 2,
bg_color,
border_color,
radius)
else:
# render only the background
display.bar_radius(ax, ay,
aw, ah,
bg_color,
ui.BG,
radius)
def render_content(self, s, ax, ay, aw, ah):
c = self.content
tx = ax + aw // 2
ty = ay + ah // 2 + 8
if isinstance(c, str):
display.text_center(
tx, ty, c, s['text-style'], s['fg-color'], s['bg-color'])
else:
display.icon(
tx - ICON // 2, ty - ICON, c, s['fg-color'], s['bg-color'])
def touch(self, event, pos):
pos = rotate(pos)
state = self.state
if state == BTN_DISABLED:
return
if event == io.TOUCH_START:
if contains(self.area, pos):
self.state = BTN_ACTIVE
self.render_next_frame = True
elif event == io.TOUCH_MOVE:
if contains(self.area, pos):
if state == BTN_FOCUSED:
self.state = BTN_ACTIVE
self.render_next_frame = True
else:
if state == BTN_ACTIVE:
self.state = BTN_FOCUSED
self.render_next_frame = True
elif event == io.TOUCH_END:
self.state = BTN_INITIAL
self.render_next_frame = True
if state == BTN_ACTIVE and contains(self.area, pos):
return BTN_CLICKED