diff --git a/src/textual/widgets/_placeholder.py b/src/textual/widgets/_placeholder.py index eabe762c9..137a0fd1c 100644 --- a/src/textual/widgets/_placeholder.py +++ b/src/textual/widgets/_placeholder.py @@ -3,7 +3,6 @@ from __future__ import annotations from itertools import cycle from .. import events -from ..containers import Container from ..css._error_tools import friendly_list from ..reactive import Reactive, reactive from ..widget import Widget, RenderResult @@ -36,19 +35,10 @@ _LOREM_IPSUM_PLACEHOLDER_TEXT = "Lorem ipsum dolor sit amet, consectetur adipisc class InvalidPlaceholderVariant(Exception): - pass + """Raised when an invalid Placeholder variant is set.""" -class _PlaceholderLabel(Widget): - def __init__(self, content, classes) -> None: - super().__init__(classes=classes) - self._content = content - - def render(self) -> RenderResult: - return self._content - - -class Placeholder(Container): +class Placeholder(Widget): """A simple placeholder widget to use before you build your custom widgets. This placeholder has a couple of variants that show different data. @@ -63,44 +53,24 @@ class Placeholder(Container): DEFAULT_CSS = """ Placeholder { - align: center middle; + content-align: center middle; overflow: hidden; + color: $text; } Placeholder.-text { padding: 1; } - - _PlaceholderLabel { - height: auto; - color: $text; - } - - Placeholder > _PlaceholderLabel { - content-align: center middle; - } - - Placeholder.-default > _PlaceholderLabel.-size, - Placeholder.-default > _PlaceholderLabel.-text, - Placeholder.-size > _PlaceholderLabel.-default, - Placeholder.-size > _PlaceholderLabel.-text, - Placeholder.-text > _PlaceholderLabel.-default, - Placeholder.-text > _PlaceholderLabel.-size { - display: none; - } - - Placeholder.-default > _PlaceholderLabel.-default, - Placeholder.-size > _PlaceholderLabel.-size, - Placeholder.-text > _PlaceholderLabel.-text { - display: block; - } """ + # Consecutive placeholders get assigned consecutive colors. _COLORS = cycle(_PLACEHOLDER_BACKGROUND_COLORS) _SIZE_RENDER_TEMPLATE = "[b]{} x {}[/b]" variant: Reactive[PlaceholderVariant] = reactive("default") + _renderables: dict[PlaceholderVariant, RenderResult] + @classmethod def reset_color_cycle(cls) -> None: """Reset the placeholder background color cycle.""" @@ -128,27 +98,14 @@ class Placeholder(Container): classes (str | None, optional): A space separated string with the CSS classes of the placeholder, if any. Defaults to None. """ - # Create and cache labels for all the variants. - self._default_label = _PlaceholderLabel( - label if label else f"#{id}" if id else "Placeholder", - "-default", - ) - self._size_label = _PlaceholderLabel( - "", - "-size", - ) - self._text_label = _PlaceholderLabel( - "\n\n".join(_LOREM_IPSUM_PLACEHOLDER_TEXT for _ in range(5)), - "-text", - ) - super().__init__( - self._default_label, - self._size_label, - self._text_label, - name=name, - id=id, - classes=classes, - ) + # Create and cache renderables for all the variants. + self._renderables = { + "default": label if label else f"#{id}" if id else "Placeholder", + "size": "", + "text": "\n\n".join(_LOREM_IPSUM_PLACEHOLDER_TEXT for _ in range(5)), + } + + super().__init__(name=name, id=id, classes=classes) self.styles.background = f"{next(Placeholder._COLORS)} 50%" @@ -158,6 +115,9 @@ class Placeholder(Container): while next(self._variants_cycle) != self.variant: pass + def render(self) -> RenderResult: + return self._renderables[self.variant] + def cycle_variant(self) -> None: """Get the next variant in the cycle.""" self.variant = next(self._variants_cycle) @@ -183,6 +143,6 @@ class Placeholder(Container): def on_resize(self, event: events.Resize) -> None: """Update the placeholder "size" variant with the new placeholder size.""" - self._size_label._content = self._SIZE_RENDER_TEMPLATE.format(*self.size) + self._renderables["size"] = self._SIZE_RENDER_TEMPLATE.format(*self.size) if self.variant == "size": - self._size_label.refresh(layout=True) + self.refresh(layout=True)