From 022bfa919ce0baf5ac1af0d6d9eccbe9d15306c9 Mon Sep 17 00:00:00 2001
From: Serge Bazanski <q3k@q3k.org>
Date: Sun, 11 Jun 2023 19:22:25 +0200
Subject: [PATCH] py: inject ctx to draw calls

---
 python_payload/apps/demo_worms.py      |  33 +++----
 python_payload/st3m/application.py     |  13 +--
 python_payload/st3m/logging.py         |   1 +
 python_payload/st3m/menu.py            |   8 +-
 python_payload/st3m/system/__init__.py |   2 -
 python_payload/st3m/ui.py              | 121 +++++++++++++------------
 6 files changed, 88 insertions(+), 90 deletions(-)

diff --git a/python_payload/apps/demo_worms.py b/python_payload/apps/demo_worms.py
index 02cc495d1b..0f7193f77d 100644
--- a/python_payload/apps/demo_worms.py
+++ b/python_payload/apps/demo_worms.py
@@ -33,27 +33,24 @@ class AppWorms(application.Application):
         for i in range(0):
             self.worms.append(Worm())
 
+        self.just_shown = True
+
     def on_foreground(self):
         print("on foreground")
-        ctx = app.ui.ctx
+        self.just_shown = True
+
+    def on_draw(self, ctx):
+        if self.just_shown:
+            ctx.rgb(*ui.BLUE).rectangle(
+                -ui.WIDTH / 2, -ui.HEIGHT / 2, ui.WIDTH, ui.HEIGHT
+            ).fill()
+            ctx.move_to(0, 0).rgb(*ui.WHITE).text("touch me :)")
+            self.just_shown = False
 
-        # center the text horizontally and vertically
         ctx.text_align = ctx.CENTER
         ctx.text_baseline = ctx.MIDDLE
-
-        # ctx.rgb() expects individual values for the channels, so unpack a list/tuple with *
-        # operations on ctx can be chained
-        # create a blue background
-        ctx.rgb(*ui.BLUE).rectangle(
-            -ui.WIDTH / 2, -ui.HEIGHT / 2, ui.WIDTH, ui.HEIGHT
-        ).fill()
-
-        # Write some text
-        ctx.move_to(0, 0).rgb(*ui.WHITE).text("touch me :)")
-
-    def on_draw(self):
         for w in self.worms:
-            w.draw()
+            w.draw(ctx)
 
     def main_foreground(self):
         now = time.ticks_ms()
@@ -100,9 +97,9 @@ class Worm:
         # (self.dx,self.dy) = xy_from_polar(1,self.direction)
         self._lastdist = 0.0
 
-    def draw(self):
-        app.ui.ctx.rgb(*self.color)
-        app.ui.ctx.round_rectangle(
+    def draw(self, ctx):
+        ctx.rgb(*self.color)
+        ctx.round_rectangle(
             self.x - self.size / 2,
             self.y - self.size / 2,
             self.size,
diff --git a/python_payload/st3m/application.py b/python_payload/st3m/application.py
index bbf54f1405..b5f57c697a 100644
--- a/python_payload/st3m/application.py
+++ b/python_payload/st3m/application.py
@@ -87,9 +87,9 @@ class Application:
         self._set_events(self._events_forground, False)
         self.state = STATE_OFF
 
-    def draw(self):
-        self.ui.draw()
-        self.on_draw()
+    def draw(self, ctx):
+        self.ui.draw(ctx)
+        self.on_draw(ctx)
 
     def tick(self):
         self.main_foreground()
@@ -116,8 +116,9 @@ class Application:
         if self._events_foreground:
             self._set_events(self._events_foreground, True)
 
-        self.ui.ctx.rgb(*ui.BLACK).rectangle(-120, -120, 240, 240).fill()
-        self.icon.draw()
+        # TODO(q3k): make this pending
+        # self.ui.ctx.rgb(*ui.BLACK).rectangle(-120,-120,240,240).fill()
+        # self.icon.draw()
 
         self.on_foreground()
 
@@ -153,7 +154,7 @@ class Application:
     def on_kill(self):
         log.info(f"app {self.title}: on_kill()")
 
-    def on_draw(self):
+    def on_draw(self, ctx):
         log.debug(f"app {self.title}: on_draw()")
 
     def main_foreground(self):
diff --git a/python_payload/st3m/logging.py b/python_payload/st3m/logging.py
index 69af2f4598..7ff504555e 100644
--- a/python_payload/st3m/logging.py
+++ b/python_payload/st3m/logging.py
@@ -1,3 +1,4 @@
+import sys
 import time
 
 DEBUG = 0
diff --git a/python_payload/st3m/menu.py b/python_payload/st3m/menu.py
index cd475fa255..96017c98fb 100644
--- a/python_payload/st3m/menu.py
+++ b/python_payload/st3m/menu.py
@@ -109,7 +109,7 @@ class Menu:
         topness = 1 - (dist / math.pi)
         return topness
 
-    def draw(self):
+    def draw(self, ctx):
         # TODO this is more like a hack...
         # if not self==active_menu:
         #    active_menu.draw()
@@ -129,10 +129,10 @@ class Menu:
 
         # black background
         # TODO transparent menu with compositing
-        ui.the_ctx.rectangle(-120, -120, 240, 240).rgb(*ui.BLACK).fill()
+        ctx.rectangle(-120, -120, 240, 240).rgb(*ui.BLACK).fill()
 
-        self.ui2.draw()
-        self.ui.draw()
+        self.ui2.draw(ctx)
+        self.ui.draw(ctx)
 
 
 class MenuControl(Menu):
diff --git a/python_payload/st3m/system/__init__.py b/python_payload/st3m/system/__init__.py
index 9a2976b844..3b3aaf1b37 100644
--- a/python_payload/st3m/system/__init__.py
+++ b/python_payload/st3m/system/__init__.py
@@ -37,5 +37,3 @@ except ModuleNotFoundError:
 
 hardware = _hardware
 audio = _audio
-
-ctx = hardware.get_ctx()
diff --git a/python_payload/st3m/ui.py b/python_payload/st3m/ui.py
index f81f45e6d4..bbb17458b6 100644
--- a/python_payload/st3m/ui.py
+++ b/python_payload/st3m/ui.py
@@ -3,7 +3,6 @@ from st3m import logging
 log = logging.Log(__name__, level=logging.INFO)
 log.info("import")
 
-from st3m.system import ctx
 import random
 import math
 import time
@@ -24,8 +23,6 @@ GREY = (0.5, 0.5, 0.5)
 GO_GREEN = (63 / 255, 255 / 255, 33 / 53)
 PUSH_RED = (251 / 255, 72 / 255, 196 / 255)
 
-the_ctx = ctx
-
 
 # Utility functions
 def xy_from_polar(r, phi):
@@ -46,16 +43,15 @@ class UIElement:
     def __init__(self, origin=(0, 0)):
         self.children = []
         self.origin = origin
-        self.ctx = the_ctx
 
-    def draw(self, offset=(0, 0)):
+    def draw(self, ctx, offset=(0, 0)):
         pos = (self.origin[0] + offset[0], self.origin[1] + offset[1])
 
-        self._draw(pos)
+        self._draw(ctx, pos)
         for child in self.children:
-            child.draw(pos)
+            child.draw(ctx, pos)
 
-    def _draw(self, pos):
+    def _draw(self, ctx, pos):
         pass
 
     def add(self, child):
@@ -63,9 +59,8 @@ class UIElement:
 
 
 class Viewport(UIElement):
-    def _draw(self, pos):
+    def _draw(self, ctx, pos):
         pass
-        # self.ctx.rgb(0.3,0.3,0.3).rectangle(-WIDTH/2,-HEIGHT/2,WIDTH,HEIGHT).fill()
 
 
 class Circle(UIElement):
@@ -78,9 +73,9 @@ class Circle(UIElement):
         self.arc_to = arc_to
         super().__init__()
 
-    def _draw(self, pos):
+    def _draw(self, ctx, pos):
         (x, y) = pos
-        self.ctx.move_to(x, y).rgb(*self.color).arc(
+        ctx.move_to(x, y).rgb(*self.color).arc(
             x, y, self.radius, self.arc_from, self.arc_to, True
         ).fill()
 
@@ -90,11 +85,11 @@ class Text(UIElement):
         self.s = s
         super().__init__()
 
-    def _draw(self, pos):
-        self.ctx.text_align = self.ctx.CENTER
-        self.ctx.text_baseline = self.ctx.MIDDLE
-        self.ctx.font_size = 30
-        self.ctx.rgb(1, 1, 1).move_to(pos[0], pos[1]).text(self.s)
+    def _draw(self, ctx, pos):
+        ctx.text_align = ctx.CENTER
+        ctx.text_baseline = ctx.MIDDLE
+        ctx.font_size = 30
+        ctx.rgb(1, 1, 1).move_to(pos[0], pos[1]).text(self.s)
 
 
 class Icon(UIElement):
@@ -106,57 +101,57 @@ class Icon(UIElement):
         self.has_highlight = False
         super().__init__()
 
-    def _draw(self, pos):
-        self.ctx.text_align = self.ctx.CENTER
-        self.ctx.text_baseline = self.ctx.MIDDLE
-        self.ctx.font_size = self.size / 3
+    def _draw(self, ctx, pos):
+        ctx.text_align = ctx.CENTER
+        ctx.text_baseline = ctx.MIDDLE
+        ctx.font_size = self.size / 3
 
         (x, y) = pos
         hs = 5
 
         if self.has_highlight:
-            self.ctx.rgb(*GO_GREEN).arc(
+            ctx.rgb(*GO_GREEN).arc(
                 x, y, self.size / 2 + hs, -math.pi, math.pi, True
             ).fill()
-        self.ctx.move_to(x, y).rgb(*self.bg).arc(
+        ctx.move_to(x, y).rgb(*self.bg).arc(
             x, y, self.size / 2, -math.pi, math.pi, True
         ).fill()
 
         y += self.size / 3
-        width = max(self.size - 10, self.ctx.text_width(self.label)) + 10
+        width = max(self.size - 10, ctx.text_width(self.label)) + 10
         height = self.size / 3 + 8
         if self.has_highlight:
-            self.ctx.rgb(*BLACK).move_to(x, y - height / 2).round_rectangle(
+            ctx.rgb(*BLACK).move_to(x, y - height / 2).round_rectangle(
                 x - width / 2, y - height / 2, width, height, width // 2
             ).fill()
-            self.ctx.rgb(*GO_GREEN).move_to(x, y).text(self.label)
+            ctx.rgb(*GO_GREEN).move_to(x, y).text(self.label)
         else:
-            self.ctx.rgb(*PUSH_RED).move_to(x, y - height / 2).round_rectangle(
+            ctx.rgb(*PUSH_RED).move_to(x, y - height / 2).round_rectangle(
                 x - width / 2, y - height / 2, width, height, width // 2
             ).fill()
-            self.ctx.rgb(*BLACK).move_to(x, y).text(self.label)
+            ctx.rgb(*BLACK).move_to(x, y).text(self.label)
 
 
 class IconLabel(Icon):
-    def _draw(self, pos):
-        self.ctx.text_align = self.ctx.CENTER
-        self.ctx.text_baseline = self.ctx.MIDDLE
-        self.ctx.font_size = self.size / 2
+    def _draw(self, ctx, pos):
+        ctx.text_align = ctx.CENTER
+        ctx.text_baseline = ctx.MIDDLE
+        ctx.font_size = self.size / 2
 
         (x, y) = pos
         hs = 5
-        width = self.ctx.text_width(self.label) + 10
+        width = ctx.text_width(self.label) + 10
         height = self.size / 2
         if self.has_highlight:
-            self.ctx.rgb(*GO_GREEN).move_to(x, y - height / 2).round_rectangle(
+            ctx.rgb(*GO_GREEN).move_to(x, y - height / 2).round_rectangle(
                 x - width / 2, y - height / 2, width, height, width // 2
             ).fill()
-            self.ctx.rgb(*BLACK).move_to(x, y).text(self.label)
+            ctx.rgb(*BLACK).move_to(x, y).text(self.label)
         else:
-            self.ctx.rgb(*PUSH_RED).move_to(x, y - height / 2).round_rectangle(
+            ctx.rgb(*PUSH_RED).move_to(x, y - height / 2).round_rectangle(
                 x - width / 2, y - height / 2, width, height, width // 2
             ).fill()
-            self.ctx.rgb(*BLACK).move_to(x, y).text(self.label)
+            ctx.rgb(*BLACK).move_to(x, y).text(self.label)
 
 
 class IconFlower(Icon):
@@ -169,10 +164,10 @@ class IconFlower(Icon):
         self.size_offset = random.randint(0, 20)
         # self.bg=PUSH_RED
 
-    def _draw(self, pos):
-        self.ctx.text_align = self.ctx.CENTER
-        self.ctx.text_baseline = self.ctx.MIDDLE
-        self.ctx.font_size = self.size / 3
+    def _draw(self, ctx, pos):
+        ctx.text_align = ctx.CENTER
+        ctx.text_baseline = ctx.MIDDLE
+        ctx.font_size = self.size / 3
 
         (x, y) = pos
         petal_size = 0
@@ -187,7 +182,7 @@ class IconFlower(Icon):
             (x_, y_) = xy_from_polar(r, phi)
             size_rnd = random.randint(-1, 1)
             if self.has_highlight:
-                self.ctx.move_to(x + x_, y + y_).rgb(*GO_GREEN).arc(
+                ctx.move_to(x + x_, y + y_).rgb(*GO_GREEN).arc(
                     x + x_,
                     y + y_,
                     petal_size / 2 + hs + size_rnd,
@@ -195,31 +190,31 @@ class IconFlower(Icon):
                     math.pi,
                     True,
                 ).fill()
-            self.ctx.move_to(x + x_, y + y_).rgb(*self.petal_color).arc(
+            ctx.move_to(x + x_, y + y_).rgb(*self.petal_color).arc(
                 x + x_, y + y_, petal_size / 2 + size_rnd, -math.pi, math.pi, True
             ).fill()
 
         if self.has_highlight:
-            self.ctx.rgb(*GO_GREEN).arc(
+            ctx.rgb(*GO_GREEN).arc(
                 x, y, self.size / 2 + hs, -math.pi, math.pi, True
             ).fill()
-        self.ctx.move_to(x, y).rgb(*self.bg).arc(
+        ctx.move_to(x, y).rgb(*self.bg).arc(
             x, y, self.size / 2, -math.pi, math.pi, True
         ).fill()
 
         y += self.size / 3
-        width = max(self.size, self.ctx.text_width(self.label) + 10)
+        width = max(self.size, ctx.text_width(self.label) + 10)
         height = self.size / 3 + 8
         if self.has_highlight:
-            self.ctx.rgb(*BLACK).move_to(x, y - height / 2).round_rectangle(
+            ctx.rgb(*BLACK).move_to(x, y - height / 2).round_rectangle(
                 x - width / 2, y - height / 2, width, height, width // 2
             ).fill()
-            self.ctx.rgb(*GO_GREEN).move_to(x, y).text(self.label)
+            ctx.rgb(*GO_GREEN).move_to(x, y).text(self.label)
         else:
-            self.ctx.rgb(*PUSH_RED).move_to(x, y - height / 2).round_rectangle(
+            ctx.rgb(*PUSH_RED).move_to(x, y - height / 2).round_rectangle(
                 x - width / 2, y - height / 2, width, height, width // 2
             ).fill()
-            self.ctx.rgb(*BLACK).move_to(x, y).text(self.label)
+            ctx.rgb(*BLACK).move_to(x, y).text(self.label)
 
 
 class IconValue(Icon):
@@ -228,7 +223,7 @@ class IconValue(Icon):
         self.value = value
         self.get_value = None
 
-    def _draw(self, pos):
+    def _draw(self, ctx, pos):
         (x, y) = pos
 
         v = self.value
@@ -236,15 +231,21 @@ class IconValue(Icon):
             v = self.get_value()
             self.value = v
 
-        self.ctx.text_align = self.ctx.CENTER
-        self.ctx.text_baseline = self.ctx.MIDDLE
-        self.ctx.font_size = self.size / 3
+        ctx.text_align = ctx.CENTER
+        ctx.text_baseline = ctx.MIDDLE
+        ctx.font_size = self.size / 3
 
         if self.has_highlight:
-            self.ctx.move_to(x, y).rgb(*WHITE).arc(
+            ctx.move_to(x, y).rgb(*WHITE).arc(
                 x, y, self.size / 2 + 5, -pi, pi, True
             ).fill()
 
+        ctx.move_to(x, y).rgb(*PUSH_RED).arc(x, y, self.size / 2, -pi, pi, True).fill()
+        ctx.move_to(x, y).rgb(*GO_GREEN).arc(
+            x, y, self.size / 2 - 5, v * 2 * pi, 0, 1
+        ).fill()
+        ctx.rgb(0, 0, 0).move_to(x, y).text(self.label)
+
         self.ctx.move_to(x, y).rgb(*PUSH_RED).arc(
             x, y, self.size / 2, -pi, pi, True
         ).fill()
@@ -265,9 +266,9 @@ class GroupRing(UIElement):
         self.element_center = element_center
         super().__init__(origin)
 
-    def draw(self, offset=(0, 0)):
+    def draw(self, ctx, offset=(0, 0)):
         pos = (self.origin[0] + offset[0], self.origin[1] + offset[1])
-        self._draw(pos)
+        self._draw(ctx, pos)
         for index in range(len(self.children)):
             # print("child",index)
             child = self.children[index]
@@ -278,12 +279,12 @@ class GroupRing(UIElement):
             x = -math.sin(angle) * self.r + pos[0]
             y = -math.cos(angle) * self.r + pos[1]
             # print("pos",(x,y))
-            child.draw(offset=(x, y))
+            child.draw(ctx, offset=(x, y))
 
-    def _draw(self, pos):
+    def _draw(self, ctx, pos):
         if self.element_center:
             self.element_center.has_highlight = False
-            self.element_center._draw(pos)
+            self.element_center._draw(ctx, pos)
 
 
 class GroupPetals(GroupRing):
-- 
GitLab