scrollbar fixes

This commit is contained in:
Will McGugan
2023-02-17 17:43:02 +00:00
parent c61e3bab1a
commit c0c49978bd
4 changed files with 33 additions and 14 deletions

View File

@@ -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."""

View File

@@ -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:

View File

@@ -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, (

View File

@@ -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.