mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-07-21 17:22:24 +08:00
BigUI WIP: We need tabs
This commit is contained in:
@@ -83,8 +83,7 @@ class AetherTile(Widget):
|
||||
self._is_pressed = False
|
||||
|
||||
def _handle_mouse_event(self, mouse_event):
|
||||
if self._is_pressed and not rl.check_collision_point_rec(mouse_event.pos, self._hit_rect):
|
||||
self._is_pressed = False
|
||||
if not rl.check_collision_point_rec(mouse_event.pos, self._hit_rect):
|
||||
self._plate_target = 0.0
|
||||
|
||||
def _animate_plate(self, dt: float):
|
||||
@@ -216,35 +215,47 @@ class HubTile(AetherTile):
|
||||
|
||||
class ToggleTile(AetherTile):
|
||||
def __init__(self, title: str, get_state: Callable[[], bool], set_state: Callable[[bool], None], icon_path: str | None = None,
|
||||
bg_color: rl.Color | str | None = None, desc: str = ""):
|
||||
bg_color: rl.Color | str | None = None, desc: str = "", is_enabled: Callable[[], bool] | None = None, disabled_label: str = ""):
|
||||
if bg_color: super().__init__(surface_color=bg_color)
|
||||
else: super().__init__(surface_color=rl.Color(0, 163, 0, 255))
|
||||
self.title = title
|
||||
self.desc = desc
|
||||
self.get_state = get_state
|
||||
self.set_state = set_state
|
||||
self.set_enabled(is_enabled or True)
|
||||
self._icon = gui_app.starpilot_texture(icon_path, 80, 80) if icon_path else None
|
||||
self._font = gui_app.font(FontWeight.BOLD)
|
||||
self._font_desc = gui_app.font(FontWeight.NORMAL)
|
||||
self._active_color = self.surface_color
|
||||
self._inactive_color = rl.Color(120, 120, 120, 255)
|
||||
self._disabled_color = rl.Color(75, 75, 75, 255)
|
||||
self._disabled_label = disabled_label
|
||||
|
||||
def _handle_mouse_release(self, mouse_pos: MousePos):
|
||||
if self._is_pressed:
|
||||
if rl.check_collision_point_rec(mouse_pos, self._hit_rect):
|
||||
if rl.check_collision_point_rec(mouse_pos, self._hit_rect) and self.enabled:
|
||||
self.set_state(not self.get_state())
|
||||
self._plate_target = 0.0
|
||||
self._is_pressed = False
|
||||
|
||||
def _render(self, rect: rl.Rectangle):
|
||||
enabled = self.enabled
|
||||
active = self.get_state()
|
||||
self.surface_color = self._active_color if active else self._inactive_color
|
||||
if enabled:
|
||||
self.surface_color = self._active_color if active else self._inactive_color
|
||||
else:
|
||||
self.surface_color = self._disabled_color
|
||||
self._plate_offset = 0.0
|
||||
self._plate_target = 0.0
|
||||
face = self._render_layers(rect)
|
||||
line_heights = [28, 30]
|
||||
_, ty = self._centered_content(face, self._icon, 0.75, 28, len(line_heights), line_heights)
|
||||
max_w = face.width - 40
|
||||
self._draw_text_fit(self._font, self.title, rl.Vector2(face.x + 20, ty), max_w, 28, align_center=True, uppercase=True)
|
||||
state_text = tr("ON") if active else tr("OFF")
|
||||
if enabled:
|
||||
state_text = tr("ON") if active else tr("OFF")
|
||||
else:
|
||||
state_text = tr(self._disabled_label) if self._disabled_label else tr("LOCKED")
|
||||
self._draw_text_fit(self._font, state_text, rl.Vector2(face.x + 20, ty + 28 + 8), max_w, 30, align_center=True, uppercase=True)
|
||||
|
||||
if self.desc:
|
||||
@@ -557,10 +568,15 @@ class RadioTileGroup(Widget):
|
||||
self._option_targets.append(0.0)
|
||||
for i in range(len(self._option_offsets)):
|
||||
self._option_offsets[i] += (self._option_targets[i] - self._option_offsets[i]) * (1 - math.exp(-dt / PLATE_TAU))
|
||||
title_size = measure_text_cached(self._font_title, self.title, 40)
|
||||
rl.draw_text_ex(self._font_title, self.title, rl.Vector2(round(rect.x), round(rect.y + (rect.height - title_size.y) / 2)), 40, 0, rl.WHITE)
|
||||
padding, option_w = 20, 200
|
||||
start_x = rect.x + rect.width - (len(self.options) * (option_w + padding))
|
||||
padding = 20
|
||||
option_w = 240 if len(self.options) <= 3 else 200
|
||||
total_width = len(self.options) * option_w + max(0, len(self.options) - 1) * padding
|
||||
if self.title:
|
||||
title_size = measure_text_cached(self._font_title, self.title, 40)
|
||||
rl.draw_text_ex(self._font_title, self.title, rl.Vector2(round(rect.x), round(rect.y + (rect.height - title_size.y) / 2)), 40, 0, rl.WHITE)
|
||||
start_x = rect.x + rect.width - total_width
|
||||
else:
|
||||
start_x = rect.x + (rect.width - total_width) / 2
|
||||
for i, opt in enumerate(self.options):
|
||||
r = rl.Rectangle(start_x + i * (option_w + padding), rect.y, option_w, rect.height)
|
||||
self._option_rects.append(r)
|
||||
@@ -582,9 +598,10 @@ class RadioTileGroup(Widget):
|
||||
|
||||
|
||||
class TileGrid(Widget):
|
||||
def __init__(self, columns: int | None = None, padding: int = 20):
|
||||
def __init__(self, columns: int | None = None, padding: int = 20, uniform_width: bool = False):
|
||||
super().__init__()
|
||||
self._columns, self.padding, self.tiles = columns, padding, []
|
||||
self._uniform_width = uniform_width
|
||||
|
||||
def add_tile(self, tile: Widget): self.tiles.append(tile)
|
||||
|
||||
@@ -607,13 +624,20 @@ class TileGrid(Widget):
|
||||
else: cols = 4
|
||||
rows = (count + cols - 1) // cols
|
||||
tile_h = (rect.height - (self.padding * (rows - 1))) / rows
|
||||
uniform_tile_w = (rect.width - (self.padding * (cols - 1))) / cols if self._uniform_width else 0
|
||||
tile_idx = 0
|
||||
for r in range(rows):
|
||||
remaining = count - tile_idx
|
||||
if remaining <= 0: break
|
||||
items_in_row = min(cols, remaining)
|
||||
row_tile_w = (rect.width - (self.padding * (items_in_row - 1))) / items_in_row
|
||||
if self._uniform_width:
|
||||
row_tile_w = uniform_tile_w
|
||||
row_width = (row_tile_w * items_in_row) + (self.padding * (items_in_row - 1))
|
||||
row_x = rect.x + (rect.width - row_width) / 2
|
||||
else:
|
||||
row_tile_w = (rect.width - (self.padding * (items_in_row - 1))) / items_in_row
|
||||
row_x = rect.x
|
||||
for c in range(items_in_row):
|
||||
tile = tiles_to_render[tile_idx]
|
||||
tile.render(rl.Rectangle(rect.x + c * (row_tile_w + self.padding), rect.y + r * (tile_h + self.padding), row_tile_w, tile_h))
|
||||
tile.render(rl.Rectangle(row_x + c * (row_tile_w + self.padding), rect.y + r * (tile_h + self.padding), row_tile_w, tile_h))
|
||||
tile_idx += 1
|
||||
|
||||
@@ -13,6 +13,7 @@ from openpilot.system.ui.widgets.confirm_dialog import ConfirmDialog, alert_dial
|
||||
from openpilot.system.ui.widgets.selection_dialog import SelectionDialog
|
||||
from openpilot.system.ui.widgets.input_dialog import InputDialog
|
||||
from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import StarPilotPanel
|
||||
from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import TileGrid
|
||||
|
||||
LEGACY_STARPILOT_PARAM_RENAMES = {
|
||||
"FrogPilotApiToken": "StarPilotApiToken",
|
||||
@@ -51,6 +52,7 @@ class StarPilotDataLayout(StarPilotPanel):
|
||||
"toggle_backups": StarPilotToggleBackupsLayout(),
|
||||
"storage": StarPilotStorageLayout(),
|
||||
}
|
||||
self._tile_grid = TileGrid(columns=2, padding=20, uniform_width=True)
|
||||
|
||||
for name, panel in self._sub_panels.items():
|
||||
if hasattr(panel, 'set_navigate_callback'):
|
||||
@@ -91,6 +93,7 @@ class StarPilotDataLayout(StarPilotPanel):
|
||||
class StarPilotBackupsLayout(StarPilotPanel):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._tile_grid = TileGrid(columns=2, padding=20, uniform_width=True)
|
||||
self.CATEGORIES = [
|
||||
{"title": tr_noop("Create Backup"), "type": "hub", "on_click": self._on_create_backup, "color": "#D43D8A"},
|
||||
{"title": tr_noop("Restore Backup"), "type": "hub", "on_click": self._on_restore_backup, "color": "#D43D8A"},
|
||||
@@ -158,6 +161,7 @@ class StarPilotBackupsLayout(StarPilotPanel):
|
||||
class StarPilotToggleBackupsLayout(StarPilotPanel):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._tile_grid = TileGrid(columns=2, padding=20, uniform_width=True)
|
||||
self.CATEGORIES = [
|
||||
{"title": tr_noop("Create Toggle Backup"), "type": "hub", "on_click": self._on_create, "color": "#D43D8A"},
|
||||
{"title": tr_noop("Restore Toggle Backup"), "type": "hub", "on_click": self._on_restore, "color": "#D43D8A"},
|
||||
@@ -232,8 +236,9 @@ class StarPilotToggleBackupsLayout(StarPilotPanel):
|
||||
class StarPilotStorageLayout(StarPilotPanel):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._tile_grid = TileGrid(columns=2, padding=20, uniform_width=True)
|
||||
self.CATEGORIES = [
|
||||
{"title": tr_noop("Driving Data"), "type": "value", "get_value": self._get_storage, "on_click": lambda: None, "color": "#D43D8A"},
|
||||
{"title": tr_noop("Driving Data"), "type": "value", "get_value": self._get_storage, "on_click": lambda: None, "color": "#D43D8A", "is_enabled": lambda: False},
|
||||
]
|
||||
self._rebuild_grid()
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ from openpilot.system.ui.widgets import DialogResult
|
||||
from openpilot.system.ui.widgets.confirm_dialog import ConfirmDialog
|
||||
from openpilot.system.ui.widgets.selection_dialog import SelectionDialog
|
||||
from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import StarPilotPanel
|
||||
from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import AetherSliderDialog
|
||||
from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import AetherSliderDialog, TileGrid
|
||||
|
||||
|
||||
class StarPilotDeviceLayout(StarPilotPanel):
|
||||
@@ -61,6 +61,7 @@ class StarPilotDeviceLayout(StarPilotPanel):
|
||||
"screen": StarPilotScreenLayout(),
|
||||
"device_settings": StarPilotDeviceManagementLayout(),
|
||||
}
|
||||
self._tile_grid = TileGrid(columns=2, padding=20, uniform_width=True)
|
||||
|
||||
for name, panel in self._sub_panels.items():
|
||||
if hasattr(panel, 'set_navigate_callback'):
|
||||
@@ -128,6 +129,7 @@ class StarPilotDeviceLayout(StarPilotPanel):
|
||||
class StarPilotScreenLayout(StarPilotPanel):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._tile_grid = TileGrid(columns=2, padding=20, uniform_width=True)
|
||||
self.CATEGORIES = [
|
||||
{
|
||||
"title": tr_noop("Screen Settings"),
|
||||
@@ -222,6 +224,7 @@ class StarPilotScreenLayout(StarPilotPanel):
|
||||
class StarPilotDeviceManagementLayout(StarPilotPanel):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._tile_grid = TileGrid(columns=2, padding=20, uniform_width=True)
|
||||
self.CATEGORIES = [
|
||||
{
|
||||
"title": tr_noop("Device Settings"),
|
||||
|
||||
@@ -16,6 +16,7 @@ from openpilot.selfdrive.ui.layouts.settings.starpilot.maps import StarPilotMaps
|
||||
from openpilot.selfdrive.ui.layouts.settings.starpilot.navigation import StarPilotNavigationLayout
|
||||
from openpilot.selfdrive.ui.layouts.settings.starpilot.data import StarPilotDataLayout
|
||||
from openpilot.selfdrive.ui.layouts.settings.starpilot.device import StarPilotDeviceLayout
|
||||
from openpilot.selfdrive.ui.layouts.settings.starpilot.system_settings import StarPilotSystemLayout
|
||||
from openpilot.selfdrive.ui.layouts.settings.starpilot.utilities import StarPilotUtilitiesLayout
|
||||
from openpilot.selfdrive.ui.layouts.settings.starpilot.visuals import StarPilotVisualsLayout
|
||||
from openpilot.selfdrive.ui.layouts.settings.starpilot.themes import StarPilotThemesLayout
|
||||
@@ -52,8 +53,8 @@ class StarPilotLayout(Widget):
|
||||
{
|
||||
"title": "System Settings",
|
||||
"icon": "icon_system.png",
|
||||
"desc": "Manage backups, device settings, screen options, storage, and tools to keep StarPilot running smoothly.",
|
||||
"buttons": [("DATA", "DATA", 0), ("DEVICE CONTROLS", "DEVICE", 0), ("UTILITIES", "UTILITIES", 0)],
|
||||
"desc": "Adjust device behavior, manage storage and backups, and access maintenance tools from one touch-friendly settings page.",
|
||||
"buttons": [("MANAGE", "SYSTEM", 0)],
|
||||
"color": "#D946EF",
|
||||
},
|
||||
{
|
||||
@@ -87,6 +88,7 @@ class StarPilotLayout(Widget):
|
||||
self._panels = {
|
||||
StarPilotPanelType.MAIN: StarPilotPanelInfo("", None),
|
||||
StarPilotPanelType.SOUNDS: StarPilotPanelInfo(tr_noop("Sounds"), StarPilotSoundsLayout()),
|
||||
StarPilotPanelType.SYSTEM: StarPilotPanelInfo(tr_noop("System Settings"), StarPilotSystemLayout()),
|
||||
StarPilotPanelType.DRIVING_MODEL: StarPilotPanelInfo(tr_noop("Driving Model"), StarPilotDrivingModelLayout()),
|
||||
StarPilotPanelType.LONGITUDINAL: StarPilotPanelInfo(tr_noop("Gas / Brake"), StarPilotLongitudinalLayout()),
|
||||
StarPilotPanelType.LATERAL: StarPilotPanelInfo(tr_noop("Steering"), StarPilotLateralLayout()),
|
||||
@@ -101,11 +103,14 @@ class StarPilotLayout(Widget):
|
||||
StarPilotPanelType.WHEEL: StarPilotPanelInfo(tr_noop("Wheel Controls"), StarPilotWheelLayout()),
|
||||
}
|
||||
|
||||
self._setup_longitudinal_sub_panels()
|
||||
self._setup_sounds_sub_panels()
|
||||
self._setup_lateral_sub_panels()
|
||||
self._setup_navigation_sub_panels()
|
||||
self._setup_maps_sub_panels()
|
||||
self._setup_sub_panels(
|
||||
StarPilotPanelType.LONGITUDINAL,
|
||||
StarPilotPanelType.SOUNDS,
|
||||
StarPilotPanelType.SYSTEM,
|
||||
StarPilotPanelType.LATERAL,
|
||||
StarPilotPanelType.NAVIGATION,
|
||||
StarPilotPanelType.MAPS,
|
||||
)
|
||||
|
||||
self._main_grid = TileGrid(columns=None, padding=20)
|
||||
self._rebuild_grid()
|
||||
@@ -162,66 +167,28 @@ class StarPilotLayout(Widget):
|
||||
self._update_depth()
|
||||
|
||||
def _update_sub_panel_visibility(self):
|
||||
if self._current_panel == StarPilotPanelType.LONGITUDINAL:
|
||||
longitudinal = self._panels[StarPilotPanelType.LONGITUDINAL].instance
|
||||
if longitudinal:
|
||||
current_sub = self._get_current_sub_panel()
|
||||
if hasattr(longitudinal, 'set_current_sub_panel'):
|
||||
longitudinal.set_current_sub_panel(current_sub)
|
||||
elif self._current_panel == StarPilotPanelType.SOUNDS:
|
||||
sounds = self._panels[StarPilotPanelType.SOUNDS].instance
|
||||
if sounds:
|
||||
current_sub = self._get_current_sub_panel()
|
||||
if hasattr(sounds, '_navigate_to'):
|
||||
sounds._current_sub_panel = current_sub
|
||||
elif self._current_panel == StarPilotPanelType.NAVIGATION:
|
||||
nav = self._panels[StarPilotPanelType.NAVIGATION].instance
|
||||
if nav:
|
||||
current_sub = self._get_current_sub_panel()
|
||||
if hasattr(nav, '_navigate_to'):
|
||||
nav._current_sub_panel = current_sub
|
||||
elif self._current_panel == StarPilotPanelType.MAPS:
|
||||
maps = self._panels[StarPilotPanelType.MAPS].instance
|
||||
if maps:
|
||||
current_sub = self._get_current_sub_panel()
|
||||
if hasattr(maps, '_navigate_to'):
|
||||
maps._current_sub_panel = current_sub
|
||||
panel = self._panels[self._current_panel].instance
|
||||
current_sub = self._get_current_sub_panel()
|
||||
if panel and hasattr(panel, 'set_current_sub_panel'):
|
||||
panel.set_current_sub_panel(current_sub)
|
||||
|
||||
def _get_current_sub_panel(self) -> str:
|
||||
if self._panel_stack and self._panel_stack[-1][0] == self._current_panel:
|
||||
return self._panel_stack[-1][1]
|
||||
return ""
|
||||
|
||||
def _setup_longitudinal_sub_panels(self):
|
||||
longitudinal = self._panels[StarPilotPanelType.LONGITUDINAL].instance
|
||||
if longitudinal and hasattr(longitudinal, 'set_navigate_callback'):
|
||||
longitudinal.set_navigate_callback(self._push_sub_panel)
|
||||
|
||||
def _setup_sounds_sub_panels(self):
|
||||
sounds = self._panels[StarPilotPanelType.SOUNDS].instance
|
||||
if sounds and hasattr(sounds, 'set_navigate_callback'):
|
||||
sounds.set_navigate_callback(self._push_sub_panel)
|
||||
|
||||
def _setup_lateral_sub_panels(self):
|
||||
lateral = self._panels[StarPilotPanelType.LATERAL].instance
|
||||
if lateral and hasattr(lateral, 'set_navigate_callback'):
|
||||
lateral.set_navigate_callback(self._push_sub_panel)
|
||||
|
||||
def _setup_navigation_sub_panels(self):
|
||||
nav = self._panels[StarPilotPanelType.NAVIGATION].instance
|
||||
if nav and hasattr(nav, 'set_navigate_callback'):
|
||||
nav.set_navigate_callback(self._push_sub_panel)
|
||||
|
||||
def _setup_maps_sub_panels(self):
|
||||
maps = self._panels[StarPilotPanelType.MAPS].instance
|
||||
if maps and hasattr(maps, 'set_navigate_callback'):
|
||||
maps.set_navigate_callback(self._push_sub_panel)
|
||||
def _setup_sub_panels(self, *panel_types: StarPilotPanelType):
|
||||
for panel_type in panel_types:
|
||||
panel = self._panels[panel_type].instance
|
||||
if panel and hasattr(panel, 'set_navigate_callback'):
|
||||
panel.set_navigate_callback(self._push_sub_panel)
|
||||
|
||||
def _rebuild_grid(self):
|
||||
self._main_grid.clear()
|
||||
|
||||
panel_type_map = {
|
||||
"SOUNDS": StarPilotPanelType.SOUNDS,
|
||||
"SYSTEM": StarPilotPanelType.SYSTEM,
|
||||
"DRIVING_MODEL": StarPilotPanelType.DRIVING_MODEL,
|
||||
"LONGITUDINAL": StarPilotPanelType.LONGITUDINAL,
|
||||
"LATERAL": StarPilotPanelType.LATERAL,
|
||||
|
||||
@@ -25,6 +25,7 @@ class StarPilotPanelType(IntEnum):
|
||||
THEMES = 11
|
||||
VEHICLE = 12
|
||||
WHEEL = 13
|
||||
SYSTEM = 14
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -55,6 +56,9 @@ class StarPilotPanel(Widget):
|
||||
def set_back_callback(self, callback: Callable):
|
||||
self._back_callback = callback
|
||||
|
||||
def set_current_sub_panel(self, sub_panel: str):
|
||||
self._current_sub_panel = sub_panel
|
||||
|
||||
def _rebuild_grid(self):
|
||||
if not self.CATEGORIES:
|
||||
return
|
||||
@@ -84,9 +88,9 @@ class StarPilotPanel(Widget):
|
||||
bg_color=cat.get("color"),
|
||||
)
|
||||
elif tile_type == "toggle":
|
||||
tile = ToggleTile(title=tr(cat["title"]), get_state=cat["get_state"], set_state=cat["set_state"], icon_path=cat.get("icon"), bg_color=cat.get("color"), desc=tr(cat.get("desc", "")))
|
||||
tile = ToggleTile(title=tr(cat["title"]), get_state=cat["get_state"], set_state=cat["set_state"], icon_path=cat.get("icon"), bg_color=cat.get("color"), desc=tr(cat.get("desc", "")), is_enabled=cat.get("is_enabled"), disabled_label=cat.get("disabled_label", ""))
|
||||
elif tile_type == "value":
|
||||
tile = ValueTile(title=tr(cat["title"]), get_value=cat["get_value"], on_click=cat["on_click"], icon_path=cat.get("icon"), bg_color=cat.get("color"), desc=tr(cat.get("desc", "")))
|
||||
tile = ValueTile(title=tr(cat["title"]), get_value=cat["get_value"], on_click=cat["on_click"], icon_path=cat.get("icon"), bg_color=cat.get("color"), is_enabled=cat.get("is_enabled"), desc=tr(cat.get("desc", "")))
|
||||
else:
|
||||
continue
|
||||
|
||||
|
||||
@@ -2,16 +2,17 @@ from __future__ import annotations
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
import pyray as rl
|
||||
|
||||
from openpilot.common.basedir import BASEDIR
|
||||
from openpilot.starpilot.common.starpilot_variables import ACTIVE_THEME_PATH
|
||||
from openpilot.system.ui.lib.application import gui_app
|
||||
from openpilot.system.ui.lib.multilang import tr, tr_noop
|
||||
from openpilot.system.ui.widgets import DialogResult
|
||||
from openpilot.system.ui.widgets.selection_dialog import SelectionDialog
|
||||
from openpilot.selfdrive.ui.ui_state import ui_state
|
||||
from openpilot.selfdrive.ui.lib.starpilot_state import starpilot_state
|
||||
from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import StarPilotPanel
|
||||
from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import TileGrid, ToggleTile, AetherSliderDialog
|
||||
from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import TileGrid, ToggleTile, AetherSliderDialog, RadioTileGroup
|
||||
|
||||
class StarPilotSoundsLayout(StarPilotPanel):
|
||||
COOLDOWN_KEY = "SwitchbackModeCooldown"
|
||||
@@ -36,41 +37,73 @@ class StarPilotSoundsLayout(StarPilotPanel):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self._section_names = ["volume_control", "custom_alerts"]
|
||||
self._active_section = self._section_names[0]
|
||||
self._sub_panels = {
|
||||
"volume_control": StarPilotVolumeControlLayout(),
|
||||
"custom_alerts": StarPilotCustomAlertsLayout(),
|
||||
}
|
||||
|
||||
self.CATEGORIES = [
|
||||
{
|
||||
"title": tr_noop("Alert Volume Controller"),
|
||||
"panel": "volume_control",
|
||||
"desc": tr_noop("Adjust volume levels for different alert types."),
|
||||
"icon": "toggle_icons/icon_mute.png",
|
||||
"color": "#E63956"
|
||||
},
|
||||
{
|
||||
"title": tr_noop("StarPilot Alerts"),
|
||||
"panel": "custom_alerts",
|
||||
"desc": tr_noop("Enable or disable specific StarPilot-only alerts."),
|
||||
"icon": "toggle_icons/icon_green_light.png",
|
||||
"color": "#E63956"
|
||||
},
|
||||
]
|
||||
self._section_tabs = RadioTileGroup(
|
||||
"",
|
||||
[tr("Volumes"), tr("Alerts")],
|
||||
0,
|
||||
self._on_section_change,
|
||||
)
|
||||
|
||||
for name, panel in self._sub_panels.items():
|
||||
if hasattr(panel, 'set_navigate_callback'):
|
||||
panel.set_navigate_callback(self._navigate_to)
|
||||
panel.set_navigate_callback(lambda sub_panel, section_name=name: self._navigate_to_child(section_name, sub_panel))
|
||||
if hasattr(panel, 'set_back_callback'):
|
||||
panel.set_back_callback(self._go_back)
|
||||
|
||||
self._rebuild_grid()
|
||||
def _on_section_change(self, index: int):
|
||||
if 0 <= index < len(self._section_names):
|
||||
self._set_active_section(self._section_names[index])
|
||||
|
||||
def refresh_visibility(self):
|
||||
for panel in self._sub_panels.values():
|
||||
if hasattr(panel, 'refresh_visibility'):
|
||||
panel.refresh_visibility()
|
||||
def _set_active_section(self, section_name: str, child_panel: str = ""):
|
||||
if section_name not in self._sub_panels:
|
||||
return
|
||||
|
||||
if section_name != self._active_section:
|
||||
self._sub_panels[self._active_section].hide_event()
|
||||
self._active_section = section_name
|
||||
self._sub_panels[self._active_section].show_event()
|
||||
|
||||
self._section_tabs.set_index(self._section_names.index(section_name))
|
||||
panel = self._sub_panels[section_name]
|
||||
if hasattr(panel, 'set_current_sub_panel'):
|
||||
panel.set_current_sub_panel(child_panel)
|
||||
|
||||
def _navigate_to_child(self, section_name: str, child_panel: str):
|
||||
self._set_active_section(section_name, child_panel)
|
||||
if self._navigate_callback:
|
||||
self._navigate_callback(f"{section_name}:{child_panel}")
|
||||
|
||||
def set_current_sub_panel(self, sub_panel: str):
|
||||
super().set_current_sub_panel(sub_panel)
|
||||
if not sub_panel:
|
||||
self._set_active_section(self._active_section, "")
|
||||
return
|
||||
|
||||
if ":" in sub_panel:
|
||||
section_name, child_panel = sub_panel.split(":", 1)
|
||||
self._set_active_section(section_name, child_panel)
|
||||
elif sub_panel in self._section_names:
|
||||
self._set_active_section(sub_panel)
|
||||
|
||||
def _render(self, rect):
|
||||
tab_rect = rl.Rectangle(rect.x, rect.y, rect.width, 110)
|
||||
panel_rect = rl.Rectangle(rect.x, rect.y + 140, rect.width, rect.height - 140)
|
||||
self._section_tabs.render(tab_rect)
|
||||
self._sub_panels[self._active_section].render(panel_rect)
|
||||
|
||||
def show_event(self):
|
||||
super().show_event()
|
||||
self._sub_panels[self._active_section].show_event()
|
||||
|
||||
def hide_event(self):
|
||||
super().hide_event()
|
||||
self._sub_panels[self._active_section].hide_event()
|
||||
|
||||
class StarPilotVolumeControlLayout(StarPilotPanel):
|
||||
COOLDOWN_INFO = {"title": tr_noop("Switchback Mode Cooldown"), "icon": "toggle_icons/icon_mute.png", "min": 0, "max": 30}
|
||||
@@ -90,6 +123,7 @@ class StarPilotVolumeControlLayout(StarPilotPanel):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._init_sound_player()
|
||||
self._tile_grid = TileGrid(columns=2, padding=20, uniform_width=True)
|
||||
|
||||
self.CATEGORIES = []
|
||||
for key in StarPilotSoundsLayout.VOLUME_KEYS:
|
||||
@@ -217,6 +251,7 @@ class StarPilotCustomAlertsLayout(StarPilotPanel):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._tile_grid = TileGrid(columns=2, padding=20, uniform_width=True)
|
||||
self.CATEGORIES = []
|
||||
for key in StarPilotSoundsLayout.CUSTOM_ALERTS_KEYS:
|
||||
info = self.ALERT_INFO[key]
|
||||
@@ -231,32 +266,32 @@ class StarPilotCustomAlertsLayout(StarPilotPanel):
|
||||
})
|
||||
self._rebuild_grid()
|
||||
|
||||
def refresh_visibility(self):
|
||||
self._rebuild_grid()
|
||||
|
||||
def _rebuild_grid(self):
|
||||
# Override to add custom BSM/SLC visibility logic
|
||||
if not self.CATEGORIES: return
|
||||
if self._tile_grid is None: self._tile_grid = TileGrid(columns=None, padding=20)
|
||||
if not self.CATEGORIES:
|
||||
return
|
||||
self._tile_grid.clear()
|
||||
|
||||
for cat in self.CATEGORIES:
|
||||
key = cat.get("key")
|
||||
visible = True
|
||||
is_enabled = lambda: True
|
||||
disabled_label = ""
|
||||
|
||||
if key == "LoudBlindspotAlert":
|
||||
visible &= starpilot_state.car_state.hasBSM
|
||||
is_enabled = lambda: starpilot_state.car_state.hasBSM
|
||||
disabled_label = tr_noop("Needs BSM")
|
||||
elif key == "SpeedLimitChangedAlert":
|
||||
visible &= self._params.get_bool("ShowSpeedLimits") or (
|
||||
is_enabled = lambda: self._params.get_bool("ShowSpeedLimits") or (
|
||||
starpilot_state.car_state.hasOpenpilotLongitudinal and self._params.get_bool("SpeedLimitController")
|
||||
)
|
||||
disabled_label = tr_noop("Needs Speed Limits")
|
||||
|
||||
if not visible: continue
|
||||
|
||||
tile = ToggleTile( title=tr(cat["title"]),
|
||||
tile = ToggleTile(
|
||||
title=tr(cat["title"]),
|
||||
get_state=cat["get_state"],
|
||||
set_state=cat["set_state"],
|
||||
icon_path=cat.get("icon"),
|
||||
bg_color=cat.get("color")
|
||||
bg_color=cat.get("color"),
|
||||
is_enabled=is_enabled,
|
||||
disabled_label=tr(disabled_label) if disabled_label else "",
|
||||
)
|
||||
self._tile_grid.add_tile(tile)
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import pyray as rl
|
||||
|
||||
from openpilot.system.ui.lib.multilang import tr
|
||||
|
||||
from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import StarPilotPanel
|
||||
from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import RadioTileGroup
|
||||
from openpilot.selfdrive.ui.layouts.settings.starpilot.data import StarPilotDataLayout
|
||||
from openpilot.selfdrive.ui.layouts.settings.starpilot.device import StarPilotDeviceLayout
|
||||
from openpilot.selfdrive.ui.layouts.settings.starpilot.utilities import StarPilotUtilitiesLayout
|
||||
|
||||
|
||||
class StarPilotSystemLayout(StarPilotPanel):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self._section_names = ["device", "data_and_backups", "utilities"]
|
||||
self._active_section = self._section_names[0]
|
||||
self._sub_panels = {
|
||||
"device": StarPilotDeviceLayout(),
|
||||
"data_and_backups": StarPilotDataLayout(),
|
||||
"utilities": StarPilotUtilitiesLayout(),
|
||||
}
|
||||
|
||||
self._section_tabs = RadioTileGroup(
|
||||
"",
|
||||
[tr("Device"), tr("Data"), tr("Utilities")],
|
||||
0,
|
||||
self._on_section_change,
|
||||
)
|
||||
|
||||
for name, panel in self._sub_panels.items():
|
||||
if hasattr(panel, 'set_navigate_callback'):
|
||||
panel.set_navigate_callback(lambda sub_panel, section_name=name: self._navigate_to_child(section_name, sub_panel))
|
||||
if hasattr(panel, 'set_back_callback'):
|
||||
panel.set_back_callback(self._go_back)
|
||||
|
||||
def _on_section_change(self, index: int):
|
||||
if 0 <= index < len(self._section_names):
|
||||
self._set_active_section(self._section_names[index])
|
||||
|
||||
def _set_active_section(self, section_name: str, child_panel: str = ""):
|
||||
if section_name not in self._sub_panels:
|
||||
return
|
||||
|
||||
if section_name != self._active_section:
|
||||
self._sub_panels[self._active_section].hide_event()
|
||||
self._active_section = section_name
|
||||
self._sub_panels[self._active_section].show_event()
|
||||
|
||||
self._section_tabs.set_index(self._section_names.index(section_name))
|
||||
panel = self._sub_panels[section_name]
|
||||
if hasattr(panel, 'set_current_sub_panel'):
|
||||
panel.set_current_sub_panel(child_panel)
|
||||
|
||||
def _navigate_to_child(self, section_name: str, child_panel: str):
|
||||
self._set_active_section(section_name, child_panel)
|
||||
if self._navigate_callback:
|
||||
self._navigate_callback(f"{section_name}:{child_panel}")
|
||||
|
||||
def set_current_sub_panel(self, sub_panel: str):
|
||||
super().set_current_sub_panel(sub_panel)
|
||||
if not sub_panel:
|
||||
self._set_active_section(self._active_section, "")
|
||||
return
|
||||
|
||||
if ":" in sub_panel:
|
||||
section_name, child_panel = sub_panel.split(":", 1)
|
||||
self._set_active_section(section_name, child_panel)
|
||||
elif sub_panel in self._section_names:
|
||||
self._set_active_section(sub_panel)
|
||||
|
||||
def _render(self, rect):
|
||||
tab_rect = rl.Rectangle(rect.x, rect.y, rect.width, 110)
|
||||
panel_rect = rl.Rectangle(rect.x, rect.y + 140, rect.width, rect.height - 140)
|
||||
self._section_tabs.render(tab_rect)
|
||||
self._sub_panels[self._active_section].render(panel_rect)
|
||||
|
||||
def show_event(self):
|
||||
super().show_event()
|
||||
self._sub_panels[self._active_section].show_event()
|
||||
|
||||
def hide_event(self):
|
||||
super().hide_event()
|
||||
self._sub_panels[self._active_section].hide_event()
|
||||
@@ -8,6 +8,7 @@ from openpilot.system.ui.widgets.confirm_dialog import ConfirmDialog, alert_dial
|
||||
from openpilot.system.ui.widgets.selection_dialog import SelectionDialog
|
||||
from openpilot.system.ui.widgets.input_dialog import InputDialog
|
||||
from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import StarPilotPanel
|
||||
from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import TileGrid
|
||||
|
||||
EXCLUDED_KEYS = {
|
||||
"AvailableModels",
|
||||
@@ -38,6 +39,7 @@ REPORT_CATEGORIES = [
|
||||
class StarPilotUtilitiesLayout(StarPilotPanel):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._tile_grid = TileGrid(columns=2, padding=20, uniform_width=True)
|
||||
self.CATEGORIES = [
|
||||
{
|
||||
"title": tr_noop("Debug Mode"),
|
||||
|
||||
Reference in New Issue
Block a user