BigUI WIP: More map cleanup

This commit is contained in:
firestarsdog
2026-04-28 02:14:16 -04:00
parent cb56102da7
commit 65a9fcf3ec
2 changed files with 76 additions and 69 deletions
@@ -818,8 +818,8 @@ class AetherTile(Widget):
class HubTile(AetherTile):
def __init__(
self,
title: str,
desc: str,
title: str | Callable[[], str],
desc: str | Callable[[], str],
icon_path: str,
on_click: Callable | None = None,
starpilot_icon: bool = False,
@@ -848,6 +848,8 @@ class HubTile(AetherTile):
self._draw_signal_edge(face, self.surface_color, width=TILE_SIGNAL_WIDTH, alpha=48)
status_text = self.get_status() if self.get_status else ""
title_text = str(_resolve_value(self.title, ""))
fallback_desc = str(_resolve_value(self.desc, ""))
if status_text:
import re
@@ -861,11 +863,11 @@ class HubTile(AetherTile):
rl.draw_rectangle_rec(_snap_rect(meter_rect), rl.Color(255, 255, 255, 14))
rl.draw_rectangle_rec(_snap_rect(fill_rect), _with_alpha(self.surface_color, 170))
desc_to_render = status_text if status_text else self.desc
desc_to_render = status_text if status_text else fallback_desc
self._render_tile_stack(
face,
icon=self._icon,
title=self.title,
title=title_text,
primary=desc_to_render,
desc="",
title_font=self._font_title,
+70 -65
View File
@@ -156,7 +156,7 @@ class ActionButtonStrip(Widget):
self._secondary_button.render(rl.Rectangle(rect.x + primary_w + gap, rect.y, secondary_w, rect.height))
class MapSummaryRow(Widget):
class MapStatusCard(Widget):
def __init__(self, controller: "StarPilotMapsLayout"):
super().__init__()
self._controller = controller
@@ -176,17 +176,47 @@ class MapSummaryRow(Widget):
self._controller._on_remove()
def _render(self, rect: rl.Rectangle):
draw_list_row_shell(rect, current=True, is_last=True, current_bg=rl.Color(89, 116, 151, 16), current_border=rl.Color(116, 136, 168, 40))
draw_soft_card(rect, rl.Color(255, 255, 255, 4), rl.Color(255, 255, 255, 16))
left_w = max(220.0, rect.width * 0.31)
gui_label(rl.Rectangle(rect.x + 18, rect.y + 12, left_w, 22), tr("Selected Regions"), 18, AetherListColors.MUTED, FontWeight.MEDIUM)
gui_label(rl.Rectangle(rect.x + 18, rect.y + 36, left_w, 28), self._controller._selection_summary_title(), 24, AetherListColors.HEADER, FontWeight.SEMI_BOLD)
left_w = rect.width * 0.52
right_x = rect.x + left_w + 20
right_w = rect.x + rect.width - right_x - 18
top_y = rect.y + 16
meta_text = self._controller._selection_summary_meta()
gui_text_box(rl.Rectangle(rect.x + left_w + 8, rect.y + 18, rect.width * 0.38, 48), meta_text, 18, AetherListColors.SUBTEXT, font_weight=FontWeight.NORMAL, line_scale=0.95)
gui_label(rl.Rectangle(rect.x + 20, top_y, left_w - 20, 24), self._controller._progress_title(), 24, AetherListColors.HEADER, FontWeight.SEMI_BOLD)
gui_text_box(
rl.Rectangle(rect.x + 20, top_y + 28, left_w - 26, 40),
self._controller._progress_body(),
17,
AetherListColors.SUBTEXT,
font_weight=FontWeight.NORMAL,
line_scale=0.94,
)
gui_label(rl.Rectangle(rect.x + 20, rect.y + rect.height - 22, left_w - 20, 18), self._controller._status_footer_text(), 16, AetherListColors.MUTED, FontWeight.MEDIUM)
action_w = 152
self._remove_rect = rl.Rectangle(rect.x + rect.width - action_w - 20, rect.y + 17, action_w, 42)
metric_gap = 18
metric_w = max(120.0, (right_w - metric_gap) / 2)
gui_label(rl.Rectangle(right_x, top_y, metric_w, 18), tr("Storage"), 16, AetherListColors.MUTED, FontWeight.MEDIUM)
gui_label(rl.Rectangle(right_x, top_y + 16, metric_w, 24), self._controller._storage_text, 22, AetherListColors.HEADER, FontWeight.SEMI_BOLD)
gui_label(rl.Rectangle(right_x + metric_w + metric_gap, top_y, metric_w, 18), tr("Last Updated"), 16, AetherListColors.MUTED, FontWeight.MEDIUM)
gui_label(rl.Rectangle(right_x + metric_w + metric_gap, top_y + 16, metric_w, 24), self._controller._last_updated_text(), 20, AetherListColors.HEADER, FontWeight.SEMI_BOLD)
selection_y = rect.y + 54
action_w = 150
action_h = 36
selection_w = max(180.0, right_w - action_w - 14)
gui_label(rl.Rectangle(right_x, selection_y, selection_w, 18), tr("Selected Regions"), 16, AetherListColors.MUTED, FontWeight.MEDIUM)
gui_label(rl.Rectangle(right_x, selection_y + 18, selection_w, 22), self._controller._selection_summary_title(), 20, AetherListColors.HEADER, FontWeight.SEMI_BOLD)
gui_text_box(
rl.Rectangle(right_x, selection_y + 40, selection_w, 18),
self._controller._selection_summary_meta(),
16,
AetherListColors.SUBTEXT,
font_weight=FontWeight.NORMAL,
line_scale=0.92,
)
self._remove_rect = rl.Rectangle(rect.x + rect.width - action_w - 20, rect.y + rect.height - action_h - 16, action_w, action_h)
enabled = self._controller._remove_enabled()
draw_action_pill(
self._remove_rect,
@@ -194,9 +224,13 @@ class MapSummaryRow(Widget):
rl.Color(173, 78, 90, 26 if enabled else 12),
rl.Color(173, 78, 90, 58 if enabled else 24),
AetherListColors.HEADER if enabled else AetherListColors.MUTED,
font_size=18,
font_size=17,
)
if self._controller._download_state.active:
center = rl.Vector2(rect.x + rect.width - 34, rect.y + 34)
draw_busy_ring(center, rl.get_time() * 160, AetherListColors.PRIMARY, inner_radius=10, outer_radius=14, sweep=210, thickness=20)
class SelectedMapsCard(Widget):
def __init__(self, controller: "StarPilotMapsLayout"):
@@ -210,11 +244,11 @@ class SelectedMapsCard(Widget):
def _render(self, rect: rl.Rectangle):
draw_soft_card(rect, rl.Color(255, 255, 255, 4), rl.Color(255, 255, 255, 16))
gui_label(rl.Rectangle(rect.x + 18, rect.y + 14, rect.width - 36, 26), tr("Current Download Set"), 25, AetherListColors.HEADER, FontWeight.SEMI_BOLD)
gui_label(rl.Rectangle(rect.x + 18, rect.y + 40, rect.width - 36, 20), tr("Review the selected regions here. Use Countries or U.S. States below to change them."), 18, AetherListColors.SUBTEXT, FontWeight.NORMAL)
gui_label(rl.Rectangle(rect.x + 18, rect.y + 14, rect.width - 36, 26), tr("Included Regions"), 25, AetherListColors.HEADER, FontWeight.SEMI_BOLD)
gui_label(rl.Rectangle(rect.x + 18, rect.y + 40, rect.width - 36, 20), tr("Review what stays offline here. Use the source tiles above to make changes."), 18, AetherListColors.SUBTEXT, FontWeight.NORMAL)
entries = self._controller._selected_entries()
rows = entries if entries else [{"token": "", "label": tr("No map regions selected yet."), "kind": "empty"}]
rows = entries if entries else [{"token": "", "label": tr("No regions added yet."), "kind": "empty"}]
y = rect.y + 64
for index, entry in enumerate(rows):
row_rect = rl.Rectangle(rect.x + 12, y, rect.width - 24, SUMMARY_ROW_HEIGHT)
@@ -238,7 +272,7 @@ class SelectedMapsCard(Widget):
gui_label(rl.Rectangle(text_x, row_rect.y + 26, row_rect.width - 220, 36), entry["label"], 24, AetherListColors.HEADER if not is_empty else AetherListColors.SUBTEXT, FontWeight.MEDIUM)
if not is_empty:
gui_label(rl.Rectangle(row_rect.x + row_rect.width - 180, row_rect.y + 24, 162, 34), tr("Edit in source lists"), 16, AetherListColors.MUTED, FontWeight.MEDIUM, alignment=rl.GuiTextAlignment.TEXT_ALIGN_RIGHT)
gui_label(rl.Rectangle(row_rect.x + row_rect.width - 180, row_rect.y + 24, 162, 34), tr("Edit above"), 16, AetherListColors.MUTED, FontWeight.MEDIUM, alignment=rl.GuiTextAlignment.TEXT_ALIGN_RIGHT)
y += SUMMARY_ROW_HEIGHT
@@ -263,7 +297,7 @@ class MapBrowserCard(Widget):
("countries", tr_noop("Countries"), lambda: self._controller._browser_source_primary(self._controller.VIEW_COUNTRIES), lambda: self._controller._browser_source_desc(self._controller.VIEW_COUNTRIES), lambda: self._controller._set_view_index(self._controller.VIEW_COUNTRIES)),
]
for key, title, primary, desc, on_click in source_specs:
tile = self._child(HubTile(title=title, desc=desc(), icon_path="", on_click=on_click, bg_color="#10B981", get_status=primary))
tile = self._child(HubTile(title=title, desc=desc, icon_path="", on_click=on_click, bg_color="#10B981", get_status=primary))
self._source_tiles[key] = tile
self._source_grid.add_tile(tile)
@@ -272,7 +306,7 @@ class MapBrowserCard(Widget):
("whole_us", tr_noop("Whole U.S."), lambda: self._controller._browser_scope_primary(True), lambda: self._controller._browser_scope_desc(True), lambda: self._controller._set_full_us_mode(True)),
]
for key, title, primary, desc, on_click in scope_specs:
tile = self._child(HubTile(title=title, desc=desc(), icon_path="", on_click=on_click, bg_color="#10B981", get_status=primary))
tile = self._child(HubTile(title=title, desc=desc, icon_path="", on_click=on_click, bg_color="#10B981", get_status=primary))
self._scope_tiles[key] = tile
self._scope_grid.add_tile(tile)
@@ -281,7 +315,7 @@ class MapBrowserCard(Widget):
tile = self._child(
HubTile(
title=tr_noop(group["title"]),
desc=self._controller._group_secondary_text(group),
desc=lambda group=group: self._controller._group_secondary_text(group),
icon_path="",
on_click=lambda group_key=group_key: self._controller._set_active_group(group_key),
bg_color="#10B981",
@@ -295,7 +329,7 @@ class MapBrowserCard(Widget):
tile = self._child(
HubTile(
title=tr_noop(region["label"]),
desc=self._controller._region_secondary_text(token),
desc=lambda token=token: self._controller._region_secondary_text(token),
icon_path="",
on_click=lambda token=token: self._controller._toggle_region(token),
bg_color="#10B981",
@@ -462,12 +496,12 @@ class StarPilotMapsLayout(StarPilotPanel):
self._cancel_requested_at: float | None = None
self._cancel_visual_until = 0.0
self._download_state = MapsDownloadState()
self._view_index = self.VIEW_COUNTRIES
self._view_index = self.VIEW_STATES
self._active_country_group_key = COUNTRIES_SECTION["groups"][0]["key"]
self._active_state_group_key = STATES_SECTION["groups"][0]["key"]
self._full_us_mode = False
self._selected_summary = self._child(MapSummaryRow(self))
self._status_card = self._child(MapStatusCard(self))
self._selected_card = self._child(SelectedMapsCard(self))
self._download_button = self._child(
@@ -492,7 +526,6 @@ class StarPilotMapsLayout(StarPilotPanel):
self._browser_card.set_touch_valid_callback(lambda: self._scroll_panel.is_touch_valid())
self._selected_card.set_touch_valid_callback(lambda: self._scroll_panel.is_touch_valid())
self._selected_summary.set_touch_valid_callback(lambda: self._scroll_panel.is_touch_valid())
self._action_strip.set_touch_valid_callback(lambda: self._scroll_panel.is_touch_valid())
self._refresh_storage_cache(force=True)
@@ -629,7 +662,7 @@ class StarPilotMapsLayout(StarPilotPanel):
def _selection_summary_meta(self) -> str:
entries = self._selected_entries()
if not entries:
return tr("Choose only the places you actually drive. Fewer regions mean faster updates and less storage.")
return tr("Pick only the places you actually drive.")
countries = sum(1 for entry in entries if entry["token"].startswith(COUNTRY_PREFIX))
states = len(entries) - countries
@@ -963,7 +996,7 @@ class StarPilotMapsLayout(StarPilotPanel):
gate_reason = self._download_gate_reason()
if gate_reason:
if self._selected_count() == 0:
return tr("Pick countries or U.S. states below, then start the first offline download.")
return tr("Pick regions below, then start the first offline download.")
return gate_reason
return tr("Ready to refresh speed-limit map data.")
@@ -980,50 +1013,16 @@ class StarPilotMapsLayout(StarPilotPanel):
return "".join(parts)
def _measure_content_height(self, width: float) -> float:
total = ACTION_BUTTON_HEIGHT + 18 + SUMMARY_ROW_HEIGHT + SECTION_CARD_GAP
total += self._browser_card._measure_height(width)
total = self._browser_card._measure_height(width)
total += SECTION_CARD_GAP + self._selected_card._measure_height()
return total
def _draw_status_panel(self, rect: rl.Rectangle):
draw_soft_card(rect, rl.Color(255, 255, 255, 4), rl.Color(255, 255, 255, 16))
left_w = rect.width * 0.54
right_x = rect.x + left_w + 20
right_w = rect.x + rect.width - right_x - 18
top_y = rect.y + 16
gui_label(rl.Rectangle(rect.x + 20, top_y, left_w - 20, 24), self._progress_title(), 24, AetherListColors.HEADER, FontWeight.SEMI_BOLD)
gui_label(rl.Rectangle(rect.x + 20, top_y + 28, left_w - 20, 18), self._progress_body().replace("\n", " "), 17, AetherListColors.SUBTEXT, FontWeight.NORMAL)
gui_label(rl.Rectangle(rect.x + 20, rect.y + rect.height - 22, left_w - 20, 18), self._status_footer_text(), 16, AetherListColors.MUTED, FontWeight.MEDIUM)
gui_label(rl.Rectangle(right_x, top_y, 110, 18), tr("Storage"), 16, AetherListColors.MUTED, FontWeight.MEDIUM)
gui_label(rl.Rectangle(right_x, top_y + 16, 150, 24), self._storage_text, 22, AetherListColors.HEADER, FontWeight.SEMI_BOLD)
gui_label(rl.Rectangle(right_x + 168, top_y, 130, 18), tr("Last Updated"), 16, AetherListColors.MUTED, FontWeight.MEDIUM)
gui_label(rl.Rectangle(right_x + 168, top_y + 16, max(100.0, right_w - 168), 24), self._last_updated_text(), 20, AetherListColors.HEADER, FontWeight.SEMI_BOLD)
gui_label(rl.Rectangle(right_x, rect.y + 54, right_w, 18), tr("Coverage"), 16, AetherListColors.MUTED, FontWeight.MEDIUM)
gui_label(rl.Rectangle(right_x, rect.y + 72, right_w, 22), self._selection_summary_title(), 20, AetherListColors.HEADER, FontWeight.SEMI_BOLD)
gui_label(rl.Rectangle(right_x, rect.y + 94, right_w, 18), self._selection_summary_meta() if self._selected_count() > 0 else tr("No regions chosen yet"), 16, AetherListColors.SUBTEXT, FontWeight.NORMAL)
if self._download_state.active:
center = rl.Vector2(rect.x + rect.width - 34, rect.y + 34)
draw_busy_ring(center, rl.get_time() * 160, AetherListColors.PRIMARY, inner_radius=10, outer_radius=14, sweep=210, thickness=20)
def _draw_scroll_content(self, rect: rl.Rectangle, width: float):
self._action_strip.set_parent_rect(rect)
self._browser_card.set_parent_rect(rect)
self._selected_summary.set_parent_rect(rect)
self._selected_card.set_parent_rect(rect)
y = rect.y + self._scroll_offset
self._action_strip.render(rl.Rectangle(rect.x, y, width, ACTION_BUTTON_HEIGHT))
y += ACTION_BUTTON_HEIGHT + 18
self._selected_summary.render(rl.Rectangle(rect.x, y, width, SUMMARY_ROW_HEIGHT))
y += SUMMARY_ROW_HEIGHT + SECTION_CARD_GAP
browser_height = self._browser_card._measure_height(width)
self._browser_card.render(rl.Rectangle(rect.x, y, width, browser_height))
y += browser_height + SECTION_CARD_GAP
@@ -1048,19 +1047,25 @@ class StarPilotMapsLayout(StarPilotPanel):
header_status_y = title_y + HEADER_TITLE_HEIGHT + HEADER_SUBTITLE_HEIGHT + 8
header_status_rect = rl.Rectangle(hdr.x, header_status_y, hdr.width, hdr.y + hdr.height - header_status_y - HEADER_BOTTOM_GAP)
self._draw_status_panel(header_status_rect)
self._status_card.render(header_status_rect)
scroll_rect = frame.scroll
content_width = scroll_rect.width - 18
action_rect = rl.Rectangle(scroll_rect.x, scroll_rect.y, content_width, ACTION_BUTTON_HEIGHT)
self._action_strip.set_parent_rect(scroll_rect)
self._action_strip.render(action_rect)
scroll_content_y = action_rect.y + ACTION_BUTTON_HEIGHT + SECTION_CARD_GAP
scroll_content_rect = rl.Rectangle(scroll_rect.x, scroll_content_y, scroll_rect.width, max(0.0, scroll_rect.height - ACTION_BUTTON_HEIGHT - SECTION_CARD_GAP))
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))
self._scroll_offset = self._scroll_panel.update(scroll_content_rect, max(self._content_height, scroll_content_rect.height))
rl.begin_scissor_mode(int(scroll_rect.x), int(scroll_rect.y), int(scroll_rect.width), int(scroll_rect.height))
self._draw_scroll_content(scroll_rect, content_width)
rl.begin_scissor_mode(int(scroll_content_rect.x), int(scroll_content_rect.y), int(scroll_content_rect.width), int(scroll_content_rect.height))
self._draw_scroll_content(scroll_content_rect, content_width)
rl.end_scissor_mode()
if self._content_height > scroll_rect.height:
self._scrollbar.render(scroll_rect, self._content_height, self._scroll_offset)
if self._content_height > scroll_content_rect.height:
self._scrollbar.render(scroll_content_rect, self._content_height, self._scroll_offset)
draw_list_scroll_fades(scroll_rect, self._content_height, self._scroll_offset, AetherListColors.PANEL_BG)
draw_list_scroll_fades(scroll_content_rect, self._content_height, self._scroll_offset, AetherListColors.PANEL_BG)