Source code for simvx.ide.panels.scroll_mixin

"""Reusable scroll mixin for IDE panels with vertical scrolling."""


from __future__ import annotations

import logging

log = logging.getLogger(__name__)

[docs] class ScrollableMixin: """Mixin providing scroll_y tracking, key handling, and row-at-y mapping. Panels using this mixin should call ``_handle_scroll(key, content_height, visible_height)`` from their ``_on_gui_input`` and ``_row_at_y(py, content_top, row_height)`` for click mapping. """ _scroll_y: float = 0.0 _scroll_step: float = 20.0 def _handle_scroll(self, key: str, content_height: float, visible_height: float) -> bool: """Handle scroll_up/scroll_down keys, clamping to valid range. Returns True if handled.""" if key == "scroll_up": self._scroll_y = max(0.0, self._scroll_y - self._scroll_step) return True if key == "scroll_down": max_scroll = max(0.0, content_height - visible_height) self._scroll_y = min(max_scroll, self._scroll_y + self._scroll_step) return True return False def _row_at_y(self, py: float, content_top: float, row_height: float) -> int: """Map a screen Y coordinate to a row index accounting for scroll offset.""" return int((py - content_top + self._scroll_y) / row_height) def _clamp_scroll(self, content_height: float, visible_height: float) -> None: """Clamp current scroll_y to valid range (useful after content changes).""" max_scroll = max(0.0, content_height - visible_height) self._scroll_y = max(0.0, min(self._scroll_y, max_scroll))