fix for visiblity

This commit is contained in:
Will McGugan
2022-12-07 14:41:30 +00:00
parent 8760c3cc5e
commit 23c2c3edd3
6 changed files with 282 additions and 27 deletions

View File

@@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Fixed ### Fixed
- Type selectors can now contain numbers https://github.com/Textualize/textual/issues/1253 - Type selectors can now contain numbers https://github.com/Textualize/textual/issues/1253
- Fixed visibility not affecting children https://github.com/Textualize/textual/issues/1313
## [0.5.0] - 2022-11-20 ## [0.5.0] - 2022-11-20

View File

@@ -347,6 +347,7 @@ class Compositor:
order: tuple[tuple[int, ...], ...], order: tuple[tuple[int, ...], ...],
layer_order: int, layer_order: int,
clip: Region, clip: Region,
visible: bool,
) -> None: ) -> None:
"""Called recursively to place a widget and its children in the map. """Called recursively to place a widget and its children in the map.
@@ -356,7 +357,12 @@ class Compositor:
order (tuple[int, ...]): A tuple of ints to define the order. order (tuple[int, ...]): A tuple of ints to define the order.
clip (Region): The clipping region (i.e. the viewport which contains it). clip (Region): The clipping region (i.e. the viewport which contains it).
""" """
widgets.add(widget) visibility = widget.styles.get_rule("visibility")
if visibility is not None:
visible = visibility == "visible"
if visible:
widgets.add(widget)
styles_offset = widget.styles.offset styles_offset = widget.styles.offset
layout_offset = ( layout_offset = (
styles_offset.resolve(region.size, clip.size) styles_offset.resolve(region.size, clip.size)
@@ -420,32 +426,34 @@ class Compositor:
widget_order, widget_order,
layer_order, layer_order,
sub_clip, sub_clip,
visible,
) )
layer_order -= 1 layer_order -= 1
# Add any scrollbars if visible:
for chrome_widget, chrome_region in widget._arrange_scrollbars( # Add any scrollbars
container_region for chrome_widget, chrome_region in widget._arrange_scrollbars(
): container_region
map[chrome_widget] = MapGeometry( ):
chrome_region + layout_offset, map[chrome_widget] = MapGeometry(
chrome_region + layout_offset,
order,
clip,
container_size,
container_size,
chrome_region,
)
map[widget] = MapGeometry(
region + layout_offset,
order, order,
clip, clip,
total_region.size,
container_size, container_size,
container_size, virtual_region,
chrome_region,
) )
map[widget] = MapGeometry( elif visible:
region + layout_offset,
order,
clip,
total_region.size,
container_size,
virtual_region,
)
else:
# Add the widget to the map # Add the widget to the map
map[widget] = MapGeometry( map[widget] = MapGeometry(
region + layout_offset, region + layout_offset,
@@ -457,7 +465,15 @@ class Compositor:
) )
# Add top level (root) widget # Add top level (root) widget
add_widget(root, size.region, size.region, ((0,),), layer_order, size.region) add_widget(
root,
size.region,
size.region,
((0,),),
layer_order,
size.region,
True,
)
return map, widgets return map, widgets
@property @property
@@ -630,11 +646,6 @@ class Compositor:
if not self.map: if not self.map:
return return
def is_visible(widget: Widget) -> bool:
"""Return True if the widget is (literally) visible by examining various
properties which affect whether it can be seen or not."""
return widget.visible and widget.styles.opacity > 0
_Region = Region _Region = Region
visible_widgets = self.visible_widgets visible_widgets = self.visible_widgets
@@ -644,13 +655,13 @@ class Compositor:
widget_regions = [ widget_regions = [
(widget, region, clip) (widget, region, clip)
for widget, (region, clip) in visible_widgets.items() for widget, (region, clip) in visible_widgets.items()
if crop_overlaps(clip) and is_visible(widget) if crop_overlaps(clip) and widget.styles.opacity > 0
] ]
else: else:
widget_regions = [ widget_regions = [
(widget, region, clip) (widget, region, clip)
for widget, (region, clip) in visible_widgets.items() for widget, (region, clip) in visible_widgets.items()
if is_visible(widget) if widget.styles.opacity > 0
] ]
intersection = _Region.intersection intersection = _Region.intersection

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,34 @@
<html>
<head>
<style>
#outer {
visibility: visible;
background: red;
}
#inner {
visibility: visible;
}
</style>
</head>
<div id="outer">
<div>
<div id="inner">
Hello, World
</div>
</div>
</div>
</html>

View File

@@ -0,0 +1,48 @@
from textual.app import App
from textual.containers import Vertical
from textual.widgets import Static
class Visibility(App):
"""Check that visibility: hidden also makes children invisible;"""
CSS = """
Screen {
layout: horizontal;
}
Vertical {
width: 1fr;
border: solid red;
}
#container1 {
visibility: hidden;
}
.float {
border: solid blue;
}
/* Make a child of a hidden widget visible again */
#container1 .float {
visibility: visible;
}
"""
def compose(self):
yield Vertical(
Static("foo"),
Static("float", classes="float"),
id="container1",
)
yield Vertical(
Static("bar"),
Static("float", classes="float"),
id="container2",
)
if __name__ == "__main__":
app = Visibility()
app.run()

View File

@@ -100,6 +100,10 @@ def test_fr_units(snap_compare):
assert snap_compare("snapshot_apps/fr_units.py") assert snap_compare("snapshot_apps/fr_units.py")
def test_visibility(snap_compare):
assert snap_compare("snapshot_apps/visibility.py")
def test_tree_example(snap_compare): def test_tree_example(snap_compare):
assert snap_compare(WIDGET_EXAMPLES_DIR / "tree.py") assert snap_compare(WIDGET_EXAMPLES_DIR / "tree.py")