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()
|
self._dirty_regions: set[Region] = set()
|
||||||
|
|
||||||
# Mapping of line numbers on to lists of widget and regions
|
# Mapping of line numbers on to lists of widget and regions
|
||||||
self._layers_visible: dict[
|
self._layers_visible: list[list[tuple[Widget, Region, Region]]] | None = None
|
||||||
int, list[tuple[Widget, Region, Region]]
|
|
||||||
] | None = None
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _regions_to_spans(
|
def _regions_to_spans(
|
||||||
@@ -480,38 +478,38 @@ class Compositor:
|
|||||||
return self._layers
|
return self._layers
|
||||||
|
|
||||||
@property
|
@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."""
|
"""Visible widgets and regions in layers order."""
|
||||||
|
screen_height = self.size.height
|
||||||
if self._layers_visible is None:
|
if self._layers_visible is None:
|
||||||
layers_visible: dict[int, list[tuple[Widget, Region, Region]]]
|
layers_visible: list[list[tuple[Widget, Region, Region]]]
|
||||||
layers_visible = {y: [] for y in range(self.size.height)}
|
layers_visible = [[] for y in range(self.size.height)]
|
||||||
layers_visible_appends = {
|
layers_visible_appends = [layer.append for layer in layers_visible]
|
||||||
y: layer.append for y, layer in layers_visible.items()
|
|
||||||
}
|
|
||||||
intersection = Region.intersection
|
intersection = Region.intersection
|
||||||
|
_range = range
|
||||||
for widget, (region, _, clip, _, _, _) in self.layers:
|
for widget, (region, _, clip, _, _, _) in self.layers:
|
||||||
cropped_region = intersection(region, clip)
|
_x, y, _width, height = region
|
||||||
_x, region_y, _width, height = cropped_region
|
if -height <= y < screen_height:
|
||||||
widget_location = (widget, cropped_region, region)
|
cropped_region = intersection(region, clip)
|
||||||
for y in range(region_y, region_y + height):
|
_x, region_y, _width, region_height = cropped_region
|
||||||
layers_visible_appends[y](widget_location)
|
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
|
self._layers_visible = layers_visible
|
||||||
return self._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
|
"""Iterate map with information regarding each widget and is position
|
||||||
|
|
||||||
Yields:
|
Yields:
|
||||||
Iterator[tuple[Widget, Region, Region, Size, Size]]: Iterates a tuple of
|
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
|
layers = self.layers
|
||||||
intersection = Region.intersection
|
|
||||||
for widget, (region, _order, clip, virtual_size, container_size, _) in layers:
|
for widget, (region, _order, clip, virtual_size, container_size, _) in layers:
|
||||||
yield (
|
yield (
|
||||||
widget,
|
widget,
|
||||||
intersection(region, clip),
|
|
||||||
region,
|
region,
|
||||||
virtual_size,
|
virtual_size,
|
||||||
container_size,
|
container_size,
|
||||||
@@ -539,7 +537,7 @@ class Compositor:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
contains = Region.contains
|
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:
|
if contains(cropped_region, x, y) and widget.visible:
|
||||||
return widget, region
|
return widget, region
|
||||||
raise errors.NoWidget(f"No widget under screen coordinate ({x}, {y})")
|
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
|
# We want to send a resize event to widgets that were just added or change since last layout
|
||||||
send_resize = shown | resized
|
send_resize = shown | resized
|
||||||
|
ResizeEvent = events.Resize
|
||||||
|
|
||||||
for (
|
layers = self._compositor.layers
|
||||||
widget,
|
for widget, (
|
||||||
_region,
|
region,
|
||||||
unclipped_region,
|
_order,
|
||||||
|
_clip,
|
||||||
virtual_size,
|
virtual_size,
|
||||||
container_size,
|
container_size,
|
||||||
) in self._compositor:
|
_,
|
||||||
widget._size_updated(
|
) in layers:
|
||||||
unclipped_region.size, virtual_size, container_size
|
widget._size_updated(region.size, virtual_size, container_size)
|
||||||
)
|
|
||||||
if widget in send_resize:
|
if widget in send_resize:
|
||||||
widget.post_message_no_wait(
|
widget.post_message_no_wait(
|
||||||
events.Resize(
|
ResizeEvent(self, region.size, virtual_size, container_size)
|
||||||
self, unclipped_region.size, virtual_size, container_size
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
|
|||||||
Reference in New Issue
Block a user