From b38b170d998722371edf43b7da1998799930b779 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Wed, 5 Jun 2024 15:11:14 +0100 Subject: [PATCH] hatch docs --- docs/css_types/hatch.md | 40 +++++++++++++++++++ docs/examples/styles/hatch.py | 22 +++++++++++ docs/examples/styles/hatch.tcss | 19 +++++++++ docs/styles/hatch.md | 58 ++++++++++++++++++++++++++++ mkdocs-nav.yml | 2 + src/textual/css/_style_properties.py | 17 ++++++-- src/textual/css/_styles_builder.py | 9 +---- src/textual/css/constants.py | 7 ++++ 8 files changed, 164 insertions(+), 10 deletions(-) create mode 100644 docs/css_types/hatch.md create mode 100644 docs/examples/styles/hatch.py create mode 100644 docs/examples/styles/hatch.tcss create mode 100644 docs/styles/hatch.md diff --git a/docs/css_types/hatch.md b/docs/css_types/hatch.md new file mode 100644 index 000000000..0e41a5065 --- /dev/null +++ b/docs/css_types/hatch.md @@ -0,0 +1,40 @@ +# <hatch> + +The `` CSS type represents a character used in the [hatch](../styles/hatch.md) rule. + +## Syntax + +| Value | Description | +| ------------ | ------------------------------ | +| `cross` | A diagonal crossed line. | +| `horizontal` | A horizontal line. | +| `left` | A left leaning diagonal line. | +| `right` | A right leaning diagonal line. | +| `vertical` | A vertical line. | + + + + +## Examples + +### CSS + + + +```css +.some-class { + hatch: cross green; +} +``` + +### Python + + + +```py +widget.styles.hatch = ("cross", "red") +``` diff --git a/docs/examples/styles/hatch.py b/docs/examples/styles/hatch.py new file mode 100644 index 000000000..bbdce366f --- /dev/null +++ b/docs/examples/styles/hatch.py @@ -0,0 +1,22 @@ +from textual.app import App, ComposeResult +from textual.containers import Horizontal, Vertical +from textual.widgets import Static + +HATCHES = ("cross", "horizontal", "custom", "left", "right") + + +class HatchApp(App): + CSS_PATH = "hatch.tcss" + + def compose(self) -> ComposeResult: + with Horizontal(): + for hatch in HATCHES: + static = Static(classes=f"hatch {hatch}") + static.border_title = hatch + with Vertical(): + yield static + + +if __name__ == "__main__": + app = HatchApp() + app.run() diff --git a/docs/examples/styles/hatch.tcss b/docs/examples/styles/hatch.tcss new file mode 100644 index 000000000..989d35efa --- /dev/null +++ b/docs/examples/styles/hatch.tcss @@ -0,0 +1,19 @@ +.hatch { + height: 1fr; + border: solid $secondary; + &.cross { + hatch: cross $success; + } + &.horizontal { + hatch: horizontal $success 80%; + } + &.custom { + hatch: "T" $success 60%; + } + &.left { + hatch: left $success 40%; + } + &.right { + hatch: right $success 20%; + } +} diff --git a/docs/styles/hatch.md b/docs/styles/hatch.md new file mode 100644 index 000000000..41cac23ed --- /dev/null +++ b/docs/styles/hatch.md @@ -0,0 +1,58 @@ +# Hatch + +The `hatch` style fills a widget's background with a repeating character for a pleasing textured effect. + +## Syntax + +--8<-- "docs/snippets/syntax_block_start.md" +hatch: (<hatch> | CHARACTER) <color> [<percentage>] +--8<-- "docs/snippets/syntax_block_end.md" + +The hatch type can be specified with a constant, or a string. For example, `cross` for cross hatch, or `"T"` for a custom character. + +The color can be any Textual color value. + +An optional percentage can be used to set the opacity. + +## Examples + + +An app to show a few hatch effects. + +=== "Output" + + ```{.textual path="docs/examples/styles/hatch.py"} + ``` + +=== "hatch.py" + + ```py + --8<-- "docs/examples/styles/hatch.py" + ``` + +=== "hatch.tcss" + + ```css + --8<-- "docs/examples/styles/hatch.tcss" + ``` + + +## CSS + +```css +/* Red cross hatch */ +hatch: cross red; +/* Right diagonals, 50% transparent green. */ +hatch: right green 50%; +/* T custom character in 80% blue. **/ +hatch: "T" blue 80%; +``` + + +## Python + +```py +widget.styles.hatch = ("cross", "red") +widget.styles.hatch = ("right", "rgba(0,255,0,128)") +widget.styles.hatch = ("T", "blue") +``` diff --git a/mkdocs-nav.yml b/mkdocs-nav.yml index 9c1e4c0aa..169f3ef0d 100644 --- a/mkdocs-nav.yml +++ b/mkdocs-nav.yml @@ -30,6 +30,7 @@ nav: - "css_types/index.md" - "css_types/border.md" - "css_types/color.md" + - "css_types/hatch.md" - "css_types/horizontal.md" - "css_types/integer.md" - "css_types/keyline.md" @@ -96,6 +97,7 @@ nav: - "styles/grid/grid_rows.md" - "styles/grid/grid_size.md" - "styles/grid/row_span.md" + - "styles/hatch.md" - "styles/height.md" - "styles/keyline.md" - "styles/layer.md" diff --git a/src/textual/css/_style_properties.py b/src/textual/css/_style_properties.py index 95745b165..06db0b26c 100644 --- a/src/textual/css/_style_properties.py +++ b/src/textual/css/_style_properties.py @@ -31,7 +31,7 @@ from ._help_text import ( string_enum_help_text, style_flags_property_help_text, ) -from .constants import VALID_STYLE_FLAGS +from .constants import HATCHES, VALID_STYLE_FLAGS from .errors import StyleTypeError, StyleValueError from .scalar import ( NULL_SCALAR, @@ -1147,5 +1147,16 @@ class HatchProperty: def __get__(self, obj: StylesBase, type: type[StylesBase]) -> tuple[str, Color]: return cast("tuple[str, Color]", obj.get_rule("hatch", (" ", TRANSPARENT))) - def __set__(self, obj: StylesBase, value: tuple[str, Color]) -> None: - obj.set_rule("hatch", value) + def __set__(self, obj: StylesBase, value: tuple[str, Color | str]) -> None: + character, color = value + if len(character) != 1: + try: + character = HATCHES[character] + except KeyError: + raise ValueError( + f"Expected a character or hatch value here; found {character!r}" + ) from None + if isinstance(color, str): + color = Color.parse(color) + hatch = (character, color) + obj.set_rule("hatch", hatch) diff --git a/src/textual/css/_styles_builder.py b/src/textual/css/_styles_builder.py index b266cde0d..760024cd5 100644 --- a/src/textual/css/_styles_builder.py +++ b/src/textual/css/_styles_builder.py @@ -37,6 +37,7 @@ from ._help_text import ( text_align_help_text, ) from .constants import ( + HATCHES, VALID_ALIGN_HORIZONTAL, VALID_ALIGN_VERTICAL, VALID_BORDER, @@ -1060,13 +1061,7 @@ class StylesBuilder: character = " " color = TRANSPARENT opacity = 1.0 - HATCHES = { - "left": "╲", - "right": "╱", - "cross": "╳", - "horizontal": "─", - "vertical": "│", - } + for token in tokens: if token.name == "token": if token.value not in VALID_HATCH: diff --git a/src/textual/css/constants.py b/src/textual/css/constants.py index 083fb3520..07e252398 100644 --- a/src/textual/css/constants.py +++ b/src/textual/css/constants.py @@ -75,3 +75,10 @@ VALID_OVERLAY: Final = {"none", "screen"} VALID_CONSTRAIN: Final = {"x", "y", "both", "inflect", "none"} VALID_KEYLINE: Final = {"none", "thin", "heavy", "double"} VALID_HATCH: Final = {"left", "right", "cross", "vertical", "horizontal"} +HATCHES: Final = { + "left": "╲", + "right": "╱", + "cross": "╳", + "horizontal": "─", + "vertical": "│", +}