mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-07-03 04:22:09 +08:00
BigUI WIP: Lil scrolling cleanup
This commit is contained in:
@@ -507,6 +507,10 @@ class PanelManagerView(AetherInteractiveMixin, Widget):
|
||||
def _draw_scroll_content(self, scroll_rect: rl.Rectangle, content_width: float) -> None:
|
||||
"""Override to render visible content rows inside the scissor region."""
|
||||
|
||||
@property
|
||||
def vertical_scrolling_disabled(self) -> bool:
|
||||
return False
|
||||
|
||||
# ── render pipeline ───────────────────────────────────────
|
||||
|
||||
def _render(self, rect: rl.Rectangle) -> None:
|
||||
@@ -521,8 +525,15 @@ class PanelManagerView(AetherInteractiveMixin, Widget):
|
||||
|
||||
self._content_height = self._measure_content_height(content_width)
|
||||
self._scroll_panel.set_enabled(self.is_visible)
|
||||
|
||||
scroll_disabled = self.vertical_scrolling_disabled
|
||||
effective_height = scroll_rect.height if scroll_disabled else self._content_height
|
||||
|
||||
self._scroll_offset = self._scroll_panel.update(
|
||||
scroll_rect, max(self._content_height, scroll_rect.height))
|
||||
scroll_rect, max(effective_height, scroll_rect.height))
|
||||
|
||||
if scroll_disabled:
|
||||
self._scroll_offset = 0.0
|
||||
|
||||
rl.begin_scissor_mode(
|
||||
int(scroll_rect.x), int(scroll_rect.y),
|
||||
@@ -530,12 +541,12 @@ class PanelManagerView(AetherInteractiveMixin, Widget):
|
||||
self._draw_scroll_content(scroll_rect, content_width)
|
||||
rl.end_scissor_mode()
|
||||
|
||||
if self._content_height > scroll_rect.height:
|
||||
if self._content_height > scroll_rect.height and not scroll_disabled:
|
||||
self._scrollbar.render(scroll_rect, self._content_height, self._scroll_offset)
|
||||
|
||||
draw_list_scroll_fades(scroll_rect, self._content_height, self._scroll_offset,
|
||||
AetherListColors.PANEL_BG)
|
||||
self._draw_page_dots(frame.scroll)
|
||||
if not scroll_disabled:
|
||||
draw_list_scroll_fades(scroll_rect, self._content_height, self._scroll_offset,
|
||||
AetherListColors.PANEL_BG)
|
||||
|
||||
# ── shared layout helpers ─────────────────────────────────
|
||||
|
||||
@@ -613,6 +624,12 @@ class PanelManagerView(AetherInteractiveMixin, Widget):
|
||||
def _has_pagination(self) -> bool:
|
||||
return self._page_count > 1
|
||||
|
||||
def measure_page_grid_height(self, grid: TileGrid, width: float) -> float:
|
||||
h = grid.measure_height(width)
|
||||
if self._has_pagination:
|
||||
h += 32
|
||||
return h
|
||||
|
||||
def register_page_grid(self, grid: TileGrid) -> None:
|
||||
self._page_grid = grid
|
||||
if grid not in self._children:
|
||||
@@ -671,59 +688,61 @@ class PanelManagerView(AetherInteractiveMixin, Widget):
|
||||
self._page_anim_from = from_offset
|
||||
|
||||
def _render_page_grid(self, grid: TileGrid, rect: rl.Rectangle, clip_rect: rl.Rectangle | None = None) -> None:
|
||||
pagination_padding = 32.0 if self._has_pagination else 0.0
|
||||
|
||||
if clip_rect is None:
|
||||
clip_rect = rl.Rectangle(rect.x - self.GRID_PADDING, rect.y - self.GRID_PADDING,
|
||||
rect.width + self.GRID_PADDING * 2, rect.height + self.GRID_PADDING * 2)
|
||||
self._page_clip_rect = clip_rect
|
||||
|
||||
grid_rect = rl.Rectangle(rect.x, rect.y, rect.width, max(0.0, rect.height - pagination_padding))
|
||||
|
||||
# active drag
|
||||
if self._page_drag_active:
|
||||
drag_off = self._page_drag_offset
|
||||
self._page_scissor_push(clip_rect)
|
||||
grid.render(rl.Rectangle(rect.x + drag_off, rect.y, rect.width, rect.height))
|
||||
grid.render(rl.Rectangle(grid_rect.x + drag_off, grid_rect.y, grid_rect.width, grid_rect.height))
|
||||
self._page_scissor_pop()
|
||||
return
|
||||
|
||||
# no animation
|
||||
if not self._page_animating:
|
||||
elif not self._page_animating:
|
||||
# no animation
|
||||
grid.set_parent_rect(self._scroll_rect)
|
||||
grid.render(rect)
|
||||
return
|
||||
|
||||
# animation
|
||||
elapsed = time.monotonic() - self._page_anim_start
|
||||
duration = self.PAGE_ANIM_DURATION if self._page_anim_committed else self.PAGE_SNAP_DURATION
|
||||
if elapsed >= duration:
|
||||
self._page_animating = False
|
||||
self._page_anim_prev_tiles.clear()
|
||||
grid.set_parent_rect(self._scroll_rect)
|
||||
grid.render(rect)
|
||||
return
|
||||
|
||||
t = elapsed / duration
|
||||
t = 1.0 - (1.0 - t) ** 3
|
||||
|
||||
if self._page_anim_committed:
|
||||
direction = 1 if self._page_anim_from < 0 else -1
|
||||
old_target = -direction * rect.width
|
||||
prev_offset = self._page_anim_from + (old_target - self._page_anim_from) * t
|
||||
cur_offset = direction * rect.width + (0.0 - direction * rect.width) * t
|
||||
|
||||
self._page_scissor_push(clip_rect)
|
||||
if self._page_anim_prev_tiles:
|
||||
old_grid = TileGrid(columns=grid.get_column_count(), padding=grid.gap, tile_height=grid._tile_height)
|
||||
old_grid.tiles.extend(self._page_anim_prev_tiles)
|
||||
old_grid.set_parent_rect(self._scroll_rect)
|
||||
old_grid.render(rl.Rectangle(rect.x + prev_offset, rect.y, rect.width, rect.height))
|
||||
grid.set_parent_rect(self._scroll_rect)
|
||||
grid.render(rl.Rectangle(rect.x + cur_offset, rect.y, rect.width, rect.height))
|
||||
self._page_scissor_pop()
|
||||
grid.render(grid_rect)
|
||||
else:
|
||||
cur_offset = self._page_anim_from * (1.0 - t)
|
||||
self._page_scissor_push(clip_rect)
|
||||
grid.set_parent_rect(self._scroll_rect)
|
||||
grid.render(rl.Rectangle(rect.x + cur_offset, rect.y, rect.width, rect.height))
|
||||
self._page_scissor_pop()
|
||||
# animation
|
||||
elapsed = time.monotonic() - self._page_anim_start
|
||||
duration = self.PAGE_ANIM_DURATION if self._page_anim_committed else self.PAGE_SNAP_DURATION
|
||||
if elapsed >= duration:
|
||||
self._page_animating = False
|
||||
self._page_anim_prev_tiles.clear()
|
||||
grid.set_parent_rect(self._scroll_rect)
|
||||
grid.render(grid_rect)
|
||||
else:
|
||||
t = elapsed / duration
|
||||
t = 1.0 - (1.0 - t) ** 3
|
||||
|
||||
if self._page_anim_committed:
|
||||
direction = 1 if self._page_anim_from < 0 else -1
|
||||
old_target = -direction * rect.width
|
||||
prev_offset = self._page_anim_from + (old_target - self._page_anim_from) * t
|
||||
cur_offset = direction * rect.width + (0.0 - direction * rect.width) * t
|
||||
|
||||
self._page_scissor_push(clip_rect)
|
||||
if self._page_anim_prev_tiles:
|
||||
old_grid = TileGrid(columns=grid.get_column_count(), padding=grid.gap, tile_height=grid._tile_height)
|
||||
old_grid.tiles.extend(self._page_anim_prev_tiles)
|
||||
old_grid.set_parent_rect(self._scroll_rect)
|
||||
old_grid.render(rl.Rectangle(grid_rect.x + prev_offset, grid_rect.y, grid_rect.width, grid_rect.height))
|
||||
grid.set_parent_rect(self._scroll_rect)
|
||||
grid.render(rl.Rectangle(grid_rect.x + cur_offset, grid_rect.y, grid_rect.width, grid_rect.height))
|
||||
self._page_scissor_pop()
|
||||
else:
|
||||
cur_offset = self._page_anim_from * (1.0 - t)
|
||||
self._page_scissor_push(clip_rect)
|
||||
grid.set_parent_rect(self._scroll_rect)
|
||||
grid.render(rl.Rectangle(grid_rect.x + cur_offset, grid_rect.y, grid_rect.width, grid_rect.height))
|
||||
self._page_scissor_pop()
|
||||
|
||||
self._draw_page_dots(rect)
|
||||
|
||||
# ── mouse handling ─────────────────────────────────────────
|
||||
|
||||
@@ -785,11 +804,10 @@ class PanelManagerView(AetherInteractiveMixin, Widget):
|
||||
def _draw_page_dots(self, rect: rl.Rectangle) -> None:
|
||||
if not self._has_pagination:
|
||||
return
|
||||
clip = self._page_clip_rect
|
||||
n = min(self._page_count, 8)
|
||||
total_w = n * self.PAGE_DOT_RADIUS * 2 + max(0, n - 1) * self.PAGE_DOT_GAP
|
||||
start_x = (clip.x + (clip.width - total_w) / 2) if clip else rect.x + (rect.width - total_w) / 2
|
||||
dot_y = rect.y + rect.height + 8
|
||||
start_x = rect.x + (rect.width - total_w) / 2
|
||||
dot_y = rect.y + rect.height - 12
|
||||
for i in range(n):
|
||||
cx = start_x + i * (self.PAGE_DOT_RADIUS * 2 + self.PAGE_DOT_GAP) + self.PAGE_DOT_RADIUS
|
||||
fill = self.PANEL_STYLE.accent if i == self._current_page else _with_alpha(AetherListColors.MUTED, 100)
|
||||
@@ -2339,19 +2357,27 @@ class AetherSettingsView(PanelManagerView):
|
||||
|
||||
self._content_height = self._measure_content_height(content_width)
|
||||
self._scroll_panel.set_enabled(self.is_visible)
|
||||
|
||||
scroll_disabled = getattr(self, "vertical_scrolling_disabled", False)
|
||||
effective_height = self._scroll_rect.height if scroll_disabled else self._content_height
|
||||
|
||||
self._scroll_offset = self._scroll_panel.update(
|
||||
self._scroll_rect, max(self._content_height, self._scroll_rect.height))
|
||||
self._scroll_rect, max(effective_height, self._scroll_rect.height))
|
||||
|
||||
if scroll_disabled:
|
||||
self._scroll_offset = 0.0
|
||||
|
||||
rl.begin_scissor_mode(int(self._scroll_rect.x), int(self._scroll_rect.y),
|
||||
int(self._scroll_rect.width), int(self._scroll_rect.height))
|
||||
self._draw_scroll_content(self._scroll_rect, content_width)
|
||||
rl.end_scissor_mode()
|
||||
|
||||
if self._content_height > self._scroll_rect.height:
|
||||
if self._content_height > self._scroll_rect.height and not scroll_disabled:
|
||||
self._scrollbar.render(self._scroll_rect, self._content_height, self._scroll_offset)
|
||||
|
||||
draw_list_scroll_fades(self._scroll_rect, self._content_height, self._scroll_offset,
|
||||
AetherListColors.PANEL_BG, fade_height=self._fade_height)
|
||||
if not scroll_disabled:
|
||||
draw_list_scroll_fades(self._scroll_rect, self._content_height, self._scroll_offset,
|
||||
AetherListColors.PANEL_BG, fade_height=self._fade_height)
|
||||
|
||||
def _draw_header(self, rect: rl.Rectangle):
|
||||
title = tr(self._header_title) if self._header_title else ""
|
||||
|
||||
@@ -67,6 +67,10 @@ def _theme_display_name(value: str) -> str:
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
class AppearanceManagerView(AetherSettingsView):
|
||||
@property
|
||||
def vertical_scrolling_disabled(self) -> bool:
|
||||
return self._active_tab_key == "widgets"
|
||||
|
||||
def __init__(self, controller, sections, **kwargs):
|
||||
super().__init__(controller, sections, **kwargs)
|
||||
self._toggle_grid = TileGrid(columns=2, padding=12)
|
||||
@@ -252,7 +256,7 @@ class AppearanceManagerView(AetherSettingsView):
|
||||
section_overhead = self._metrics.section_header_height + self._metrics.section_header_gap
|
||||
left_column_total_h = left_h + section_overhead
|
||||
|
||||
tiles_content_h = self._toggle_grid.measure_height(col_width - 24)
|
||||
tiles_content_h = self.measure_page_grid_height(self._toggle_grid, col_width - 24)
|
||||
right_column_total_h = tiles_content_h + 24 + section_overhead
|
||||
|
||||
tab_h = self.TAB_HEIGHT + self.TAB_BOTTOM_GAP if self._tab_defs else 0
|
||||
@@ -310,7 +314,7 @@ class AppearanceManagerView(AetherSettingsView):
|
||||
tr("Widgets"), style=self._panel_style
|
||||
)
|
||||
y += self._metrics.section_header_height + self._metrics.section_header_gap
|
||||
tiles_content_h = self._toggle_grid.measure_height(width - 24)
|
||||
tiles_content_h = self.measure_page_grid_height(self._toggle_grid, width - 24)
|
||||
draw_list_group_shell(rl.Rectangle(rect.x, y, width, tiles_content_h + 24), style=self._panel_style)
|
||||
self._render_page_grid(self._toggle_grid, rl.Rectangle(rect.x + 12, y + 12, width - 24, tiles_content_h))
|
||||
|
||||
|
||||
@@ -53,6 +53,10 @@ SOUNDS_PANEL_METRICS = replace(
|
||||
class SoundsManagerView(PanelManagerView):
|
||||
METRICS = SOUNDS_PANEL_METRICS
|
||||
|
||||
@property
|
||||
def vertical_scrolling_disabled(self) -> bool:
|
||||
return True
|
||||
|
||||
def __init__(self, controller: StarPilotSoundsLayout):
|
||||
super().__init__()
|
||||
self._controller = controller
|
||||
|
||||
@@ -110,6 +110,10 @@ class SystemSettingsManagerView(PanelManagerView):
|
||||
DANGER_PILL_WIDTH = 112
|
||||
METRICS = SYSTEM_PANEL_METRICS
|
||||
|
||||
@property
|
||||
def vertical_scrolling_disabled(self) -> bool:
|
||||
return True
|
||||
|
||||
def __init__(self, controller: StarPilotSystemLayout):
|
||||
super().__init__()
|
||||
self._controller = controller
|
||||
@@ -478,7 +482,7 @@ class SystemSettingsManagerView(PanelManagerView):
|
||||
left_h = display_container_h + power_container_h + header_overhead + section_gap
|
||||
return self._compute_two_column_height(left_h)
|
||||
else:
|
||||
tiles_content_h = self._connectivity_tile_grid.measure_height(width - 24)
|
||||
tiles_content_h = self.measure_page_grid_height(self._connectivity_tile_grid, width - 24)
|
||||
return self._stacked_section_height([display_h, power_h, tiles_content_h + 24])
|
||||
|
||||
def _slider_section_height(self, keys: list[str], width: float) -> float:
|
||||
@@ -519,7 +523,7 @@ class SystemSettingsManagerView(PanelManagerView):
|
||||
self._draw_connectivity_tiles_section(y, x, width)
|
||||
|
||||
def _draw_connectivity_tiles_section(self, y: float, x: float, width: float):
|
||||
tiles_content_h = self._connectivity_tile_grid.measure_height(width - 24)
|
||||
tiles_content_h = self.measure_page_grid_height(self._connectivity_tile_grid, width - 24)
|
||||
|
||||
draw_list_group_shell(rl.Rectangle(x, y, width, tiles_content_h + 24), style=PANEL_STYLE)
|
||||
self._render_page_grid(self._connectivity_tile_grid, rl.Rectangle(x + 12, y + 12, width - 24, tiles_content_h))
|
||||
|
||||
@@ -328,7 +328,7 @@ class VehicleSettingsManagerView(PanelManagerView):
|
||||
if not self._uses_two_columns(width):
|
||||
self._toggle_grid._columns = 3
|
||||
avail_w = width - 24
|
||||
tiles_content_h = self._toggle_grid.measure_height(avail_w)
|
||||
tiles_content_h = self.measure_page_grid_height(self._toggle_grid, avail_w)
|
||||
tiles_height = SECTION_GAP + self._section_block_height(tiles_content_h + 24)
|
||||
|
||||
if self._uses_two_columns(width):
|
||||
@@ -420,7 +420,7 @@ class VehicleSettingsManagerView(PanelManagerView):
|
||||
|
||||
self._toggle_grid._columns = 3
|
||||
avail_w = width - 24
|
||||
tiles_content_h = self._toggle_grid.measure_height(avail_w)
|
||||
tiles_content_h = self.measure_page_grid_height(self._toggle_grid, avail_w)
|
||||
|
||||
draw_list_group_shell(rl.Rectangle(x, y, width, tiles_content_h + 24), style=PANEL_STYLE)
|
||||
self._render_page_grid(self._toggle_grid, rl.Rectangle(x + 12, y + 12, avail_w, tiles_content_h))
|
||||
|
||||
Reference in New Issue
Block a user