Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DRAFT] Support 320x240 screen sizes and ili9341 displays #597

Draft
wants to merge 13 commits into
base: dev
Choose a base branch
from
50 changes: 39 additions & 11 deletions src/seedsigner/gui/renderer.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from PIL import Image, ImageDraw
from threading import Lock

from seedsigner.gui.components import Fonts, GUIConstants
from seedsigner.hardware.ST7789 import ST7789
# from seedsigner.hardware.st7789_mpy import ST7789
from seedsigner.hardware.displays.display_driver import ALL_DISPLAY_TYPES, DISPLAY_TYPE__ILI9341, DISPLAY_TYPE__ILI9486, DISPLAY_TYPE__ST7789, DisplayDriver
from seedsigner.hardware.displays.ili9341 import ILI9341, ILI9341_TFTWIDTH, ILI9341_TFTHEIGHT
from seedsigner.models.settings import Settings
from seedsigner.models.settings_definition import SettingsConstants
from seedsigner.models.singleton import ConfigurableSingleton


Expand All @@ -23,19 +26,44 @@ def configure_instance(cls):
renderer = cls.__new__(cls)
cls._instance = renderer

# Eventually we'll be able to plug in other display controllers
renderer.disp = ST7789()
renderer.canvas_width = renderer.disp.width
renderer.canvas_height = renderer.disp.height
renderer.initialize_display()

renderer.canvas = Image.new('RGB', (renderer.canvas_width, renderer.canvas_height))
renderer.draw = ImageDraw.Draw(renderer.canvas)

def initialize_display(self):
# May be called while already running with a previous display driver; must
# prevent any other screen writes while we're changing the display driver.
self.lock.acquire()

display_config = Settings.get_instance().get_value(SettingsConstants.SETTING__DISPLAY_CONFIGURATION, default_if_none=True)
self.display_type = display_config.split("_")[0]
if self.display_type not in ALL_DISPLAY_TYPES:
raise Exception(f"Invalid display type: {self.display_type}")

width, height = display_config.split("_")[1].split("x")
self.disp = DisplayDriver(self.display_type, width=int(width), height=int(height))

if Settings.get_instance().get_value(SettingsConstants.SETTING__DISPLAY_COLOR_INVERTED, default_if_none=True) == SettingsConstants.OPTION__ENABLED:
self.disp.invert()

if self.display_type == DISPLAY_TYPE__ST7789:
self.canvas_width = self.disp.width
self.canvas_height = self.disp.height

elif self.display_type in [DISPLAY_TYPE__ILI9341, DISPLAY_TYPE__ILI9486]:
# Swap for the natively portrait-oriented displays
self.canvas_width = self.disp.height
self.canvas_height = self.disp.width

self.canvas = Image.new('RGB', (self.canvas_width, self.canvas_height))
self.draw = ImageDraw.Draw(self.canvas)

self.lock.release()


def show_image(self, image=None, alpha_overlay=None, show_direct=False):
if show_direct:
# Use the incoming image as the canvas and immediately render
self.disp.ShowImage(image, 0, 0)
self.disp.show_image(image, 0, 0)
return

if alpha_overlay:
Expand All @@ -47,7 +75,7 @@ def show_image(self, image=None, alpha_overlay=None, show_direct=False):
# Always write to the current canvas, rather than trying to replace it
self.canvas.paste(image)

self.disp.ShowImage(self.canvas, 0, 0)
self.disp.show_image(self.canvas, 0, 0)


def show_image_pan(self, image, start_x, start_y, end_x, end_y, rate, alpha_overlay=None):
Expand Down Expand Up @@ -81,7 +109,7 @@ def show_image_pan(self, image, start_x, start_y, end_x, end_y, rate, alpha_over
# Always keep a copy of the current display in the canvas
self.canvas.paste(crop)

self.disp.ShowImage(crop, 0, 0)
self.disp.show_image(crop, 0, 0)



Expand Down
6 changes: 4 additions & 2 deletions src/seedsigner/gui/screens/screen.py
Original file line number Diff line number Diff line change
Expand Up @@ -522,9 +522,11 @@ def __post_init__(self):
if len(self.button_data) not in [2, 4]:
raise Exception("LargeButtonScreen only supports 2 or 4 buttons")

# Maximize 2-across width; calc height with a 4:3 aspect ratio
# Maximize 2-across width
button_width = int((self.canvas_width - (2 * GUIConstants.EDGE_PADDING) - GUIConstants.COMPONENT_PADDING) / 2)
button_height = int(button_width * (3.0 / 4.0))

# Maximize 2-row height
button_height = int((self.canvas_height - self.top_nav.height - (2 * GUIConstants.COMPONENT_PADDING) - GUIConstants.EDGE_PADDING) / 2)

# Vertically center the buttons
if len(self.button_data) == 2:
Expand Down
21 changes: 18 additions & 3 deletions src/seedsigner/gui/screens/seed_screens.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,17 @@ def __post_init__(self):

self.possible_alphabet = "abcdefghijklmnopqrstuvwxyz"

# Measure the width required to display the longest word in the English bip39
# wordlist.
# TODO: If we ever support other wordlist languages, adjust accordingly.
matches_list_highlight_font_name = GUIConstants.FIXED_WIDTH_EMPHASIS_FONT_NAME
matches_list_highlight_font_size = GUIConstants.BUTTON_FONT_SIZE + 4
(left, top, right, bottom) = Fonts.get_font(matches_list_highlight_font_name, matches_list_highlight_font_size).getbbox("mushroom", anchor="ls")
matches_list_max_text_width = right - left
matches_list_button_width = matches_list_max_text_width + 2*GUIConstants.COMPONENT_PADDING

# Set up the keyboard params
self.keyboard_width = 128
self.keyboard_width = self.canvas_width - GUIConstants.EDGE_PADDING - matches_list_button_width
text_entry_display_y = self.top_nav.height
text_entry_display_height = 30

Expand Down Expand Up @@ -77,7 +86,7 @@ def __post_init__(self):
else:
self.keyboard.set_selected_key(selected_letter=self.letters[-1])

self.matches_list_x = GUIConstants.EDGE_PADDING + self.keyboard.width + GUIConstants.COMPONENT_PADDING
self.matches_list_x = self.canvas_width - matches_list_button_width
self.matches_list_y = self.top_nav.height
self.highlighted_row_y = int((self.canvas_height - GUIConstants.BUTTON_HEIGHT)/2)

Expand Down Expand Up @@ -616,11 +625,17 @@ def __post_init__(self):
)
self.components.append(self.derivation_line)

font_name = GUIConstants.FIXED_WIDTH_FONT_NAME
font_size = GUIConstants.BODY_FONT_SIZE + 2
left, top, right, bottom = Fonts.get_font(font_name, font_size).getbbox("X")
char_width = right - left
num_chars = int((self.canvas_width - GUIConstants.ICON_FONT_SIZE - 2*GUIConstants.COMPONENT_PADDING) / char_width) - 3 # ellipsis

self.xpub_line = IconTextLine(
icon_name=FontAwesomeIconConstants.X,
icon_color=GUIConstants.INFO_COLOR,
label_text="Xpub",
value_text=f"{self.xpub[:18]}...",
value_text=f"{self.xpub[:num_chars]}...",
font_name=GUIConstants.FIXED_WIDTH_FONT_NAME,
font_size=GUIConstants.BODY_FONT_SIZE + 2,
screen_x=GUIConstants.COMPONENT_PADDING,
Expand Down
38 changes: 38 additions & 0 deletions src/seedsigner/gui/screens/tools_screens.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from dataclasses import dataclass
from typing import Any
from PIL.Image import Image
from seedsigner.gui.renderer import Renderer
from seedsigner.hardware.camera import Camera
from seedsigner.gui.components import FontAwesomeIconConstants, Fonts, GUIConstants, IconTextLine, SeedSignerIconConstants, TextArea

Expand Down Expand Up @@ -432,3 +433,40 @@ def __post_init__(self):
screen_x=GUIConstants.EDGE_PADDING,
screen_y=self.top_nav.height + GUIConstants.COMPONENT_PADDING,
))



@dataclass
class ToolsAddressExplorerAddressListScreen(ButtonListScreen):
start_index: int = 0
addresses: list[str] = None
next_button: tuple = None

def __post_init__(self):
self.button_font_name = GUIConstants.FIXED_WIDTH_EMPHASIS_FONT_NAME
self.button_font_size = GUIConstants.BUTTON_FONT_SIZE + 4
self.is_button_text_centered = False
self.is_bottom_list = True

left, top, right, bottom = Fonts.get_font(self.button_font_name, self.button_font_size).getbbox("X")
char_width = right - left

last_index = self.start_index + len(self.addresses) - 1
index_digits = len(str(last_index))

# Calculate how many pixels we have available within each address button,
# remembering to account for the index number that will be displayed.
# Note: because we haven't called the parent's post_init yet, we don't have a
# self.canvas_width set; have to use the Renderer singleton to get it.
available_width = Renderer.get_instance().canvas_width - 2*GUIConstants.EDGE_PADDING - 2*GUIConstants.COMPONENT_PADDING - (index_digits + 1)*char_width
displayable_chars = int(available_width / char_width) - 3 # ellipsis
displayable_half = int(displayable_chars/2)

self.button_data = []
for i, address in enumerate(self.addresses):
cur_index = i + self.start_index
self.button_data.append(f"{cur_index}:{address[:displayable_half]}...{address[-1*displayable_half:]}")

self.button_data.append(self.next_button)

super().__post_init__()
169 changes: 0 additions & 169 deletions src/seedsigner/hardware/ST7789.py

This file was deleted.

Empty file.
Loading
Loading