Size the board and the rail by proportion, not by pixel constants
"Some screens scroll sideways, some don't" had two causes, and both were a number that was right on one monitor. The lanes. _KanbanColumn set a 150px floor with a comment claiming seven of them fit a 1280 window; measured, the row wanted 1242px where 1280 leaves 1091, so a 1280 screen scrolled and a 1920 one did not — this machine has one of each. The floor is gone. The seven lanes share the board through the layout's stretch, which is a proportion of whatever width there is, and the only pixel question left — how narrow before scrolling beats squeezing — is answered from the font: eight characters of a title plus padding, so it holds at 125%/150% scaling too. No horizontal scroll now at 1280×720 through 1936×1048, at three rail widths each, including the rail dragged to its maximum. Each lane also grew its own scrollbar: QListWidget's column hint runs 1-6px past its viewport, and which lanes overflowed changed with the window width — 36 of 38 widths had at least one. Cards word-wrap, so there was never anything to reach sideways; the bar is off. The rail. Its 360px ceiling was a quarter of a 1440 screen and more than that of a 1280 one. It is now 22% of the window, capped at 360 — and recomputed on resize, which is its own bug fixed: read once at construction off a not-yet-sized window, it sat at 162px on every monitor, so the handle barely moved. check_kanban_scroll covers five screen sizes × three rail widths. A rail dragged to maximum on a 1280 screen still scrolls the board — that is the user's own trade, so it is reported rather than failed. 19/19 checkers pass. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
a0cef768c9
commit
77976405b1
@@ -41,8 +41,14 @@ _NAV_COLLAPSED_WIDTH = 54
|
||||
# something if the rail can actually take a width from it, so the expanded rail
|
||||
# is a range rather than one number; long project and thread names in RECENTS
|
||||
# are the reason someone would widen it.
|
||||
#
|
||||
# The ceiling is a SHARE of the window, not a pixel count: 360px is a quarter
|
||||
# of a 1440 screen and more than a quarter of a 1280 one, where it left the
|
||||
# seven Kanban lanes 920px of the 1067 they need. A share behaves the same on
|
||||
# every monitor.
|
||||
_NAV_MIN_WIDTH = 132
|
||||
_NAV_MAX_WIDTH = 360
|
||||
_NAV_MAX_SHARE = 0.22
|
||||
_NAV_MAX_CEILING = 360
|
||||
|
||||
|
||||
def app_icon() -> QIcon:
|
||||
@@ -220,7 +226,7 @@ class MainWindow(QMainWindow):
|
||||
self._nav_wrap = QWidget()
|
||||
self._nav_wrap.setObjectName("navWrap")
|
||||
self._nav_width = _NAV_EXPANDED_WIDTH # remembered across collapses
|
||||
self._set_nav_width_range(_NAV_MIN_WIDTH, _NAV_MAX_WIDTH)
|
||||
self._set_nav_width_range(_NAV_MIN_WIDTH, self._nav_max_width())
|
||||
nvl = QVBoxLayout(self._nav_wrap)
|
||||
nvl.setContentsMargins(0, 0, 0, 0)
|
||||
nvl.setSpacing(0)
|
||||
@@ -372,6 +378,11 @@ class MainWindow(QMainWindow):
|
||||
|
||||
def resizeEvent(self, event): # noqa: N802 - Qt override
|
||||
super().resizeEvent(event)
|
||||
# The rail's ceiling is a share of the window, so it moves with the
|
||||
# window. Computed once at construction it was read off a not-yet-sized
|
||||
# window and stuck at 162px on every monitor.
|
||||
if getattr(self, "_nav_wrap", None) is not None and not self._nav_collapsed:
|
||||
self._set_nav_width_range(_NAV_MIN_WIDTH, self._nav_max_width())
|
||||
# Keep the floating Help assistant pinned to the bottom-right corner.
|
||||
if getattr(self, "help_agent", None) is not None:
|
||||
self.help_agent.reposition()
|
||||
@@ -755,6 +766,11 @@ class MainWindow(QMainWindow):
|
||||
def _nav_new_chat_enabled(self) -> bool:
|
||||
return bool(self.workspace.project_choices())
|
||||
|
||||
def _nav_max_width(self) -> int:
|
||||
"""The rail's ceiling for THIS window, as a share of it."""
|
||||
return max(_NAV_MIN_WIDTH,
|
||||
min(_NAV_MAX_CEILING, int(self.width() * _NAV_MAX_SHARE)))
|
||||
|
||||
def _set_nav_width_range(self, lo: int, hi: int) -> None:
|
||||
"""setFixedWidth would leave the splitter handle inert — visible, and
|
||||
doing nothing when dragged."""
|
||||
@@ -764,19 +780,19 @@ class MainWindow(QMainWindow):
|
||||
def _on_split_moved(self, _pos: int, _index: int) -> None:
|
||||
if not self._nav_collapsed:
|
||||
self._nav_width = max(_NAV_MIN_WIDTH,
|
||||
min(_NAV_MAX_WIDTH, self._nav_wrap.width()))
|
||||
min(self._nav_max_width(), self._nav_wrap.width()))
|
||||
|
||||
def _toggle_nav(self) -> None:
|
||||
if not self._nav_collapsed:
|
||||
self._nav_width = max(_NAV_MIN_WIDTH,
|
||||
min(_NAV_MAX_WIDTH, self._nav_wrap.width()))
|
||||
min(self._nav_max_width(), self._nav_wrap.width()))
|
||||
self._nav_collapsed = not self._nav_collapsed
|
||||
if self._nav_collapsed:
|
||||
width = _NAV_COLLAPSED_WIDTH
|
||||
self._set_nav_width_range(width, width)
|
||||
else:
|
||||
width = self._nav_width
|
||||
self._set_nav_width_range(_NAV_MIN_WIDTH, _NAV_MAX_WIDTH)
|
||||
self._set_nav_width_range(_NAV_MIN_WIDTH, self._nav_max_width())
|
||||
self._apply_nav_labels()
|
||||
# Same chevron convention as every other collapsible panel: right-
|
||||
# pointing (fill-right) means "click to expand", left means "collapse".
|
||||
|
||||
Reference in New Issue
Block a user