pull/35003/head
Cameron Clough 1 week ago
parent cf70261248
commit b9d7c604eb
  1. 47
      system/ui/lib/wrapper.py
  2. 43
      system/ui/spinner.py
  3. 15
      system/ui/text.py

@ -0,0 +1,47 @@
import threading
import time
from openpilot.system.ui.lib.application import gui_app
class Wrapper:
def __init__(self, title: str, renderer_cls, *args):
self._title = title
self._renderer_class = renderer_cls
self._args = args
self._renderer = None
self._stop_event = threading.Event()
self._thread = threading.Thread(target=self._run, args=(self._stop_event,), daemon=True)
self._thread.start()
def _run(self, stop_event: threading.Event):
gui_app.init_window(self._title)
self._renderer = self._renderer_class(*self._args)
try:
for _ in gui_app.render():
if stop_event.is_set():
break
self._renderer.render()
finally:
gui_app.close()
def __enter__(self):
return self
def wait(self):
"""wait for renderer to be initialized"""
while self._renderer is None and self._thread is not None and self._thread.is_alive():
time.sleep(0.01)
def close(self):
if self._thread is not None and self._thread.is_alive():
self._stop_event.set()
self._thread.join(timeout=2.0)
if self._thread.is_alive():
print(f"WARNING: failed to join {self._title} thread")
self._thread = None
def __del__(self):
self.close()
def __exit__(self, exc_type, exc_value, traceback):
self.close()

@ -2,9 +2,9 @@
import pyray as rl import pyray as rl
import os import os
import threading import threading
import time
from openpilot.common.basedir import BASEDIR from openpilot.common.basedir import BASEDIR
from openpilot.system.ui.lib.wrapper import Wrapper
from openpilot.system.ui.lib.application import gui_app from openpilot.system.ui.lib.application import gui_app
# Constants # Constants
@ -68,54 +68,21 @@ class Renderer:
rl.Vector2(center.x - text_size.x / 2, y_pos), FONT_SIZE, 1.0, rl.WHITE) rl.Vector2(center.x - text_size.x / 2, y_pos), FONT_SIZE, 1.0, rl.WHITE)
class Spinner: class Spinner(Wrapper):
def __init__(self): def __init__(self):
self._stop_event = threading.Event() super().__init__("Spinner", Renderer)
self._renderer: Renderer | None = None
self._thread = threading.Thread(target=self._run, args=(self._stop_event,), daemon=True)
self._thread.start()
def _run(self, stop_event: threading.Event):
gui_app.init_window("Spinner")
self._renderer = Renderer()
try:
for _ in gui_app.render():
if stop_event.is_set():
break
self._renderer.render()
finally:
gui_app.close()
self._renderer = None
def __enter__(self):
return self
def update(self, spinner_text: str): def update(self, spinner_text: str):
# wait for renderer to be initialized self.wait()
while self._renderer is None and self._thread is not None and self._thread.is_alive():
time.sleep(0.01)
if self._renderer: if self._renderer:
self._renderer.set_text(spinner_text) self._renderer.set_text(spinner_text)
def update_progress(self, cur: float, total: float): def update_progress(self, cur: float, total: float):
self.update(str(round(100 * cur / total))) self.update(str(round(100 * cur / total)))
def close(self):
if self._thread is not None and self._thread.is_alive():
self._stop_event.set()
self._thread.join(timeout=2.0)
if self._thread.is_alive():
print("WARNING: failed to join spinner thread")
self._thread = None
def __del__(self):
self.close()
def __exit__(self, exc_type, exc_value, traceback):
self.close()
if __name__ == "__main__": if __name__ == "__main__":
import time
with Spinner() as s: with Spinner() as s:
s.update("Spinner text") s.update("Spinner text")
time.sleep(5) time.sleep(5)

@ -3,6 +3,7 @@ import pyray as rl
from openpilot.system.hardware import HARDWARE from openpilot.system.hardware import HARDWARE
from openpilot.system.ui.lib.button import gui_button, ButtonStyle from openpilot.system.ui.lib.button import gui_button, ButtonStyle
from openpilot.system.ui.lib.scroll_panel import GuiScrollPanel from openpilot.system.ui.lib.scroll_panel import GuiScrollPanel
from openpilot.system.ui.lib.wrapper import Wrapper
from openpilot.system.ui.lib.application import gui_app from openpilot.system.ui.lib.application import gui_app
MARGIN = 50 MARGIN = 50
@ -31,7 +32,7 @@ def wrap_text(text, font_size, max_width):
return lines return lines
class TextWindow: class Renderer:
def __init__(self, text: str): def __init__(self, text: str):
self._textarea_rect = rl.Rectangle(MARGIN, MARGIN, gui_app.width - MARGIN * 2, gui_app.height - MARGIN * 2) self._textarea_rect = rl.Rectangle(MARGIN, MARGIN, gui_app.width - MARGIN * 2, gui_app.height - MARGIN * 2)
self._wrapped_lines = wrap_text(text, FONT_SIZE, self._textarea_rect.width - 20) self._wrapped_lines = wrap_text(text, FONT_SIZE, self._textarea_rect.width - 20)
@ -55,12 +56,12 @@ class TextWindow:
return ret return ret
def show_text_in_window(text: str): class TextWindow(Wrapper):
gui_app.init_window("Text") def __init__(self, text: str):
text_window = TextWindow(text) super().__init__("Text", Renderer, text)
for _ in gui_app.render():
text_window.render()
if __name__ == "__main__": if __name__ == "__main__":
show_text_in_window(DEMO_TEXT) import time
with TextWindow(DEMO_TEXT):
time.sleep(5)

Loading…
Cancel
Save