ai-station/.venv/lib/python3.12/site-packages/textual/widgets/_digits.py

111 lines
3.3 KiB
Python

from __future__ import annotations
from typing import TYPE_CHECKING, cast
from rich.align import Align, AlignMethod
if TYPE_CHECKING:
from textual.app import RenderResult
from textual.geometry import Size
from textual.renderables.digits import Digits as DigitsRenderable
from textual.selection import Selection
from textual.widget import Widget
class Digits(Widget):
"""A widget to display numerical values using a 3x3 grid of unicode characters."""
DEFAULT_CSS = """
Digits {
width: 1fr;
height: auto;
text-align: left;
box-sizing: border-box;
}
"""
def __init__(
self,
value: str = "",
*,
name: str | None = None,
id: str | None = None,
classes: str | None = None,
disabled: bool = False,
) -> None:
"""Initialize a Digits widget.
Args:
value: Value to display in widget.
name: The name of the widget.
id: The ID of the widget in the DOM.
classes: The CSS classes of the widget.
disabled: Whether the widget is disabled or not.
"""
if not isinstance(value, str):
raise TypeError("value must be a str")
super().__init__(name=name, id=id, classes=classes, disabled=disabled)
self._value = value
@property
def value(self) -> str:
"""The current value displayed in the Digits."""
return self._value
def get_selection(self, selection: Selection) -> str | None:
return self._value
def update(self, value: str) -> None:
"""Update the Digits with a new value.
Args:
value: New value to display.
Raises:
TypeError: If the value isn't a `str`.
"""
if not isinstance(value, str):
raise TypeError("value must be a str")
layout_required = len(value) != len(self._value) or (
DigitsRenderable.get_width(self._value) != DigitsRenderable.get_width(value)
)
self._value = value
self.refresh(layout=layout_required)
def render(self) -> RenderResult:
"""Render digits."""
rich_style = self.rich_style
if self.text_selection:
rich_style += self.selection_style
digits = DigitsRenderable(self._value, rich_style)
text_align = self.styles.text_align
align = "left" if text_align not in {"left", "center", "right"} else text_align
return Align(digits, cast(AlignMethod, align), rich_style)
def get_content_width(self, container: Size, viewport: Size) -> int:
"""Called by textual to get the width of the content area.
Args:
container: Size of the container (immediate parent) widget.
viewport: Size of the viewport.
Returns:
The optimal width of the content.
"""
return DigitsRenderable.get_width(self._value)
def get_content_height(self, container: Size, viewport: Size, width: int) -> int:
"""Called by Textual to get the height of the content area.
Args:
container: Size of the container (immediate parent) widget.
viewport: Size of the viewport.
width: Width of renderable.
Returns:
The height of the content.
"""
return 3 # Always 3 lines