mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
scrollbar fixes
This commit is contained in:
@@ -298,7 +298,7 @@ class Compositor:
|
||||
resized=resized_widgets,
|
||||
)
|
||||
|
||||
def reflow_visible(self, parent: Widget, size: Size) -> None:
|
||||
def reflow_visible(self, parent: Widget, size: Size) -> set[Widget]:
|
||||
"""Reflow only the visible children.
|
||||
|
||||
This is a fast-path for scrolling.
|
||||
@@ -320,6 +320,7 @@ class Compositor:
|
||||
old_map = self.map
|
||||
map, widgets = self._arrange_root(parent, size, visible_only=True)
|
||||
|
||||
exposed_widgets = widgets - self.widgets
|
||||
# Replace map and widgets
|
||||
self.map = map
|
||||
self.widgets = widgets
|
||||
@@ -340,6 +341,8 @@ class Compositor:
|
||||
}
|
||||
self._dirty_regions.update(regions)
|
||||
|
||||
return exposed_widgets
|
||||
|
||||
@property
|
||||
def full_map(self) -> CompositorMap:
|
||||
"""Lazily built compositor map that covers all widgets."""
|
||||
|
||||
@@ -10,9 +10,12 @@ ValueType = TypeVar("ValueType")
|
||||
|
||||
|
||||
class SpatialMap(Generic[ValueType]):
|
||||
"""A spatial map allows for data to be associated with a rectangular regions
|
||||
"""A spatial map allows for data to be associated with rectangular regions
|
||||
in Euclidean space, and efficiently queried.
|
||||
|
||||
When the SpatialMap is populated, a reference to each value is placed in a bucket associated
|
||||
with a regular grid that covers 2D space.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, grid_width: int = 100, grid_height: int = 20) -> None:
|
||||
|
||||
@@ -428,9 +428,24 @@ class Screen(Widget):
|
||||
|
||||
self._compositor.update_widgets(self._dirty_widgets)
|
||||
self.update_timer.pause()
|
||||
ResizeEvent = events.Resize
|
||||
try:
|
||||
if scroll:
|
||||
self._compositor.reflow_visible(self, size)
|
||||
exposed_widgets = self._compositor.reflow_visible(self, size)
|
||||
if exposed_widgets:
|
||||
layers = self._compositor.layers
|
||||
for widget, (
|
||||
region,
|
||||
_order,
|
||||
_clip,
|
||||
virtual_size,
|
||||
container_size,
|
||||
_,
|
||||
) in layers:
|
||||
widget._size_updated(region.size, virtual_size, container_size)
|
||||
widget.post_message_no_wait(
|
||||
ResizeEvent(self, region.size, virtual_size, container_size)
|
||||
)
|
||||
else:
|
||||
hidden, shown, resized = self._compositor.reflow(self, size)
|
||||
Hide = events.Hide
|
||||
@@ -441,7 +456,6 @@ class Screen(Widget):
|
||||
|
||||
# We want to send a resize event to widgets that were just added or change since last layout
|
||||
send_resize = shown | resized
|
||||
ResizeEvent = events.Resize
|
||||
|
||||
layers = self._compositor.layers
|
||||
for widget, (
|
||||
|
||||
@@ -38,6 +38,7 @@ from . import errors, events, messages
|
||||
from ._animator import DEFAULT_EASING, Animatable, BoundAnimator, EasingFunction
|
||||
from ._arrange import DockArrangeResult, arrange
|
||||
from ._asyncio import create_task
|
||||
from ._cache import FIFOCache
|
||||
from ._context import active_app
|
||||
from ._easing import DEFAULT_SCROLL_EASING
|
||||
from ._layout import Layout
|
||||
@@ -260,8 +261,9 @@ class Widget(DOMNode):
|
||||
self._content_width_cache: tuple[object, int] = (None, 0)
|
||||
self._content_height_cache: tuple[object, int] = (None, 0)
|
||||
|
||||
self._arrangement_cache_key: tuple[Size, int] = (Size(), -1)
|
||||
self._cached_arrangement: DockArrangeResult | None = None
|
||||
self._arrangement_cache: FIFOCache[
|
||||
tuple[Size, int], DockArrangeResult
|
||||
] = FIFOCache(4)
|
||||
|
||||
self._styles_cache = StylesCache()
|
||||
self._rich_style_cache: dict[str, tuple[Style, Style]] = {}
|
||||
@@ -474,14 +476,11 @@ class Widget(DOMNode):
|
||||
assert self.is_container
|
||||
|
||||
cache_key = (size, self._nodes._updates)
|
||||
if (
|
||||
self._arrangement_cache_key == cache_key
|
||||
and self._cached_arrangement is not None
|
||||
):
|
||||
return self._cached_arrangement
|
||||
cached_result = self._arrangement_cache.get(cache_key)
|
||||
if cached_result is not None:
|
||||
return cached_result
|
||||
|
||||
self._arrangement_cache_key = cache_key
|
||||
arrangement = self._cached_arrangement = arrange(
|
||||
arrangement = self._arrangement_cache[cache_key] = arrange(
|
||||
self, self._nodes, size, self.screen.size
|
||||
)
|
||||
|
||||
@@ -489,7 +488,7 @@ class Widget(DOMNode):
|
||||
|
||||
def _clear_arrangement_cache(self) -> None:
|
||||
"""Clear arrangement cache, forcing a new arrange operation."""
|
||||
self._cached_arrangement = None
|
||||
self._arrangement_cache.clear()
|
||||
|
||||
def _get_virtual_dom(self) -> Iterable[Widget]:
|
||||
"""Get widgets not part of the DOM.
|
||||
|
||||
Reference in New Issue
Block a user