|
from typing import Optional, Union |
|
|
|
from .color import Color |
|
from .console import Console, ConsoleOptions, RenderResult |
|
from .jupyter import JupyterMixin |
|
from .measure import Measurement |
|
from .segment import Segment |
|
from .style import Style |
|
|
|
|
|
|
|
BEGIN_BLOCK_ELEMENTS = ["β", "β", "β", "β", "β", "β", "β", "β"] |
|
END_BLOCK_ELEMENTS = [" ", "β", "β", "β", "β", "β", "β", "β"] |
|
FULL_BLOCK = "β" |
|
|
|
|
|
class Bar(JupyterMixin): |
|
"""Renders a solid block bar. |
|
|
|
Args: |
|
size (float): Value for the end of the bar. |
|
begin (float): Begin point (between 0 and size, inclusive). |
|
end (float): End point (between 0 and size, inclusive). |
|
width (int, optional): Width of the bar, or ``None`` for maximum width. Defaults to None. |
|
color (Union[Color, str], optional): Color of the bar. Defaults to "default". |
|
bgcolor (Union[Color, str], optional): Color of bar background. Defaults to "default". |
|
""" |
|
|
|
def __init__( |
|
self, |
|
size: float, |
|
begin: float, |
|
end: float, |
|
*, |
|
width: Optional[int] = None, |
|
color: Union[Color, str] = "default", |
|
bgcolor: Union[Color, str] = "default", |
|
): |
|
self.size = size |
|
self.begin = max(begin, 0) |
|
self.end = min(end, size) |
|
self.width = width |
|
self.style = Style(color=color, bgcolor=bgcolor) |
|
|
|
def __repr__(self) -> str: |
|
return f"Bar({self.size}, {self.begin}, {self.end})" |
|
|
|
def __rich_console__( |
|
self, console: Console, options: ConsoleOptions |
|
) -> RenderResult: |
|
|
|
width = min( |
|
self.width if self.width is not None else options.max_width, |
|
options.max_width, |
|
) |
|
|
|
if self.begin >= self.end: |
|
yield Segment(" " * width, self.style) |
|
yield Segment.line() |
|
return |
|
|
|
prefix_complete_eights = int(width * 8 * self.begin / self.size) |
|
prefix_bar_count = prefix_complete_eights // 8 |
|
prefix_eights_count = prefix_complete_eights % 8 |
|
|
|
body_complete_eights = int(width * 8 * self.end / self.size) |
|
body_bar_count = body_complete_eights // 8 |
|
body_eights_count = body_complete_eights % 8 |
|
|
|
|
|
|
|
|
|
|
|
prefix = " " * prefix_bar_count |
|
if prefix_eights_count: |
|
prefix += BEGIN_BLOCK_ELEMENTS[prefix_eights_count] |
|
|
|
body = FULL_BLOCK * body_bar_count |
|
if body_eights_count: |
|
body += END_BLOCK_ELEMENTS[body_eights_count] |
|
|
|
suffix = " " * (width - len(body)) |
|
|
|
yield Segment(prefix + body[len(prefix) :] + suffix, self.style) |
|
yield Segment.line() |
|
|
|
def __rich_measure__( |
|
self, console: Console, options: ConsoleOptions |
|
) -> Measurement: |
|
return ( |
|
Measurement(self.width, self.width) |
|
if self.width is not None |
|
else Measurement(4, options.max_width) |
|
) |
|
|