remove spatial map

This commit is contained in:
Will McGugan
2022-11-24 17:41:24 +08:00
parent 9dc3e13a3f
commit 935020101d
5 changed files with 10 additions and 143 deletions

View File

@@ -50,7 +50,7 @@ def arrange(
get_dock = attrgetter("styles.dock")
styles = widget.styles
for index, widgets in enumerate(dock_layers.values()):
for widgets in dock_layers.values():
layout_widgets, dock_widgets = partition(get_dock, widgets)

View File

@@ -381,12 +381,9 @@ class Compositor:
if widget.is_container:
# Arrange the layout
spatial_map, arranged_widgets, spacing = widget._arrange(
placements, arranged_widgets, spacing = widget._arrange(
child_region.size
)
total_region = total_region.union(
spatial_map.total_region.grow(spacing)
)
widgets.update(arranged_widgets)
@@ -394,10 +391,6 @@ class Compositor:
placement_offset = container_region.offset + layout_offset
placement_scroll_offset = placement_offset - widget.scroll_offset
placements = spatial_map.get_placements(
(child_region.size.region).translate(widget.scroll_offset)
)
_layers = widget.layers
layers_to_index = {
layer_name: index for index, layer_name in enumerate(_layers)
@@ -405,11 +398,16 @@ class Compositor:
get_layer_index = layers_to_index.get
# Add all the widgets
for sub_region, _, sub_widget, z, fixed in reversed(placements):
for sub_region, margin, sub_widget, z, fixed in reversed(
placements
):
# Combine regions with children to calculate the "virtual size"
if fixed:
widget_region = sub_region + placement_offset
else:
total_region = total_region.union(
sub_region.grow(spacing + margin)
)
widget_region = sub_region + placement_scroll_offset
widget_order = order + (

View File

@@ -8,10 +8,9 @@ from ._typing import TypeAlias
if TYPE_CHECKING:
from .widget import Widget
from ._spatial_map import SpatialMap
ArrangeResult: TypeAlias = "tuple[list[WidgetPlacement], set[Widget]]"
DockArrangeResult: TypeAlias = "SpacialMap, set[Widget], Spacing]"
DockArrangeResult: TypeAlias = "list[WidgetPlacement], set[Widget], Spacing]"
class WidgetPlacement(NamedTuple):

View File

@@ -1,129 +0,0 @@
from __future__ import annotations
from collections import defaultdict
from itertools import product
from operator import attrgetter
from typing import Iterable, Sequence
from ._layout import WidgetPlacement
from .geometry import Region, Spacing
from ._partition import partition
from ._profile import timer
class SpatialMap:
"""An object to return WidgetPlacements within a given region.
The widget area is split in to a regular grid of buckets. Each placement is assigned to
any bucket it overlaps, which may be 1 or more buckets.
The `get_placements` function will calculate which buckets overlap the screen area, and combine
the placements from those buckets. This generally means that widgets that aren't overlapping or
near the screen area can be quickly discarded. The result will typically be a superset of visible
placements, which can then be filtered normally.
"""
def __init__(
self,
placements: Sequence[WidgetPlacement],
*,
block_width: int = 40,
block_height: int = 20,
) -> None:
self._placements = placements
self._total_region = Region()
self._block_width = block_width
self._block_height = block_height
self._fixed: list[WidgetPlacement] = []
self._map: defaultdict[tuple[int, int], list[WidgetPlacement]] | None = None
self.placement_map = self._build_placements(placements)
def __iter__(self) -> Iterable[WidgetPlacement]:
yield from self._placements
def __reversed__(self) -> Iterable[WidgetPlacement]:
yield from reversed(self._placements)
def _build_placements(
self, placements: Iterable[WidgetPlacement]
) -> defaultdict[tuple[int, int], list[WidgetPlacement]]:
"""Add placements to map.
Args:
placements (Iterable[WidgetPlacement]): A number of placements.
"""
map: defaultdict[tuple[int, int], list[WidgetPlacement]] = defaultdict(list)
get_bucket = map.__getitem__
block_width = self._block_width
block_height = self._block_height
self.total_region = Region.from_union(
[
placement.region.grow(placement.margin)
for placement in placements
if not placement.fixed
]
)
placements, self._fixed = partition(attrgetter("fixed"), placements)
for placement in placements:
x1, y1, width, height = placement.region
x2 = x1 + width
y2 = y1 + height
for coord in product(
range(x1 // block_width, x2 // block_width + 1),
range(y1 // block_height, y2 // block_height + 1),
):
get_bucket(coord).append(placement)
return map
def get_placements(self, screen_region: Region) -> list[WidgetPlacement]:
"""Get placements that may overlap a given region. There may be false positives,
but no false negatives.
Args:
region (Region): Container region.
Returns:
Iterable[WidgetPlacement]: A super-set of Widget placements that may be in the screen.
"""
return [
placement
for placement in self._placements
if screen_region.overlaps(placement.region)
]
x1, y1, width, height = screen_region
x2 = x1 + width
y2 = y1 + height
block_width = self._block_width
block_height = self._block_height
placements: set[WidgetPlacement] = set()
extend_placements = placements.update
map = self.placement_map
map_get = map.get
overlaps_screen = screen_region.overlaps
for coord in product(
range(x1 // block_width, x2 // block_width + 1),
range(y1 // block_height, y2 // block_height + 1),
):
block_placements = map_get(coord)
if block_placements is not None:
extend_placements(block_placements)
_placements = [
placement
for placement in self._placements
if placement in placements and not placement.fixed
]
visible_placements = self._fixed + [
placement for placement in _placements if overlaps_screen(placement.region)
]
return visible_placements

View File

@@ -39,7 +39,6 @@ from ._context import active_app
from ._easing import DEFAULT_SCROLL_EASING
from ._layout import Layout
from ._segment_tools import align_lines
from ._spatial_map import SpatialMap
from ._styles_cache import StylesCache
from ._types import Lines
from .await_remove import AwaitRemove
@@ -429,7 +428,7 @@ class Widget(DOMNode):
placements, widgets, spacing = arrange(
self, self.children, size, self.screen.size
)
arrange_result = SpatialMap(placements), widgets, spacing
arrange_result = placements, widgets, spacing
self._arrangement = arrange_result
return self._arrangement