diff --git a/src/textual/widgets/__init__.py b/src/textual/widgets/__init__.py index 12c7071957f..50f04fea326 100644 --- a/src/textual/widgets/__init__.py +++ b/src/textual/widgets/__init__.py @@ -48,6 +48,7 @@ "Checkbox", "ContentSwitcher", "DataTable", + "DigitDisplay", "DirectoryTree", "Footer", "Header", @@ -77,7 +78,6 @@ "Tooltip", "Tree", "Welcome", - "DigitDisplay", ] _WIDGETS_LAZY_LOADING_CACHE: dict[str, type[Widget]] = {} diff --git a/src/textual/widgets/_digit_display.py b/src/textual/widgets/_digit_display.py index c58769af294..671c0efbb72 100644 --- a/src/textual/widgets/_digit_display.py +++ b/src/textual/widgets/_digit_display.py @@ -2,12 +2,15 @@ from textual.reactive import reactive from textual.widget import Widget from textual.widgets import Static +from ..geometry import Size _character_map: dict[str, str] = {} -# in the mappings below, we use underscores to make spaces more visible, -# we will strip them out later +_VIRTUAL_SPACE = "·" + +# in the mappings below, we use a dot instead of spaces to make them more +# visible, we will strip them out later _character_map[ "0" ] = """ @@ -158,9 +161,9 @@ _character_map[ "=" ] = """ -··· -╺━· -╺━· +·· +╺━ +╺━ """ _character_map[ @@ -189,8 +192,6 @@ """ -_VIRTUAL_SPACE = "·" - # here we strip spaces and replace virtual spaces with spaces _character_map = { k: v.strip().replace(_VIRTUAL_SPACE, " ") for k, v in _character_map.items() @@ -198,20 +199,52 @@ class _SingleDigitDisplay(Static): + """ + A widget to display a single digit or basic arithmetic symbol using Unicode blocks. + """ + digit = reactive(" ", layout=True) """The digit to display.""" DEFAULT_CSS = """ - _SingleDigitDisplay { - height: 3; - min-width: 2; - max-width: 3; - } + _SingleDigitDisplay { + height: 3; + min-width: 2; + max-width: 3; + } """ - def __init__(self, initial_value=" ", **kwargs): - super().__init__(**kwargs) + def __init__( + self, + initial_value: str = " ", + expand: bool = False, + shrink: bool = False, + markup: bool = True, + name: str | None = None, + id: str | None = None, + classes: str | None = None, + disabled: bool = False, + ): + """ + Create a single digit display widget. + + Example: + ```py + class Example(App): + def compose(self) -> ComposeResult: + return _SingleDigitDisplay("1") + """ + super().__init__( + expand=expand, + shrink=shrink, + markup=markup, + name=name, + id=id, + classes=classes, + disabled=disabled, + ) self.digit = initial_value + self._content_width = 3 def validate_digit(self, digit: str) -> str: """Sanitize and validate the digit input.""" @@ -224,11 +257,21 @@ def validate_digit(self, digit: str) -> str: def _watch_digit(self, digit: str) -> None: """Called when the digit attribute changes and passes validation.""" - self.update(_character_map[digit.upper()]) + content = _character_map[digit.upper()] + self._content_width = len(content.splitlines()[0]) + self.update(content) + + def get_content_width(self, container: Size, viewport: Size) -> int: + return self._content_width + + def get_content_height(self, container: Size, viewport: Size, width: int) -> int: + return 3 class DigitDisplay(Widget): - """A widget to display digits and basic arithmetic operators using Unicode blocks.""" + """ + A widget to display digits and basic arithmetic symbols using Unicode blocks. + """ digits = reactive("", layout=True) """The digits to display.""" @@ -243,8 +286,31 @@ class DigitDisplay(Widget): } """ - def __init__(self, initial_value="", **kwargs): - super().__init__(**kwargs) + def __init__( + self, + initial_value: str = "", + name: str | None = None, + id: str | None = None, + classes: str | None = None, + disabled: bool = False, + ): + """ + Create a Digit Display widget. + + Example: + ```py + class Example(App): + def compose(self) -> ComposeResult: + return DigitDisplay("123+456") + + Args: + initial_value (str, optional): The initial value to display. Defaults to "". + name: The name of the widget. + id: The ID of the widget in the DOM. + classes: The CSS classes for the widget. + disabled: Whether the widget is disabled or not. + """ + super().__init__(name=name, id=id, classes=classes, disabled=disabled) self._displays = [_SingleDigitDisplay(d) for d in initial_value] self.digits = initial_value diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr index 1611004818a..b04fb6d7e34 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr +++ b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr @@ -13742,131 +13742,131 @@ font-weight: 700; } - .terminal-4012950226-matrix { + .terminal-3468730299-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-4012950226-title { + .terminal-3468730299-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-4012950226-r1 { fill: #e1e1e1 } - .terminal-4012950226-r2 { fill: #c5c8c6 } + .terminal-3468730299-r1 { fill: #e1e1e1 } + .terminal-3468730299-r2 { fill: #c5c8c6 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - MyApp + MyApp - - - - Digits: 0123456789 - ┏━┓ ┓ ╺━┓╺━┓╻ ╻┏━╸┏━╸╺━┓┏━┓┏━┓ - ┃╱┃ ┃ ┏━┛ ━┫┗━┫┗━┓┣━┓  ╹┣━┫┗━┫ - ┗━┛╺┻╸┗━╸╺━┛  ╹╺━┛┗━┛ ╹ ┗━┛╺━┛ - Punctuation:  .+,XYZ^*/-= - ╻ ╻╻ ╻╺━┓ ╻   ╻ - ╺╋╸ ╋  ┳  ▞ ▝ ▘ ✱  ▞ ╺━╸╺━  -  • ▞╹ ╹ ╹ ┗━╸╹  ╺━  - Equation: x = y^2 + 3.14159*y + 10 - ╻ ╻╻ ╻ ╻ ╺━┓╺━┓ ┓ ╻ ╻ ┓ ┏━╸┏━┓╻ ╻ ┓ ┏━┓ -  ╋ ╺━  ┳ ▝ ▘┏━┛╺╋╸ ━┫ ┃ ┗━┫ ┃ ┗━┓┗━┫ ✱  ┳ ╺╋╸ ┃ ┃╱┃ - ╹ ╹╺━  ╹ ┗━╸╺━┛ •╺┻╸  ╹╺┻╸╺━┛╺━┛ ╹ ╺┻╸┗━┛ - - - - - - - - - - - + + + + Digits: 0123456789 + ┏━┓ ┓ ╺━┓╺━┓╻ ╻┏━╸┏━╸╺━┓┏━┓┏━┓ + ┃╱┃ ┃ ┏━┛ ━┫┗━┫┗━┓┣━┓  ╹┣━┫┗━┫ + ┗━┛╺┻╸┗━╸╺━┛  ╹╺━┛┗━┛ ╹ ┗━┛╺━┛ + Punctuation:  .+,XYZ^*/-= + ╻ ╻╻ ╻╺━┓ ╻   ╻ + ╺╋╸ ╋  ┳  ▞ ▝ ▘ ✱  ▞ ╺━╸╺━ +  • ▞╹ ╹ ╹ ┗━╸╹  ╺━ + Equation: x = y^2 + 3.14159*y + 10 + ╻ ╻╻ ╻ ╻ ╺━┓╺━┓ ┓ ╻ ╻ ┓ ┏━╸┏━┓╻ ╻ ┓ ┏━┓ +  ╋ ╺━ ┳ ▝ ▘┏━┛╺╋╸ ━┫ ┃ ┗━┫ ┃ ┗━┓┗━┫ ✱  ┳ ╺╋╸ ┃ ┃╱┃ + ╹ ╹╺━ ╹ ┗━╸╺━┛ •╺┻╸  ╹╺┻╸╺━┛╺━┛ ╹ ╺┻╸┗━┛ + + + + + + + + + + +