From 031d77a61535ff38a3bbb25e617e2378e07464ff Mon Sep 17 00:00:00 2001 From: Jake Walker Date: Wed, 5 Jun 2024 20:48:35 +0100 Subject: [PATCH 1/3] Initial improved keyboard --- modules/app_components/dialog.py | 165 +++++++++++++++++++++++++------ modules/app_components/tokens.py | 2 + 2 files changed, 136 insertions(+), 31 deletions(-) diff --git a/modules/app_components/dialog.py b/modules/app_components/dialog.py index ee465b7..564826f 100644 --- a/modules/app_components/dialog.py +++ b/modules/app_components/dialog.py @@ -4,7 +4,21 @@ from events.input import BUTTON_TYPES, ButtonDownEvent from system.eventbus import eventbus -from .tokens import label_font_size, set_color +from .tokens import label_font_size, set_color, small_font_size + +SPECIAL_KEY_META = "..." +SPECIAL_KEY_DONE = "Done" +SPECIAL_KEY_BACK = "Back" +SPECIAL_KEY_CANCEL = "Cancel" +SPECIAL_KEY_BACKSPACE = "Bksp" +SPECIAL_KEY_SYMBOL = "Sym" +SPECIAL_KEY_SHIFT = "Shift" +SPECIAL_KEY_CAPS = "Caps Lock" +SPECIAL_KEY_SPACE = "Space" + +LOWERCASE_ALPHABET = list("abcdefghijklmnopqrstuvwxyz") +UPPERCASE_ALPHABET = list("ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890") +SYMBOL_ALPHABET = list("-=!\"£$%^&*()_+[];'#,./{}:@~<>?") + [SPECIAL_KEY_SPACE] class YesNoDialog: @@ -69,8 +83,6 @@ def _handle_buttondown(self, event: ButtonDownEvent): class TextDialog: - alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890-=!\"£$%^&*()_+[];'#,./{}:@~<>?" - def __init__(self, message, app, masked=False, on_complete=None, on_cancel=None): self.open = True self.app = app @@ -79,9 +91,46 @@ def __init__(self, message, app, masked=False, on_complete=None, on_cancel=None) self.complete_handler = on_complete self.masked = masked self.text = "" - self.current = 0 + self._current_alphabet = LOWERCASE_ALPHABET + self._keys = [] + self._caps = False + self._layer = 0 self._result = None eventbus.on(ButtonDownEvent, self._handle_buttondown, self.app) + self._update_keys() + + + def _update_keys(self): + if self._layer == -1: + self._keys = [ + [SPECIAL_KEY_CANCEL], + [SPECIAL_KEY_SYMBOL], + [SPECIAL_KEY_SHIFT], + [SPECIAL_KEY_CAPS], + [SPECIAL_KEY_BACKSPACE], + [SPECIAL_KEY_BACK], + ] + return + + buttons = 4 if self._layer == 0 else 6 + group_size = len(self._current_alphabet) // buttons + + if group_size == 0: + group_size = 1 + + self._keys = [] + for i in range(buttons): + start_index = group_size * i + end_index = (group_size * i) + group_size + + if i + 1 == buttons: + end_index = len(self._current_alphabet) + + self._keys.append(self._current_alphabet[start_index:end_index]) + + if self._layer == 0: + self._keys.insert(4, [SPECIAL_KEY_META]) + self._keys.insert(2, [SPECIAL_KEY_DONE]) def _cleanup(self): eventbus.remove(ButtonDownEvent, self._handle_buttondown, self.app) @@ -106,12 +155,27 @@ def draw_message(self, ctx): set_color(ctx, "label") ctx.move_to(0, -15).text(self.message) - ctx.move_to(0, 15).text( - (self.text if not self.masked else ("*" * len(self.text))) - + "[" - + self.alphabet[self.current] - + "]" - ) + ctx.move_to(0, 15).text(self.text if not self.masked else ("*" * len(self.text))) + + def draw_legend(self, ctx): + if len(self._keys) != 6: + return + + set_color(ctx, "label") + + ctx.font_size = small_font_size + ctx.text_align = ctx.CENTER + ctx.text_baseline = ctx.MIDDLE + ctx.move_to(0, -100).text(''.join(self._keys[0])) + ctx.move_to(0, 100).text(''.join(self._keys[3])) + + ctx.text_align = ctx.RIGHT + ctx.move_to(75, -75).text(''.join(self._keys[1])) + ctx.move_to(75, 75).text(''.join(self._keys[2])) + + ctx.text_align = ctx.LEFT + ctx.move_to(-75, -75).text(''.join(self._keys[5])) + ctx.move_to(-75, 75).text(''.join(self._keys[4])) def draw(self, ctx): ctx.save() @@ -119,30 +183,69 @@ def draw(self, ctx): display.hexagon(ctx, 0, 0, 120) self.draw_message(ctx) + self.draw_legend(ctx) ctx.restore() def _handle_buttondown(self, event: ButtonDownEvent): - if BUTTON_TYPES["CANCEL"] in event.button: - self._cleanup() - self._result = False - if self.cancel_handler is not None: - self.cancel_handler() - - if BUTTON_TYPES["CONFIRM"] in event.button: - self._cleanup() - self._result = self.text - if self.complete_handler is not None: - self.complete_handler() + key = -1 if BUTTON_TYPES["UP"] in event.button: - self.current = (self.current - 1) % len(self.alphabet) - - if BUTTON_TYPES["DOWN"] in event.button: - self.current = (self.current + 1) % len(self.alphabet) - - if BUTTON_TYPES["RIGHT"] in event.button: - self.text += self.alphabet[self.current] - - if BUTTON_TYPES["LEFT"] in event.button: - if len(self.text) > 0: + key = 0 + elif BUTTON_TYPES["RIGHT"] in event.button: + key = 1 + elif BUTTON_TYPES["DOWN"] in event.button: + key = 3 + elif BUTTON_TYPES["LEFT"] in event.button: + key = 4 + elif BUTTON_TYPES["CANCEL"] in event.button: + key = 5 + elif BUTTON_TYPES["CONFIRM"] in event.button: + key = 2 + + if key == -1: + return + + selected = self._keys[key] + if len(selected) == 1: + selected = self._keys[key][0] + + if selected == SPECIAL_KEY_SPACE: + selected = " " + + if selected == SPECIAL_KEY_DONE: + self._cleanup() + self._result = self.text + if self.complete_handler is not None: + self.complete_handler() + elif selected == SPECIAL_KEY_CANCEL: + self._cleanup() + self._result = False + if self.cancel_handler is not None: + self.cancel_handler() + elif selected == SPECIAL_KEY_BACKSPACE: self.text = self.text[:-1] + elif selected == SPECIAL_KEY_BACK: + self._layer = 0 + elif selected == SPECIAL_KEY_META: + self._layer = -1 + elif selected == SPECIAL_KEY_SYMBOL: + self._layer = 0 + self._current_alphabet = SYMBOL_ALPHABET + elif selected == SPECIAL_KEY_SHIFT or selected == SPECIAL_KEY_CAPS: + self._layer = 0 + self._current_alphabet = UPPERCASE_ALPHABET + if selected == SPECIAL_KEY_CAPS: + self._caps = True + else: + self.text += selected + self._layer = 0 + + if self._caps: + self._current_alphabet = UPPERCASE_ALPHABET + else: + self._current_alphabet = LOWERCASE_ALPHABET + elif len(selected) > 0: + self._current_alphabet = selected + self._layer = 1 + + self._update_keys() diff --git a/modules/app_components/tokens.py b/modules/app_components/tokens.py index df440a8..976728f 100644 --- a/modules/app_components/tokens.py +++ b/modules/app_components/tokens.py @@ -8,12 +8,14 @@ # Font size one_pt = ppi / 72 +seven_pt = 7 * one_pt ten_pt = 10 * one_pt twelve_pt = 12 * one_pt fourteen_pt = 14 * one_pt sixteen_pt = 16 * one_pt eighteen_pt = 18 * one_pt twentyfour_pt = 24 * one_pt +small_font_size = seven_pt label_font_size = ten_pt heading_font_size = eighteen_pt From 43033dbd9582f19d968afbdfcb19777c7fba1000 Mon Sep 17 00:00:00 2001 From: Jake Walker Date: Wed, 5 Jun 2024 20:58:36 +0100 Subject: [PATCH 2/3] Move button labels method to tokens --- modules/app_components/dialog.py | 32 +++++++++++--------------------- modules/app_components/tokens.py | 24 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/modules/app_components/dialog.py b/modules/app_components/dialog.py index 564826f..938bf1f 100644 --- a/modules/app_components/dialog.py +++ b/modules/app_components/dialog.py @@ -4,7 +4,7 @@ from events.input import BUTTON_TYPES, ButtonDownEvent from system.eventbus import eventbus -from .tokens import label_font_size, set_color, small_font_size +from .tokens import label_font_size, set_color, small_font_size, button_labels SPECIAL_KEY_META = "..." SPECIAL_KEY_DONE = "Done" @@ -66,6 +66,7 @@ def draw(self, ctx): display.hexagon(ctx, 0, 0, 120) self.draw_message(ctx) + button_labels(ctx, confirm_label="Yes", cancel_label="No") ctx.restore() def _handle_buttondown(self, event: ButtonDownEvent): @@ -157,25 +158,6 @@ def draw_message(self, ctx): ctx.move_to(0, -15).text(self.message) ctx.move_to(0, 15).text(self.text if not self.masked else ("*" * len(self.text))) - def draw_legend(self, ctx): - if len(self._keys) != 6: - return - - set_color(ctx, "label") - - ctx.font_size = small_font_size - ctx.text_align = ctx.CENTER - ctx.text_baseline = ctx.MIDDLE - ctx.move_to(0, -100).text(''.join(self._keys[0])) - ctx.move_to(0, 100).text(''.join(self._keys[3])) - - ctx.text_align = ctx.RIGHT - ctx.move_to(75, -75).text(''.join(self._keys[1])) - ctx.move_to(75, 75).text(''.join(self._keys[2])) - - ctx.text_align = ctx.LEFT - ctx.move_to(-75, -75).text(''.join(self._keys[5])) - ctx.move_to(-75, 75).text(''.join(self._keys[4])) def draw(self, ctx): ctx.save() @@ -183,7 +165,15 @@ def draw(self, ctx): display.hexagon(ctx, 0, 0, 120) self.draw_message(ctx) - self.draw_legend(ctx) + if len(self._keys) == 6: + button_labels(ctx, + up_label=''.join(self._keys[0]), + down_label=''.join(self._keys[3]), + left_label=''.join(self._keys[4]), + right_label=''.join(self._keys[1]), + confirm_label=''.join(self._keys[2]), + cancel_label=''.join(self._keys[5])) + ctx.restore() def _handle_buttondown(self, event: ButtonDownEvent): diff --git a/modules/app_components/tokens.py b/modules/app_components/tokens.py index 976728f..1254eeb 100644 --- a/modules/app_components/tokens.py +++ b/modules/app_components/tokens.py @@ -54,3 +54,27 @@ def clear_background(ctx): def set_color(ctx, color): ctx.rgb(*ui_colors.get(color, colors.get(color, color))) + + +def button_labels(ctx, up_label=None, down_label=None, left_label=None, right_label=None, cancel_label=None, confirm_label=None): + set_color(ctx, "label") + + ctx.font_size = small_font_size + ctx.text_align = ctx.CENTER + ctx.text_baseline = ctx.MIDDLE + if up_label is not None: + ctx.move_to(0, -100).text(up_label) + if down_label is not None: + ctx.move_to(0, 100).text(down_label) + + ctx.text_align = ctx.RIGHT + if right_label is not None: + ctx.move_to(75, -75).text(right_label) + if confirm_label is not None: + ctx.move_to(75, 75).text(confirm_label) + + ctx.text_align = ctx.LEFT + if cancel_label is not None: + ctx.move_to(-75, -75).text(cancel_label) + if left_label is not None: + ctx.move_to(-75, 75).text(left_label) From ffc0915ad304f43b474ad8725f176be8e5d59ed3 Mon Sep 17 00:00:00 2001 From: Jake Walker Date: Thu, 6 Jun 2024 17:56:09 +0100 Subject: [PATCH 3/3] Format code --- modules/app_components/dialog.py | 24 +++++++++++++----------- modules/app_components/tokens.py | 10 +++++++++- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/modules/app_components/dialog.py b/modules/app_components/dialog.py index 938bf1f..c30f48b 100644 --- a/modules/app_components/dialog.py +++ b/modules/app_components/dialog.py @@ -4,7 +4,7 @@ from events.input import BUTTON_TYPES, ButtonDownEvent from system.eventbus import eventbus -from .tokens import label_font_size, set_color, small_font_size, button_labels +from .tokens import button_labels, label_font_size, set_color SPECIAL_KEY_META = "..." SPECIAL_KEY_DONE = "Done" @@ -100,7 +100,6 @@ def __init__(self, message, app, masked=False, on_complete=None, on_cancel=None) eventbus.on(ButtonDownEvent, self._handle_buttondown, self.app) self._update_keys() - def _update_keys(self): if self._layer == -1: self._keys = [ @@ -156,8 +155,9 @@ def draw_message(self, ctx): set_color(ctx, "label") ctx.move_to(0, -15).text(self.message) - ctx.move_to(0, 15).text(self.text if not self.masked else ("*" * len(self.text))) - + ctx.move_to(0, 15).text( + self.text if not self.masked else ("*" * len(self.text)) + ) def draw(self, ctx): ctx.save() @@ -166,13 +166,15 @@ def draw(self, ctx): self.draw_message(ctx) if len(self._keys) == 6: - button_labels(ctx, - up_label=''.join(self._keys[0]), - down_label=''.join(self._keys[3]), - left_label=''.join(self._keys[4]), - right_label=''.join(self._keys[1]), - confirm_label=''.join(self._keys[2]), - cancel_label=''.join(self._keys[5])) + button_labels( + ctx, + up_label="".join(self._keys[0]), + down_label="".join(self._keys[3]), + left_label="".join(self._keys[4]), + right_label="".join(self._keys[1]), + confirm_label="".join(self._keys[2]), + cancel_label="".join(self._keys[5]), + ) ctx.restore() diff --git a/modules/app_components/tokens.py b/modules/app_components/tokens.py index 1254eeb..29c8f7b 100644 --- a/modules/app_components/tokens.py +++ b/modules/app_components/tokens.py @@ -56,7 +56,15 @@ def set_color(ctx, color): ctx.rgb(*ui_colors.get(color, colors.get(color, color))) -def button_labels(ctx, up_label=None, down_label=None, left_label=None, right_label=None, cancel_label=None, confirm_label=None): +def button_labels( + ctx, + up_label=None, + down_label=None, + left_label=None, + right_label=None, + cancel_label=None, + confirm_label=None, +): set_color(ctx, "label") ctx.font_size = small_font_size