From ae4c155c6e46adceb2e5893677231d51fce494ef Mon Sep 17 00:00:00 2001 From: firestarsdog <229254897+firestarsdog@users.noreply.github.com> Date: Fri, 1 May 2026 01:35:44 -0400 Subject: [PATCH] BigUI WIP: Cleanerish --- .../layouts/settings/starpilot/aethergrid.py | 52 +++++++++ .../settings/starpilot/driving_model.py | 102 +++++++----------- .../ui/layouts/settings/starpilot/maps.py | 17 ++- .../ui/layouts/settings/starpilot/sounds.py | 38 +++---- .../settings/starpilot/system_settings.py | 25 ++--- 5 files changed, 119 insertions(+), 115 deletions(-) diff --git a/selfdrive/ui/layouts/settings/starpilot/aethergrid.py b/selfdrive/ui/layouts/settings/starpilot/aethergrid.py index a0948eef5..4fbd6828c 100644 --- a/selfdrive/ui/layouts/settings/starpilot/aethergrid.py +++ b/selfdrive/ui/layouts/settings/starpilot/aethergrid.py @@ -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) diff --git a/selfdrive/ui/layouts/settings/starpilot/driving_model.py b/selfdrive/ui/layouts/settings/starpilot/driving_model.py index d44f996d9..66db297aa 100644 --- a/selfdrive/ui/layouts/settings/starpilot/driving_model.py +++ b/selfdrive/ui/layouts/settings/starpilot/driving_model.py @@ -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): diff --git a/selfdrive/ui/layouts/settings/starpilot/maps.py b/selfdrive/ui/layouts/settings/starpilot/maps.py index a06f62387..bd4fb317c 100644 --- a/selfdrive/ui/layouts/settings/starpilot/maps.py +++ b/selfdrive/ui/layouts/settings/starpilot/maps.py @@ -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) diff --git a/selfdrive/ui/layouts/settings/starpilot/sounds.py b/selfdrive/ui/layouts/settings/starpilot/sounds.py index 8f3054d1b..0feba95e1 100644 --- a/selfdrive/ui/layouts/settings/starpilot/sounds.py +++ b/selfdrive/ui/layouts/settings/starpilot/sounds.py @@ -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") diff --git a/selfdrive/ui/layouts/settings/starpilot/system_settings.py b/selfdrive/ui/layouts/settings/starpilot/system_settings.py index 27b951d8f..b1e97371f 100644 --- a/selfdrive/ui/layouts/settings/starpilot/system_settings.py +++ b/selfdrive/ui/layouts/settings/starpilot/system_settings.py @@ -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, )