diff --git a/src/textual/_styles_cache.py b/src/textual/_styles_cache.py index e11acc0bbd..15e292357d 100644 --- a/src/textual/_styles_cache.py +++ b/src/textual/_styles_cache.py @@ -63,6 +63,8 @@ def __init__(self) -> None: self._cache: dict[int, Strip] = {} self._dirty_lines: set[int] = set() self._width = 1 + self._simple_strip: Strip | None = None + """A simple strip consisting of left border + background + right border, which may be reused in a render.""" def __rich_repr__(self) -> rich.repr.Result: if self._dirty_lines: @@ -106,6 +108,7 @@ def render_widget(self, widget: Widget, crop: Region) -> list[Strip]: """ border_title = widget._border_title border_subtitle = widget._border_subtitle + self._simple_strip = None base_background, background = widget.background_colors styles = widget.styles @@ -348,6 +351,7 @@ def post(segments: Iterable[Segment]) -> Iterable[Segment]: segments = _apply_opacity(segments, base_background, opacity) return segments + cache_simple_strip: bool = False line: Iterable[Segment] # Draw top or bottom borders (A) if (border_top and y == 0) or (border_bottom and y == height - 1): @@ -411,11 +415,13 @@ def post(segments: Iterable[Segment]) -> Iterable[Segment]: label_segments, label_alignment, # type: ignore ) - # Draw padding (B) elif (pad_top and y < gutter.top) or ( pad_bottom and y >= height - gutter.bottom ): + if self._simple_strip is not None: + return self._simple_strip + cache_simple_strip = True background_rich_style = inner.rich_style left_style = Style( foreground=base_background + border_left_color.multiply_alpha(opacity) @@ -498,6 +504,7 @@ def post(segments: Iterable[Segment]) -> Iterable[Segment]: line = [left, *line] else: line = [*line, right] - strip = Strip(post(line), width) + if cache_simple_strip: + self._simple_strip = strip return strip diff --git a/src/textual/widgets/_collapsible.py b/src/textual/widgets/_collapsible.py index a35d7e2eb0..2185e96d70 100644 --- a/src/textual/widgets/_collapsible.py +++ b/src/textual/widgets/_collapsible.py @@ -17,6 +17,8 @@ class CollapsibleTitle(Static, can_focus=True): """Title and symbol for the Collapsible.""" + BINDING_GROUP_TITLE = "Collapsible" + ALLOW_SELECT = False DEFAULT_CSS = """ CollapsibleTitle { diff --git a/src/textual/widgets/_help_panel.py b/src/textual/widgets/_help_panel.py index 36717d2445..d6346e66c0 100644 --- a/src/textual/widgets/_help_panel.py +++ b/src/textual/widgets/_help_panel.py @@ -96,7 +96,11 @@ def update_help(self, focused_widget: Widget | None) -> None: return self.set_class(focused_widget is not None, "-show-help") if focused_widget is not None: - help = focused_widget.HELP or "" + help: str = "" + for node in focused_widget.ancestors_with_self: + if isinstance(node, Widget) and node.HELP: + help = node.HELP + break if not help: self.remove_class("-show-help") try: diff --git a/src/textual/widgets/_input.py b/src/textual/widgets/_input.py index e8470ddfbb..e117060dbc 100644 --- a/src/textual/widgets/_input.py +++ b/src/textual/widgets/_input.py @@ -71,6 +71,7 @@ def is_empty(self) -> bool: class Input(ScrollView): """A text input widget.""" + BINDING_GROUP_TITLE = "Input" BINDINGS: ClassVar[list[BindingType]] = [ Binding("left", "cursor_left", "Move cursor left", show=False), Binding( diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_help_panel.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_help_panel.svg index 51a3cb6fc3..1788ba88af 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots/test_help_panel.svg +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_help_panel.svg @@ -36,9 +36,10 @@ .terminal-r2 { fill: #0178d4 } .terminal-r3 { fill: #4f4f4f } .terminal-r4 { fill: #c5c8c6 } -.terminal-r5 { fill: #ffc473;font-weight: bold } -.terminal-r6 { fill: #e0e0e0 } -.terminal-r7 { fill: #000000 } +.terminal-r5 { fill: #e0e0e0 } +.terminal-r6 { fill: #57a5e2;text-decoration: underline; } +.terminal-r7 { fill: #ffc473;font-weight: bold } +.terminal-r8 { fill: #000000 } @@ -142,38 +143,38 @@ - + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ -         ↑Scroll Up       -▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁         ↓Scroll Down     -         ←Move cursor     -left            -         →Move cursor     -right or accept -the completion  -suggestion      -   home ^aGo to start     -    end ^eGo to end       -      pgupPage Up         -      pgdnPage Down       -     ^pgupPage Left      ▁▁ -     ^pgdnPage Right      -   shift+←Move cursor     -left and select -        ^←Move cursor     -left a word     -  shift+^←Move cursor     -left a word and -select          -   shift+→Move cursor     -right and       -select          -        ^→Move cursor     -right a word    -  shift+^→Move cursor     -right a word    -and select      +Input +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁         ↑Scroll Up       +         ↓Scroll Down     +         ←Move cursor     +left            +         →Move cursor     +right or accept +the completion  +suggestion      +   home ^aGo to start     +    end ^eGo to end       +      pgupPage Up         +      pgdnPage Down      ▂▂ +     ^pgupPage Left       +     ^pgdnPage Right      +   shift+←Move cursor     +left and select +        ^←Move cursor     +left a word     +  shift+^←Move cursor     +left a word and +select          +   shift+→Move cursor     +right and       +select          +        ^→Move cursor     +right a word    +  shift+^→Move cursor     +right a word