mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
fix for update region
This commit is contained in:
@@ -384,6 +384,9 @@ class Compositor:
|
|||||||
spatial_map, arranged_widgets, spacing = widget._arrange(
|
spatial_map, arranged_widgets, spacing = widget._arrange(
|
||||||
child_region.size
|
child_region.size
|
||||||
)
|
)
|
||||||
|
total_region = total_region.union(
|
||||||
|
spatial_map.total_region.grow(spacing)
|
||||||
|
)
|
||||||
|
|
||||||
placements = spatial_map.get_placements(
|
placements = spatial_map.get_placements(
|
||||||
child_region.reset_offset.translate(widget.scroll_offset)
|
child_region.reset_offset.translate(widget.scroll_offset)
|
||||||
@@ -402,16 +405,11 @@ class Compositor:
|
|||||||
get_layer_index = layers_to_index.get
|
get_layer_index = layers_to_index.get
|
||||||
|
|
||||||
# Add all the widgets
|
# Add all the widgets
|
||||||
for sub_region, margin, sub_widget, z, fixed in reversed(
|
for sub_region, _, sub_widget, z, fixed in reversed(placements):
|
||||||
placements
|
|
||||||
):
|
|
||||||
# Combine regions with children to calculate the "virtual size"
|
# Combine regions with children to calculate the "virtual size"
|
||||||
if fixed:
|
if fixed:
|
||||||
widget_region = sub_region + placement_offset
|
widget_region = sub_region + placement_offset
|
||||||
else:
|
else:
|
||||||
total_region = total_region.union(
|
|
||||||
sub_region.grow(spacing + margin)
|
|
||||||
)
|
|
||||||
widget_region = sub_region + placement_scroll_offset
|
widget_region = sub_region + placement_scroll_offset
|
||||||
|
|
||||||
widget_order = order + (
|
widget_order = order + (
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ from __future__ import annotations
|
|||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from itertools import product
|
from itertools import product
|
||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
from typing import Iterable, Mapping, Sequence
|
from typing import Iterable, Sequence
|
||||||
|
|
||||||
from ._layout import WidgetPlacement
|
from ._layout import WidgetPlacement
|
||||||
from .geometry import Region
|
from .geometry import Region, Spacing
|
||||||
from ._partition import partition
|
from ._partition import partition
|
||||||
|
|
||||||
|
|
||||||
@@ -26,10 +26,12 @@ class SpatialMap:
|
|||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
placements: Sequence[WidgetPlacement],
|
placements: Sequence[WidgetPlacement],
|
||||||
|
*,
|
||||||
block_width: int = 80,
|
block_width: int = 80,
|
||||||
block_height: int = 80,
|
block_height: int = 80,
|
||||||
) -> None:
|
) -> None:
|
||||||
self._placements = placements
|
self._placements = placements
|
||||||
|
self._total_region = Region()
|
||||||
self._block_width = block_width
|
self._block_width = block_width
|
||||||
self._block_height = block_height
|
self._block_height = block_height
|
||||||
self._fixed: list[WidgetPlacement] = []
|
self._fixed: list[WidgetPlacement] = []
|
||||||
@@ -37,6 +39,8 @@ class SpatialMap:
|
|||||||
|
|
||||||
self.placement_map = self._build_placements(placements)
|
self.placement_map = self._build_placements(placements)
|
||||||
|
|
||||||
|
print("SPATIAL", len(placements))
|
||||||
|
|
||||||
def __iter__(self) -> Iterable[WidgetPlacement]:
|
def __iter__(self) -> Iterable[WidgetPlacement]:
|
||||||
yield from self._placements
|
yield from self._placements
|
||||||
|
|
||||||
@@ -57,6 +61,14 @@ class SpatialMap:
|
|||||||
block_width = self._block_width
|
block_width = self._block_width
|
||||||
block_height = self._block_height
|
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)
|
placements, self._fixed = partition(attrgetter("fixed"), placements)
|
||||||
|
|
||||||
for placement in placements:
|
for placement in placements:
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from functools import lru_cache
|
||||||
|
from sys import intern
|
||||||
from typing import TYPE_CHECKING, Callable, Iterable, List
|
from typing import TYPE_CHECKING, Callable, Iterable, List
|
||||||
|
|
||||||
from rich.segment import Segment
|
from rich.segment import Segment
|
||||||
@@ -52,6 +54,20 @@ def style_links(
|
|||||||
return segments
|
return segments
|
||||||
|
|
||||||
|
|
||||||
|
@lru_cache(1024 * 8)
|
||||||
|
def make_blank(width, style: Style) -> Segment:
|
||||||
|
"""Make a blank segment.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
width (_type_): Width of blank.
|
||||||
|
style (Style): Style of blank.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Segment: A single segment
|
||||||
|
"""
|
||||||
|
return Segment(intern(" " * width), style)
|
||||||
|
|
||||||
|
|
||||||
class StylesCache:
|
class StylesCache:
|
||||||
"""Responsible for rendering CSS Styles and keeping a cache of rendered lines.
|
"""Responsible for rendering CSS Styles and keeping a cache of rendered lines.
|
||||||
|
|
||||||
@@ -319,20 +335,20 @@ class StylesCache:
|
|||||||
right_style = from_color(color=(background + border_right_color).rich_color)
|
right_style = from_color(color=(background + border_right_color).rich_color)
|
||||||
right = get_box(border_right, inner, outer, right_style)[1][2]
|
right = get_box(border_right, inner, outer, right_style)[1][2]
|
||||||
if border_left and border_right:
|
if border_left and border_right:
|
||||||
line = [left, Segment(" " * (width - 2), background_style), right]
|
line = [left, make_blank(width - 2, background_style), right]
|
||||||
elif border_left:
|
elif border_left:
|
||||||
line = [left, Segment(" " * (width - 1), background_style)]
|
line = [left, make_blank(width - 1, background_style)]
|
||||||
elif border_right:
|
elif border_right:
|
||||||
line = [Segment(" " * (width - 1), background_style), right]
|
line = [make_blank(width, background_style), right]
|
||||||
else:
|
else:
|
||||||
line = [Segment(" " * width, background_style)]
|
line = [make_blank(width, background_style)]
|
||||||
else:
|
else:
|
||||||
# Content with border and padding (C)
|
# Content with border and padding (C)
|
||||||
content_y = y - gutter.top
|
content_y = y - gutter.top
|
||||||
if content_y < content_height:
|
if content_y < content_height:
|
||||||
line = render_content_line(y - gutter.top)
|
line = render_content_line(y - gutter.top)
|
||||||
else:
|
else:
|
||||||
line = [Segment(" " * content_width, inner)]
|
line = [make_blank(content_width, inner)]
|
||||||
if inner:
|
if inner:
|
||||||
line = Segment.apply_style(line, inner)
|
line = Segment.apply_style(line, inner)
|
||||||
line = line_pad(line, pad_left, pad_right, inner)
|
line = line_pad(line, pad_left, pad_right, inner)
|
||||||
|
|||||||
@@ -305,7 +305,7 @@ class BoxProperty:
|
|||||||
current_value: tuple[str, Color] = cast(
|
current_value: tuple[str, Color] = cast(
|
||||||
"tuple[str, Color]", obj.get_rule(self.name)
|
"tuple[str, Color]", obj.get_rule(self.name)
|
||||||
)
|
)
|
||||||
has_edge = current_value and current_value[0]
|
has_edge = bool(current_value and current_value[0])
|
||||||
new_edge = bool(_type)
|
new_edge = bool(_type)
|
||||||
if obj.set_rule(self.name, new_value):
|
if obj.set_rule(self.name, new_value):
|
||||||
obj.refresh(layout=has_edge != new_edge)
|
obj.refresh(layout=has_edge != new_edge)
|
||||||
|
|||||||
@@ -594,8 +594,10 @@ class Styles(StylesBase):
|
|||||||
Returns:
|
Returns:
|
||||||
bool: ``True`` if a rule was cleared, or ``False`` if it was already not set.
|
bool: ``True`` if a rule was cleared, or ``False`` if it was already not set.
|
||||||
"""
|
"""
|
||||||
self._updates += 1
|
changed = self._rules.pop(rule, None) is not None
|
||||||
return self._rules.pop(rule, None) is not None
|
if changed:
|
||||||
|
self._updates += 1
|
||||||
|
return changed
|
||||||
|
|
||||||
def get_rules(self) -> RulesMap:
|
def get_rules(self) -> RulesMap:
|
||||||
return self._rules.copy()
|
return self._rules.copy()
|
||||||
@@ -610,12 +612,17 @@ class Styles(StylesBase):
|
|||||||
Returns:
|
Returns:
|
||||||
bool: ``True`` if the rule changed, otherwise ``False``.
|
bool: ``True`` if the rule changed, otherwise ``False``.
|
||||||
"""
|
"""
|
||||||
self._updates += 1
|
|
||||||
if value is None:
|
if value is None:
|
||||||
return self._rules.pop(rule, None) is not None
|
changed = self._rules.pop(rule, None) is not None
|
||||||
|
if changed:
|
||||||
|
self._updates += 1
|
||||||
|
return changed
|
||||||
current = self._rules.get(rule)
|
current = self._rules.get(rule)
|
||||||
self._rules[rule] = value
|
self._rules[rule] = value
|
||||||
return current != value
|
changed = current != value
|
||||||
|
if changed:
|
||||||
|
self._updates += 1
|
||||||
|
return changed
|
||||||
|
|
||||||
def get_rule(self, rule: str, default: object = None) -> object:
|
def get_rule(self, rule: str, default: object = None) -> object:
|
||||||
return self._rules.get(rule, default)
|
return self._rules.get(rule, default)
|
||||||
|
|||||||
Reference in New Issue
Block a user