mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
Merge pull request #1268 from Textualize/spatial-map
Optimisations and fixes
This commit is contained in:
@@ -10,7 +10,7 @@ if TYPE_CHECKING:
|
||||
from .widget import Widget
|
||||
|
||||
ArrangeResult: TypeAlias = "tuple[list[WidgetPlacement], set[Widget]]"
|
||||
DockArrangeResult: TypeAlias = "tuple[list[WidgetPlacement], set[Widget], Spacing]"
|
||||
DockArrangeResult: TypeAlias = "tuple[list[WidgetPlacement], set[Widget], Spacing]]"
|
||||
|
||||
|
||||
class WidgetPlacement(NamedTuple):
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from functools import lru_cache
|
||||
from sys import intern
|
||||
from typing import TYPE_CHECKING, Callable, Iterable, List
|
||||
|
||||
from rich.segment import Segment
|
||||
@@ -52,6 +54,20 @@ def style_links(
|
||||
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:
|
||||
"""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 = get_box(border_right, inner, outer, right_style)[1][2]
|
||||
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:
|
||||
line = [left, Segment(" " * (width - 1), background_style)]
|
||||
line = [left, make_blank(width - 1, background_style)]
|
||||
elif border_right:
|
||||
line = [Segment(" " * (width - 1), background_style), right]
|
||||
line = [make_blank(width - 1, background_style), right]
|
||||
else:
|
||||
line = [Segment(" " * width, background_style)]
|
||||
line = [make_blank(width, background_style)]
|
||||
else:
|
||||
# Content with border and padding (C)
|
||||
content_y = y - gutter.top
|
||||
if content_y < content_height:
|
||||
line = render_content_line(y - gutter.top)
|
||||
else:
|
||||
line = [Segment(" " * content_width, inner)]
|
||||
line = [make_blank(content_width, inner)]
|
||||
if inner:
|
||||
line = Segment.apply_style(line, inner)
|
||||
line = line_pad(line, pad_left, pad_right, inner)
|
||||
|
||||
@@ -305,7 +305,7 @@ class BoxProperty:
|
||||
current_value: tuple[str, Color] = cast(
|
||||
"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)
|
||||
if obj.set_rule(self.name, new_value):
|
||||
obj.refresh(layout=has_edge != new_edge)
|
||||
|
||||
@@ -594,8 +594,10 @@ class Styles(StylesBase):
|
||||
Returns:
|
||||
bool: ``True`` if a rule was cleared, or ``False`` if it was already not set.
|
||||
"""
|
||||
self._updates += 1
|
||||
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
|
||||
|
||||
def get_rules(self) -> RulesMap:
|
||||
return self._rules.copy()
|
||||
@@ -610,12 +612,17 @@ class Styles(StylesBase):
|
||||
Returns:
|
||||
bool: ``True`` if the rule changed, otherwise ``False``.
|
||||
"""
|
||||
self._updates += 1
|
||||
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)
|
||||
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:
|
||||
return self._rules.get(rule, default)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections import Counter
|
||||
from asyncio import Event as AsyncEvent
|
||||
from asyncio import Lock, create_task, wait
|
||||
from collections import Counter
|
||||
from fractions import Fraction
|
||||
from itertools import islice
|
||||
from operator import attrgetter
|
||||
@@ -53,7 +53,6 @@ from .message import Message
|
||||
from .messages import CallbackType
|
||||
from .reactive import Reactive
|
||||
from .render import measure
|
||||
from .await_remove import AwaitRemove
|
||||
from .walk import walk_depth_first
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -755,14 +754,12 @@ class Widget(DOMNode):
|
||||
def watch_scroll_x(self, new_value: float) -> None:
|
||||
if self.show_horizontal_scrollbar:
|
||||
self.horizontal_scrollbar.position = int(new_value)
|
||||
self.horizontal_scrollbar.refresh()
|
||||
self.refresh(layout=True)
|
||||
self.refresh(layout=True, repaint=False)
|
||||
|
||||
def watch_scroll_y(self, new_value: float) -> None:
|
||||
if self.show_vertical_scrollbar:
|
||||
self.vertical_scrollbar.position = int(new_value)
|
||||
self.vertical_scrollbar.refresh()
|
||||
self.refresh(layout=True)
|
||||
self.refresh(layout=True, repaint=False)
|
||||
|
||||
def validate_scroll_x(self, value: float) -> float:
|
||||
return clamp(value, 0, self.max_scroll_x)
|
||||
|
||||
Reference in New Issue
Block a user