ui: adapt network to raylib touch api (#35881)

* start

* for now

* con

* more
pull/35886/head
Maxime Desroches 1 month ago committed by GitHub
parent 5c73681be8
commit cb5299be5a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 4
      system/ui/widgets/button.py
  2. 60
      system/ui/widgets/confirm_dialog.py
  3. 31
      system/ui/widgets/network.py

@ -15,6 +15,7 @@ class ButtonStyle(IntEnum):
TRANSPARENT = 3 # For buttons with transparent background and border
ACTION = 4
LIST_ACTION = 5 # For list items with action buttons
NO_EFFECT = 6
class TextAlignment(IntEnum):
@ -36,6 +37,7 @@ BUTTON_TEXT_COLOR = {
ButtonStyle.TRANSPARENT: rl.BLACK,
ButtonStyle.ACTION: rl.Color(0, 0, 0, 255),
ButtonStyle.LIST_ACTION: rl.Color(228, 228, 228, 255),
ButtonStyle.NO_EFFECT: rl.Color(228, 228, 228, 255),
}
BUTTON_BACKGROUND_COLORS = {
@ -45,6 +47,7 @@ BUTTON_BACKGROUND_COLORS = {
ButtonStyle.TRANSPARENT: rl.BLACK,
ButtonStyle.ACTION: rl.Color(189, 189, 189, 255),
ButtonStyle.LIST_ACTION: rl.Color(57, 57, 57, 255),
ButtonStyle.NO_EFFECT: rl.Color(51, 51, 51, 255),
}
BUTTON_PRESSED_BACKGROUND_COLORS = {
@ -54,6 +57,7 @@ BUTTON_PRESSED_BACKGROUND_COLORS = {
ButtonStyle.TRANSPARENT: rl.BLACK,
ButtonStyle.ACTION: rl.Color(130, 130, 130, 255),
ButtonStyle.LIST_ACTION: rl.Color(74, 74, 74, 74),
ButtonStyle.NO_EFFECT: rl.Color(51, 51, 51, 255),
}
_pressed_buttons: set[str] = set() # Track mouse press state globally

@ -1,8 +1,9 @@
import pyray as rl
from openpilot.system.ui.lib.application import gui_app, FontWeight
from openpilot.system.ui.widgets import DialogResult
from openpilot.system.ui.widgets.button import gui_button, ButtonStyle
from openpilot.system.ui.widgets.button import gui_button, ButtonStyle, Button
from openpilot.system.ui.widgets.label import gui_text_box
from openpilot.system.ui.widgets import Widget
DIALOG_WIDTH = 1520
DIALOG_HEIGHT = 600
@ -11,6 +12,63 @@ MARGIN = 50
TEXT_AREA_HEIGHT_REDUCTION = 200
BACKGROUND_COLOR = rl.Color(27, 27, 27, 255)
class ConfirmDialog(Widget):
def __init__(self, text: str, confirm_text: str, cancel_text: str = "Cancel"):
super().__init__()
self.text = text
self._cancel_button = Button(cancel_text, self._cancel_button_callback)
self._confirm_button = Button(confirm_text, self._confirm_button_callback, button_style=ButtonStyle.PRIMARY)
self._dialog_result = DialogResult.NO_ACTION
self._cancel_text = cancel_text
def reset(self):
self._dialog_result = DialogResult.NO_ACTION
def _cancel_button_callback(self):
self._dialog_result = DialogResult.CANCEL
def _confirm_button_callback(self):
self._dialog_result = DialogResult.CONFIRM
def _render(self, rect: rl.Rectangle):
dialog_x = (gui_app.width - DIALOG_WIDTH) / 2
dialog_y = (gui_app.height - DIALOG_HEIGHT) / 2
dialog_rect = rl.Rectangle(dialog_x, dialog_y, DIALOG_WIDTH, DIALOG_HEIGHT)
bottom = dialog_rect.y + dialog_rect.height
button_width = (dialog_rect.width - 3 * MARGIN) // 2
cancel_button_x = dialog_rect.x + MARGIN
confirm_button_x = dialog_rect.x + dialog_rect.width - button_width - MARGIN
button_y = bottom - BUTTON_HEIGHT - MARGIN
cancel_button = rl.Rectangle(cancel_button_x, button_y, button_width, BUTTON_HEIGHT)
confirm_button = rl.Rectangle(confirm_button_x, button_y, button_width, BUTTON_HEIGHT)
rl.draw_rectangle_rec(dialog_rect, BACKGROUND_COLOR)
text_rect = rl.Rectangle(dialog_rect.x + MARGIN, dialog_rect.y, dialog_rect.width - 2 * MARGIN, dialog_rect.height - TEXT_AREA_HEIGHT_REDUCTION)
gui_text_box(
text_rect,
self.text,
font_size=70,
alignment=rl.GuiTextAlignment.TEXT_ALIGN_CENTER,
alignment_vertical=rl.GuiTextAlignmentVertical.TEXT_ALIGN_MIDDLE,
font_weight=FontWeight.BOLD,
)
if rl.is_key_pressed(rl.KeyboardKey.KEY_ENTER):
self._dialog_result = DialogResult.CONFIRM
elif rl.is_key_pressed(rl.KeyboardKey.KEY_ESCAPE):
self._dialog_result = DialogResult.CANCEL
if self._cancel_text:
self._confirm_button.render(confirm_button)
self._cancel_button.render(cancel_button)
else:
centered_button_x = dialog_rect.x + (dialog_rect.width - button_width) / 2
centered_confirm_button = rl.Rectangle(centered_button_x, button_y, button_width, BUTTON_HEIGHT)
self._confirm_button.render(centered_confirm_button)
return self._dialog_result
def confirm_dialog(message: str, confirm_text: str, cancel_text: str = "Cancel") -> DialogResult:
dialog_x = (gui_app.width - DIALOG_WIDTH) / 2

@ -1,4 +1,5 @@
from dataclasses import dataclass
from functools import partial
from threading import Lock
from typing import Literal
@ -7,8 +8,8 @@ from openpilot.system.ui.lib.application import gui_app
from openpilot.system.ui.lib.scroll_panel import GuiScrollPanel
from openpilot.system.ui.lib.wifi_manager import NetworkInfo, WifiManagerCallbacks, WifiManagerWrapper, SecurityType
from openpilot.system.ui.widgets import Widget
from openpilot.system.ui.widgets.button import ButtonStyle, gui_button
from openpilot.system.ui.widgets.confirm_dialog import confirm_dialog
from openpilot.system.ui.widgets.button import ButtonStyle, Button, TextAlignment
from openpilot.system.ui.widgets.confirm_dialog import ConfirmDialog
from openpilot.system.ui.widgets.keyboard import Keyboard
from openpilot.system.ui.widgets.label import gui_label
@ -67,8 +68,11 @@ class WifiManagerUI(Widget):
self.keyboard = Keyboard(max_text_size=MAX_PASSWORD_LENGTH, min_text_size=MIN_PASSWORD_LENGTH, show_password_toggle=True)
self._networks: list[NetworkInfo] = []
self._networks_buttons: dict[str, Button] = {}
self._forget_networks_buttons: dict[str, Button] = {}
self._lock = Lock()
self.wifi_manager = wifi_manager
self._confirm_dialog = ConfirmDialog("", "Forget", "Cancel")
self.wifi_manager.set_callbacks(
WifiManagerCallbacks(
@ -91,10 +95,12 @@ class WifiManagerUI(Widget):
match self.state:
case StateNeedsAuth(network):
self.keyboard.set_title("Enter password", f"for {network.ssid}")
self.keyboard.reset()
gui_app.set_modal_overlay(self.keyboard, lambda result: self._on_password_entered(network, result))
case StateShowForgetConfirm(network):
gui_app.set_modal_overlay(lambda: confirm_dialog(f'Forget Wi-Fi Network "{network.ssid}"?', "Forget"),
callback=lambda result: self.on_forgot_confirm_finished(network, result))
self._confirm_dialog.text = f'Forget Wi-Fi Network "{network.ssid}"?'
self._confirm_dialog.reset()
gui_app.set_modal_overlay(self._confirm_dialog, callback=lambda result: self.on_forgot_confirm_finished(network, result))
case _:
self._draw_network_list(rect)
@ -139,7 +145,7 @@ class WifiManagerUI(Widget):
signal_icon_rect = rl.Rectangle(rect.x + rect.width - ICON_SIZE, rect.y + (ITEM_HEIGHT - ICON_SIZE) / 2, ICON_SIZE, ICON_SIZE)
security_icon_rect = rl.Rectangle(signal_icon_rect.x - spacing - ICON_SIZE, rect.y + (ITEM_HEIGHT - ICON_SIZE) / 2, ICON_SIZE, ICON_SIZE)
gui_label(ssid_rect, network.ssid, 55)
self._networks_buttons[network.ssid].render(ssid_rect)
status_text = ""
match self.state:
@ -162,18 +168,23 @@ class WifiManagerUI(Widget):
self.btn_width,
80,
)
if isinstance(self.state, StateIdle) and gui_button(forget_btn_rect, "Forget", button_style=ButtonStyle.ACTION) and clicked:
self.state = StateShowForgetConfirm(network)
self._forget_networks_buttons[network.ssid].render(forget_btn_rect)
self._draw_status_icon(security_icon_rect, network)
self._draw_signal_strength_icon(signal_icon_rect, network)
if isinstance(self.state, StateIdle) and rl.check_collision_point_rec(rl.get_mouse_position(), ssid_rect) and clicked:
def _networks_buttons_callback(self, network):
if self.scroll_panel.is_touch_valid():
if not network.is_saved and network.security_type != SecurityType.OPEN:
self.state = StateNeedsAuth(network)
elif not network.is_connected:
self.connect_to_network(network)
def _forget_networks_buttons_callback(self, network):
if self.scroll_panel.is_touch_valid():
if isinstance(self.state, StateIdle):
self.state = StateShowForgetConfirm(network)
def _draw_status_icon(self, rect, network: NetworkInfo):
"""Draw the status icon based on network's connection state"""
icon_file = None
@ -211,6 +222,10 @@ class WifiManagerUI(Widget):
def _on_network_updated(self, networks: list[NetworkInfo]):
with self._lock:
self._networks = networks
for n in self._networks:
self._networks_buttons[n.ssid] = Button(n.ssid, partial(self._networks_buttons_callback, n), font_size=55, text_alignment=TextAlignment.LEFT,
button_style=ButtonStyle.NO_EFFECT)
self._forget_networks_buttons[n.ssid] = Button("Forget", partial(self._forget_networks_buttons_callback, n), button_style=ButtonStyle.ACTION)
def _on_need_auth(self, ssid):
with self._lock:

Loading…
Cancel
Save