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