mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
Simplify Placeholder implementation.
Instead of creating a private widget that is the only child of 'Placeholder', that was inheriting from 'Container', simplify everything. 'Placeholder' now inherits directly from 'Widget' and it saves a dictionary with its renderables per variant, instead of deferring that to the child '_PlaceholderLabel'.
This commit is contained in:
@@ -3,7 +3,6 @@ from __future__ import annotations
|
|||||||
from itertools import cycle
|
from itertools import cycle
|
||||||
|
|
||||||
from .. import events
|
from .. import events
|
||||||
from ..containers import Container
|
|
||||||
from ..css._error_tools import friendly_list
|
from ..css._error_tools import friendly_list
|
||||||
from ..reactive import Reactive, reactive
|
from ..reactive import Reactive, reactive
|
||||||
from ..widget import Widget, RenderResult
|
from ..widget import Widget, RenderResult
|
||||||
@@ -36,19 +35,10 @@ _LOREM_IPSUM_PLACEHOLDER_TEXT = "Lorem ipsum dolor sit amet, consectetur adipisc
|
|||||||
|
|
||||||
|
|
||||||
class InvalidPlaceholderVariant(Exception):
|
class InvalidPlaceholderVariant(Exception):
|
||||||
pass
|
"""Raised when an invalid Placeholder variant is set."""
|
||||||
|
|
||||||
|
|
||||||
class _PlaceholderLabel(Widget):
|
class Placeholder(Widget):
|
||||||
def __init__(self, content, classes) -> None:
|
|
||||||
super().__init__(classes=classes)
|
|
||||||
self._content = content
|
|
||||||
|
|
||||||
def render(self) -> RenderResult:
|
|
||||||
return self._content
|
|
||||||
|
|
||||||
|
|
||||||
class Placeholder(Container):
|
|
||||||
"""A simple placeholder widget to use before you build your custom widgets.
|
"""A simple placeholder widget to use before you build your custom widgets.
|
||||||
|
|
||||||
This placeholder has a couple of variants that show different data.
|
This placeholder has a couple of variants that show different data.
|
||||||
@@ -63,44 +53,24 @@ class Placeholder(Container):
|
|||||||
|
|
||||||
DEFAULT_CSS = """
|
DEFAULT_CSS = """
|
||||||
Placeholder {
|
Placeholder {
|
||||||
align: center middle;
|
content-align: center middle;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
color: $text;
|
||||||
}
|
}
|
||||||
|
|
||||||
Placeholder.-text {
|
Placeholder.-text {
|
||||||
padding: 1;
|
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.
|
# Consecutive placeholders get assigned consecutive colors.
|
||||||
_COLORS = cycle(_PLACEHOLDER_BACKGROUND_COLORS)
|
_COLORS = cycle(_PLACEHOLDER_BACKGROUND_COLORS)
|
||||||
_SIZE_RENDER_TEMPLATE = "[b]{} x {}[/b]"
|
_SIZE_RENDER_TEMPLATE = "[b]{} x {}[/b]"
|
||||||
|
|
||||||
variant: Reactive[PlaceholderVariant] = reactive("default")
|
variant: Reactive[PlaceholderVariant] = reactive("default")
|
||||||
|
|
||||||
|
_renderables: dict[PlaceholderVariant, RenderResult]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def reset_color_cycle(cls) -> None:
|
def reset_color_cycle(cls) -> None:
|
||||||
"""Reset the placeholder background color cycle."""
|
"""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
|
classes (str | None, optional): A space separated string with the CSS classes
|
||||||
of the placeholder, if any. Defaults to None.
|
of the placeholder, if any. Defaults to None.
|
||||||
"""
|
"""
|
||||||
# Create and cache labels for all the variants.
|
# Create and cache renderables for all the variants.
|
||||||
self._default_label = _PlaceholderLabel(
|
self._renderables = {
|
||||||
label if label else f"#{id}" if id else "Placeholder",
|
"default": label if label else f"#{id}" if id else "Placeholder",
|
||||||
"-default",
|
"size": "",
|
||||||
)
|
"text": "\n\n".join(_LOREM_IPSUM_PLACEHOLDER_TEXT for _ in range(5)),
|
||||||
self._size_label = _PlaceholderLabel(
|
}
|
||||||
"",
|
|
||||||
"-size",
|
super().__init__(name=name, id=id, classes=classes)
|
||||||
)
|
|
||||||
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,
|
|
||||||
)
|
|
||||||
|
|
||||||
self.styles.background = f"{next(Placeholder._COLORS)} 50%"
|
self.styles.background = f"{next(Placeholder._COLORS)} 50%"
|
||||||
|
|
||||||
@@ -158,6 +115,9 @@ class Placeholder(Container):
|
|||||||
while next(self._variants_cycle) != self.variant:
|
while next(self._variants_cycle) != self.variant:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def render(self) -> RenderResult:
|
||||||
|
return self._renderables[self.variant]
|
||||||
|
|
||||||
def cycle_variant(self) -> None:
|
def cycle_variant(self) -> None:
|
||||||
"""Get the next variant in the cycle."""
|
"""Get the next variant in the cycle."""
|
||||||
self.variant = next(self._variants_cycle)
|
self.variant = next(self._variants_cycle)
|
||||||
@@ -183,6 +143,6 @@ class Placeholder(Container):
|
|||||||
|
|
||||||
def on_resize(self, event: events.Resize) -> None:
|
def on_resize(self, event: events.Resize) -> None:
|
||||||
"""Update the placeholder "size" variant with the new placeholder size."""
|
"""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":
|
if self.variant == "size":
|
||||||
self._size_label.refresh(layout=True)
|
self.refresh(layout=True)
|
||||||
|
|||||||
Reference in New Issue
Block a user