From 0698326412d075c7123ba25d9453826dc7e4078e Mon Sep 17 00:00:00 2001
From: ave <flow3r@ave.zone>
Date: Sun, 19 Nov 2023 19:52:08 +0000
Subject: [PATCH] Split sunmenu into its own file

---
 python_payload/st3m/run.py                  |  97 ++--------
 python_payload/st3m/ui/elements/menus.py    |  59 +-----
 python_payload/st3m/ui/elements/sun_menu.py | 188 ++++++++++++++++++++
 3 files changed, 205 insertions(+), 139 deletions(-)
 create mode 100644 python_payload/st3m/ui/elements/sun_menu.py

diff --git a/python_payload/st3m/run.py b/python_payload/st3m/run.py
index 149847203a..420789c5c8 100644
--- a/python_payload/st3m/run.py
+++ b/python_payload/st3m/run.py
@@ -10,7 +10,8 @@ from st3m.ui.menu import (
 )
 from st3m.ui.elements import overlays
 from st3m.ui.view import View, ViewManager, ViewTransitionBlend, ViewTransitionDirection
-from st3m.ui.elements.menus import SimpleMenu, SunMenu
+from st3m.ui.elements.menus import SimpleMenu
+from st3m.ui.elements.sun_menu import SunMenu
 from st3m.application import (
     BundleManager,
     BundleMetadata,
@@ -24,7 +25,14 @@ from st3m.ui import led_patterns
 import st3m.wifi
 import st3m.utils
 
-import captouch, audio, leds, gc, sys_buttons, sys_display, sys_mode, media, bl00mbox
+import captouch
+import audio
+import leds
+import gc
+import sys_buttons
+import sys_display
+import sys_mode
+import bl00mbox
 import os
 
 import machine
@@ -63,55 +71,6 @@ def run_responder(r: Responder) -> None:
     reactor.run()
 
 
-class ApplicationMenu(SimpleMenu):
-    def _restore_sys_defaults(self) -> None:
-        if (
-            not self.vm
-            or not self.is_active()
-            or self.vm.direction != ViewTransitionDirection.BACKWARD
-        ):
-            return
-        # fall back to system defaults on app exit
-        st3m.wifi._onoff_wifi_update()
-        # set the default graphics mode, this is a no-op if
-        # it is already set
-        sys_display.set_mode(0)
-        sys_display.fbconfig(240, 240, 0, 0)
-        leds.set_slew_rate(100)
-        leds.set_gamma(1.0, 1.0, 1.0)
-        leds.set_auto_update(False)
-        leds.set_brightness(settings.num_leds_brightness.value)
-        sys_display.set_backlight(settings.num_display_brightness.value)
-        led_patterns.set_menu_colors()
-        # media.stop()
-
-    def on_enter(self, vm: Optional[ViewManager]) -> None:
-        super().on_enter(vm)
-        self._restore_sys_defaults()
-
-    def on_enter_done(self):
-        # set the defaults again in case the app continued
-        # doing stuff during the transition
-        self._restore_sys_defaults()
-        leds.update()
-
-
-def _get_bundle_menu_kinds(mgr: BundleManager) -> Set[str]:
-    kinds: Set[str] = set()
-    for bundle in mgr.bundles.values():
-        kinds.update(bundle.menu_kinds())
-    return kinds
-
-
-def _get_bundle_menu_entries(mgr: BundleManager, kind: str) -> List[MenuItem]:
-    entries: List[MenuItem] = []
-    ids = sorted(mgr.bundles.keys(), key=str.lower)
-    for id in ids:
-        bundle = mgr.bundles[id]
-        entries += bundle.menu_entries(kind)
-    return entries
-
-
 def _make_compositor(reactor: Reactor, vm: ViewManager) -> overlays.Compositor:
     """
     Set up top-level compositor (for combining viewmanager with overlays).
@@ -223,8 +182,6 @@ def run_main() -> None:
 
     leds.set_rgb(0, 255, 0, 0)
     leds.update()
-    bundles = BundleManager()
-    bundles.update()
 
     led_patterns.set_menu_colors()
     leds.set_slew_rate(20)
@@ -241,34 +198,8 @@ def run_main() -> None:
         bl00mbox.Channel(i).clear()
         bl00mbox.Channel(i).free = True
 
-    menu_settings = settings.build_menu()
-    menu_system = ApplicationMenu(
-        [
-            MenuItemBack(),
-            MenuItemLaunchPersistentView("About", About),
-            MenuItemForeground("Settings", menu_settings),
-            MenuItemAppLaunch(BundleMetadata("/flash/sys/apps/gr33nhouse")),
-            MenuItemAppLaunch(BundleMetadata("/flash/sys/apps/updat3r")),
-            MenuItemAction("Disk Mode (Flash)", machine.disk_mode_flash),
-            MenuItemAction("Disk Mode (SD)", machine.disk_mode_sd),
-            MenuItemAction("Yeet Local Changes", _yeet_local_changes),
-            MenuItemAction("Reboot", machine.reset),
-        ],
-    )
-
-    app_kinds = _get_bundle_menu_kinds(bundles)
-    menu_categories = ["Badge", "Music", "Media", "Apps", "Games"]
-    for kind in app_kinds:
-        if kind not in ["Hidden", "System"] and kind not in menu_categories:
-            menu_categories.append(kind)
-
-    categories = [
-        MenuItemForeground(kind, ApplicationMenu([MenuItemBack()] + entries))
-        for kind in menu_categories
-        if (entries := _get_bundle_menu_entries(bundles, kind))
-    ]
-    categories.append(MenuItemForeground("System", menu_system))
-    menu_main = SunMenu(categories)
+    bundles = BundleManager()
+    bundles.update()
 
     if override_main_app is not None:
         requested = [b for b in bundles.bundles.values() if b.name == override_main_app]
@@ -277,7 +208,9 @@ def run_main() -> None:
         if len(requested) == 0:
             raise Exception(f"Requested bundle {override_main_app} not found")
         run_view(requested[0].load(), debug_vm=True)
-    run_view(menu_main, debug_vm=False)
+    else:
+        menu_main = SunMenu(bundles)
+        run_view(menu_main, debug_vm=False)
 
 
 __all__ = [
diff --git a/python_payload/st3m/ui/elements/menus.py b/python_payload/st3m/ui/elements/menus.py
index 667b97df99..898494ba82 100644
--- a/python_payload/st3m/ui/elements/menus.py
+++ b/python_payload/st3m/ui/elements/menus.py
@@ -1,6 +1,5 @@
-from st3m.goose import Optional, List, ABCBase, abstractmethod
-from st3m.ui.view import ViewManager
-from st3m.ui.elements.visuals import Sun, GroupRing, FlowerIcon
+from st3m.goose import List
+from st3m.ui.elements.visuals import GroupRing, FlowerIcon
 from st3m.ui.menu import MenuController, MenuItem
 
 from st3m import InputState
@@ -44,60 +43,6 @@ class SimpleMenu(MenuController):
             ctx.restore()
 
 
-class SunMenu(MenuController):
-    """
-    A circular menu with a rotating sun.
-    """
-
-    __slots__ = (
-        "_ts",
-        "_sun",
-    )
-
-    def __init__(self, items: List[MenuItem]) -> None:
-        self._ts = 0
-        self._sun = Sun()
-        super().__init__(items)
-
-    def think(self, ins: InputState, delta_ms: int) -> None:
-        super().think(ins, delta_ms)
-        self._sun.think(ins, delta_ms)
-        self._ts += delta_ms
-
-    def _draw_item_angled(
-        self, ctx: Context, item: MenuItem, angle: float, activity: float
-    ) -> None:
-        size = lerp(20, 40, activity)
-        color = lerp(0, 1, activity)
-        if color < 0.01:
-            return
-
-        ctx.save()
-        ctx.translate(-120, 0).rotate(angle).translate(140, 0)
-        ctx.font_size = size
-        ctx.rgba(1.0, 1.0, 1.0, color).move_to(0, 0)
-        item.draw(ctx)
-        ctx.restore()
-
-    def draw(self, ctx: Context) -> None:
-        ctx.gray(0)
-        ctx.rectangle(-120, -120, 240, 240).fill()
-
-        self._sun.draw(ctx)
-
-        ctx.font_size = 40
-        ctx.text_align = ctx.CENTER
-        ctx.text_baseline = ctx.MIDDLE
-
-        angle_per_item = 0.4
-
-        current = self._scroll_controller.current_position()
-
-        for ix, item in enumerate(self._items):
-            rot = (ix - current) * angle_per_item
-            self._draw_item_angled(ctx, item, rot, 1 - abs(rot))
-
-
 class FlowerMenu(MenuController):
     """
     A circular menu with flowers.
diff --git a/python_payload/st3m/ui/elements/sun_menu.py b/python_payload/st3m/ui/elements/sun_menu.py
new file mode 100644
index 0000000000..3110f05c4f
--- /dev/null
+++ b/python_payload/st3m/ui/elements/sun_menu.py
@@ -0,0 +1,188 @@
+import os
+import machine
+
+import sys_display
+import leds
+from ctx import Context
+
+from st3m.goose import Optional, List, Set
+from st3m.ui.view import ViewManager, ViewTransitionDirection
+from st3m.ui.elements.visuals import Sun
+from st3m import InputState
+from st3m import settings_menu as settings
+from st3m.utils import lerp
+import st3m.wifi
+from st3m.ui import led_patterns
+from st3m.ui.menu import (
+    MenuController,
+    MenuItem,
+    MenuItemBack,
+    MenuItemForeground,
+    MenuItemAction,
+    MenuItemLaunchPersistentView,
+)
+from st3m.application import (
+    BundleManager,
+    BundleMetadata,
+    MenuItemAppLaunch,
+)
+from st3m.about import About
+from st3m.ui.elements.menus import SimpleMenu
+
+
+class ApplicationMenu(SimpleMenu):
+    def _restore_sys_defaults(self) -> None:
+        if (
+            not self.vm
+            or not self.is_active()
+            or self.vm.direction != ViewTransitionDirection.BACKWARD
+        ):
+            return
+        # fall back to system defaults on app exit
+        st3m.wifi._onoff_wifi_update()
+        # set the default graphics mode, this is a no-op if
+        # it is already set
+        sys_display.set_mode(0)
+        sys_display.fbconfig(240, 240, 0, 0)
+        leds.set_slew_rate(100)
+        leds.set_gamma(1.0, 1.0, 1.0)
+        leds.set_auto_update(False)
+        leds.set_brightness(settings.num_leds_brightness.value)
+        sys_display.set_backlight(settings.num_display_brightness.value)
+        led_patterns.set_menu_colors()
+        # media.stop()
+
+    def on_enter(self, vm: Optional[ViewManager]) -> None:
+        super().on_enter(vm)
+        self._restore_sys_defaults()
+
+    def on_enter_done(self):
+        # set the defaults again in case the app continued
+        # doing stuff during the transition
+        self._restore_sys_defaults()
+        leds.update()
+
+
+def _get_bundle_menu_kinds(mgr: BundleManager) -> Set[str]:
+    kinds: Set[str] = set()
+    for bundle in mgr.bundles.values():
+        kinds.update(bundle.menu_kinds())
+    return kinds
+
+
+def _get_bundle_menu_entries(mgr: BundleManager, kind: str) -> List[MenuItem]:
+    entries: List[MenuItem] = []
+    ids = sorted(mgr.bundles.keys(), key=str.lower)
+    for id in ids:
+        bundle = mgr.bundles[id]
+        entries += bundle.menu_entries(kind)
+    return entries
+
+
+def _yeet_local_changes() -> None:
+    os.remove("/flash/sys/.sys-installed")
+    machine.reset()
+
+
+class SunMenu(MenuController):
+    """
+    A circular menu with a rotating sun.
+    """
+
+    __slots__ = (
+        "_ts",
+        "_sun",
+    )
+
+    def __init__(self, bundles: Optional[list] = None) -> None:
+        self._ts = 0
+        self._sun = Sun()
+        if bundles:
+            self._bundles = bundles
+        else:
+            self._bundles = BundleManager()
+            self._bundles.update()
+
+        self.load_menu(reload_bundles=False)
+
+    def load_menu(self, reload_bundles: bool = True) -> None:
+        """
+        (Re)loads the menu.
+        Calling this after it has been loaded is a potential memory leak issue.
+        """
+        if reload_bundles:
+            self._bundles.bundles = {}
+            self._bundles.update()
+        self.build_menu_items()
+        super().__init__(self._items)
+
+    def build_menu_items(self) -> None:
+        menu_settings = settings.build_menu()
+        menu_system = ApplicationMenu(
+            [
+                MenuItemBack(),
+                MenuItemLaunchPersistentView("About", About),
+                MenuItemForeground("Settings", menu_settings),
+                MenuItemAppLaunch(BundleMetadata("/flash/sys/apps/gr33nhouse")),
+                MenuItemAppLaunch(BundleMetadata("/flash/sys/apps/updat3r")),
+                MenuItemAction("Disk Mode (Flash)", machine.disk_mode_flash),
+                MenuItemAction("Disk Mode (SD)", machine.disk_mode_sd),
+                MenuItemAction("Yeet Local Changes", _yeet_local_changes),
+                MenuItemAction("Reboot", machine.reset),
+            ],
+        )
+
+        app_kinds = _get_bundle_menu_kinds(self._bundles)
+        menu_categories = ["Badge", "Music", "Media", "Apps", "Games"]
+        for kind in app_kinds:
+            if kind not in ["Hidden", "System"] and kind not in menu_categories:
+                menu_categories.append(kind)
+
+        categories = [
+            MenuItemForeground(kind, ApplicationMenu([MenuItemBack()] + entries))
+            for kind in menu_categories
+            if (entries := _get_bundle_menu_entries(self._bundles, kind))
+        ]
+        categories.append(MenuItemForeground("System", menu_system))
+
+        self._items = categories
+        # # self._scroll_controller = ScrollController()
+        # self._scroll_controller.set_item_count(len(categories))
+
+    def think(self, ins: InputState, delta_ms: int) -> None:
+        super().think(ins, delta_ms)
+        self._sun.think(ins, delta_ms)
+        self._ts += delta_ms
+
+    def _draw_item_angled(
+        self, ctx: Context, item: MenuItem, angle: float, activity: float
+    ) -> None:
+        size = lerp(20, 40, activity)
+        color = lerp(0, 1, activity)
+        if color < 0.01:
+            return
+
+        ctx.save()
+        ctx.translate(-120, 0).rotate(angle).translate(140, 0)
+        ctx.font_size = size
+        ctx.rgba(1.0, 1.0, 1.0, color).move_to(0, 0)
+        item.draw(ctx)
+        ctx.restore()
+
+    def draw(self, ctx: Context) -> None:
+        ctx.gray(0)
+        ctx.rectangle(-120, -120, 240, 240).fill()
+
+        self._sun.draw(ctx)
+
+        ctx.font_size = 40
+        ctx.text_align = ctx.CENTER
+        ctx.text_baseline = ctx.MIDDLE
+
+        angle_per_item = 0.4
+
+        current = self._scroll_controller.current_position()
+
+        for ix, item in enumerate(self._items):
+            rot = (ix - current) * angle_per_item
+            self._draw_item_angled(ctx, item, rot, 1 - abs(rot))
-- 
GitLab