From a40300a6f5f78c5b2dd41bf36e282cbea2af7ff1 Mon Sep 17 00:00:00 2001 From: darrenburns Date: Mon, 29 May 2023 18:23:49 +0100 Subject: [PATCH] Ensure reflow reflows non-visible widgets, fix scroll_to_center issue (#2684) --- CHANGELOG.md | 1 + src/textual/_compositor.py | 6 +- .../__snapshots__/test_snapshots.ambr | 119 +++++++++--------- .../snapshot_apps/scroll_to_center.py | 31 ++--- tests/snapshot_tests/test_snapshots.py | 3 - 5 files changed, 81 insertions(+), 79 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86027123b..5cc55decb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - Fixed zero division error https://github.com/Textualize/textual/issues/2673 +- Fix `scroll_to_center` when there were nested layers out of view (Compositor full_map not populated fully) https://github.com/Textualize/textual/pull/2684 ### Added diff --git a/src/textual/_compositor.py b/src/textual/_compositor.py index fca3b9e3d..caf6d1e6e 100644 --- a/src/textual/_compositor.py +++ b/src/textual/_compositor.py @@ -266,7 +266,6 @@ class Compositor: def __init__(self) -> None: # A mapping of Widget on to its "render location" (absolute position / depth) - self._full_map: CompositorMap = {} self._full_map_invalidated = True self._visible_map: CompositorMap | None = None @@ -358,7 +357,7 @@ class Compositor: old_map = self._full_map old_widgets = old_map.keys() - map, widgets = self._arrange_root(parent, size) + map, widgets = self._arrange_root(parent, size, visible_only=False) new_widgets = map.keys() @@ -1021,11 +1020,12 @@ class Compositor: return StripRenderable(self.render_strips()) def update_widgets(self, widgets: set[Widget]) -> None: - """Update a given widget in the composition. + """Update the given widgets in the composition. Args: widgets: Set of Widgets to update. """ + # If there are any *new* widgets we need to invalidate the full map if not self._full_map_invalidated and not widgets.issubset( self.visible_widgets.keys() diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr index fa3b4a920..e1b1456d8 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr +++ b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr @@ -22750,134 +22750,137 @@ font-weight: 700; } - .terminal-1349433035-matrix { + .terminal-2224040135-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1349433035-title { + .terminal-2224040135-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1349433035-r1 { fill: #004578 } - .terminal-1349433035-r2 { fill: #c5c8c6 } - .terminal-1349433035-r3 { fill: #e1e1e1 } - .terminal-1349433035-r4 { fill: #14191f } + .terminal-2224040135-r1 { fill: #e1e1e1 } + .terminal-2224040135-r2 { fill: #c5c8c6 } + .terminal-2224040135-r3 { fill: #004578 } + .terminal-2224040135-r4 { fill: #23568b } + .terminal-2224040135-r5 { fill: #fea62b } + .terminal-2224040135-r6 { fill: #cc555a } + .terminal-2224040135-r7 { fill: #14191f } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - MyApp + MyApp - - - - ────────────────────────────────────────────────────────────────────────────── - SPAM - SPAM▁▁ - SPAM - SPAM - SPAM - SPAM - SPAM - SPAM - SPAM - SPAM - SPAM - SPAM - SPAM - SPAM - SPAM - SPAM - SPAM - SPAM - SPAM - SPAM - SPAM - SPAM - ────────────────────────────────────────────────────────────────────────────── + + + + SPAM + ──────────────────────────────────────────────────────────────────────────── + SPAM + SPAM + SPAM + SPAM + SPAM + SPAM + SPAM + SPAM▁▁ + SPAM▁▁ + ──────────────────────────────────────────────────────────────────────── + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@>>bullseye<<@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + ▅▅ + ▄▄ + + + + + + + ──────────────────────────────────────────────────────────────────────────── + SPAM + SPAM diff --git a/tests/snapshot_tests/snapshot_apps/scroll_to_center.py b/tests/snapshot_tests/snapshot_apps/scroll_to_center.py index d26ee7a84..44b6857f1 100644 --- a/tests/snapshot_tests/snapshot_apps/scroll_to_center.py +++ b/tests/snapshot_tests/snapshot_apps/scroll_to_center.py @@ -5,32 +5,33 @@ from textual.widgets import Label class MyApp(App[None]): CSS = """ - VerticalScroll, HorizontalScroll { + VerticalScroll { border: round $primary; } #vertical { height: 21; } HorizontalScroll { + border: round $secondary; height: auto; } + Label { + height: auto; + width: auto; + } """ def compose(self) -> ComposeResult: - with VerticalScroll(): - yield Label(("SPAM\n" * 205)[:-1]) - with VerticalScroll(): - yield Label(("SPAM\n" * 53)[:-1]) - with VerticalScroll(id="vertical"): - yield Label(("SPAM\n" * 78)[:-1]) - with HorizontalScroll(): - yield Label(("v\n" * 17)[:-1]) - yield Label("@" * 302) - yield Label("[red]>>bullseye<<[/red]", id="bullseye") - yield Label("@" * 99) - yield Label(("SPAM\n" * 49)[:-1]) - yield Label(("SPAM\n" * 51)[:-1]) - yield Label(("SPAM\n" * 59)[:-1]) + yield Label(("SPAM\n" * 53)[:-1]) + with VerticalScroll(id="vertical"): + yield Label(("SPAM\n" * 78)[:-1]) + with HorizontalScroll(): + yield Label(("v\n" * 17)[:-1]) + yield Label("@" * 302) + yield Label("[red]>>bullseye<<[/red]", id="bullseye") + yield Label("@" * 99) + yield Label(("SPAM\n" * 49)[:-1]) + yield Label(("SPAM\n" * 51)[:-1]) def key_s(self) -> None: self.screen.scroll_to_center(self.query_one("#bullseye")) diff --git a/tests/snapshot_tests/test_snapshots.py b/tests/snapshot_tests/test_snapshots.py index 3e14c4ecd..67de7687a 100644 --- a/tests/snapshot_tests/test_snapshots.py +++ b/tests/snapshot_tests/test_snapshots.py @@ -518,9 +518,6 @@ def test_scroll_visible(snap_compare): assert snap_compare(SNAPSHOT_APPS_DIR / "scroll_visible.py", press=["t"]) -@pytest.mark.xfail( - reason="Unpredictable while https://github.com/Textualize/textual/issues/2254 is open." -) def test_scroll_to_center(snap_compare): # READ THIS IF THIS TEST FAILS: # While https://github.com/Textualize/textual/issues/2254 is open, the snapshot