From 7d4db0f811d49d9364024a600c77ea42ab34d5d2 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 1 Oct 2022 21:09:38 +0100 Subject: [PATCH 1/3] optimizations for compositor --- src/textual/_compositor.py | 22 ++++++++++++---------- src/textual/screen.py | 22 +++++++++++----------- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/textual/_compositor.py b/src/textual/_compositor.py index bc64632a3..b00466f6a 100644 --- a/src/textual/_compositor.py +++ b/src/textual/_compositor.py @@ -482,7 +482,7 @@ class Compositor: @property def layers_visible(self) -> dict[int, 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)} @@ -490,28 +490,30 @@ class Compositor: y: layer.append for y, layer in layers_visible.items() } 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, diff --git a/src/textual/screen.py b/src/textual/screen.py index 8db9b91d7..bf96c5082 100644 --- a/src/textual/screen.py +++ b/src/textual/screen.py @@ -216,22 +216,22 @@ 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, + _size_updated = Widget._size_updated + 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: + _size_updated(widget, 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: From 540ca7c5e59de3182829760fcd4a41e58a58f271 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sat, 1 Oct 2022 22:30:25 +0100 Subject: [PATCH 2/3] dict to list --- src/textual/_compositor.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/textual/_compositor.py b/src/textual/_compositor.py index b00466f6a..3fe955270 100644 --- a/src/textual/_compositor.py +++ b/src/textual/_compositor.py @@ -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,15 +478,13 @@ 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: @@ -541,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})") From b627e34353f8837f5fe904a5efd83c497891f549 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Sun, 2 Oct 2022 09:19:56 +0100 Subject: [PATCH 3/3] fix stupid optiization --- src/textual/screen.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/textual/screen.py b/src/textual/screen.py index bf96c5082..284bdd283 100644 --- a/src/textual/screen.py +++ b/src/textual/screen.py @@ -218,7 +218,6 @@ class Screen(Widget): send_resize = shown | resized ResizeEvent = events.Resize - _size_updated = Widget._size_updated layers = self._compositor.layers for widget, ( region, @@ -228,7 +227,7 @@ class Screen(Widget): container_size, _, ) in layers: - _size_updated(widget, region.size, virtual_size, container_size) + widget._size_updated(region.size, virtual_size, container_size) if widget in send_resize: widget.post_message_no_wait( ResizeEvent(self, region.size, virtual_size, container_size)