diff --git a/CHANGELOG.md b/CHANGELOG.md index 6eed95593..8da8e3b9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - The styles `scrollbar-background-active` and `scrollbar-color-hover` are no longer ignored https://github.com/Textualize/textual/pull/1480 +- The widget `Placeholder` can now have its width set to `auto` https://github.com/Textualize/textual/pull/1508 ## [0.9.1] - 2022-12-30 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) diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr index 4a9464a81..d920e8d87 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr +++ b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr @@ -7800,145 +7800,142 @@ font-weight: 700; } - .terminal-2023815619-matrix { + .terminal-1570661136-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-2023815619-title { + .terminal-1570661136-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-2023815619-r1 { fill: #e8e0e7 } - .terminal-2023815619-r2 { fill: #c5c8c6 } - .terminal-2023815619-r3 { fill: #eae3e5 } - .terminal-2023815619-r4 { fill: #ede6e6 } - .terminal-2023815619-r5 { fill: #efe9e4 } - .terminal-2023815619-r6 { fill: #efeedf } - .terminal-2023815619-r7 { fill: #e9eee5 } - .terminal-2023815619-r8 { fill: #e4eee8 } - .terminal-2023815619-r9 { fill: #dfebed } - .terminal-2023815619-r10 { fill: #e2edeb } - .terminal-2023815619-r11 { fill: #e4eee8;font-weight: bold } - .terminal-2023815619-r12 { fill: #dfebed;font-weight: bold } - .terminal-2023815619-r13 { fill: #e3e6eb } - .terminal-2023815619-r14 { fill: #dfe9ed } - .terminal-2023815619-r15 { fill: #e3e6eb;font-weight: bold } - .terminal-2023815619-r16 { fill: #e6e3e9 } + .terminal-1570661136-r1 { fill: #c5c8c6 } + .terminal-1570661136-r2 { fill: #eae3e5 } + .terminal-1570661136-r3 { fill: #e8e0e7 } + .terminal-1570661136-r4 { fill: #efe9e4 } + .terminal-1570661136-r5 { fill: #ede6e6 } + .terminal-1570661136-r6 { fill: #efeedf } + .terminal-1570661136-r7 { fill: #e9eee5 } + .terminal-1570661136-r8 { fill: #e2edeb } + .terminal-1570661136-r9 { fill: #e4eee8;font-weight: bold } + .terminal-1570661136-r10 { fill: #dfebed;font-weight: bold } + .terminal-1570661136-r11 { fill: #dfe9ed } + .terminal-1570661136-r12 { fill: #e3e6eb;font-weight: bold } + .terminal-1570661136-r13 { fill: #e6e3e9 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - PlaceholderApp + PlaceholderApp - - - - - Placeholder p2 here! - This is a custom label for p1. - #p4 - #p3#p5Placeholde - r - - Lorem ipsum dolor sit  - 26 x 6amet, consectetur 27 x 6 - adipiscing elit. Etiam  - feugiat ac elit sit amet  - - - Lorem ipsum dolor sit amet,  - consectetur adipiscing elit. Etiam 40 x 6 - feugiat ac elit sit amet accumsan.  - Suspendisse bibendum nec libero quis  - gravida. Phasellus id eleifend ligula. - Nullam imperdiet sem tellus, sed  - vehicula nisl faucibus sit amet. Lorem ipsum dolor sit amet,  - Praesent iaculis tempor ultricies. Sedconsectetur adipiscing elit. Etiam  - lacinia, tellus id rutrum lacinia, feugiat ac elit sit amet accumsan.  - sapien sapien congue mauris, sit amet Suspendisse bibendum nec libero quis  + + + + + Placeholder p2 here! + This is a custom label for p1. + #p4 + #p3#p5Placeholde + r + + Lorem ipsum dolor sit  + 26 x 6amet, consectetur 27 x 6 + adipiscing elit. Etiam  + feugiat ac elit sit amet  + + + Lorem ipsum dolor sit amet,  + consectetur adipiscing elit. Etiam 40 x 6 + feugiat ac elit sit amet accumsan.  + Suspendisse bibendum nec libero quis  + gravida. Phasellus id eleifend ligula. + Nullam imperdiet sem tellus, sed  + vehicula nisl faucibus sit amet. Lorem ipsum dolor sit amet,  + Praesent iaculis tempor ultricies. Sedconsectetur adipiscing elit. Etiam  + lacinia, tellus id rutrum lacinia, feugiat ac elit sit amet accumsan.  + sapien sapien congue mauris, sit amet Suspendisse bibendum nec libero quis