mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
Merge pull request #812 from Textualize/need-for-speed
optimizations for compositor
This commit is contained in:
@@ -202,9 +202,7 @@ class Compositor:
|
||||
self._dirty_regions: set[Region] = set()
|
||||
|
||||
# Mapping of line numbers on to lists of widget and regions
|
||||
self._layers_visible: dict[
|
||||
int, list[tuple[Widget, Region, Region]]
|
||||
] | None = None
|
||||
self._layers_visible: list[list[tuple[Widget, Region, Region]]] | None = None
|
||||
|
||||
@classmethod
|
||||
def _regions_to_spans(
|
||||
@@ -480,38 +478,38 @@ class Compositor:
|
||||
return self._layers
|
||||
|
||||
@property
|
||||
def layers_visible(self) -> dict[int, list[tuple[Widget, Region, Region]]]:
|
||||
def layers_visible(self) -> list[list[tuple[Widget, Region, Region]]]:
|
||||
"""Visible widgets and regions in layers order."""
|
||||
|
||||
screen_height = self.size.height
|
||||
if self._layers_visible is None:
|
||||
layers_visible: dict[int, list[tuple[Widget, Region, Region]]]
|
||||
layers_visible = {y: [] for y in range(self.size.height)}
|
||||
layers_visible_appends = {
|
||||
y: layer.append for y, layer in layers_visible.items()
|
||||
}
|
||||
layers_visible: list[list[tuple[Widget, Region, Region]]]
|
||||
layers_visible = [[] for y in range(self.size.height)]
|
||||
layers_visible_appends = [layer.append for layer in layers_visible]
|
||||
intersection = Region.intersection
|
||||
_range = range
|
||||
for widget, (region, _, clip, _, _, _) in self.layers:
|
||||
cropped_region = intersection(region, clip)
|
||||
_x, region_y, _width, height = cropped_region
|
||||
widget_location = (widget, cropped_region, region)
|
||||
for y in range(region_y, region_y + height):
|
||||
layers_visible_appends[y](widget_location)
|
||||
_x, y, _width, height = region
|
||||
if -height <= y < screen_height:
|
||||
cropped_region = intersection(region, clip)
|
||||
_x, region_y, _width, region_height = cropped_region
|
||||
if region_height:
|
||||
widget_location = (widget, cropped_region, region)
|
||||
for y in _range(region_y, region_y + region_height):
|
||||
layers_visible_appends[y](widget_location)
|
||||
self._layers_visible = layers_visible
|
||||
return self._layers_visible
|
||||
|
||||
def __iter__(self) -> Iterator[tuple[Widget, Region, Region, Size, Size]]:
|
||||
def __iter__(self) -> Iterator[tuple[Widget, Region, Size, Size]]:
|
||||
"""Iterate map with information regarding each widget and is position
|
||||
|
||||
Yields:
|
||||
Iterator[tuple[Widget, Region, Region, Size, Size]]: Iterates a tuple of
|
||||
Widget, clip region, region, virtual size, and container size.
|
||||
Widget, region, virtual size, and container size.
|
||||
"""
|
||||
layers = self.layers
|
||||
intersection = Region.intersection
|
||||
for widget, (region, _order, clip, virtual_size, container_size, _) in layers:
|
||||
yield (
|
||||
widget,
|
||||
intersection(region, clip),
|
||||
region,
|
||||
virtual_size,
|
||||
container_size,
|
||||
@@ -539,7 +537,7 @@ class Compositor:
|
||||
"""
|
||||
|
||||
contains = Region.contains
|
||||
for widget, cropped_region, region in self.layers_visible.get(y, []):
|
||||
for widget, cropped_region, region in self.layers_visible[y]:
|
||||
if contains(cropped_region, x, y) and widget.visible:
|
||||
return widget, region
|
||||
raise errors.NoWidget(f"No widget under screen coordinate ({x}, {y})")
|
||||
|
||||
@@ -216,22 +216,21 @@ 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
|
||||
|
||||
for (
|
||||
widget,
|
||||
_region,
|
||||
unclipped_region,
|
||||
layers = self._compositor.layers
|
||||
for widget, (
|
||||
region,
|
||||
_order,
|
||||
_clip,
|
||||
virtual_size,
|
||||
container_size,
|
||||
) in self._compositor:
|
||||
widget._size_updated(
|
||||
unclipped_region.size, virtual_size, container_size
|
||||
)
|
||||
_,
|
||||
) in layers:
|
||||
widget._size_updated(region.size, virtual_size, container_size)
|
||||
if widget in send_resize:
|
||||
widget.post_message_no_wait(
|
||||
events.Resize(
|
||||
self, unclipped_region.size, virtual_size, container_size
|
||||
)
|
||||
ResizeEvent(self, region.size, virtual_size, container_size)
|
||||
)
|
||||
|
||||
except Exception as error:
|
||||
|
||||
Reference in New Issue
Block a user