mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
Merge pull request #436 from Textualize/bugfix-display-none-is-being-ignored-in-vertical-and-horizontal-layouts
[layout][bugfix] Horizontal & Vertical layouts shouldn't display children that have `display: none`
This commit is contained in:
@@ -521,6 +521,7 @@ class App(DOMNode):
|
|||||||
mount_event = events.Mount(sender=self)
|
mount_event = events.Mount(sender=self)
|
||||||
await self.dispatch_message(mount_event)
|
await self.dispatch_message(mount_event)
|
||||||
|
|
||||||
|
# TODO: don't override `self.console` here
|
||||||
self.console = Console(file=sys.__stdout__)
|
self.console = Console(file=sys.__stdout__)
|
||||||
self.title = self._title
|
self.title = self._title
|
||||||
self.refresh()
|
self.refresh()
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ if TYPE_CHECKING:
|
|||||||
class RulesMap(TypedDict, total=False):
|
class RulesMap(TypedDict, total=False):
|
||||||
"""A typed dict for CSS rules.
|
"""A typed dict for CSS rules.
|
||||||
|
|
||||||
Any key may be absent, indiciating that rule has not been set.
|
Any key may be absent, indicating that rule has not been set.
|
||||||
|
|
||||||
Does not define composite rules, that is a rule that is made of a combination of other rules.
|
Does not define composite rules, that is a rule that is made of a combination of other rules.
|
||||||
|
|
||||||
|
|||||||
@@ -278,6 +278,10 @@ class DOMNode(MessagePump):
|
|||||||
add_children(tree, self)
|
add_children(tree, self)
|
||||||
return tree
|
return tree
|
||||||
|
|
||||||
|
@property
|
||||||
|
def displayed_children(self) -> list[DOMNode]:
|
||||||
|
return [child for child in self.children if child.display]
|
||||||
|
|
||||||
def get_pseudo_classes(self) -> Iterable[str]:
|
def get_pseudo_classes(self) -> Iterable[str]:
|
||||||
"""Get any pseudo classes applicable to this Node, e.g. hover, focus.
|
"""Get any pseudo classes applicable to this Node, e.g. hover, focus.
|
||||||
|
|
||||||
|
|||||||
@@ -50,10 +50,9 @@ class DockLayout(Layout):
|
|||||||
|
|
||||||
def get_docks(self, parent: Widget) -> list[Dock]:
|
def get_docks(self, parent: Widget) -> list[Dock]:
|
||||||
groups: dict[str, list[Widget]] = defaultdict(list)
|
groups: dict[str, list[Widget]] = defaultdict(list)
|
||||||
for child in parent.children:
|
for child in parent.displayed_children:
|
||||||
assert isinstance(child, Widget)
|
assert isinstance(child, Widget)
|
||||||
if child.display:
|
groups[child.styles.dock].append(child)
|
||||||
groups[child.styles.dock].append(child)
|
|
||||||
docks: list[Dock] = []
|
docks: list[Dock] = []
|
||||||
append_dock = docks.append
|
append_dock = docks.append
|
||||||
for name, edge, z in parent.styles.docks:
|
for name, edge, z in parent.styles.docks:
|
||||||
|
|||||||
@@ -39,7 +39,9 @@ class HorizontalLayout(Layout):
|
|||||||
|
|
||||||
x = box_models[0].margin.left if box_models else 0
|
x = box_models[0].margin.left if box_models else 0
|
||||||
|
|
||||||
for widget, box_model, margin in zip(parent.children, box_models, margins):
|
displayed_children = parent.displayed_children
|
||||||
|
|
||||||
|
for widget, box_model, margin in zip(displayed_children, box_models, margins):
|
||||||
content_width, content_height = box_model.size
|
content_width, content_height = box_model.size
|
||||||
offset_y = widget.styles.align_height(content_height, parent_size.height)
|
offset_y = widget.styles.align_height(content_height, parent_size.height)
|
||||||
region = Region(x, offset_y, content_width, content_height)
|
region = Region(x, offset_y, content_width, content_height)
|
||||||
@@ -53,4 +55,4 @@ class HorizontalLayout(Layout):
|
|||||||
total_region = Region(0, 0, max_width, max_height)
|
total_region = Region(0, 0, max_width, max_height)
|
||||||
add_placement(WidgetPlacement(total_region, None, 0))
|
add_placement(WidgetPlacement(total_region, None, 0))
|
||||||
|
|
||||||
return placements, set(parent.children)
|
return placements, set(displayed_children)
|
||||||
|
|||||||
@@ -40,10 +40,13 @@ class VerticalLayout(Layout):
|
|||||||
|
|
||||||
y = box_models[0].margin.top if box_models else 0
|
y = box_models[0].margin.top if box_models else 0
|
||||||
|
|
||||||
for widget, box_model, margin in zip(parent.children, box_models, margins):
|
displayed_children = parent.displayed_children
|
||||||
|
|
||||||
|
for widget, box_model, margin in zip(displayed_children, box_models, margins):
|
||||||
content_width, content_height = box_model.size
|
content_width, content_height = box_model.size
|
||||||
offset_x = widget.styles.align_width(content_width, parent_size.width)
|
offset_x = widget.styles.align_width(content_width, parent_size.width)
|
||||||
region = Region(offset_x, y, content_width, content_height)
|
region = Region(offset_x, y, content_width, content_height)
|
||||||
|
# TODO: it seems that `max_height` is not used?
|
||||||
max_height = max(max_height, content_height)
|
max_height = max(max_height, content_height)
|
||||||
add_placement(WidgetPlacement(region, widget, 0))
|
add_placement(WidgetPlacement(region, widget, 0))
|
||||||
y += region.height + margin
|
y += region.height + margin
|
||||||
@@ -54,4 +57,4 @@ class VerticalLayout(Layout):
|
|||||||
total_region = Region(0, 0, max_width, max_height)
|
total_region = Region(0, 0, max_width, max_height)
|
||||||
add_placement(WidgetPlacement(total_region, None, 0))
|
add_placement(WidgetPlacement(total_region, None, 0))
|
||||||
|
|
||||||
return placements, set(parent.children)
|
return placements, set(displayed_children)
|
||||||
|
|||||||
30
tests/layouts/test_common_layout_features.py
Normal file
30
tests/layouts/test_common_layout_features.py
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from textual.screen import Screen
|
||||||
|
from textual.widget import Widget
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"layout,display,expected_in_displayed_children",
|
||||||
|
[
|
||||||
|
("dock", "block", True),
|
||||||
|
("horizontal", "block", True),
|
||||||
|
("vertical", "block", True),
|
||||||
|
("dock", "none", False),
|
||||||
|
("horizontal", "none", False),
|
||||||
|
("vertical", "none", False),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_nodes_take_display_property_into_account_when_they_display_their_children(
|
||||||
|
layout: str, display: str, expected_in_displayed_children: bool
|
||||||
|
):
|
||||||
|
widget = Widget(name="widget that might not be visible 🥷 ")
|
||||||
|
widget.styles.display = display
|
||||||
|
|
||||||
|
screen = Screen()
|
||||||
|
screen.styles.layout = layout
|
||||||
|
screen.add_child(widget)
|
||||||
|
|
||||||
|
displayed_children = screen.displayed_children
|
||||||
|
assert isinstance(displayed_children, list)
|
||||||
|
assert (widget in screen.displayed_children) is expected_in_displayed_children
|
||||||
Reference in New Issue
Block a user