From 3188043aa67a6bfb0aa1768d54d5dd9ec57699e8 Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Tue, 18 Jan 2022 13:51:15 +0000 Subject: [PATCH] Rename visible property to display, add setter --- examples/calculator.py | 6 +++--- src/textual/dom.py | 29 ++++++++++++++++++++++++++++- src/textual/layouts/dock.py | 2 +- src/textual/layouts/grid.py | 2 +- src/textual/view.py | 2 +- src/textual/widget.py | 4 ---- tests/test_dom.py | 25 +++++++++++++++++++++++++ 7 files changed, 59 insertions(+), 11 deletions(-) create mode 100644 tests/test_dom.py diff --git a/examples/calculator.py b/examples/calculator.py index 7e514adc6..462a65d4a 100644 --- a/examples/calculator.py +++ b/examples/calculator.py @@ -101,8 +101,8 @@ class Calculator(GridView): def watch_show_ac(self, show_ac: bool) -> None: """When the show_ac attribute change we need to update the buttons.""" # Show AC and hide C or vice versa - self.c.visible = not show_ac - self.ac.visible = show_ac + self.c.display = not show_ac + self.ac.display = show_ac def on_mount(self) -> None: """Event when widget is first mounted (added to a parent view).""" @@ -131,7 +131,7 @@ class Calculator(GridView): self.zero = make_button("0", self.DARK) self.ac = make_button("AC", self.LIGHT) self.c = make_button("C", self.LIGHT) - self.c.visible = False + self.c.display = False # Set basic grid settings self.grid.set_gap(2, 1) diff --git a/src/textual/dom.py b/src/textual/dom.py index 308d577db..8b17700ed 100644 --- a/src/textual/dom.py +++ b/src/textual/dom.py @@ -8,6 +8,9 @@ from rich.pretty import Pretty from rich.style import Style from rich.tree import Tree +from .css._error_tools import friendly_list +from .css.constants import VALID_DISPLAY +from .css.errors import StyleValueError from .css.styles import Styles from .message_pump import MessagePump from ._node_list import NodeList @@ -130,9 +133,33 @@ class DOMNode(MessagePump): return result[::-1] @property - def visible(self) -> bool: + def display(self) -> bool: + """ + Returns: ``True`` if this DOMNode is displayed (``display != "none"``), ``False`` otherwise. + """ return self.styles.display != "none" + @display.setter + def display(self, new_val: bool | str) -> None: + """ + Args: + new_val (bool | str): Shortcut to set the ``display`` CSS property. + ``False`` will set ``display: none``. ``True`` will set ``display: block``. + A ``False`` value will prevent the DOMNode from consuming space in the layout. + """ + # TODO: This will forget what the original "display" value was, so if a user + # toggles to False then True, we'll reset to the default "block", rather than + # what the user initially specified. + if isinstance(new_val, bool): + self.styles.display = "block" if new_val else "none" + elif new_val in VALID_DISPLAY: + self.styles.display = new_val + else: + raise StyleValueError( + f"invalid value for display (received {new_val!r}, " + f"expected {friendly_list(VALID_DISPLAY)})", + ) + @property def z(self) -> tuple[int, ...]: """Get the z index tuple for this node. diff --git a/src/textual/layouts/dock.py b/src/textual/layouts/dock.py index 2f49ec460..16b4f152b 100644 --- a/src/textual/layouts/dock.py +++ b/src/textual/layouts/dock.py @@ -51,7 +51,7 @@ class DockLayout(Layout): groups: dict[str, list[Widget]] = defaultdict(list) for child in view.children: assert isinstance(child, Widget) - if child.visible: + if child.display: groups[child.styles.dock].append(child) docks: list[Dock] = [] append_dock = docks.append diff --git a/src/textual/layouts/grid.py b/src/textual/layouts/grid.py index 4e0cb1cbf..f53127190 100644 --- a/src/textual/layouts/grid.py +++ b/src/textual/layouts/grid.py @@ -352,7 +352,7 @@ class GridLayout(Layout): widget_areas = ( (widget, area) for widget, area in self.widgets.items() - if area and widget.visible + if area and widget.display ) free_slots = { diff --git a/src/textual/view.py b/src/textual/view.py index 6793e3b74..d6cd03784 100644 --- a/src/textual/view.py +++ b/src/textual/view.py @@ -263,5 +263,5 @@ class View(Widget): async def action_toggle(self, name: str) -> None: widget = self[name] - widget.visible = not widget.visible + widget.visible = not widget.display await self.post_message(messages.Layout(self)) diff --git a/src/textual/widget.py b/src/textual/widget.py index a9ecfb25b..e02118239 100644 --- a/src/textual/widget.py +++ b/src/textual/widget.py @@ -183,10 +183,6 @@ class Widget(DOMNode): return renderable - @property - def visible(self) -> bool: - return self.styles.display == "block" - @property def size(self) -> Size: return self._size diff --git a/tests/test_dom.py b/tests/test_dom.py new file mode 100644 index 000000000..cf1c70283 --- /dev/null +++ b/tests/test_dom.py @@ -0,0 +1,25 @@ +import pytest + +from textual.css.errors import StyleValueError +from textual.dom import DOMNode + + +def test_display_default(): + node = DOMNode() + assert node.display is True + + +@pytest.mark.parametrize( + "setter_value,style_value", + [[True, "block"], [False, "none"], ["block", "block"], ["none", "none"]], +) +def test_display_set_bool(setter_value, style_value): + node = DOMNode() + node.display = setter_value + assert node.styles.display == style_value + + +def test_display_set_invalid_value(): + node = DOMNode() + with pytest.raises(StyleValueError): + node.display = "blah"