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