Skip to content

Commit

Permalink
Merge pull request #5048 from Textualize/new-widgets
Browse files Browse the repository at this point in the history
fix missing new widgets
  • Loading branch information
willmcgugan authored Sep 24, 2024
2 parents 7b31e6e + 702d33b commit 0deb1dc
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 5 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

- Tree will no longer scroll the X axis when moving the cursor https://github.com/Textualize/textual/pull/5047

### Fixed

- Fixed widgets occasionally not getting Resize events https://github.com/Textualize/textual/pull/5048

## [0.80.1] - 2024-09-24

### Fixed
Expand Down
10 changes: 8 additions & 2 deletions src/textual/_compositor.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,9 @@ def __init__(self) -> None:
# Mapping of line numbers on to lists of widget and regions
self._layers_visible: list[list[tuple[Widget, Region, Region]]] | None = None

# New widgets added between updates
self._new_widgets: set[Widget] = set()

def clear(self) -> None:
"""Remove all references to widgets (used when the screen closes)."""
self._full_map.clear()
Expand Down Expand Up @@ -387,7 +390,9 @@ def reflow(self, parent: Widget, size: Size) -> ReflowResult:
new_widgets = map.keys()

# Newly visible widgets
shown_widgets = new_widgets - old_widgets
shown_widgets = (new_widgets - old_widgets) | self._new_widgets
self._new_widgets.clear()

# Newly hidden widgets
hidden_widgets = self.widgets - widgets

Expand Down Expand Up @@ -419,7 +424,6 @@ def reflow(self, parent: Widget, size: Size) -> ReflowResult:
for widget, (region, *_) in changes
if (widget in common_widgets and old_map[widget].region[2:] != region[2:])
}

return ReflowResult(
hidden=hidden_widgets,
shown=shown_widgets,
Expand Down Expand Up @@ -483,6 +487,8 @@ def full_map(self) -> CompositorMap:
if self._full_map_invalidated:
self._full_map_invalidated = False
map, _widgets = self._arrange_root(self.root, self.size, visible_only=False)
# Update any widgets which became visible in the interim
self._new_widgets.update(map.keys() - self._full_map.keys())
self._full_map = map
self._visible_widgets = None
self._visible_map = None
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 30 additions & 3 deletions tests/snapshot_tests/test_snapshots.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from textual import events
from textual.app import App, ComposeResult
from textual.binding import Binding
from textual.containers import Vertical
from textual.containers import Vertical, VerticalScroll
from textual.pilot import Pilot
from textual.screen import Screen
from textual.widgets import (
Expand All @@ -24,8 +24,7 @@
OptionList,
SelectionList,
)
from textual.widgets import Switch
from textual.widgets import Label
from textual.widgets import ProgressBar, Label, Switch
from textual.widgets.text_area import BUILTIN_LANGUAGES, Selection, TextAreaTheme

# These paths should be relative to THIS directory.
Expand Down Expand Up @@ -1992,3 +1991,31 @@ def on_mount(self) -> None:

app = DisabledApp()
assert snap_compare(app)


def test_missing_new_widgets(snap_compare):
"""Regression test for https://github.com/Textualize/textual/issues/5024"""

class MRE(App):
BINDINGS = [("z", "toggle_console", "Console")]
CSS = """
RichLog { border-top: dashed blue; height: 6; }
.hidden { display: none; }
"""

def compose(self):
yield VerticalScroll()
yield ProgressBar(
classes="hidden"
) # removing or displaying this widget prevents the bug
yield Footer() # clicking "Console" in the footer prevents the bug
yield RichLog(classes="hidden")

def on_ready(self) -> None:
self.query_one(RichLog).write("\n".join(f"line #{i}" for i in range(5)))

def action_toggle_console(self) -> None:
self.query_one(RichLog).toggle_class("hidden")

app = MRE()
assert snap_compare(app, press=["space", "space", "z"])

0 comments on commit 0deb1dc

Please sign in to comment.