mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-07-03 20:42:09 +08:00
BigUI WIP: Cleanerish
This commit is contained in:
@@ -333,6 +333,58 @@ def draw_list_panel_shell(frame: AetherListFrame, style: PanelStyle | None = Non
|
||||
_draw_rounded_stroke(glow_rect, _with_alpha(glow, 14), radius_px=20)
|
||||
|
||||
|
||||
def init_list_panel(rect: rl.Rectangle, style: PanelStyle | None = None) -> tuple[AetherListFrame, rl.Rectangle, float]:
|
||||
frame = build_list_panel_frame(rect)
|
||||
draw_list_panel_shell(frame, style)
|
||||
scroll_rect = frame.scroll
|
||||
content_width = scroll_rect.width - AETHER_LIST_METRICS.content_right_gutter
|
||||
return frame, scroll_rect, content_width
|
||||
|
||||
|
||||
def draw_interactive_rect(target_id: str, rect: rl.Rectangle, interactive_rects: dict[str, rl.Rectangle],
|
||||
pressed_target: str | None, scroll_rect: rl.Rectangle | None = None,
|
||||
pad_x: float = 6, pad_y: float = 0) -> tuple[bool, bool]:
|
||||
interactive_rects[target_id] = rect
|
||||
mouse_pos = gui_app.last_mouse_event.pos
|
||||
hovered = _point_hits(mouse_pos, rect, scroll_rect, pad_x=pad_x, pad_y=pad_y)
|
||||
pressed = pressed_target == target_id and hovered
|
||||
return hovered, pressed
|
||||
|
||||
|
||||
def resolve_interactive_target(mouse_pos: MousePos, interactive_rects: dict[str, rl.Rectangle],
|
||||
scroll_rect: rl.Rectangle | None = None,
|
||||
pad_x: float = 6, pad_y: float = 0) -> str | None:
|
||||
for target_id, rect in interactive_rects.items():
|
||||
if _point_hits(mouse_pos, rect, scroll_rect, pad_x=pad_x, pad_y=pad_y):
|
||||
return target_id
|
||||
return None
|
||||
|
||||
|
||||
PANEL_HEADER_TITLE_Y: int = 4
|
||||
PANEL_HEADER_SUBTITLE_Y: int = 48
|
||||
PANEL_HEADER_TITLE_FONT_SIZE: int = 40
|
||||
PANEL_HEADER_SUBTITLE_FONT_SIZE: int = 22
|
||||
PANEL_HEADER_TITLE_FONT: FontWeight = FontWeight.SEMI_BOLD
|
||||
PANEL_HEADER_SUBTITLE_FONT: FontWeight = FontWeight.NORMAL
|
||||
|
||||
|
||||
def draw_settings_panel_header(header_rect: rl.Rectangle, title: str, subtitle: str | None = None,
|
||||
*,
|
||||
title_size: int = PANEL_HEADER_TITLE_FONT_SIZE,
|
||||
subtitle_size: int = PANEL_HEADER_SUBTITLE_FONT_SIZE,
|
||||
max_title_width: float = 0.55,
|
||||
max_subtitle_width: float = 0.58,
|
||||
title_color: rl.Color = AetherListColors.HEADER,
|
||||
subtitle_color: rl.Color = AetherListColors.SUBTEXT,
|
||||
title_weight: FontWeight = PANEL_HEADER_TITLE_FONT,
|
||||
subtitle_weight: FontWeight = PANEL_HEADER_SUBTITLE_FONT):
|
||||
title_rect = rl.Rectangle(header_rect.x, header_rect.y + PANEL_HEADER_TITLE_Y, header_rect.width * max_title_width, title_size + 2)
|
||||
gui_label(title_rect, title, title_size, title_color, title_weight)
|
||||
if subtitle:
|
||||
subtitle_rect = rl.Rectangle(header_rect.x, header_rect.y + PANEL_HEADER_SUBTITLE_Y, header_rect.width * max_subtitle_width, subtitle_size + 4)
|
||||
gui_label(subtitle_rect, subtitle, subtitle_size, subtitle_color, subtitle_weight)
|
||||
|
||||
|
||||
def draw_soft_card(rect: rl.Rectangle, fill: rl.Color, border: rl.Color, radius: float = 0.08, segments: int = 18):
|
||||
radius_px = radius * min(rect.width, rect.height)
|
||||
_draw_rounded_fill(rect, fill, radius_px=radius_px, segments=segments)
|
||||
|
||||
@@ -38,6 +38,7 @@ from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import (
|
||||
AetherListColors,
|
||||
AetherScrollbar,
|
||||
AetherSliderDialog,
|
||||
DEFAULT_PANEL_STYLE,
|
||||
_point_hits,
|
||||
draw_action_rail,
|
||||
draw_action_pill,
|
||||
@@ -52,29 +53,15 @@ from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import (
|
||||
draw_list_scroll_fades,
|
||||
draw_section_header,
|
||||
draw_settings_list_row,
|
||||
draw_settings_panel_header,
|
||||
draw_status_led,
|
||||
draw_overflow_dots,
|
||||
init_list_panel,
|
||||
draw_interactive_rect,
|
||||
resolve_interactive_target,
|
||||
)
|
||||
|
||||
|
||||
MODEL_PANEL_BG = AetherListColors.PANEL_BG
|
||||
MODEL_HEADER_TEXT = AetherListColors.HEADER
|
||||
MODEL_SUBTEXT = AetherListColors.SUBTEXT
|
||||
MODEL_MUTED = AetherListColors.MUTED
|
||||
MODEL_ROW_BG = AetherListColors.ROW_BG
|
||||
MODEL_ROW_BORDER = AetherListColors.ROW_BORDER
|
||||
MODEL_ROW_SEPARATOR = AetherListColors.ROW_SEPARATOR
|
||||
MODEL_ROW_HOVER = AetherListColors.ROW_HOVER
|
||||
MODEL_CURRENT_BG = AetherListColors.CURRENT_BG
|
||||
MODEL_CURRENT_BORDER = AetherListColors.CURRENT_BORDER
|
||||
MODEL_ACTION_BG = AetherListColors.ACTION_BG
|
||||
MODEL_ACTION_SEPARATOR = AetherListColors.ACTION_SEPARATOR
|
||||
MODEL_PRIMARY = AetherListColors.PRIMARY
|
||||
MODEL_PRIMARY_SOFT = AetherListColors.PRIMARY_SOFT
|
||||
MODEL_DANGER = AetherListColors.DANGER
|
||||
MODEL_DANGER_SOFT = AetherListColors.DANGER_SOFT
|
||||
MODEL_WARNING = AetherListColors.WARNING
|
||||
|
||||
SECTION_GAP = AETHER_LIST_METRICS.section_gap
|
||||
SECTION_HEADER_HEIGHT = AETHER_LIST_METRICS.section_header_height
|
||||
SECTION_HEADER_GAP = AETHER_LIST_METRICS.section_header_gap
|
||||
@@ -86,6 +73,7 @@ BUTTON_HEIGHT = AETHER_LIST_METRICS.header_button_height
|
||||
FADE_HEIGHT = AETHER_LIST_METRICS.fade_height
|
||||
CONFIRM_TIMEOUT_SECONDS = 3.0
|
||||
TRANSITION_SECONDS = 0.24
|
||||
PANEL_STYLE = DEFAULT_PANEL_STYLE
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -309,17 +297,11 @@ class DrivingModelManagerView(Widget):
|
||||
self._utility_rects.clear()
|
||||
self._menu_sub_rects.clear()
|
||||
|
||||
frame = build_list_panel_frame(rect)
|
||||
frame, scroll_rect, content_width = init_list_panel(rect, PANEL_STYLE)
|
||||
self._shell_rect = frame.shell
|
||||
draw_list_panel_shell(frame)
|
||||
|
||||
header_rect = frame.header
|
||||
self._draw_header(header_rect)
|
||||
|
||||
scroll_rect = frame.scroll
|
||||
self._scroll_rect = scroll_rect
|
||||
|
||||
content_width = scroll_rect.width - AETHER_LIST_METRICS.content_right_gutter
|
||||
self._draw_header(frame.header)
|
||||
self._content_height = self._measure_content_height(content_width)
|
||||
self._scroll_panel.set_enabled(lambda: not self._controller._is_download_active())
|
||||
self._scroll_offset = self._scroll_panel.update(scroll_rect, max(self._content_height, scroll_rect.height))
|
||||
@@ -331,22 +313,16 @@ class DrivingModelManagerView(Widget):
|
||||
if self._content_height > scroll_rect.height:
|
||||
self._draw_scrollbar(scroll_rect)
|
||||
|
||||
draw_list_scroll_fades(scroll_rect, self._content_height, self._scroll_offset, MODEL_PANEL_BG, fade_height=FADE_HEIGHT)
|
||||
draw_list_scroll_fades(scroll_rect, self._content_height, self._scroll_offset, AetherListColors.PANEL_BG, fade_height=FADE_HEIGHT)
|
||||
|
||||
def _draw_header(self, rect: rl.Rectangle):
|
||||
title_rect = rl.Rectangle(rect.x, rect.y + 4, rect.width * 0.55, 40)
|
||||
gui_label(title_rect, tr("Driving Models"), 40, MODEL_HEADER_TEXT, FontWeight.SEMI_BOLD)
|
||||
|
||||
subtitle_text = self._controller.header_description_text()
|
||||
if subtitle_text:
|
||||
subtitle_rect = rl.Rectangle(rect.x, rect.y + 48, rect.width * 0.58, 36)
|
||||
gui_label(subtitle_rect, subtitle_text, 24, MODEL_SUBTEXT, FontWeight.NORMAL)
|
||||
draw_settings_panel_header(rect, tr("Driving Models"), self._controller.header_description_text(), subtitle_size=24)
|
||||
|
||||
current_label_rect = rl.Rectangle(rect.x, rect.y + 96, 150, 22)
|
||||
gui_label(current_label_rect, tr("Current Model"), 20, MODEL_MUTED, FontWeight.MEDIUM)
|
||||
gui_label(current_label_rect, tr("Current Model"), 20, AetherListColors.MUTED, FontWeight.MEDIUM)
|
||||
|
||||
current_value_rect = rl.Rectangle(rect.x + 150, rect.y + 94, rect.width * 0.44, 24)
|
||||
gui_label(current_value_rect, self._controller._current_model_name, 22, MODEL_HEADER_TEXT, FontWeight.MEDIUM)
|
||||
gui_label(current_value_rect, self._controller._current_model_name, 22, AetherListColors.HEADER, FontWeight.MEDIUM)
|
||||
|
||||
right_panel_w = min(390, rect.width * 0.35)
|
||||
btn_gap = 10
|
||||
@@ -422,12 +398,11 @@ class DrivingModelManagerView(Widget):
|
||||
body_inset_x=48,
|
||||
title_top_padding=42,
|
||||
body_height=72,
|
||||
fill=rl.Color(255, 255, 255, 5),
|
||||
border=rl.Color(255, 255, 255, 14),
|
||||
style=PANEL_STYLE,
|
||||
)
|
||||
|
||||
def _draw_model_section(self, x: float, y: float, width: float, title: str, entries: list[ModelCatalogEntry]) -> float:
|
||||
draw_section_header(rl.Rectangle(x, y, width - AETHER_LIST_METRICS.content_right_gutter, SECTION_HEADER_HEIGHT), title)
|
||||
draw_section_header(rl.Rectangle(x, y, width - AETHER_LIST_METRICS.content_right_gutter, SECTION_HEADER_HEIGHT), title, style=PANEL_STYLE)
|
||||
y += SECTION_HEADER_HEIGHT + SECTION_HEADER_GAP
|
||||
|
||||
for index, entry in enumerate(entries):
|
||||
@@ -457,17 +432,17 @@ class DrivingModelManagerView(Widget):
|
||||
pressed=pressed,
|
||||
is_last=is_last,
|
||||
alpha=alpha,
|
||||
row_bg=MODEL_ROW_BG,
|
||||
row_border=MODEL_ROW_BORDER,
|
||||
row_separator=MODEL_ROW_SEPARATOR,
|
||||
row_hover=MODEL_ROW_HOVER,
|
||||
current_bg=MODEL_CURRENT_BG,
|
||||
current_border=MODEL_CURRENT_BORDER,
|
||||
row_bg=AetherListColors.ROW_BG,
|
||||
row_border=AetherListColors.ROW_BORDER,
|
||||
row_separator=AetherListColors.ROW_SEPARATOR,
|
||||
row_hover=AetherListColors.ROW_HOVER,
|
||||
current_bg=AetherListColors.CURRENT_BG,
|
||||
current_border=AetherListColors.CURRENT_BORDER,
|
||||
row_radius=ROW_RADIUS,
|
||||
separator_inset=22,
|
||||
)
|
||||
|
||||
action_rect = draw_action_rail(draw_rect, ACTION_WIDTH, current=current, alpha=alpha, fill=MODEL_ACTION_BG, separator=MODEL_ACTION_SEPARATOR, inset_y=18)
|
||||
action_rect = draw_action_rail(draw_rect, ACTION_WIDTH, current=current, alpha=alpha, fill=AetherListColors.ACTION_BG, separator=AetherListColors.ACTION_SEPARATOR, inset_y=18)
|
||||
|
||||
info_rect = rl.Rectangle(draw_rect.x + 24, draw_rect.y + 18, draw_rect.width - ACTION_WIDTH - 42, draw_rect.height - 36)
|
||||
row_touchable = entry.installed and not self._controller._params.get_bool("ModelRandomizer")
|
||||
@@ -499,11 +474,11 @@ class DrivingModelManagerView(Widget):
|
||||
draw_heart_icon(heart_center, heart_color)
|
||||
heart_offset = 34
|
||||
title_rect = rl.Rectangle(rect.x + heart_offset, rect.y, rect.width - heart_offset, 34)
|
||||
gui_label(title_rect, entry.name, 34, MODEL_HEADER_TEXT, FontWeight.MEDIUM)
|
||||
gui_label(title_rect, entry.name, 34, AetherListColors.HEADER, FontWeight.MEDIUM)
|
||||
|
||||
meta_parts = [part for part in (entry.series, entry.released) if part]
|
||||
meta_rect = rl.Rectangle(rect.x, rect.y + 42, rect.width, 24)
|
||||
gui_label(meta_rect, " • ".join(meta_parts), 22, MODEL_SUBTEXT, FontWeight.NORMAL)
|
||||
gui_label(meta_rect, " • ".join(meta_parts), 22, AetherListColors.SUBTEXT, FontWeight.NORMAL)
|
||||
|
||||
badge_parts: list[str] = []
|
||||
if current:
|
||||
@@ -519,18 +494,18 @@ class DrivingModelManagerView(Widget):
|
||||
|
||||
if badge_parts:
|
||||
badge_rect = rl.Rectangle(rect.x, rect.y + 78, rect.width, 22)
|
||||
badge_color = MODEL_WARNING if entry.partial else MODEL_MUTED
|
||||
badge_color = AetherListColors.WARNING if entry.partial else AetherListColors.MUTED
|
||||
gui_label(badge_rect, " • ".join(badge_parts), 20, badge_color, FontWeight.MEDIUM)
|
||||
|
||||
def _draw_download_action(self, rect: rl.Rectangle):
|
||||
center_x = rect.x + rect.width / 2
|
||||
center_y = rect.y + rect.height / 2 - 8
|
||||
draw_download_icon(rl.Vector2(center_x, center_y), MODEL_HEADER_TEXT)
|
||||
draw_download_icon(rl.Vector2(center_x, center_y), AetherListColors.HEADER)
|
||||
gui_label(
|
||||
rl.Rectangle(rect.x + 16, rect.y + rect.height - 40, rect.width - 32, 22),
|
||||
tr("Download"),
|
||||
18,
|
||||
MODEL_SUBTEXT,
|
||||
AetherListColors.SUBTEXT,
|
||||
FontWeight.MEDIUM,
|
||||
alignment=rl.GuiTextAlignment.TEXT_ALIGN_CENTER,
|
||||
)
|
||||
@@ -538,14 +513,14 @@ class DrivingModelManagerView(Widget):
|
||||
def _draw_downloading_action(self, rect: rl.Rectangle, progress_text: str):
|
||||
center = rl.Vector2(rect.x + rect.width / 2, rect.y + rect.height / 2 - 8)
|
||||
phase = (time.monotonic() * 240.0) % 360.0
|
||||
draw_busy_ring(center, phase, MODEL_PRIMARY)
|
||||
draw_busy_ring(center, phase, AetherListColors.PRIMARY)
|
||||
|
||||
label = progress_text if progress_text else tr("Downloading")
|
||||
gui_label(
|
||||
rl.Rectangle(rect.x + 16, rect.y + rect.height - 40, rect.width - 32, 22),
|
||||
label,
|
||||
17,
|
||||
MODEL_SUBTEXT,
|
||||
AetherListColors.SUBTEXT,
|
||||
FontWeight.MEDIUM,
|
||||
alignment=rl.GuiTextAlignment.TEXT_ALIGN_CENTER,
|
||||
)
|
||||
@@ -555,12 +530,12 @@ class DrivingModelManagerView(Widget):
|
||||
# Three-dot menu indicator
|
||||
center_x = rect.x + rect.width / 2
|
||||
center_y = rect.y + rect.height / 2 - 10
|
||||
draw_overflow_dots(rl.Vector2(center_x, center_y), rl.Color(MODEL_HEADER_TEXT.r, MODEL_HEADER_TEXT.g, MODEL_HEADER_TEXT.b, min(MODEL_HEADER_TEXT.a, 200)))
|
||||
draw_overflow_dots(rl.Vector2(center_x, center_y), rl.Color(AetherListColors.HEADER.r, AetherListColors.HEADER.g, AetherListColors.HEADER.b, min(AetherListColors.HEADER.a, 200)))
|
||||
gui_label(
|
||||
rl.Rectangle(rect.x + 16, rect.y + rect.height - 38, rect.width - 32, 22),
|
||||
tr("Options"),
|
||||
18,
|
||||
MODEL_SUBTEXT,
|
||||
AetherListColors.SUBTEXT,
|
||||
FontWeight.MEDIUM,
|
||||
alignment=rl.GuiTextAlignment.TEXT_ALIGN_CENTER,
|
||||
)
|
||||
@@ -578,31 +553,31 @@ class DrivingModelManagerView(Widget):
|
||||
self._menu_sub_rects[f"{entry.key}:favorite"] = fav_rect
|
||||
|
||||
# Delete button
|
||||
draw_action_pill(delete_rect, tr("Delete"), MODEL_DANGER_SOFT, rl.Color(MODEL_DANGER.r, MODEL_DANGER.g, MODEL_DANGER.b, min(MODEL_DANGER.a, 70)), MODEL_DANGER)
|
||||
draw_action_pill(delete_rect, tr("Delete"), AetherListColors.DANGER_SOFT, rl.Color(AetherListColors.DANGER.r, AetherListColors.DANGER.g, AetherListColors.DANGER.b, min(AetherListColors.DANGER.a, 70)), AetherListColors.DANGER)
|
||||
|
||||
# Favorite toggle button
|
||||
is_fav = entry.user_favorite
|
||||
fav_fill = rl.Color(210, 100, 130, 44) if is_fav else MODEL_PRIMARY_SOFT
|
||||
fav_border = rl.Color((210 if is_fav else MODEL_PRIMARY.r), (100 if is_fav else MODEL_PRIMARY.g), (130 if is_fav else MODEL_PRIMARY.b), min((255 if is_fav else MODEL_PRIMARY.a), 70))
|
||||
fav_text_color = rl.Color(210, 100, 130, 255) if is_fav else MODEL_PRIMARY
|
||||
fav_fill = rl.Color(210, 100, 130, 44) if is_fav else AetherListColors.PRIMARY_SOFT
|
||||
fav_border = rl.Color((210 if is_fav else AetherListColors.PRIMARY.r), (100 if is_fav else AetherListColors.PRIMARY.g), (130 if is_fav else AetherListColors.PRIMARY.b), min((255 if is_fav else AetherListColors.PRIMARY.a), 70))
|
||||
fav_text_color = rl.Color(210, 100, 130, 255) if is_fav else AetherListColors.PRIMARY
|
||||
fav_label = tr("Unfavorite") if is_fav else tr("Favorite")
|
||||
draw_action_pill(fav_rect, fav_label, fav_fill, fav_border, fav_text_color)
|
||||
|
||||
def _draw_current_action(self, rect: rl.Rectangle):
|
||||
chip_rect = rl.Rectangle(rect.x + 24, rect.y + (rect.height - 42) / 2, rect.width - 48, 42)
|
||||
AetherChip(tr("Current"), rl.Color(89, 116, 151, 26), rl.Color(116, 136, 168, 52), MODEL_HEADER_TEXT, font_size=18).render(chip_rect)
|
||||
AetherChip(tr("Current"), rl.Color(89, 116, 151, 26), rl.Color(116, 136, 168, 52), AetherListColors.HEADER, font_size=18).render(chip_rect)
|
||||
|
||||
def _draw_protected_action(self, rect: rl.Rectangle):
|
||||
chip_rect = rl.Rectangle(rect.x + 20, rect.y + (rect.height - 42) / 2, rect.width - 40, 42)
|
||||
AetherChip(tr("Protected"), rl.Color(255, 255, 255, 10), MODEL_MUTED, MODEL_SUBTEXT, font_size=18).render(chip_rect)
|
||||
AetherChip(tr("Protected"), rl.Color(255, 255, 255, 10), AetherListColors.MUTED, AetherListColors.SUBTEXT, font_size=18).render(chip_rect)
|
||||
|
||||
def _draw_utility_section(self, x: float, y: float, width: float, rows: list[dict]):
|
||||
content_w = width - AETHER_LIST_METRICS.content_right_gutter
|
||||
draw_section_header(rl.Rectangle(x, y, content_w, SECTION_HEADER_HEIGHT), tr("Automation and Tuning"))
|
||||
draw_section_header(rl.Rectangle(x, y, content_w, SECTION_HEADER_HEIGHT), tr("Automation and Tuning"), style=PANEL_STYLE)
|
||||
y += SECTION_HEADER_HEIGHT + SECTION_HEADER_GAP
|
||||
|
||||
container_rect = rl.Rectangle(x, y, content_w, len(rows) * UTILITY_ROW_HEIGHT)
|
||||
draw_list_group_shell(container_rect, fill=rl.Color(255, 255, 255, 4), border=rl.Color(255, 255, 255, 15))
|
||||
draw_list_group_shell(container_rect, style=PANEL_STYLE)
|
||||
|
||||
for index, row in enumerate(rows):
|
||||
row_rect = rl.Rectangle(x, y + index * UTILITY_ROW_HEIGHT, content_w, UTILITY_ROW_HEIGHT)
|
||||
@@ -622,6 +597,7 @@ class DrivingModelManagerView(Widget):
|
||||
hovered=hovered,
|
||||
pressed=pressed,
|
||||
is_last=is_last,
|
||||
style=PANEL_STYLE,
|
||||
)
|
||||
|
||||
def _draw_scrollbar(self, rect: rl.Rectangle):
|
||||
|
||||
@@ -36,7 +36,9 @@ from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import (
|
||||
draw_tab_card,
|
||||
draw_selection_list_row,
|
||||
draw_list_scroll_fades,
|
||||
draw_settings_panel_header,
|
||||
draw_soft_card,
|
||||
init_list_panel,
|
||||
_point_hits,
|
||||
)
|
||||
from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import StarPilotPanel
|
||||
@@ -206,7 +208,7 @@ class MapStatusCard(Widget):
|
||||
selection_chip_rect,
|
||||
self._controller._selected_summary_text(),
|
||||
rl.Color(94, 168, 130, 22),
|
||||
rl.Color(94, 168, 130, 44),
|
||||
AetherListColors.SUCCESS_SOFT,
|
||||
AetherListColors.HEADER,
|
||||
font_size=15,
|
||||
)
|
||||
@@ -1121,21 +1123,16 @@ class StarPilotMapsLayout(StarPilotPanel):
|
||||
|
||||
def _render(self, rect: rl.Rectangle):
|
||||
self.set_rect(rect)
|
||||
frame = build_list_panel_frame(rect)
|
||||
draw_list_panel_shell(frame, MAPS_PANEL_STYLE)
|
||||
frame, scroll_rect, content_width = init_list_panel(rect, MAPS_PANEL_STYLE)
|
||||
|
||||
hdr = frame.header
|
||||
title_y = hdr.y + HEADER_TOP_OFFSET
|
||||
subtitle_y = hdr.y + 48
|
||||
gui_label(rl.Rectangle(hdr.x, title_y, hdr.width, HEADER_TITLE_HEIGHT), tr("Map Data"), 40, AetherListColors.HEADER, FontWeight.SEMI_BOLD)
|
||||
gui_label(rl.Rectangle(hdr.x, subtitle_y, hdr.width * 0.60, HEADER_SUBTITLE_HEIGHT), tr("Use offline maps for speed-limit control and keep only the regions you need."), 22, AetherListColors.SUBTEXT, FontWeight.NORMAL)
|
||||
draw_settings_panel_header(hdr, tr("Map Data"), tr("Use offline maps for speed-limit control and keep only the regions you need."),
|
||||
max_title_width=1.0, max_subtitle_width=0.60)
|
||||
|
||||
header_status_y = subtitle_y + HEADER_SUBTITLE_HEIGHT + 12
|
||||
header_status_y = hdr.y + 48 + HEADER_SUBTITLE_HEIGHT + 12
|
||||
header_status_rect = rl.Rectangle(hdr.x, header_status_y, hdr.width, hdr.y + hdr.height - header_status_y - HEADER_BOTTOM_GAP)
|
||||
self._status_card.render(header_status_rect)
|
||||
|
||||
scroll_rect = frame.scroll
|
||||
content_width = scroll_rect.width - AETHER_LIST_METRICS.content_right_gutter
|
||||
scroll_content_rect = rl.Rectangle(scroll_rect.x, scroll_rect.y, scroll_rect.width, scroll_rect.height)
|
||||
self._content_height = self._measure_content_height(content_width)
|
||||
self._scroll_panel.set_enabled(self.is_visible)
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
from __future__ import annotations
|
||||
import math
|
||||
import subprocess
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
import pyray as rl
|
||||
@@ -10,26 +8,22 @@ 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, FontWeight, MouseEvent, MousePos
|
||||
from openpilot.system.ui.lib.multilang import tr, tr_noop
|
||||
from openpilot.system.ui.lib.text_measure import measure_text_cached
|
||||
from openpilot.system.ui.widgets import Widget
|
||||
from openpilot.system.ui.widgets.label import gui_label
|
||||
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 (
|
||||
AETHER_LIST_METRICS,
|
||||
AetherListColors,
|
||||
build_list_panel_frame,
|
||||
draw_list_panel_shell,
|
||||
AetherContinuousSlider,
|
||||
AetherListColors,
|
||||
DEFAULT_PANEL_STYLE,
|
||||
_point_hits,
|
||||
draw_settings_panel_header,
|
||||
draw_toggle_pill,
|
||||
init_list_panel,
|
||||
)
|
||||
|
||||
MODEL_PANEL_BG = AetherListColors.PANEL_BG
|
||||
MODEL_HEADER_TEXT = AetherListColors.HEADER
|
||||
MODEL_SUBTEXT = AetherListColors.SUBTEXT
|
||||
MODEL_MUTED = AetherListColors.MUTED
|
||||
|
||||
PANEL_STYLE = DEFAULT_PANEL_STYLE
|
||||
SECTION_GAP = AETHER_LIST_METRICS.section_gap
|
||||
|
||||
|
||||
@@ -43,7 +37,6 @@ class SoundsManagerView(Widget):
|
||||
self._sliders: dict[str, AetherContinuousSlider] = {}
|
||||
self._slider_was_dragging: dict[str, bool] = {}
|
||||
self._toggle_rects: dict[str, rl.Rectangle] = {}
|
||||
self._font = gui_app.font(FontWeight.BOLD)
|
||||
|
||||
self._init_sliders()
|
||||
|
||||
@@ -109,7 +102,7 @@ class SoundsManagerView(Widget):
|
||||
|
||||
def _target_at(self, mouse_pos: MousePos) -> str | None:
|
||||
for key, rect in self._toggle_rects.items():
|
||||
if rl.check_collision_point_rec(mouse_pos, rect):
|
||||
if _point_hits(mouse_pos, rect, pad_x=6, pad_y=6):
|
||||
return f"toggle:{key}"
|
||||
return None
|
||||
|
||||
@@ -125,16 +118,13 @@ class SoundsManagerView(Widget):
|
||||
self.set_rect(rect)
|
||||
self._toggle_rects.clear()
|
||||
|
||||
frame = build_list_panel_frame(rect)
|
||||
draw_list_panel_shell(frame)
|
||||
frame, _scroll_rect, _content_width = init_list_panel(rect, PANEL_STYLE)
|
||||
|
||||
header_rect = frame.header
|
||||
self._draw_header(header_rect)
|
||||
self._draw_header(frame.header)
|
||||
|
||||
# Reclaim the dead space! The global header allocates 210px, but our text only uses ~100px.
|
||||
metrics = AETHER_LIST_METRICS
|
||||
actual_header_height = 100
|
||||
content_y = header_rect.y + actual_header_height
|
||||
content_y = frame.header.y + actual_header_height
|
||||
content_h = (frame.shell.y + frame.shell.height) - content_y - metrics.panel_padding_bottom
|
||||
|
||||
content_rect = rl.Rectangle(
|
||||
@@ -159,11 +149,7 @@ class SoundsManagerView(Widget):
|
||||
self._slider_was_dragging[key] = is_dragging
|
||||
|
||||
def _draw_header(self, rect: rl.Rectangle):
|
||||
title_rect = rl.Rectangle(rect.x, rect.y + 4, rect.width * 0.55, 40)
|
||||
gui_label(title_rect, tr("Sounds & Alerts"), 40, MODEL_HEADER_TEXT, FontWeight.SEMI_BOLD)
|
||||
|
||||
subtitle_rect = rl.Rectangle(rect.x, rect.y + 48, rect.width * 0.58, 36)
|
||||
gui_label(subtitle_rect, tr("Manage system volumes and custom alert toggles."), 24, MODEL_SUBTEXT, FontWeight.NORMAL)
|
||||
draw_settings_panel_header(rect, tr("Sounds & Alerts"), tr("Manage system volumes and custom alert toggles."), subtitle_size=24)
|
||||
|
||||
def _draw_volume_section(self, rect: rl.Rectangle):
|
||||
num_volumes = len(self._controller.VOLUME_KEYS)
|
||||
@@ -205,7 +191,7 @@ class SoundsManagerView(Widget):
|
||||
is_enabled = info.get("is_enabled", lambda: True)()
|
||||
|
||||
mouse_pos = gui_app.last_mouse_event.pos
|
||||
hovered = rl.check_collision_point_rec(mouse_pos, padded_rect)
|
||||
hovered = _point_hits(mouse_pos, padded_rect, pad_x=6, pad_y=6)
|
||||
pressed = self._pressed_target == f"toggle:{key}"
|
||||
|
||||
status_str = tr("ON") if current_val else tr("OFF")
|
||||
|
||||
@@ -33,12 +33,14 @@ from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import (
|
||||
_point_hits,
|
||||
build_list_panel_frame,
|
||||
draw_list_panel_shell,
|
||||
init_list_panel,
|
||||
draw_list_group_shell,
|
||||
draw_list_scroll_fades,
|
||||
draw_metric_strip,
|
||||
draw_section_header,
|
||||
draw_selection_list_row,
|
||||
draw_settings_list_row,
|
||||
draw_settings_panel_header,
|
||||
draw_soft_card,
|
||||
draw_tab_card,
|
||||
)
|
||||
@@ -78,9 +80,7 @@ REPORT_CATEGORIES = [
|
||||
|
||||
|
||||
class SystemSettingsManagerView(Widget):
|
||||
HEADER_TITLE_HEIGHT = 40
|
||||
HEADER_SUBTITLE_HEIGHT = 24
|
||||
HEADER_TOP_OFFSET = 4
|
||||
HEADER_SUMMARY_GAP = 12
|
||||
HEADER_CARD_HEIGHT = 108
|
||||
TAB_HEIGHT = 52
|
||||
@@ -89,9 +89,7 @@ class SystemSettingsManagerView(Widget):
|
||||
SECTION_GAP = AETHER_LIST_METRICS.section_gap
|
||||
SECTION_HEADER_HEIGHT = AETHER_LIST_METRICS.section_header_height
|
||||
SECTION_HEADER_GAP = AETHER_LIST_METRICS.section_header_gap
|
||||
SLIDER_ROW_HEIGHT = AETHER_LIST_METRICS.range_row_height
|
||||
ROW_HEIGHT = AETHER_COMPACT_ROW_HEIGHT
|
||||
CONTENT_GUTTER = AETHER_LIST_METRICS.content_right_gutter
|
||||
FADE_HEIGHT = AETHER_LIST_METRICS.fade_height
|
||||
COLUMN_GAP = 22
|
||||
TWO_COLUMN_BREAKPOINT = 1180
|
||||
@@ -495,16 +493,12 @@ class SystemSettingsManagerView(Widget):
|
||||
def _render(self, rect: rl.Rectangle):
|
||||
self.set_rect(rect)
|
||||
|
||||
frame = build_list_panel_frame(rect)
|
||||
draw_list_panel_shell(frame, self.PANEL_STYLE)
|
||||
frame, scroll_rect, content_width = init_list_panel(rect, self.PANEL_STYLE)
|
||||
self._scroll_rect = scroll_rect
|
||||
|
||||
self._drive_mode_control.set_parent_rect(frame.header)
|
||||
|
||||
self._draw_header(frame.header)
|
||||
|
||||
scroll_rect = frame.scroll
|
||||
self._scroll_rect = scroll_rect
|
||||
content_width = scroll_rect.width - self.CONTENT_GUTTER
|
||||
self._content_height = self._measure_content_height(content_width)
|
||||
self._scroll_panel.set_enabled(self.is_visible)
|
||||
self._scroll_offset = self._scroll_panel.update(scroll_rect, max(self._content_height, scroll_rect.height))
|
||||
@@ -519,12 +513,11 @@ class SystemSettingsManagerView(Widget):
|
||||
draw_list_scroll_fades(scroll_rect, self._content_height, self._scroll_offset, AetherListColors.PANEL_BG, fade_height=self.FADE_HEIGHT)
|
||||
|
||||
def _draw_header(self, rect: rl.Rectangle):
|
||||
title_y = rect.y + self.HEADER_TOP_OFFSET
|
||||
subtitle_y = rect.y + 48
|
||||
gui_label(rl.Rectangle(rect.x, title_y, rect.width * 0.60, self.HEADER_TITLE_HEIGHT), tr("System Settings"), 40, AetherListColors.HEADER, FontWeight.SEMI_BOLD)
|
||||
gui_label(rl.Rectangle(rect.x, subtitle_y, rect.width * 0.62, self.HEADER_SUBTITLE_HEIGHT), tr("Manage display, backups, connectivity, and device maintenance from one touch-first panel."), 22, AetherListColors.SUBTEXT, FontWeight.NORMAL)
|
||||
draw_settings_panel_header(rect, tr("System Settings"),
|
||||
tr("Manage display, backups, connectivity, and device maintenance from one touch-first panel."),
|
||||
max_title_width=0.60, max_subtitle_width=0.62)
|
||||
|
||||
summary_y = subtitle_y + self.HEADER_SUBTITLE_HEIGHT + self.HEADER_SUMMARY_GAP
|
||||
summary_y = rect.y + 48 + self.HEADER_SUBTITLE_HEIGHT + self.HEADER_SUMMARY_GAP
|
||||
summary_rect = rl.Rectangle(rect.x, summary_y, rect.width, min(self.HEADER_CARD_HEIGHT, rect.y + rect.height - summary_y))
|
||||
self._draw_summary_card(summary_rect)
|
||||
|
||||
@@ -753,7 +746,7 @@ class SystemSettingsManagerView(Widget):
|
||||
subtitle_size=17,
|
||||
action_text_size=15,
|
||||
row_separator=self.PANEL_STYLE.divider_color,
|
||||
action_fill=rl.Color(89, 116, 151, 18),
|
||||
action_fill=AetherListColors.CURRENT_BG,
|
||||
action_border=rl.Color(89, 116, 151, 42),
|
||||
action_text_color=AetherListColors.HEADER,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user