Generalizing reusable components

This commit is contained in:
kdmukai
2021-07-08 22:13:23 -05:00
parent cdd7b99a95
commit ab3cb06f4e
5 changed files with 131 additions and 52 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
from .buttons import *
from .camera_process import *
from .keyboard import Keyboard
from .keyboard import Keyboard, TextEntryDisplay
from .path import *
from .qr import *
from .ST7789 import *
+33
View File
@@ -341,3 +341,36 @@ class Keyboard:
raise Exception(f"""`selected_letter` "{selected_letter}" not found in keyboard""")
@dataclass
class TextEntryDisplay:
draw: any
rect: (int,int,int,int)
font: any
font_color: any
is_centered: bool = True
cur_text: str = " "
def render(self, cur_text=None):
""" Render the live text entry display """
if cur_text:
self.cur_text = cur_text
self.draw.rectangle(self.rect, fill="black")
cursor_block_width = 18
cursor_block_height = 33
# Draw n-1 of the selected letters
tw, th = self.font.getsize(self.cur_text[:-1])
if self.is_centered:
word_offset = int(self.rect[2] - tw - cursor_block_width)/2
else:
word_offset = 0
self.draw.text((word_offset, 2), self.cur_text[:-1], fill=self.font_color, font=self.font)
# Draw the highlighted cursor block
cursor_block_offset = word_offset + tw - 1
self.draw.rectangle((cursor_block_offset,2, cursor_block_offset + cursor_block_width, cursor_block_height), fill="#111")
self.draw.text((cursor_block_offset + 1, 2), self.cur_text[-1], fill=self.font_color, font=self.font)
+56 -51
View File
@@ -7,7 +7,7 @@ import time
# Internal file class dependencies
from . import View
from seedsigner.helpers import B, QR, CameraPoll, Keyboard
from seedsigner.helpers import B, QR, CameraPoll, Keyboard, TextEntryDisplay
class SeedToolsView(View):
@@ -198,49 +198,10 @@ class SeedToolsView(View):
)
def render_previous_button(highlight=False):
# Set up the "back" arrow in the upper left
arrow = "<"
word_font = View.ROBOTOCONDENSED_BOLD_26
tw, th = word_font.getsize(arrow)
if highlight:
View.draw.rectangle((0,0, tw + 6, th + 6), fill=View.color)
View.draw.text((3, 3), arrow, fill="black", font=word_font)
else:
View.draw.rectangle((0,0, tw + 6, th + 6), fill="black")
View.draw.text((3, 3), arrow, fill=View.color, font=word_font)
return tw + 6
def render_text_entry_display(draw=View.draw):
""" Internal helper method to render the live text entry display at the top.
(has access to all vars in the parent's context)
"""
draw.rectangle((previous_button_width,0, View.canvas_width,text_entry_display_height), fill="black")
# Render the live text entry display
title = f"#{num_word}: {''.join(self.letters)}"
cursor_block_width = 18
cursor_block_height = 33
# Draw n-1 of the selected letters
word_font = View.ROBOTOCONDENSED_BOLD_26
tw, th = word_font.getsize(title[:-1])
word_offset = int(View.canvas_width - tw - cursor_block_width)/2
draw.text((word_offset, 2), title[:-1], fill=View.color, font=word_font)
# Draw the highlighted cursor block
cursor_block_offset = word_offset + tw - 1
draw.rectangle((cursor_block_offset,2, cursor_block_offset + cursor_block_width, cursor_block_height), fill="#111")
draw.text((cursor_block_offset + 1, 2), ''.join(self.letters[-1:]), fill=View.color, font=word_font)
# Clear the screen
View.draw.rectangle((0,0, View.canvas_width,View.canvas_height), fill="black")
previous_button_width = render_previous_button()
self.render_previous_button()
previous_button_is_active = False
arrow_up_is_active = False
arrow_down_is_active = False
@@ -261,8 +222,18 @@ class SeedToolsView(View):
rect=(0,text_entry_display_height + 1, keyboard_width,240),
auto_wrap=[Keyboard.WRAP_LEFT, Keyboard.WRAP_RIGHT])
# Initialize the current letters/current matches
# Render the top text entry display
self.letters = initial_letters
text_entry_display = TextEntryDisplay(
View.draw,
rect=(self.previous_button_width,0, View.canvas_width,text_entry_display_height),
font=View.ROBOTOCONDENSED_BOLD_26,
font_color=View.color,
cur_text="".join(self.letters)
)
text_entry_display.render()
# Initialize the current matches
self.possible_words = []
if len(self.letters) > 1:
self.letters.append(" ") # "Lock in" the last letter as if KEY_PRESS
@@ -274,9 +245,6 @@ class SeedToolsView(View):
keyboard.render_keys()
render_possible_matches()
# Render the top text entry display
render_text_entry_display()
View.DispShowImage()
# Start the interactive update loop
@@ -295,13 +263,13 @@ class SeedToolsView(View):
input = Keyboard.ENTER_BOTTOM
# Re-render it without the highlight
previous_button_is_active = False
render_previous_button()
self.render_previous_button()
elif input == B.KEY_DOWN:
input = Keyboard.ENTER_TOP
# Re-render it without the highlight
previous_button_is_active = False
render_previous_button()
self.render_previous_button()
elif input in [B.KEY_RIGHT, B.KEY_LEFT]:
# no action in this context
@@ -310,7 +278,7 @@ class SeedToolsView(View):
ret_val = keyboard.update_from_input(input)
if ret_val in Keyboard.EXIT_DIRECTIONS:
render_previous_button(highlight=True)
self.render_previous_button(highlight=True)
previous_button_is_active = True
elif ret_val in Keyboard.ADDITIONAL_KEYS:
@@ -378,7 +346,7 @@ class SeedToolsView(View):
# Animate the selection storage, then return the word to the caller
self.letters = list(final_selection + " ")
render_possible_matches(highlight_word=final_selection)
render_text_entry_display()
text_entry_display.render("".join(self.letters))
View.DispShowImage()
return final_selection
@@ -433,11 +401,48 @@ class SeedToolsView(View):
render_possible_matches()
# Render the text entry display and cursor block
render_text_entry_display()
text_entry_display.render("".join(self.letters))
View.DispShowImage()
def draw_passphrase_keyboard_entry(self):
# Clear the screen
View.draw.rectangle((0,0, View.canvas_width,View.canvas_height), fill="black")
self.render_previous_button()
previous_button_is_active = False
# Have to ensure that we don't carry any effects from a previous run
# TODO: This shouldn't be a member var
self.passphrase = " "
# Set up the keyboard params
right_key_nav_width = 50
keyboard_width = View.canvas_width - right_key_nav_width
text_entry_display_height = 39
keyboard = Keyboard(View.draw,
charset=list("1234567890").append(SeedToolsView.ALPHABET),
rows=4,
cols=10,
rect=(0,text_entry_display_height + 1, keyboard_width,240),
auto_wrap=[Keyboard.WRAP_LEFT, Keyboard.WRAP_RIGHT, Keyboard.WRAP_TOP, Keyboard.WRAP_BOTTOM])
# Render the top text entry display
text_entry_display = TextEntryDisplay(
View.draw,
rect=(self.previous_button_width,0, View.canvas_width,text_entry_display_height),
font=View.ROBOTOCONDENSED_BOLD_26,
font_color=View.color,
is_centered=False,
cur_text=''.join(self.passphrase)
)
text_entry_display.render()
View.DispShowImage()
def gather_words_up(self):
View.draw.polygon([(8 + ((len(self.letters)-1)*30), 85) , (14 + ((len(self.letters)-1)*30), 69) , (20 + ((len(self.letters)-1)*30), 85 )], outline=View.color, fill=View.color)
View.DispShowImage()
@@ -551,10 +556,10 @@ class SeedToolsView(View):
return
###
### Display Gather PassPhrase Screen
###
def display_gather_passphrase_screen(self, slot_num = 0) -> str:
self.reset()
self.pass_letter = "a"
+22
View File
@@ -64,6 +64,7 @@ class View:
bus = 0
device = 0
disp = None
previous_button_width = None
def __init__(self, controller) -> None:
@@ -259,3 +260,24 @@ class View:
def display_blank_screen(self):
View.draw.rectangle((0, 0, View.canvas_width, View.canvas_height), outline=0, fill=0)
View.DispShowImage()
###
### Reusable components
###
def render_previous_button(self, highlight=False):
# Set up the "back" arrow in the upper left
arrow = "<"
word_font = View.ROBOTOCONDENSED_BOLD_26
padding = 3
tw, th = word_font.getsize(arrow)
self.previous_button_width = tw + 2 * padding
if highlight:
View.draw.rectangle((0,0, tw + 2 * padding, th + 2 * padding), fill=View.color)
View.draw.text((padding, padding), arrow, fill="black", font=word_font)
else:
View.draw.rectangle((0,0, tw + 2 * padding, th + 2 * padding), fill="black")
View.draw.text((padding, padding), arrow, fill=View.color, font=word_font)
+19
View File
@@ -0,0 +1,19 @@
if __name__ == "__main__":
import qrcode
import sys
from embit import bip39
print(sys.argv)
seed_phrase = sys.argv[1:]
print(seed_phrase)
data = ""
for word in seed_phrase:
index = bip39.WORDLIST.index(word)
data += str("%04d" % index)
qr = qrcode.QRCode( version=1, error_correction=qrcode.constants.ERROR_CORRECT_L, box_size=5, border=3)
qr.add_data(data)
qr.make(fit=True)
qr.make_image(fill_color="black", back_color="white").resize((240,240)).convert('RGB').show()