From 4d644a0b136540892f69a7a9727c17eca492d0ce Mon Sep 17 00:00:00 2001 From: Matthew Wilkes Date: Sat, 1 Jun 2024 14:57:51 +0100 Subject: [PATCH] Update settings editor Some bugfixes and adds toggling of some major settings --- modules/app_components/dialog.py | 2 +- modules/app_components/layout.py | 22 +++- modules/firmware_apps/settings_app.py | 164 ++++++++++++++++++++------ 3 files changed, 143 insertions(+), 45 deletions(-) diff --git a/modules/app_components/dialog.py b/modules/app_components/dialog.py index 0a85fcf..ee465b7 100644 --- a/modules/app_components/dialog.py +++ b/modules/app_components/dialog.py @@ -69,7 +69,7 @@ def _handle_buttondown(self, event: ButtonDownEvent): class TextDialog: - alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890-=!\"£$%^&*()_+[];'#,./{}:@~<>?" def __init__(self, message, app, masked=False, on_complete=None, on_cancel=None): self.open = True diff --git a/modules/app_components/layout.py b/modules/app_components/layout.py index 5fab83c..45f1ef1 100644 --- a/modules/app_components/layout.py +++ b/modules/app_components/layout.py @@ -42,15 +42,16 @@ def draw(self, ctx, focused=False): class ButtonDisplay(Layoutable): - def __init__(self, text, font_size=None, rgb=None): + def __init__(self, text, font_size=None, rgb=None, button_handler=None): self.text = text - self.height = 40 + self.height = 60 + self.button_handler = button_handler def draw(self, ctx, focused=False): ctx.save() # Draw button - ctx.translate(30, 5) + ctx.translate(30, 0) ctx.scale(0.75, 0.75) if focused: bg = tokens.ui_colors["active_button_background"] @@ -69,12 +70,23 @@ def draw(self, ctx, focused=False): ctx.restore() + async def button_event(self, event): + if self.button_handler: + return await self.button_handler(event) + return False + class DefinitionDisplay(Layoutable): - def __init__(self, label, value): + def __init__(self, label, value, button_handler=None): self.label = label self.value = value self.height = 0 + self.button_handler = button_handler + + async def button_event(self, event): + if self.button_handler: + return await self.button_handler(event) + return False def draw(self, ctx, focused=False): ctx.save() @@ -145,7 +157,7 @@ def centred_component(self): cumulative_height += item.height * self.scale_factor if round(cumulative_height) > round(120 - self.y_offset): return item - return item + return self.items[0] async def button_event(self, event) -> bool: focused = self.centred_component() diff --git a/modules/firmware_apps/settings_app.py b/modules/firmware_apps/settings_app.py index adda82b..0a258b4 100644 --- a/modules/firmware_apps/settings_app.py +++ b/modules/firmware_apps/settings_app.py @@ -1,9 +1,8 @@ import settings import app -from app_components import layout, tokens, TextDialog, YesNoDialog +from app_components import layout, tokens, TextDialog from events.input import BUTTON_TYPES, ButtonDownEvent from system.eventbus import eventbus -from system.scheduler.events import RequestForegroundPushEvent def string_formatter(value): @@ -12,25 +11,35 @@ def string_formatter(value): else: return str(value) -async def string_editor(self, label, id, render_update): - dialog = TextDialog(label, self) - dialog._settings_id = id - self.overlays = [dialog] + +def pct_formatter(value): + if value is None: + return "Default" + else: + return f"{value:.0%}" + def reset_wifi_settings(): print("RESET WIFI") - for s in ["wifi_ssid","wifi_password", "wifi_wpa2ent_username"]: + for s in ["wifi_ssid", "wifi_password", "wifi_wpa2ent_username"]: settings.set(s, None) +PATTERNS = ["rainbow", "cylon", "flash", "off"] +BRIGHTNESSES = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0] + + class SettingsApp(app.App): def __init__(self): - self.layout = layout.LinearLayout(items=[]) + self.layout = layout.LinearLayout(items=[layout.DefinitionDisplay("", "")]) self.overlays = [] + self.dialog = None eventbus.on_async(ButtonDownEvent, self._button_handler, self) - #eventbus.on(RequestForegroundPushEvent, self.make_layout_children, self) - + # eventbus.on(RequestForegroundPushEvent, self.make_layout_children, self) + async def string_editor(self, label, id, render_update): + self.dialog = TextDialog(label, self) + self.dialog._settings_id = id async def _button_handler(self, event): if not self.overlays: @@ -39,59 +48,133 @@ async def _button_handler(self, event): if BUTTON_TYPES["CANCEL"] in event.button: settings.save() self.minimise() + else: + return True + + async def update_values(self): + for item in self.layout.items: + if isinstance(item, layout.DefinitionDisplay): + for id, label, formatter, editor in self.settings_options(): + if item.label == label: + value = settings.get(id) + item.value = formatter(value) async def run(self, render_update): while True: self.layout.items = [] for id, label, formatter, editor in self.settings_options(): value = settings.get(id) - entry = layout.DefinitionDisplay(label, formatter(value)) + print(editor) if editor: - async def _button_event(event, self=self, id=id, label=label, editor=editor): + + async def _button_event(event, label=label, id=id, editor=editor): if BUTTON_TYPES["CONFIRM"] in event.button: - await editor(self, label, id, render_update) + print(f"Event: {id} - {editor}") + await editor(label, id, render_update) return True return False - entry.button_event =_button_event + + entry = layout.DefinitionDisplay( + label, formatter(value), button_handler=_button_event + ) + else: + entry = layout.DefinitionDisplay(label, formatter(value)) self.layout.items.append(entry) - entry = layout.DefinitionDisplay("WLAN EMF defaults", "reset") - async def _button_event_w(event, self=self): - if BUTTON_TYPES["CONFIRM"] in event.button: - dialog = YesNoDialog("Reset WLAN settings", self) - dialog._settings_id = "WIFI_MAGIC" - self.overlays = [dialog] + if id == "pattern": + + async def _button_event_pattern_toggle(event): + print(event) + if BUTTON_TYPES["CONFIRM"] in event.button: + pattern = settings.get("pattern") + if not pattern: + pattern = "rainbow" + idx = PATTERNS.index(pattern) + 1 + if idx >= len(PATTERNS): + idx = 0 + print(f"{PATTERNS} {idx}") + settings.set("pattern", PATTERNS[idx]) + await self.update_values() + await render_update() + return True + return False + + entry = layout.ButtonDisplay( + "Next pattern", button_handler=_button_event_pattern_toggle + ) + self.layout.items.append(entry) + + if id == "pattern_brightness": + + async def _button_event_pattern_toggle(event): + print(event) + if BUTTON_TYPES["CONFIRM"] in event.button: + bright = settings.get("pattern_brightness") + if not bright: + bright = 0.1 + idx = BRIGHTNESSES.index(bright) + 1 + if idx >= len(BRIGHTNESSES): + idx = 0 + print(f"{BRIGHTNESSES} {idx}") + settings.set("pattern_brightness", BRIGHTNESSES[idx]) + await self.update_values() + await render_update() + return True + return False + + entry = layout.ButtonDisplay( + "Toggle", button_handler=_button_event_pattern_toggle + ) + self.layout.items.append(entry) + async def _button_event_w(event): + print(event) + if BUTTON_TYPES["CONFIRM"] in event.button: + print("wifi") + reset_wifi_settings() + print("update") + await self.update_values() + print("render") + await render_update() return True return False - entry.button_event =_button_event_w + + entry = layout.ButtonDisplay("Reset WiFi", button_handler=_button_event_w) self.layout.items.append(entry) while True: await render_update() - if self.overlays: - dialog = self.overlays[0] - result = await dialog.run(render_update) - if result != False: #!= because we want to allow entering empty strings - if dialog._settings_id == "WIFI_MAGIC": - reset_wifi_settings() - else: - settings.set(dialog._settings_id, result) - self.overlays = [] - dialog = None - if result: - break - + if self.dialog: + result = await self.dialog.run(render_update) + if ( + result is not False + ): #!= because we want to allow entering empty strings + settings.set(self.dialog._settings_id, result) + self.dialog = None + if result: + break def settings_options(self): return [ - ("name", "Name", string_formatter, string_editor), + ("name", "Name", string_formatter, self.string_editor), ("pattern", "LED Pattern", string_formatter, None), + ("pattern_brightness", "Pattern brightness", pct_formatter, None), + ("pattern_mirror_hexpansions", "Mirror pattern", string_formatter, None), ("wifi_tx_power", "WiFi TX power", string_formatter, None), - ("wifi_connection_timeout", "WiFi connection timeout", string_formatter, None), - ("wifi_ssid", "WiFi SSID", string_formatter, string_editor), - ("wifi_password", "WiFi password", string_formatter, string_editor), - ("wifi_wpa2ent_username", "WPA2 Enterprise Username", string_formatter, string_editor), + ( + "wifi_connection_timeout", + "WiFi connection timeout", + string_formatter, + None, + ), + ("wifi_ssid", "WiFi SSID", string_formatter, self.string_editor), + ("wifi_password", "WiFi password", string_formatter, self.string_editor), + ( + "wifi_wpa2ent_username", + "WPA2 Enterprise Username", + string_formatter, + self.string_editor, + ), ] def update(self, delta): @@ -101,3 +184,6 @@ def draw(self, ctx): tokens.clear_background(ctx) self.layout.draw(ctx) self.draw_overlays(ctx) + + +__app_export__ = SettingsApp