Merge pull request #212 from Textualize/visibility

Visibility
This commit is contained in:
Darren Burns
2022-01-19 16:09:54 +00:00
committed by GitHub
7 changed files with 92 additions and 26 deletions

View File

@@ -2,6 +2,7 @@
App > View { App > View {
docks: side=left/1; docks: side=left/1;
text: on #20639b;
} }
Widget:hover { Widget:hover {
@@ -28,6 +29,10 @@ Widget:hover {
border: hkey; border: hkey;
} }
#header.-visible {
visibility: hidden;
}
#content { #content {
text: white on #20639b; text: white on #20639b;
border-bottom: hkey #0f2b41; border-bottom: hkey #0f2b41;

View File

@@ -8,6 +8,7 @@ class BasicApp(App):
def on_load(self): def on_load(self):
"""Bind keys here.""" """Bind keys here."""
self.bind("tab", "toggle_class('#sidebar', '-active')") self.bind("tab", "toggle_class('#sidebar', '-active')")
self.bind("a", "toggle_class('#header', '-visible')")
def on_mount(self): def on_mount(self):
"""Build layout here.""" """Build layout here."""

32
src/textual/blank.py Normal file
View File

@@ -0,0 +1,32 @@
from __future__ import annotations
from rich.console import Console, ConsoleOptions
from rich.segment import Segment
from rich.style import StyleType
class Blank:
"""
Render an empty rectangle.
Args:
style (StyleType): Style to apply to the box.
width (int, optional): Width of the box in number of cells. Will expand to fit parent if ``None``.
height (int, optional): Height of the box in number of cells. Will expand to fit parent if ``None``.
"""
def __init__(
self, style: StyleType, width: int | None = None, height: int | None = None
):
self.style = style
self.width = width
self.height = height
def __rich_console__(self, console: Console, console_options: ConsoleOptions):
render_width = self.width or console_options.max_width
render_height = (
self.height or console_options.height or console_options.max_height
)
style = console.get_style(self.style)
for _ in range(render_height):
yield Segment(" " * render_width + "\n", style)

View File

@@ -235,6 +235,13 @@ class Styles:
else: else:
return None return None
def reset(self) -> None:
"""
Reset internal style rules to ``None``, reverting to default styles.
"""
for rule_name in INTERNAL_RULE_NAMES:
setattr(self, rule_name, None)
def extract_rules( def extract_rules(
self, specificity: Specificity3 self, specificity: Specificity3
) -> list[tuple[str, Specificity4, Any]]: ) -> list[tuple[str, Specificity4, Any]]:

View File

@@ -113,8 +113,14 @@ class Stylesheet:
rule_attributes = defaultdict(list) rule_attributes = defaultdict(list)
_check_rule = self._check_rule _check_rule = self._check_rule
node.styles.reset()
# Get the default node CSS rules
for key, default_specificity, value in node._default_rules: for key, default_specificity, value in node._default_rules:
rule_attributes[key].append((default_specificity, value)) rule_attributes[key].append((default_specificity, value))
# Apply styles on top of the default node CSS rules
for rule in self.rules: for rule in self.rules:
for specificity in _check_rule(rule, node): for specificity in _check_rule(rule, node):
for key, rule_specificity, value in rule.styles.extract_rules( for key, rule_specificity, value in rule.styles.extract_rules(
@@ -123,13 +129,6 @@ class Stylesheet:
rule_attributes[key].append((rule_specificity, value)) rule_attributes[key].append((rule_specificity, value))
get_first_item = itemgetter(0) get_first_item = itemgetter(0)
log("")
log(node)
for key, attributes in rule_attributes.items():
log(key, key in node.styles.important)
log("\t", attributes)
node_rules = [ node_rules = [
(name, max(specificity_rules, key=get_first_item)[1]) (name, max(specificity_rules, key=get_first_item)[1])
for name, specificity_rules in rule_attributes.items() for name, specificity_rules in rule_attributes.items()

View File

@@ -14,11 +14,13 @@ from typing import (
import rich.repr import rich.repr
from rich import box from rich import box
from rich.align import Align from rich.align import Align
from rich.console import Console, RenderableType from rich.console import Console, RenderableType, ConsoleOptions
from rich.measure import Measurement
from rich.panel import Panel from rich.panel import Panel
from rich.padding import Padding from rich.padding import Padding
from rich.pretty import Pretty from rich.pretty import Pretty
from rich.style import Style from rich.segment import Segment
from rich.style import Style, StyleType
from rich.styled import Styled from rich.styled import Styled
from rich.text import Text, TextType from rich.text import Text, TextType
@@ -27,6 +29,7 @@ from . import errors
from ._animator import BoundAnimator from ._animator import BoundAnimator
from ._border import Border, BORDER_STYLES from ._border import Border, BORDER_STYLES
from ._callback import invoke from ._callback import invoke
from .blank import Blank
from .dom import DOMNode from .dom import DOMNode
from ._context import active_app from ._context import active_app
from .geometry import Size, Spacing, SpacingDimensions from .geometry import Size, Spacing, SpacingDimensions
@@ -158,28 +161,36 @@ class Widget(DOMNode):
renderable = self.render() renderable = self.render()
styles = self.styles styles = self.styles
parent_text_style = self.parent.text_style parent_text_style = self.parent.text_style
text_style = styles.text
renderable_text_style = parent_text_style + text_style
if renderable_text_style:
renderable = Styled(renderable, renderable_text_style)
if styles.has_padding: if styles.visibility == "hidden":
renderable = Padding( renderable = Blank(parent_text_style)
renderable, styles.padding, style=renderable_text_style else:
) text_style = styles.text
renderable_text_style = parent_text_style + text_style
if renderable_text_style:
renderable = Styled(renderable, renderable_text_style)
if styles.has_border: if styles.has_padding:
renderable = Border(renderable, styles.border, style=renderable_text_style) renderable = Padding(
renderable, styles.padding, style=renderable_text_style
)
if styles.has_margin: if styles.has_border:
renderable = Padding(renderable, styles.margin, style=parent_text_style) renderable = Border(
renderable, styles.border, style=renderable_text_style
)
if styles.has_outline: if styles.has_margin:
renderable = Border( renderable = Padding(renderable, styles.margin, style=parent_text_style)
renderable, styles.outline, outline=True, style=renderable_text_style
) if styles.has_outline:
renderable = Border(
renderable,
styles.outline,
outline=True,
style=renderable_text_style,
)
return renderable return renderable

11
tests/test_styles.py Normal file
View File

@@ -0,0 +1,11 @@
from rich.style import Style
from textual.css.styles import Styles
def test_styles_reset():
styles = Styles()
styles.text_style = "not bold"
assert styles.text_style == Style(bold=False)
styles.reset()
assert styles.text_style is Style.null()