new border renderable includes outline

This commit is contained in:
Will McGugan
2021-10-24 09:59:16 +01:00
parent 6f0819848a
commit b40c13d379

View File

@@ -14,25 +14,55 @@ class Border:
self,
renderable: RenderableType,
edge_styles: tuple[EdgeStyle, EdgeStyle, EdgeStyle, EdgeStyle],
outline: bool = False,
):
self.renderable = renderable
self.edge_styles = edge_styles
self.outline = outline
@property
def sides(self) -> tuple[str, str, str, str]:
(top, _), (right, _), (bottom, _), (left, _) = self.edge_styles
return (top or "none", right or "none", bottom or "none", left or "none")
(
(top, top_style),
(right, right_style),
(bottom, bottom_style),
(left, left_style),
) = edge_styles
self._sides = (top or "none", right or "none", bottom or "none", left or "none")
self._styles = (top_style, right_style, bottom_style, left_style)
@property
def styles(self) -> tuple[Style, Style, Style, Style]:
(_, top), (_, right), (_, left), (_, bottom) = self.edge_styles
return (top, right, left, bottom)
def _crop_renderable(self, lines: list[list[Segment]], width: int) -> None:
"""Crops a renderable in place.
Args:
lines (list[list[Segment]]): Segment lines.
width (int): Desired width.
"""
top, right, bottom, left = self._sides
has_left = left != "none"
has_right = right != "none"
has_top = top != "none"
has_bottom = bottom != "none"
if has_top:
lines.pop(0)
if has_bottom:
lines.pop(-1)
divide = Segment.divide
if has_left and has_right:
for line in lines:
_, line[:] = divide(line, [1, width - 1])
elif has_left:
for line in lines:
_, line[:] = divide(line, [1, width])
elif has_right:
for line in lines:
line[:], _ = divide(line, [width - 1, width])
def __rich_console__(
self, console: "Console", options: "ConsoleOptions"
) -> "RenderResult":
top, right, bottom, left = self.sides
top_style, right_style, bottom_style, left_style = self.styles
top, right, bottom, left = self._sides
top_style, right_style, bottom_style, left_style = self._styles
BOX = BOX_STYLES
has_left = left != "none"
@@ -41,6 +71,9 @@ class Border:
has_bottom = bottom != "none"
width = options.max_width - has_left - has_right
if self.outline:
render_options = options
else:
if options.height is None:
render_options = options.update_width(width)
else:
@@ -48,6 +81,8 @@ class Border:
render_options = options.update_dimensions(width, height)
lines = console.render_lines(self.renderable, render_options)
if self.outline:
self._crop_renderable(lines, options.max_width)
_Segment = Segment
new_line = _Segment.line()
@@ -63,13 +98,12 @@ class Border:
box_left = BOX[left][1][0]
box_right = BOX[right][1][2]
left_segment = _Segment(box_left, left_style)
right_segment = _Segment(box_right, right_style)
right_segment = _Segment(box_right + "\n", right_style)
if has_left and has_right:
for line in lines:
yield left_segment
yield from line
yield right_segment
yield new_line
elif has_left:
for line in lines:
yield left_segment
@@ -79,7 +113,6 @@ class Border:
for line in lines:
yield from line
yield right_segment
yield new_line
else:
for line in lines:
yield from line
@@ -100,14 +133,18 @@ if __name__ == "__main__":
from rich.text import Text
text = Text("Textual " * 40, style="dim")
print(
Border(
border = Border(
text,
(
("outer", Style.parse("green on red")),
("none", Style.parse("green")),
("double", Style.parse("green")),
("double", Style.parse("green")),
("outer", Style.parse("green")),
("outer", Style.parse("green")),
("outer", Style.parse("green")),
("outer", Style.parse("green")),
),
)
)
print(text)
print()
print(border)
print()
border.outline = True
print(border)