This commit is contained in:
Will McGugan
2021-10-24 17:46:38 +01:00
parent 4b2e44c86c
commit e2faad8f46
9 changed files with 70 additions and 62 deletions

View File

@@ -27,8 +27,6 @@ class MyApp(App):
# Dock the body in the remaining space
await self.view.dock(body, edge="right")
# self.panic(self.tree)
async def get_markdown(filename: str) -> None:
with open(filename, "rt") as fh:
readme = Markdown(fh.read(), hyperlinks=True)

View File

@@ -1,12 +1,23 @@
from __future__ import annotations
from rich.console import Console, ConsoleOptions, RenderResult, RenderableType
from rich.segment import Segment
from rich.segment import Segment, SegmentLines
from rich.style import Style
from .css.types import EdgeStyle
from ._box import BOX_STYLES
BORDER_STYLES: dict[str, tuple[str, str, str]] = {
"": (" ", " ", " "),
"none": (" ", " ", " "),
"round": ("╭─╮", "│ │", "╰─╯"),
"solid": ("┌─┐", "│ │", "└─┘"),
"double": ("╔═╗", "║ ║", "╚═╝"),
"dashed": ("┏╍┓", "╏ ╏", "┗╍┛"),
"heavy": ("┏━┓", "┃ ┃", "┗━┛"),
"inner": ("▗▄▖", "▐ ▌", "▝▀▘"),
"outer": ("▛▀▜", "▌ ▐", "▙▄▟"),
}
class Border:
@@ -63,7 +74,7 @@ class Border:
) -> "RenderResult":
top, right, bottom, left = self._sides
top_style, right_style, bottom_style, left_style = self._styles
BOX = BOX_STYLES
BOX = BORDER_STYLES
has_left = left != "none"
has_right = right != "none"
@@ -71,6 +82,12 @@ class Border:
has_bottom = bottom != "none"
width = options.max_width - has_left - has_right
if width <= 2:
lines = console.render_lines(self.renderable, options, new_lines=True)
yield SegmentLines(lines)
return
if self.outline:
render_options = options
else:
@@ -81,6 +98,9 @@ class Border:
render_options = options.update_dimensions(width, height)
lines = console.render_lines(self.renderable, render_options)
if len(lines) <= 2:
yield SegmentLines(lines, new_lines=True)
return
if self.outline:
self._crop_renderable(lines, options.max_width)

View File

@@ -5,7 +5,6 @@ from rich.segment import Segment
BOX_STYLES: dict[str, tuple[str, str, str]] = {
"": (" ", " ", " "),
"none": (" ", " ", " "),
"rounded": ("╭─╮", "│ │", "╰─╯"),
"solid": ("┌─┐", "│ │", "└─┘"),
"double": ("╔═╗", "║ ║", "╚═╝"),

View File

@@ -6,10 +6,10 @@ import rich.repr
from rich.color import Color
from rich.style import Style
from ..geometry import Offset, Spacing, SpacingDimensions
from .constants import NULL_SPACING
from .constants import NULL_SPACING, VALID_EDGE
from .errors import StyleValueError
from ._error_tools import friendly_list
if TYPE_CHECKING:
from .styles import Styles
@@ -48,20 +48,23 @@ class _BoxProperty:
@rich.repr.auto
class Edges(NamedTuple):
"""Stores edges for border / outline."""
top: tuple[str, Style]
right: tuple[str, Style]
bottom: tuple[str, Style]
left: tuple[str, Style]
def __rich_repr__(self) -> rich.repr.Result:
if self.top[0]:
yield "top", self.top
if self.right[0]:
yield "right", self.right
if self.bottom[0]:
yield "bottom", self.bottom
if self.left[0]:
yield "left", self.left
top, right, bottom, left = self
if top[0]:
yield "top", top
if right[0]:
yield "right", right
if bottom[0]:
yield "bottom", bottom
if left[0]:
yield "left", left
class _BorderProperty:
@@ -190,3 +193,14 @@ class _OffsetProperty:
_offset = Offset(*offset)
setattr(obj, self._internal_name, _offset)
return offset
class _DockEdgeProperty:
def __get__(self, obj: Styles, objtype: type[Styles] | None = None) -> str:
return obj._dock_edge or ""
def __set__(self, obj: Styles, edge: str | None) -> str | None:
if isinstance(edge, str) and edge not in VALID_EDGE:
raise ValueError(f"dock edge must be one of {friendly_list(VALID_EDGE)}")
obj._dock_edge = edge
return edge

View File

@@ -7,7 +7,7 @@ from rich.color import ANSI_COLOR_NAMES, Color
from rich.style import Style
from .constants import VALID_BORDER, VALID_DISPLAY, VALID_VISIBILITY
from .errors import DeclarationError
from .errors import DeclarationError, StyleValueError
from ._error_tools import friendly_list
from ..geometry import Offset, Spacing, SpacingDimensions
from .model import Declaration

View File

@@ -18,7 +18,7 @@ VALID_BORDER: Final = {
"inner",
"outer",
}
VALID_EDGE: Final = {"", "top", "right", "bottom", "left"}
VALID_EDGE: Final = {"top", "right", "bottom", "left"}
VALID_LAYOUT: Final = {"dock", "vertical", "grid"}

View File

@@ -4,7 +4,6 @@ from dataclasses import dataclass, field
from rich import print
import rich.repr
from rich.color import Color
from rich.style import Style
from .errors import StyleValueError
@@ -12,7 +11,6 @@ from ._error_tools import friendly_list
from .constants import (
VALID_DISPLAY,
VALID_VISIBILITY,
VALID_EDGE,
VALID_LAYOUT,
NULL_SPACING,
)
@@ -20,6 +18,7 @@ from ..geometry import NULL_OFFSET, Offset, Spacing
from ._style_properties import (
_BorderProperty,
_BoxProperty,
_DockEdgeProperty,
_DocksProperty,
_DockGroupProperty,
_OffsetProperty,
@@ -53,7 +52,7 @@ class Styles:
_outline_left: tuple[str, Style] | None = None
_dock_group: str | None = None
_dock_edge: str = ""
_dock_edge: str | None = None
_docks: tuple[str, ...] | None = None
important: set[str] = field(default_factory=set)
@@ -102,13 +101,12 @@ class Styles:
margin = _SpacingProperty()
border = _BorderProperty()
outline = _BorderProperty()
border_top = _BoxProperty()
border_right = _BoxProperty()
border_bottom = _BoxProperty()
border_left = _BoxProperty()
outline = _BorderProperty()
outline_top = _BoxProperty()
outline_right = _BoxProperty()
outline_bottom = _BoxProperty()
@@ -117,16 +115,7 @@ class Styles:
dock_group = _DockGroupProperty()
docks = _DocksProperty()
@property
def dock_edge(self) -> str:
return self._dock_edge
@dock_edge.setter
def dock_edge(self, edge: str) -> str:
if edge not in VALID_EDGE:
raise ValueError(f"dock edge must be one of {friendly_list(VALID_EDGE)}")
self._dock_edge = edge
return edge
dock_edge = _DockEdgeProperty()
@property
def has_border(self) -> bool:
@@ -249,13 +238,9 @@ if __name__ == "__main__":
styles.docks = "foo bar"
styles.text = "italic blue"
styles.dock_group = "bar"
styles.dock_edge = "sdfsdf"
from rich import inspect, print
print(styles)
print(styles.css)
# print(styles)
# print(styles.outline)
# inspect(styles)

View File

@@ -64,18 +64,6 @@ class View(Widget):
cls.layout_factory = layout
super().__init_subclass__(**kwargs)
# @property
# def layout(self) -> str:
# return self._layout
# @layout.setter
# def layout(self, layout: str | Layout) -> None:
# if isinstance(layout, str):
# new_layout = get_layout(layout)
# else:
# new_layout = layout
# self._layout = new_layout
layout = LayoutProperty()
background: Reactive[str] = Reactive("")
@@ -91,11 +79,11 @@ class View(Widget):
def scroll(self) -> Offset:
return Offset(self.scroll_x, self.scroll_y)
def __rich_console__(
self, console: Console, options: ConsoleOptions
) -> RenderResult:
return
yield
# def __rich_console__(
# self, console: Console, options: ConsoleOptions
# ) -> RenderResult:
# return
# yield
def __rich_repr__(self) -> rich.repr.Result:
yield "name", self.name

View File

@@ -25,6 +25,7 @@ from rich.text import TextType
from . import events
from . import errors
from ._animator import BoundAnimator
from ._border import Border, BORDER_STYLES
from ._callback import invoke
from ._widget_list import WidgetList
from ._context import active_app
@@ -96,11 +97,9 @@ class Widget(MessagePump):
padding: Reactive[Spacing | None] = Reactive(None, layout=True)
margin: Reactive[Spacing | None] = Reactive(None, layout=True)
border: Reactive[str] = Reactive("none", layout=True)
border_style: Reactive[str] = Reactive("")
border_style: Reactive[str] = Reactive("green")
border_title: Reactive[TextType] = Reactive("")
BOX_MAP = {"normal": box.SQUARE, "round": box.ROUNDED, "bold": box.HEAVY}
def validate_padding(self, padding: SpacingDimensions) -> Spacing:
return Spacing.unpack(padding)
@@ -188,11 +187,16 @@ class Widget(MessagePump):
renderable = self.render()
if self.padding is not None:
renderable = Padding(renderable, self.padding)
if self.border in self.BOX_MAP:
renderable = Panel(
if self.border not in ("", "none"):
_border_style = self.console.get_style(self.border_style)
renderable = Border(
renderable,
box=self.BOX_MAP.get(self.border) or box.SQUARE,
style=self.border_style,
(
("heavy", _border_style),
("heavy", _border_style),
("heavy", _border_style),
("heavy", _border_style),
),
)
if self.margin is not None:
renderable = Padding(renderable, self.margin)