mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
fix for visiblity
This commit is contained in:
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
34
tests/snapshot_tests/snapshot_apps/vis.html
Normal file
34
tests/snapshot_tests/snapshot_apps/vis.html
Normal 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>
|
||||||
48
tests/snapshot_tests/snapshot_apps/visibility.py
Normal file
48
tests/snapshot_tests/snapshot_apps/visibility.py
Normal 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()
|
||||||
@@ -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")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user