raylib: base widget class (#35484)

* use some widgets

* consistent name draw -> render

* more

* rest
pull/35487/head
Shane Smiskol 5 days ago committed by GitHub
parent a1ee5f5ba8
commit 3ce87d0ac9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 4
      selfdrive/ui/layouts/home.py
  2. 3
      selfdrive/ui/layouts/main.py
  3. 3
      selfdrive/ui/layouts/network.py
  4. 3
      selfdrive/ui/layouts/settings/developer.py
  5. 3
      selfdrive/ui/layouts/settings/device.py
  6. 4
      selfdrive/ui/layouts/settings/settings.py
  7. 3
      selfdrive/ui/layouts/settings/software.py
  8. 3
      selfdrive/ui/layouts/settings/toggles.py
  9. 4
      selfdrive/ui/layouts/sidebar.py
  10. 8
      selfdrive/ui/onroad/alert_renderer.py
  11. 8
      selfdrive/ui/onroad/augmented_road_view.py
  12. 4
      selfdrive/ui/onroad/cameraview.py
  13. 13
      selfdrive/ui/onroad/driver_camera_view.py
  14. 10
      selfdrive/ui/onroad/driver_state.py
  15. 8
      selfdrive/ui/onroad/hud_renderer.py
  16. 8
      selfdrive/ui/onroad/model_renderer.py
  17. 4
      selfdrive/ui/widgets/offroad_alerts.py
  18. 7
      system/ui/lib/application.py
  19. 4
      system/ui/lib/inputbox.py
  20. 19
      system/ui/lib/list_view.py
  21. 3
      system/ui/lib/toggle.py
  22. 4
      system/ui/reset.py
  23. 4
      system/ui/setup.py
  24. 6
      system/ui/spinner.py
  25. 6
      system/ui/text.py
  26. 6
      system/ui/updater.py
  27. 4
      system/ui/widgets/keyboard.py
  28. 4
      system/ui/widgets/network.py
  29. 3
      system/ui/widgets/option_dialog.py

@ -6,7 +6,7 @@ from openpilot.common.params import Params
from openpilot.selfdrive.ui.widgets.offroad_alerts import UpdateAlert, OffroadAlert
from openpilot.system.ui.lib.text_measure import measure_text_cached
from openpilot.system.ui.lib.label import gui_label
from openpilot.system.ui.lib.application import gui_app, FontWeight, DEFAULT_TEXT_COLOR
from openpilot.system.ui.lib.application import gui_app, FontWeight, DEFAULT_TEXT_COLOR, Widget
HEADER_HEIGHT = 80
HEAD_BUTTON_FONT_SIZE = 40
@ -24,7 +24,7 @@ class HomeLayoutState(IntEnum):
ALERTS = 2
class HomeLayout:
class HomeLayout(Widget):
def __init__(self):
self.params = Params()

@ -5,6 +5,7 @@ from openpilot.selfdrive.ui.layouts.home import HomeLayout
from openpilot.selfdrive.ui.layouts.settings.settings import SettingsLayout
from openpilot.selfdrive.ui.ui_state import ui_state
from openpilot.selfdrive.ui.onroad.augmented_road_view import AugmentedRoadView
from openpilot.system.ui.lib.application import Widget
class MainState(IntEnum):
@ -13,7 +14,7 @@ class MainState(IntEnum):
ONROAD = 2
class MainLayout:
class MainLayout(Widget):
def __init__(self):
self._sidebar = Sidebar()
self._sidebar_visible = True

@ -1,9 +1,10 @@
import pyray as rl
from openpilot.system.ui.lib.application import Widget
from openpilot.system.ui.lib.wifi_manager import WifiManagerWrapper
from openpilot.system.ui.widgets.network import WifiManagerUI
class NetworkLayout:
class NetworkLayout(Widget):
def __init__(self):
self.wifi_manager = WifiManagerWrapper()
self.wifi_ui = WifiManagerUI(self.wifi_manager)

@ -1,3 +1,4 @@
from openpilot.system.ui.lib.application import Widget
from openpilot.system.ui.lib.list_view import ListView, toggle_item
from openpilot.common.params import Params
@ -11,7 +12,7 @@ DESCRIPTIONS = {
}
class DeveloperLayout:
class DeveloperLayout(Widget):
def __init__(self):
self._params = Params()
items = [

@ -1,3 +1,4 @@
from openpilot.system.ui.lib.application import Widget
from openpilot.system.ui.lib.list_view import ListView, text_item, button_item
from openpilot.common.params import Params
from openpilot.system.hardware import TICI
@ -14,7 +15,7 @@ DESCRIPTIONS = {
}
class DeviceLayout:
class DeviceLayout(Widget):
def __init__(self):
params = Params()
dongle_id = params.get("DongleId", encoding="utf-8") or "N/A"

@ -7,7 +7,7 @@ from openpilot.selfdrive.ui.layouts.settings.developer import DeveloperLayout
from openpilot.selfdrive.ui.layouts.settings.device import DeviceLayout
from openpilot.selfdrive.ui.layouts.settings.software import SoftwareLayout
from openpilot.selfdrive.ui.layouts.settings.toggles import TogglesLayout
from openpilot.system.ui.lib.application import gui_app, FontWeight
from openpilot.system.ui.lib.application import gui_app, FontWeight, Widget
from openpilot.system.ui.lib.label import gui_text_box
from openpilot.system.ui.lib.text_measure import measure_text_cached
from openpilot.selfdrive.ui.layouts.network import NetworkLayout
@ -48,7 +48,7 @@ class PanelInfo:
button_rect: rl.Rectangle
class SettingsLayout:
class SettingsLayout(Widget):
def __init__(self):
self._params = Params()
self._current_panel = PanelType.DEVICE

@ -1,7 +1,8 @@
from openpilot.system.ui.lib.application import Widget
from openpilot.system.ui.lib.list_view import ListView, button_item, text_item
class SoftwareLayout:
class SoftwareLayout(Widget):
def __init__(self):
items = [
text_item("Current Version", ""),

@ -1,3 +1,4 @@
from openpilot.system.ui.lib.application import Widget
from openpilot.system.ui.lib.list_view import ListView, toggle_item
from openpilot.common.params import Params
@ -18,7 +19,7 @@ DESCRIPTIONS = {
}
class TogglesLayout:
class TogglesLayout(Widget):
def __init__(self):
self._params = Params()
items = [

@ -4,7 +4,7 @@ from dataclasses import dataclass
from collections.abc import Callable
from cereal import log
from openpilot.selfdrive.ui.ui_state import ui_state
from openpilot.system.ui.lib.application import gui_app, FontWeight
from openpilot.system.ui.lib.application import gui_app, FontWeight, Widget
from openpilot.system.ui.lib.text_measure import measure_text_cached
SIDEBAR_WIDTH = 300
@ -60,7 +60,7 @@ class MetricData:
self.color = color
class Sidebar:
class Sidebar(Widget):
def __init__(self):
self._net_type = NETWORK_TYPES.get(NetworkType.none)
self._net_strength = 0

@ -3,7 +3,7 @@ import pyray as rl
from dataclasses import dataclass
from cereal import messaging, log
from openpilot.system.hardware import TICI
from openpilot.system.ui.lib.application import gui_app, FontWeight, DEFAULT_FPS
from openpilot.system.ui.lib.application import gui_app, FontWeight, DEFAULT_FPS, Widget
from openpilot.system.ui.lib.label import gui_text_box
from openpilot.system.ui.lib.text_measure import measure_text_cached
from openpilot.selfdrive.ui.ui_state import ui_state
@ -59,7 +59,7 @@ ALERT_CRITICAL_REBOOT = Alert(
)
class AlertRenderer:
class AlertRenderer(Widget):
def __init__(self):
self.font_regular: rl.Font = gui_app.font(FontWeight.NORMAL)
self.font_bold: rl.Font = gui_app.font(FontWeight.BOLD)
@ -91,8 +91,8 @@ class AlertRenderer:
# Return current alert
return Alert(text1=ss.alertText1, text2=ss.alertText2, size=ss.alertSize, status=ss.alertStatus)
def draw(self, rect: rl.Rectangle, sm: messaging.SubMaster) -> None:
alert = self.get_alert(sm)
def render(self, rect: rl.Rectangle) -> None:
alert = self.get_alert(ui_state.sm)
if not alert:
return

@ -78,10 +78,10 @@ class AugmentedRoadView(CameraView):
super().render(rect)
# Draw all UI overlays
self.model_renderer.draw(self._content_rect, ui_state.sm)
self._hud_renderer.draw(self._content_rect, ui_state.sm)
self.alert_renderer.draw(self._content_rect, ui_state.sm)
self.driver_state_renderer.draw(self._content_rect, ui_state.sm)
self.model_renderer.render(self._content_rect)
self._hud_renderer.render(self._content_rect)
self.alert_renderer.render(self._content_rect)
self.driver_state_renderer.render(self._content_rect, ui_state.sm)
# Custom UI extension point - add custom overlays here
# Use self._content_rect for positioning within camera bounds

@ -4,7 +4,7 @@ import pyray as rl
from openpilot.system.hardware import TICI
from msgq.visionipc import VisionIpcClient, VisionStreamType, VisionBuf
from openpilot.common.swaglog import cloudlog
from openpilot.system.ui.lib.application import gui_app
from openpilot.system.ui.lib.application import gui_app, Widget
from openpilot.system.ui.lib.egl import init_egl, create_egl_image, destroy_egl_image, bind_egl_image_to_texture, EGLImage
CONNECTION_RETRY_INTERVAL = 0.2 # seconds between connection attempts
@ -55,7 +55,7 @@ else:
"""
class CameraView:
class CameraView(Widget):
def __init__(self, name: str, stream_type: VisionStreamType):
self._name = name
# Primary stream

@ -1,9 +1,9 @@
import numpy as np
import pyray as rl
from cereal import messaging
from msgq.visionipc import VisionStreamType
from openpilot.selfdrive.ui.onroad.cameraview import CameraView
from openpilot.selfdrive.ui.onroad.driver_state import DriverStateRenderer
from openpilot.selfdrive.ui.ui_state import ui_state
from openpilot.system.ui.lib.application import gui_app, FontWeight
from openpilot.system.ui.lib.label import gui_label
@ -13,7 +13,7 @@ class DriverCameraView(CameraView):
super().__init__("camerad", stream_type)
self.driver_state_renderer = DriverStateRenderer()
def render(self, rect, sm):
def render(self, rect):
super().render(rect)
if not self.frame:
@ -26,8 +26,8 @@ class DriverCameraView(CameraView):
)
return
self._draw_face_detection(rect, sm)
self.driver_state_renderer.draw(rect, sm)
self._draw_face_detection(rect, ui_state.sm)
self.driver_state_renderer.draw(rect, ui_state.sm)
def _draw_face_detection(self, rect: rl.Rectangle, sm) -> None:
driver_state = sm["driverStateV2"]
@ -83,12 +83,11 @@ class DriverCameraView(CameraView):
if __name__ == "__main__":
gui_app.init_window("Driver Camera View")
sm = messaging.SubMaster(["selfdriveState", "driverStateV2", "driverMonitoringState"])
driver_camera_view = DriverCameraView(VisionStreamType.VISION_STREAM_DRIVER)
try:
for _ in gui_app.render():
sm.update()
driver_camera_view.render(rl.Rectangle(0, 0, gui_app.width, gui_app.height), sm)
ui_state.update()
driver_camera_view.render(rl.Rectangle(0, 0, gui_app.width, gui_app.height))
finally:
driver_camera_view.close()

@ -2,7 +2,7 @@ import numpy as np
import pyray as rl
from dataclasses import dataclass
from openpilot.selfdrive.ui.ui_state import ui_state, UI_BORDER_SIZE
from openpilot.system.ui.lib.application import gui_app
from openpilot.system.ui.lib.application import gui_app, Widget
# Default 3D coordinates for face keypoints as a NumPy array
DEFAULT_FACE_KPTS_3D = np.array([
@ -41,7 +41,7 @@ class ArcData:
thickness: float
class DriverStateRenderer:
class DriverStateRenderer(Widget):
def __init__(self):
# Initial state with NumPy arrays
self.face_kpts_draw = DEFAULT_FACE_KPTS_3D.copy()
@ -74,11 +74,11 @@ class DriverStateRenderer:
self.engaged_color = rl.Color(26, 242, 66, 255)
self.disengaged_color = rl.Color(139, 139, 139, 255)
def draw(self, rect, sm):
if not self._is_visible(sm):
def render(self, rect):
if not self._is_visible(ui_state.sm):
return
self._update_state(sm, rect)
self._update_state(ui_state.sm, rect)
if not self.state_updated:
return

@ -2,7 +2,7 @@ import pyray as rl
from dataclasses import dataclass
from cereal.messaging import SubMaster
from openpilot.selfdrive.ui.ui_state import ui_state, UIStatus
from openpilot.system.ui.lib.application import gui_app, FontWeight
from openpilot.system.ui.lib.application import gui_app, FontWeight, Widget
from openpilot.system.ui.lib.text_measure import measure_text_cached
from openpilot.common.conversions import Conversions as CV
@ -54,7 +54,7 @@ FONT_SIZES = FontSizes()
COLORS = Colors()
class HudRenderer:
class HudRenderer(Widget):
def __init__(self):
"""Initialize the HUD renderer."""
self.is_cruise_set: bool = False
@ -94,9 +94,9 @@ class HudRenderer:
speed_conversion = CV.MS_TO_KPH if ui_state.is_metric else CV.MS_TO_MPH
self.speed = max(0.0, v_ego * speed_conversion)
def draw(self, rect: rl.Rectangle, sm: SubMaster) -> None:
def render(self, rect: rl.Rectangle) -> None:
"""Render HUD elements to the screen."""
self._update_state(sm)
self._update_state(ui_state.sm)
rl.draw_rectangle_gradient_v(
int(rect.x),
int(rect.y),

@ -5,7 +5,7 @@ from cereal import messaging, car
from dataclasses import dataclass, field
from openpilot.common.params import Params
from openpilot.selfdrive.ui.ui_state import ui_state
from openpilot.system.ui.lib.application import DEFAULT_FPS
from openpilot.system.ui.lib.application import DEFAULT_FPS, Widget
from openpilot.system.ui.lib.shader_polygon import draw_polygon
from openpilot.selfdrive.locationd.calibrationd import HEIGHT_INIT
@ -43,7 +43,7 @@ class LeadVehicle:
fill_alpha: int = 0
class ModelRenderer:
class ModelRenderer(Widget):
def __init__(self):
self._longitudinal_control = False
self._experimental_mode = False
@ -86,7 +86,9 @@ class ModelRenderer:
self._car_space_transform = transform.astype(np.float32)
self._transform_dirty = True
def draw(self, rect: rl.Rectangle, sm: messaging.SubMaster):
def render(self, rect: rl.Rectangle):
sm = ui_state.sm
# Check if data is up-to-date
if (sm.recv_frame["liveCalibration"] < ui_state.started_frame or
sm.recv_frame["modelV2"] < ui_state.started_frame):

@ -8,7 +8,7 @@ from openpilot.system.hardware import HARDWARE
from openpilot.system.ui.lib.scroll_panel import GuiScrollPanel
from openpilot.system.ui.lib.wrap_text import wrap_text
from openpilot.system.ui.lib.text_measure import measure_text_cached
from openpilot.system.ui.lib.application import gui_app, FontWeight
from openpilot.system.ui.lib.application import gui_app, FontWeight, Widget
class AlertColors:
@ -41,7 +41,7 @@ class AlertData:
visible: bool = False
class AbstractAlert(ABC):
class AbstractAlert(Widget, ABC):
def __init__(self, has_reboot_btn: bool = False):
self.params = Params()
self.has_reboot_btn = has_reboot_btn

@ -1,3 +1,4 @@
import abc
import atexit
import os
import time
@ -26,6 +27,12 @@ ASSETS_DIR = files("openpilot.selfdrive").joinpath("assets")
FONT_DIR = ASSETS_DIR.joinpath("fonts")
class Widget(abc.ABC):
@abc.abstractmethod
def render(self, rect: rl.Rectangle) -> bool | None:
"""Render the widget within the given rectangle."""
class FontWeight(IntEnum):
THIN = 0
EXTRA_LIGHT = 1

@ -1,13 +1,13 @@
import pyray as rl
import time
from openpilot.system.ui.lib.application import gui_app
from openpilot.system.ui.lib.application import gui_app, Widget
from openpilot.system.ui.lib.text_measure import measure_text_cached
PASSWORD_MASK_CHAR = ""
PASSWORD_MASK_DELAY = 1.5 # Seconds to show character before masking
class InputBox:
class InputBox(Widget):
def __init__(self, max_text_size=255, password_mode=False):
self._max_text_size = max_text_size
self._input_text = ""

@ -4,12 +4,11 @@ from dataclasses import dataclass
from collections.abc import Callable
from abc import ABC, abstractmethod
from openpilot.system.ui.lib.scroll_panel import GuiScrollPanel
from openpilot.system.ui.lib.application import gui_app, FontWeight
from openpilot.system.ui.lib.application import gui_app, FontWeight, Widget
from openpilot.system.ui.lib.text_measure import measure_text_cached
from openpilot.system.ui.lib.wrap_text import wrap_text
from openpilot.system.ui.lib.button import gui_button
from openpilot.system.ui.lib.toggle import Toggle
from openpilot.system.ui.lib.toggle import WIDTH as TOGGLE_WIDTH, HEIGHT as TOGGLE_HEIGHT
from openpilot.system.ui.lib.toggle import Toggle, WIDTH as TOGGLE_WIDTH, HEIGHT as TOGGLE_HEIGHT
LINE_PADDING = 40
LINE_COLOR = rl.GRAY
@ -31,15 +30,11 @@ BUTTON_FONT_WEIGHT = FontWeight.MEDIUM
# Abstract base class for right-side items
class RightItem(ABC):
class RightItem(Widget, ABC):
def __init__(self, width: int = 100):
self.width = width
self.enabled = True
@abstractmethod
def draw(self, rect: rl.Rectangle) -> bool:
pass
@abstractmethod
def get_width(self) -> int:
pass
@ -52,7 +47,7 @@ class ToggleRightItem(RightItem):
self.state = initial_state
self.enabled = True
def draw(self, rect: rl.Rectangle) -> bool:
def render(self, rect: rl.Rectangle) -> bool:
if self.toggle.render(rl.Rectangle(rect.x, rect.y + (rect.height - TOGGLE_HEIGHT) / 2, self.width, TOGGLE_HEIGHT)):
self.state = not self.state
return True
@ -78,7 +73,7 @@ class ButtonRightItem(RightItem):
self.text = text
self.enabled = True
def draw(self, rect: rl.Rectangle) -> bool:
def render(self, rect: rl.Rectangle) -> bool:
return (
gui_button(
rl.Rectangle(rect.x, rect.y + (rect.height - BUTTON_HEIGHT) / 2, BUTTON_WIDTH, BUTTON_HEIGHT),
@ -108,7 +103,7 @@ class TextRightItem(RightItem):
text_width = measure_text_cached(font, text, font_size).x
super().__init__(int(text_width + 20))
def draw(self, rect: rl.Rectangle) -> bool:
def render(self, rect: rl.Rectangle) -> bool:
font = gui_app.font(FontWeight.NORMAL)
text_size = measure_text_cached(font, self.text, self.font_size)
@ -269,7 +264,7 @@ class ListView:
right_rect = item.get_right_item_rect(rect)
# Adjust for scroll offset
right_rect.y = right_rect.y
if item.right_item.draw(right_rect):
if item.right_item.render(right_rect):
# Right item was clicked/activated
if item.callback:
item.callback()

@ -1,4 +1,5 @@
import pyray as rl
from openpilot.system.ui.lib.application import Widget
ON_COLOR = rl.Color(51, 171, 76, 255)
OFF_COLOR = rl.Color(0x39, 0x39, 0x39, 255)
@ -11,7 +12,7 @@ BG_HEIGHT = 60
ANIMATION_SPEED = 8.0
class Toggle:
class Toggle(Widget):
def __init__(self, initial_state=False):
self._state = initial_state
self._enabled = True

@ -6,7 +6,7 @@ import threading
from enum import IntEnum
from openpilot.system.hardware import PC
from openpilot.system.ui.lib.application import gui_app, FontWeight
from openpilot.system.ui.lib.application import gui_app, FontWeight, Widget
from openpilot.system.ui.lib.button import gui_button, ButtonStyle
from openpilot.system.ui.lib.label import gui_label, gui_text_box
@ -27,7 +27,7 @@ class ResetState(IntEnum):
FAILED = 3
class Reset:
class Reset(Widget):
def __init__(self, mode):
self.mode = mode
self.reset_state = ResetState.NONE

@ -9,7 +9,7 @@ import pyray as rl
from cereal import log
from openpilot.system.hardware import HARDWARE
from openpilot.system.ui.lib.application import gui_app, FontWeight
from openpilot.system.ui.lib.application import gui_app, FontWeight, Widget
from openpilot.system.ui.lib.button import gui_button, ButtonStyle
from openpilot.system.ui.lib.label import gui_label, gui_text_box
from openpilot.system.ui.widgets.network import WifiManagerUI, WifiManagerWrapper
@ -39,7 +39,7 @@ class SetupState(IntEnum):
DOWNLOAD_FAILED = 6
class Setup:
class Setup(Widget):
def __init__(self):
self.state = SetupState.GETTING_STARTED
self.network_check_thread = None

@ -3,7 +3,7 @@ import pyray as rl
import select
import sys
from openpilot.system.ui.lib.application import gui_app
from openpilot.system.ui.lib.application import gui_app, Widget
from openpilot.system.ui.lib.text_measure import measure_text_cached
from openpilot.system.ui.text import wrap_text
@ -22,7 +22,7 @@ def clamp(value, min_value, max_value):
return max(min(value, max_value), min_value)
class Spinner:
class Spinner(Widget):
def __init__(self):
self._comma_texture = gui_app.texture("images/spinner_comma.png", TEXTURE_SIZE, TEXTURE_SIZE)
self._spinner_texture = gui_app.texture("images/spinner_track.png", TEXTURE_SIZE, TEXTURE_SIZE, alpha_premultiply=True)
@ -38,7 +38,7 @@ class Spinner:
self._progress = None
self._wrapped_lines = wrap_text(text, FONT_SIZE, gui_app.width - MARGIN_H)
def render(self):
def render(self, _: rl.Rectangle):
if self._wrapped_lines:
# Calculate total height required for spinner and text
spacing = 50

@ -6,7 +6,7 @@ from openpilot.system.hardware import HARDWARE, PC
from openpilot.system.ui.lib.text_measure import measure_text_cached
from openpilot.system.ui.lib.button import gui_button, ButtonStyle
from openpilot.system.ui.lib.scroll_panel import GuiScrollPanel
from openpilot.system.ui.lib.application import gui_app
from openpilot.system.ui.lib.application import gui_app, Widget
MARGIN = 50
SPACING = 40
@ -46,7 +46,7 @@ def wrap_text(text, font_size, max_width):
return lines
class TextWindow:
class TextWindow(Widget):
def __init__(self, text: str):
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)
@ -54,7 +54,7 @@ class TextWindow:
self._scroll_panel = GuiScrollPanel(show_vertical_scroll_bar=True)
self._scroll_panel._offset.y = -max(self._content_rect.height - self._textarea_rect.height, 0)
def render(self):
def render(self, _: rl.Rectangle = None):
scroll = self._scroll_panel.handle_scroll(self._textarea_rect, self._content_rect)
rl.begin_scissor_mode(int(self._textarea_rect.x), int(self._textarea_rect.y), int(self._textarea_rect.width), int(self._textarea_rect.height))
for i, line in enumerate(self._wrapped_lines):

@ -6,7 +6,7 @@ import pyray as rl
from enum import IntEnum
from openpilot.system.hardware import HARDWARE
from openpilot.system.ui.lib.application import gui_app, FontWeight
from openpilot.system.ui.lib.application import gui_app, FontWeight, Widget
from openpilot.system.ui.lib.button import gui_button, ButtonStyle
from openpilot.system.ui.lib.label import gui_text_box, gui_label
from openpilot.system.ui.lib.wifi_manager import WifiManagerWrapper
@ -30,7 +30,7 @@ class Screen(IntEnum):
PROGRESS = 2
class Updater:
class Updater(Widget):
def __init__(self, updater_path, manifest_path):
self.updater = updater_path
self.manifest = manifest_path
@ -137,7 +137,7 @@ class Updater:
HARDWARE.reboot()
return
def render(self):
def render(self, _: rl.Rectangle = None):
if self.current_screen == Screen.PROMPT:
self.render_prompt_screen()
elif self.current_screen == Screen.WIFI:

@ -1,7 +1,7 @@
import time
from typing import Literal
import pyray as rl
from openpilot.system.ui.lib.application import gui_app, FontWeight
from openpilot.system.ui.lib.application import gui_app, FontWeight, Widget
from openpilot.system.ui.lib.button import ButtonStyle, gui_button
from openpilot.system.ui.lib.inputbox import InputBox
from openpilot.system.ui.lib.label import gui_label
@ -52,7 +52,7 @@ KEYBOARD_LAYOUTS = {
}
class Keyboard:
class Keyboard(Widget):
def __init__(self, max_text_size: int = 255, min_text_size: int = 0, password_mode: bool = False, show_password_toggle: bool = False):
self._layout_name: Literal["lowercase", "uppercase", "numbers", "specials"] = "lowercase"
self._caps_lock = False

@ -3,7 +3,7 @@ from threading import Lock
from typing import Literal
import pyray as rl
from openpilot.system.ui.lib.application import gui_app
from openpilot.system.ui.lib.application import gui_app, Widget
from openpilot.system.ui.lib.button import ButtonStyle, gui_button
from openpilot.system.ui.lib.label import gui_label
from openpilot.system.ui.lib.scroll_panel import GuiScrollPanel
@ -57,7 +57,7 @@ class StateForgetting:
UIState = StateIdle | StateConnecting | StateNeedsAuth | StateShowForgetConfirm | StateForgetting
class WifiManagerUI:
class WifiManagerUI(Widget):
def __init__(self, wifi_manager: WifiManagerWrapper):
self.state: UIState = StateIdle()
self.btn_width: int = 200

@ -1,11 +1,12 @@
import pyray as rl
from openpilot.system.ui.lib.application import Widget
from openpilot.system.ui.lib.button import gui_button, ButtonStyle, TextAlignment
from openpilot.system.ui.lib.label import gui_label
from openpilot.system.ui.lib.scroll_panel import GuiScrollPanel
class MultiOptionDialog:
class MultiOptionDialog(Widget):
def __init__(self, title, options, current=""):
self._title = title
self._options = options

Loading…
Cancel
Save