Skip to content

Commit

Permalink
Merge pull request #4315 from Textualize/ping-pong-fix
Browse files Browse the repository at this point in the history
fix for flicker
  • Loading branch information
willmcgugan authored Mar 23, 2024
2 parents 5170a64 + 0955254 commit 9b6ce77
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 25 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Fixed

- Fixed a crash in `TextArea` when undoing an edit to a selection the selection was made backwards https://github.com/Textualize/textual/issues/4301
- Fixed issue with flickering scrollbars https://github.com/Textualize/textual/pull/4315
- Fix progress bar ETA not updating when setting `total` reactive https://github.com/Textualize/textual/pull/4316

### Changed
Expand Down
2 changes: 1 addition & 1 deletion src/textual/screen.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
from .css.parse import parse_selectors
from .css.query import NoMatches, QueryType
from .dom import DOMNode
from .errors import NoWidget
from .geometry import Offset, Region, Size
from .reactive import Reactive
from .renderables.background_screen import BackgroundScreen
Expand All @@ -54,7 +55,6 @@
from .command import Provider

# Unused & ignored imports are needed for the docs to link to these objects:
from .errors import NoWidget # type: ignore # noqa: F401
from .message_pump import MessagePump

# Screen updates will be batched so that they don't happen more often than 60 times per second:
Expand Down
1 change: 1 addition & 0 deletions src/textual/scroll_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ def _size_updated(
or virtual_size != self.virtual_size
or container_size != self.container_size
):
self._scrollbar_changes.clear()
self._size = size
virtual_size = self.virtual_size
self._container_size = size - self.styles.gutter.totals
Expand Down
4 changes: 3 additions & 1 deletion src/textual/signal.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,6 @@ def publish(self) -> None:
try:
callback()
except Exception as error:
log.error(f"error publishing signal to {node} ignored; {error}")
log.error(
f"error publishing signal to {node} ignored (callback={callback}); {error}"
)
49 changes: 27 additions & 22 deletions src/textual/widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,14 +361,15 @@ def __init__(

self._styles_cache = StylesCache()
self._rich_style_cache: dict[str, tuple[Style, Style]] = {}
self._stabilize_scrollbar: tuple[Size, str, str] | None = None
"""Used to prevent scrollbar logic getting stuck in an infinite loop."""

self._tooltip: RenderableType | None = None
"""The tooltip content."""
self._absolute_offset: Offset | None = None
"""Force an absolute offset for the widget (used by tooltips)."""

self._scrollbar_changes: set[tuple[bool, bool]] = set()
"""Used to stabilize scrollbars."""

super().__init__(
name=name,
id=id,
Expand Down Expand Up @@ -799,7 +800,6 @@ def _arrange(self, size: Size) -> DockArrangeResult:
def _clear_arrangement_cache(self) -> None:
"""Clear arrangement cache, forcing a new arrange operation."""
self._arrangement_cache.clear()
self._stabilize_scrollbar = None

def _get_virtual_dom(self) -> Iterable[Widget]:
"""Get widgets not part of the DOM.
Expand Down Expand Up @@ -1437,14 +1437,6 @@ def _refresh_scrollbars(self) -> None:
overflow_x = styles.overflow_x
overflow_y = styles.overflow_y

stabilize_scrollbar = (
self.container_size,
overflow_x,
overflow_y,
)
if self._stabilize_scrollbar == stabilize_scrollbar:
return

width, height = self._container_size

show_horizontal = False
Expand All @@ -1463,17 +1455,31 @@ def _refresh_scrollbars(self) -> None:
elif overflow_y == "auto":
show_vertical = self.virtual_size.height > height

# When a single scrollbar is shown, the other dimension changes, so we need to recalculate.
if overflow_x == "auto" and show_vertical and not show_horizontal:
show_horizontal = self.virtual_size.width > (
width - styles.scrollbar_size_vertical
)
if overflow_y == "auto" and show_horizontal and not show_vertical:
show_vertical = self.virtual_size.height > (
height - styles.scrollbar_size_horizontal
)
_show_horizontal = show_horizontal
_show_vertical = show_vertical

self._stabilize_scrollbar = stabilize_scrollbar
if not (
overflow_x == "auto"
and overflow_y == "auto"
and (show_horizontal, show_vertical) in self._scrollbar_changes
):
# When a single scrollbar is shown, the other dimension changes, so we need to recalculate.
if overflow_x == "auto" and show_vertical and not show_horizontal:
show_horizontal = self.virtual_size.width > (
width - styles.scrollbar_size_vertical
)
if overflow_y == "auto" and show_horizontal and not show_vertical:
show_vertical = self.virtual_size.height > (
height - styles.scrollbar_size_horizontal
)

if (
self.show_horizontal_scrollbar != show_horizontal
or self.show_vertical_scrollbar != show_vertical
):
self._scrollbar_changes.add((_show_horizontal, _show_vertical))
else:
self._scrollbar_changes.clear()

self.show_horizontal_scrollbar = show_horizontal
self.show_vertical_scrollbar = show_vertical
Expand Down Expand Up @@ -3322,7 +3328,6 @@ def refresh(
return self
if layout:
self._layout_required = True
self._stabilize_scrollbar = None
for ancestor in self.ancestors:
if not isinstance(ancestor, Widget):
break
Expand Down
2 changes: 1 addition & 1 deletion src/textual/widgets/_sparkline.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def __init__(
Args:
data: The initial data to populate the sparkline with.
summary_function: Summarises bar values into a single value used to
summary_function: Summarizes bar values into a single value used to
represent each bar.
name: The name of the widget.
id: The ID of the widget in the DOM.
Expand Down

0 comments on commit 9b6ce77

Please sign in to comment.