Consistency

This commit is contained in:
firestarsdog
2026-08-23 03:38:38 -04:00
parent 06f9e43e4e
commit e1458d4723
4 changed files with 168 additions and 79 deletions
@@ -1968,10 +1968,12 @@ def draw_metric_strip(
)
GROUP_TOP_INSET = 16.0
GROUP_HEADER_HEIGHT = 30.0
GROUP_HEADER_GAP = 1.0
GROUP_HEADER_LINE_GAP = 1.0
GROUP_OVERHEAD = 8.0 + GROUP_HEADER_HEIGHT + GROUP_HEADER_LINE_GAP + GROUP_HEADER_GAP
GROUP_HEADER_GAP = 10.0
GROUP_HEADER_LINE_GAP = 4.0
GROUP_HEADER_TOTAL_HEIGHT = GROUP_HEADER_HEIGHT + GROUP_HEADER_LINE_GAP + GROUP_HEADER_GAP
GROUP_OVERHEAD = GROUP_TOP_INSET + GROUP_HEADER_TOTAL_HEIGHT
GROUP_HAIRLINE_COLOR = rl.Color(255, 255, 255, 30)
GROUP_HEADER_COLOR = AetherListColors.HEADER
@@ -1979,7 +1981,7 @@ GROUP_HEADER_COLOR = AetherListColors.HEADER
def draw_group_header(x: float, y: float, width: float, label: str) -> float:
gui_label(rl.Rectangle(x, y, max(1.0, width), GROUP_HEADER_HEIGHT), label, 30, GROUP_HEADER_COLOR, FontWeight.MEDIUM)
y += GROUP_HEADER_HEIGHT + GROUP_HEADER_LINE_GAP
rl.draw_line(int(x), int(y), int(x + width), int(y), GROUP_HAIRLINE_COLOR)
rl.draw_line(int(round(x)), int(round(y)), int(round(x + width)), int(round(y)), GROUP_HAIRLINE_COLOR)
return y + GROUP_HEADER_GAP
@@ -2086,7 +2088,7 @@ def draw_settings_list_row(
title_size: int = 49,
subtitle_size: int = 38,
value_size: int = 44,
separator_inset: int = 22,
separator_inset: int = 24,
title_color: rl.Color | None = None,
subtitle_color: rl.Color | None = None,
value_color: rl.Color | None = None,
@@ -2096,7 +2098,12 @@ def draw_settings_list_row(
resolved_title_color = title_color or (style.title_color if enabled else style.muted_color)
resolved_subtitle_color = subtitle_color or (style.subtitle_color if enabled else style.muted_color)
resolved_value_color = value_color or (style.title_color if enabled else style.muted_color)
chevron_rect = rl.Rectangle(draw_rect.x + draw_rect.width - AETHER_LIST_METRICS.utility_chevron_right, draw_rect.y + 18, 26, 26)
is_narrow = draw_rect.width < 1000
chevron_right_inset = 28 if is_narrow else AETHER_LIST_METRICS.utility_chevron_right
chevron_y = draw_rect.y + (draw_rect.height - 26) / 2
chevron_rect = rl.Rectangle(draw_rect.x + draw_rect.width - chevron_right_inset, chevron_y, 26, 26)
draw_list_row_shell(
draw_rect,
hovered=hovered and enabled,
@@ -2110,32 +2117,40 @@ def draw_settings_list_row(
separator_inset=separator_inset,
)
# Compute text width based on right-side elements — no truncation, font-size reduces gracefully
text_left = draw_rect.x + 24
if toggle_value is not None:
text_right = draw_rect.x + draw_rect.width - AETHER_LIST_METRICS.toggle_width - AETHER_LIST_METRICS.toggle_right_inset - 12
elif value:
text_right = draw_rect.x + draw_rect.width - AETHER_LIST_METRICS.utility_value_right - 12
elif show_chevron:
text_right = draw_rect.x + draw_rect.width - AETHER_LIST_METRICS.utility_chevron_right - 26 - 12
else:
text_right = draw_rect.x + draw_rect.width - 24
text_width = max(100.0, text_right - text_left)
draw_text_fit_common(
gui_app.font(FontWeight.MEDIUM), title,
rl.Vector2(text_left, draw_rect.y + 16),
text_width, title_size,
color=resolved_title_color,
)
if subtitle:
draw_text_fit_common(
gui_app.font(FontWeight.NORMAL), subtitle,
rl.Vector2(text_left, draw_rect.y + 64),
text_width, subtitle_size,
color=resolved_subtitle_color,
)
if toggle_value is not None:
toggle_right_inset = 28 if is_narrow else AETHER_LIST_METRICS.toggle_right_inset
text_right = draw_rect.x + draw_rect.width - AETHER_LIST_METRICS.toggle_width - toggle_right_inset - 12
text_width = max(100.0, text_right - text_left)
if subtitle:
eff_title_size = min(36, title_size)
eff_sub_size = min(26, subtitle_size)
total_h = eff_title_size + eff_sub_size + 4
start_y = draw_rect.y + (draw_rect.height - total_h) / 2
draw_text_fit_common(
gui_app.font(FontWeight.MEDIUM), title,
rl.Vector2(text_left, start_y),
text_width, eff_title_size,
color=resolved_title_color,
)
draw_text_fit_common(
gui_app.font(FontWeight.NORMAL), subtitle,
rl.Vector2(text_left, start_y + eff_title_size + 4),
text_width, eff_sub_size,
color=resolved_subtitle_color,
)
else:
title_y = draw_rect.y + (draw_rect.height - title_size) / 2
draw_text_fit_common(
gui_app.font(FontWeight.MEDIUM), title,
rl.Vector2(text_left, title_y),
text_width, title_size,
color=resolved_title_color,
)
target = 1.0 if toggle_value else 0.0
current_progress = _KNOB_ANIMATION_STATES.get(title, target)
dt = rl.get_frame_time()
@@ -2151,26 +2166,99 @@ def draw_settings_list_row(
is_enabled=enabled,
track_color=style.accent,
seed_id=title,
right_inset=toggle_right_inset,
)
return
if value:
value_left = draw_rect.x + draw_rect.width - AETHER_LIST_METRICS.utility_value_right
value_right = chevron_rect.x - 16 if show_chevron else draw_rect.x + draw_rect.width - 24
value_rect = rl.Rectangle(value_left, draw_rect.y + 20, max(48.0, value_right - value_left), 34)
gui_label(
value_rect,
value,
value_size,
resolved_value_color,
FontWeight.MEDIUM,
alignment=rl.GuiTextAlignment.TEXT_ALIGN_RIGHT,
if is_narrow and draw_rect.height >= 86 and not subtitle:
# Adaptive Two-Line Stacked Layout: Title on top, Value spanning full width below
eff_title_size = min(34, title_size)
eff_value_size = min(28, value_size)
available_w = max(100.0, draw_rect.width - 48 - (32 if show_chevron else 0))
total_h = eff_title_size + eff_value_size + 6
start_y = draw_rect.y + (draw_rect.height - total_h) / 2
draw_text_fit_common(
gui_app.font(FontWeight.MEDIUM), title,
rl.Vector2(text_left, start_y),
available_w, eff_title_size,
color=resolved_title_color,
)
draw_text_fit_common(
gui_app.font(FontWeight.MEDIUM), value,
rl.Vector2(text_left, start_y + eff_title_size + 6),
available_w, eff_value_size,
color=resolved_subtitle_color if resolved_value_color == resolved_title_color else resolved_value_color,
)
else:
# Proportional Side-by-Side: 42% Title on left, 56% Value right-aligned before chevron
if is_narrow:
content_w = max(100.0, draw_rect.width - 48 - (32 if show_chevron else 0))
t_width = content_w * 0.42
v_width = content_w * 0.56
v_right = draw_rect.x + 24 + content_w
else:
v_width = max(100.0, float(AETHER_LIST_METRICS.utility_value_right - (AETHER_LIST_METRICS.utility_chevron_right if show_chevron else 24) - 16))
t_width = max(100.0, draw_rect.width - 48 - v_width - (32 if show_chevron else 0))
v_right = chevron_rect.x - 16 if show_chevron else draw_rect.x + draw_rect.width - 24
eff_title_size = min(36, title_size) if is_narrow else title_size
eff_value_size = min(30, value_size) if is_narrow else value_size
title_y = draw_rect.y + (draw_rect.height - eff_title_size) / 2
value_y = draw_rect.y + (draw_rect.height - eff_value_size) / 2
draw_text_fit_common(
gui_app.font(FontWeight.MEDIUM), title,
rl.Vector2(text_left, title_y),
t_width, eff_title_size,
color=resolved_title_color,
)
draw_text_fit_common(
gui_app.font(FontWeight.MEDIUM), value,
rl.Vector2(v_right - v_width, value_y),
v_width, eff_value_size,
align_right=True,
color=resolved_value_color,
)
if show_chevron:
draw_chevron_icon(chevron_rect, style.muted_color)
return
# Generic row without value or toggle
text_right = chevron_rect.x - 12 if show_chevron else draw_rect.x + draw_rect.width - 24
text_width = max(100.0, text_right - text_left)
if subtitle:
eff_title_size = min(36, title_size)
eff_sub_size = min(26, subtitle_size)
total_h = eff_title_size + eff_sub_size + 4
start_y = draw_rect.y + (draw_rect.height - total_h) / 2
draw_text_fit_common(
gui_app.font(FontWeight.MEDIUM), title,
rl.Vector2(text_left, start_y),
text_width, eff_title_size,
color=resolved_title_color,
)
draw_text_fit_common(
gui_app.font(FontWeight.NORMAL), subtitle,
rl.Vector2(text_left, start_y + eff_title_size + 4),
text_width, eff_sub_size,
color=resolved_subtitle_color,
)
else:
title_y = draw_rect.y + (draw_rect.height - title_size) / 2
draw_text_fit_common(
gui_app.font(FontWeight.MEDIUM), title,
rl.Vector2(text_left, title_y),
text_width, title_size,
color=resolved_title_color,
)
if show_chevron:
draw_chevron_icon(
chevron_rect,
style.muted_color,
)
draw_chevron_icon(chevron_rect, style.muted_color)
def draw_selectable_chip(rect: rl.Rectangle, text: str, *,
@@ -34,6 +34,8 @@ from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import (
GROUP_HEADER_HEIGHT,
GROUP_HEADER_GAP,
GROUP_HEADER_LINE_GAP,
GROUP_HEADER_TOTAL_HEIGHT,
GROUP_TOP_INSET,
draw_group_header,
)
@@ -199,8 +201,7 @@ class SoundsManagerView(AdjustorTogglesPanelView):
self._adjustor_rows[key].custom_row_height = None
self._adjustor_rows[self._controller.COOLDOWN_KEY].custom_row_height = None
hdr_h = GROUP_HEADER_HEIGHT + GROUP_HEADER_GAP + GROUP_HEADER_LINE_GAP
vol_overhead = 4 + 24 + 4 # top pad + "Reset All" label + gap
vol_overhead = GROUP_TOP_INSET + 28 # top pad + "Reset All" label
available_h = max(72.0, (self._scroll_rect.height if self._scroll_rect else 0.0) - 6.0)
rows_available = max(72.0 * (len(self._controller.VOLUME_KEYS) + 1), available_h - vol_overhead)
@@ -210,7 +211,7 @@ class SoundsManagerView(AdjustorTogglesPanelView):
self._adjustor_rows[self._controller.COOLDOWN_KEY].custom_row_height = ROW_HEIGHT
left_content_h = (len(self._controller.VOLUME_KEYS) + 1) * ROW_HEIGHT + vol_overhead
tiles_needed_h = self.measure_page_grid_height(self._toggle_grid, col_width - 24) + 24 + 4 + hdr_h
tiles_needed_h = self.measure_page_grid_height(self._toggle_grid, col_width - 24) + 24 + GROUP_TOP_INSET + GROUP_HEADER_TOTAL_HEIGHT
max_content_h = max(left_content_h, tiles_needed_h)
self._left_container_h = max_content_h
@@ -236,7 +237,7 @@ class SoundsManagerView(AdjustorTogglesPanelView):
style=PANEL_STYLE
)
current_y = y + 4
current_y = y + GROUP_TOP_INSET
label_rect = rl.Rectangle(x + 24, current_y, width - 48, 28)
gui_label(label_rect, tr("Reset All"), 28, AetherListColors.SUBTEXT, FontWeight.MEDIUM,
@@ -255,7 +256,7 @@ class SoundsManagerView(AdjustorTogglesPanelView):
def _draw_utility_column(self, y: float, x: float, width: float):
draw_list_group_shell(rl.Rectangle(x, y, width, self._tiles_container_h), style=PANEL_STYLE)
header_y = draw_group_header(x + 24, y + 4, width - 48, tr("Alerts"))
header_y = draw_group_header(x + 24, y + GROUP_TOP_INSET, width - 48, tr("Alerts"))
avail_h = self._tiles_container_h - (header_y - y)
self._render_page_grid(self._toggle_grid, rl.Rectangle(x + 12, header_y, width - 24, max(0.0, avail_h - 12)))
@@ -39,6 +39,8 @@ from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import (
GROUP_HEADER_GAP,
GROUP_HEADER_LINE_GAP,
GROUP_HEADER_HEIGHT,
GROUP_HEADER_TOTAL_HEIGHT,
GROUP_TOP_INSET,
draw_group_header,
AetherSliderDialog,
mix_colors,
@@ -485,9 +487,8 @@ class SystemSettingsManagerView(PanelManagerView):
draw_custom_icon("first_aid", icon_x, icon_y, s, icon_color)
def _measure_content_height(self, width: float) -> float:
hdr_h = GROUP_HEADER_HEIGHT + GROUP_HEADER_LINE_GAP + GROUP_HEADER_GAP
display_h = self._slider_section_height(self._display_slider_keys, width) + 4 + hdr_h
power_h = self._slider_section_height(self._power_slider_keys, width) + 4 + hdr_h
display_h = self._slider_section_height(self._display_slider_keys, width) + GROUP_TOP_INSET + GROUP_HEADER_TOTAL_HEIGHT
power_h = self._slider_section_height(self._power_slider_keys, width) + GROUP_TOP_INSET + GROUP_HEADER_TOTAL_HEIGHT
if self._uses_two_columns(width):
column_w = self._column_width(width)
@@ -499,7 +500,7 @@ class SystemSettingsManagerView(PanelManagerView):
display_container_h = self._slider_section_height(self._display_slider_keys, column_w)
power_container_h = self._slider_section_height(self._power_slider_keys, column_w)
left_overhead = 4.0 + 2 * (GROUP_HEADER_HEIGHT + GROUP_HEADER_LINE_GAP + GROUP_HEADER_GAP) + SECTION_GAP
left_overhead = GROUP_TOP_INSET + 2 * GROUP_HEADER_TOTAL_HEIGHT + SECTION_GAP
left_natural_content_h = left_overhead + display_container_h + power_container_h
tiles_content_h = self.measure_page_grid_height(self._connectivity_tile_grid, column_w - 24)
@@ -550,7 +551,7 @@ class SystemSettingsManagerView(PanelManagerView):
draw_list_group_shell(rl.Rectangle(x, y, column_w, adj_container_h), style=PANEL_STYLE)
current_y = y + 4
current_y = y + GROUP_TOP_INSET
current_y = draw_group_header(x + 24, current_y, column_w - 48, tr("Display"))
for index, key in enumerate(self._display_slider_keys):
current_y = self._draw_slider_row(rl.Rectangle(x, current_y, column_w, 0), key, is_last=index == len(self._display_slider_keys) - 1)
@@ -580,10 +581,10 @@ class SystemSettingsManagerView(PanelManagerView):
self._render_page_grid(self._connectivity_tile_grid, rl.Rectangle(x + 12, y + 12, width - 24, tiles_content_h))
def _draw_slider_section(self, y: float, x: float, width: float, title: str, keys: list[str]) -> float:
group_h = self._slider_section_height(keys, width) + 4 + GROUP_HEADER_HEIGHT + GROUP_HEADER_LINE_GAP + GROUP_HEADER_GAP
group_h = self._slider_section_height(keys, width) + GROUP_TOP_INSET + GROUP_HEADER_TOTAL_HEIGHT
group_rect = rl.Rectangle(x, y, width, group_h)
draw_list_group_shell(group_rect, style=PANEL_STYLE)
current_y = group_rect.y + 4
current_y = group_rect.y + GROUP_TOP_INSET
current_y = draw_group_header(x + 24, current_y, width - 48, title)
for index, key in enumerate(keys):
current_y = self._draw_slider_row(rl.Rectangle(group_rect.x, current_y, group_rect.width, 0), key, is_last=index == len(keys) - 1)
@@ -29,6 +29,8 @@ from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import (
GROUP_HEADER_GAP,
GROUP_HEADER_HEIGHT,
GROUP_HEADER_LINE_GAP,
GROUP_HEADER_TOTAL_HEIGHT,
GROUP_TOP_INSET,
draw_group_header,
draw_list_group_shell,
draw_rounded_fill,
@@ -192,17 +194,17 @@ class VehicleSettingsManagerView(PanelManagerView):
row_h = rect.height
if row_h < 90:
title_size = 36
subtitle_size = 26
value_size = 32
title_size = 30
subtitle_size = 24
value_size = 26
elif row_h < 105:
title_size = 42
subtitle_size = 32
value_size = 38
title_size = 34
subtitle_size = 26
value_size = 28
else:
title_size = 49
subtitle_size = 38
value_size = 44
title_size = 36
subtitle_size = 28
value_size = 30
if row.type == "value" or row.id.startswith("combo:"):
value_text = row.get_value() if row.get_value else ""
@@ -222,10 +224,9 @@ class VehicleSettingsManagerView(PanelManagerView):
style=PANEL_STYLE)
def _draw_section(self, y: float, x: float, width: float, title: str, rows: list[SettingRow], row_height: float = ROW_HEIGHT) -> float:
hdr_oh = GROUP_HEADER_HEIGHT + GROUP_HEADER_LINE_GAP + GROUP_HEADER_GAP
group_h = len(rows) * row_height + hdr_oh + 4
group_h = len(rows) * row_height + GROUP_HEADER_TOTAL_HEIGHT + GROUP_TOP_INSET
draw_list_group_shell(rl.Rectangle(x, y, width, group_h), style=PANEL_STYLE)
current_y = y + 4
current_y = y + GROUP_TOP_INSET
current_y = draw_group_header(x + 24, current_y, width - 48, tr(title))
for i, row in enumerate(rows):
self._draw_row(rl.Rectangle(x, current_y, width, row_height), row, i == len(rows) - 1)
@@ -242,7 +243,7 @@ class VehicleSettingsManagerView(PanelManagerView):
rx = rect.x + col_w + self.COLUMN_GAP
draw_list_group_shell(rl.Rectangle(rect.x, y, col_w, self._container_h), style=PANEL_STYLE)
row_y = y + 4
row_y = y + GROUP_TOP_INSET
row_y = draw_group_header(rect.x + 24, row_y, col_w - 48, tr("Vehicle Identity"))
for i, row in enumerate(identity_rows):
self._draw_row(rl.Rectangle(rect.x, row_y, col_w, self._left_row_height),
@@ -250,6 +251,7 @@ class VehicleSettingsManagerView(PanelManagerView):
row_y += self._left_row_height
if steering_rows:
row_y += GROUP_TOP_INSET
row_y = draw_group_header(rect.x + 24, row_y, col_w - 48, tr("Steering Controls"))
for i, row in enumerate(steering_rows):
self._draw_row(rl.Rectangle(rect.x, row_y, col_w, self._left_row_height),
@@ -258,7 +260,7 @@ class VehicleSettingsManagerView(PanelManagerView):
if self._toggle_grid.tiles:
draw_list_group_shell(rl.Rectangle(rx, y, col_w, self._container_h), style=PANEL_STYLE)
tile_y = y + 4
tile_y = y + GROUP_TOP_INSET
tile_y = draw_group_header(rx + 24, tile_y, col_w - 48, tr("Features"))
avail_h = self._container_h - (tile_y - y)
self._render_page_grid(self._toggle_grid, rl.Rectangle(rx + 12, tile_y, col_w - 24, max(0.0, avail_h - 12)))
@@ -273,10 +275,9 @@ class VehicleSettingsManagerView(PanelManagerView):
self._toggle_grid._columns = 3
avail = width - 24
th = self.measure_page_grid_height(self._toggle_grid, avail)
hdr_oh = GROUP_HEADER_HEIGHT + GROUP_HEADER_LINE_GAP + GROUP_HEADER_GAP
group_h = th + 24 + 4 + hdr_oh
group_h = th + 24 + GROUP_TOP_INSET + GROUP_HEADER_TOTAL_HEIGHT
draw_list_group_shell(rl.Rectangle(rect.x, y, width, group_h), style=PANEL_STYLE)
features_y = y + 4
features_y = y + GROUP_TOP_INSET
features_y = draw_group_header(rect.x + 24, features_y, width - 48, tr("Features"))
self._render_page_grid(self._toggle_grid, rl.Rectangle(rect.x + 12, features_y, avail, max(0.0, group_h - (features_y - y) - 12)))
@@ -297,10 +298,9 @@ class VehicleSettingsManagerView(PanelManagerView):
tiles_h = self.measure_page_grid_height(self._toggle_grid, width - 24)
if self._uses_two_columns(width):
hdr_oh = GROUP_HEADER_HEIGHT + GROUP_HEADER_LINE_GAP + GROUP_HEADER_GAP
subsection_overhead = hdr_oh + 4
subsection_overhead = GROUP_HEADER_TOTAL_HEIGHT + GROUP_TOP_INSET
if steering_rows:
subsection_overhead += hdr_oh
subsection_overhead += GROUP_HEADER_TOTAL_HEIGHT + GROUP_TOP_INSET
avail_h = self._scroll_rect.height if self._scroll_rect else 760.0
avail_for_rows = max(100.0, avail_h - subsection_overhead)
@@ -316,11 +316,10 @@ class VehicleSettingsManagerView(PanelManagerView):
self._container_h = total_h
return total_h
hdr_oh = GROUP_HEADER_HEIGHT + GROUP_HEADER_LINE_GAP + GROUP_HEADER_GAP
identity_natural_h = hdr_oh + 4 + len(identity_rows) * ROW_HEIGHT
steering_natural_h = hdr_oh + 4 + len(steering_rows) * ROW_HEIGHT
identity_natural_h = GROUP_HEADER_TOTAL_HEIGHT + GROUP_TOP_INSET + len(identity_rows) * ROW_HEIGHT
steering_natural_h = GROUP_HEADER_TOTAL_HEIGHT + GROUP_TOP_INSET + len(steering_rows) * ROW_HEIGHT
left_natural_h = identity_natural_h + SECTION_GAP + steering_natural_h
tiles_overhead = 4 + hdr_oh + 24 if tiles_h else 0
tiles_overhead = GROUP_TOP_INSET + GROUP_HEADER_TOTAL_HEIGHT + 24 if tiles_h else 0
return left_natural_h + tiles_h + tiles_overhead
def _build_driving_toggles(self) -> list[dict]: