From b5e8bf43fcfc75f33cbac53770f4e3fe465b809a Mon Sep 17 00:00:00 2001 From: nick Date: Wed, 3 Jun 2026 02:48:30 -0600 Subject: [PATCH] Add Pico touch routing abstraction --- pico-dashboard/hardware/touch.py | 21 ++++++++++++ pico-dashboard/ui/touch_router.py | 38 ++++++++++++++++++++++ tests/test_pico_core.py | 54 +++++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+) create mode 100644 pico-dashboard/ui/touch_router.py diff --git a/pico-dashboard/hardware/touch.py b/pico-dashboard/hardware/touch.py index e69de29..3fe3095 100644 --- a/pico-dashboard/hardware/touch.py +++ b/pico-dashboard/hardware/touch.py @@ -0,0 +1,21 @@ +class TouchEvent: + def __init__(self, x, y, pressed=True): + self.x = x + self.y = y + self.pressed = pressed + + +class TouchController: + def __init__(self, touch_device=None): + self.touch_device = touch_device + + def read_event(self): + if not self.touch_device: + return None + + point = self.touch_device.read() + + if not point: + return None + + return TouchEvent(point["x"], point["y"], point.get("pressed", True)) diff --git a/pico-dashboard/ui/touch_router.py b/pico-dashboard/ui/touch_router.py new file mode 100644 index 0000000..928576e --- /dev/null +++ b/pico-dashboard/ui/touch_router.py @@ -0,0 +1,38 @@ +NAV_ITEMS = [ + ("dashboard", 0, 64), + ("battery", 64, 128), + ("temps", 128, 192), + ("power", 192, 256), + ("system", 256, 320), +] + + +class TouchRouter: + def __init__(self, screen_manager, width=320, height=480, nav_height=56): + self.screen_manager = screen_manager + self.width = width + self.height = height + self.nav_height = nav_height + + def handle_touch(self, event): + if not event or not event.pressed: + return False + + if self._is_bottom_nav(event.y): + screen = self._screen_for_nav_x(event.x) + + if screen: + self.screen_manager.go_to(screen) + return True + + return False + + def _is_bottom_nav(self, y): + return y >= self.height - self.nav_height + + def _screen_for_nav_x(self, x): + for screen, start_x, end_x in NAV_ITEMS: + if start_x <= x < end_x: + return screen + + return None diff --git a/tests/test_pico_core.py b/tests/test_pico_core.py index 26b1ea4..fe96543 100644 --- a/tests/test_pico_core.py +++ b/tests/test_pico_core.py @@ -668,3 +668,57 @@ def test_buzzer_updates_from_alarm_view(): assert buzzer.enabled is False assert buzzer.pattern is None + + +def test_touch_controller_reads_event(): + from hardware.touch import TouchController + + class FakeTouchDevice: + def read(self): + return {"x": 100, "y": 200, "pressed": True} + + controller = TouchController(FakeTouchDevice()) + event = controller.read_event() + + assert event.x == 100 + assert event.y == 200 + assert event.pressed is True + + +def test_touch_router_bottom_nav_changes_screen(): + from hardware.touch import TouchEvent + from ui.touch_router import TouchRouter + + screens = ScreenManager() + router = TouchRouter(screens) + + handled = router.handle_touch(TouchEvent(200, 460, True)) + + assert handled is True + assert screens.current_screen == "power" + + +def test_touch_router_ignores_non_nav_touch(): + from hardware.touch import TouchEvent + from ui.touch_router import TouchRouter + + screens = ScreenManager() + router = TouchRouter(screens) + + handled = router.handle_touch(TouchEvent(200, 200, True)) + + assert handled is False + assert screens.current_screen == "dashboard" + + +def test_touch_router_ignores_unpressed_event(): + from hardware.touch import TouchEvent + from ui.touch_router import TouchRouter + + screens = ScreenManager() + router = TouchRouter(screens) + + handled = router.handle_touch(TouchEvent(200, 460, False)) + + assert handled is False + assert screens.current_screen == "dashboard"