diff --git a/docs/examples/widgets/digit_display.py b/docs/examples/widgets/digit_display.py
index e135782bea2..c2d95e08e11 100644
--- a/docs/examples/widgets/digit_display.py
+++ b/docs/examples/widgets/digit_display.py
@@ -1,5 +1,5 @@
from textual.app import App, ComposeResult
-from textual.widgets import Static
+from textual.widgets import Label
from textual.widgets import DigitDisplay
@@ -7,15 +7,15 @@ class MyApp(App):
BINDINGS = []
def compose(self) -> ComposeResult:
- yield Static("Digits: 0123456789")
+ yield Label("Digits: 0123456789")
yield DigitDisplay("0123456789")
- punctuation=" .+,XYZ^*/-="
- yield Static("Punctuation: " + punctuation)
+ punctuation = " .+,XYZ^*/-="
+ yield Label("Punctuation: " + punctuation)
yield DigitDisplay(punctuation)
equation = "x = y^2 + 3.14159*y + 10"
- yield Static("Equation: " + equation)
+ yield Label("Equation: " + equation)
yield DigitDisplay(equation)
diff --git a/docs/widgets/digit_display.md b/docs/widgets/digit_display.md
index e451aee1465..594e6cee54f 100644
--- a/docs/widgets/digit_display.md
+++ b/docs/widgets/digit_display.md
@@ -7,7 +7,10 @@ A widget to display digits and basic arithmetic operators using Unicode blocks.
## Examples
-=== "Static example"
+
+### Static display example
+
+=== "Screenshot"
```{.textual path="docs/examples/widgets/digit_display.py"}
```
@@ -18,9 +21,12 @@ A widget to display digits and basic arithmetic operators using Unicode blocks.
--8<-- "docs/examples/widgets/digit_display.py"
```
-=== "Reacting to an input"
- ```{.textual path="docs/examples/widgets/digit_display_reacting.py"}
+### Reacting to an input
+
+=== "Screenshot"
+
+ ```{.textual path="docs/examples/widgets/digit_display_reacting.py" press="1,2,3"}
```
=== "digit_display_reacting.py"
@@ -31,16 +37,16 @@ A widget to display digits and basic arithmetic operators using Unicode blocks.
## Reactive attributes
-| Name | Type | Default | Description |
-| ------ | ------ | ------- | ---------------------------------------------- |
-| `digits` | `str` | `""` | Use this to update the digits to be displayed. |
+| Name | Type | Default | Description |
+| ------ | ------ | ------- | ---------------------------------------------- |
+| `digits` | `str` | `""` | Use this to update the digits to be displayed. |
## Read-only attributes
-| Name | Type | Description |
-| ------ | ------ | ----------------------------------------- |
-| `supported_digits` | `frozenset[str]` | Contains the list of supported digits/characters.
+| Name | Type | Description |
+| ------ | ------ | ----------------------------------------- |
+| `supported_digits` | `frozenset[str]` | Contains the list of supported digits/characters. |
## Messages
diff --git a/src/textual/widgets/_digit_display.py b/src/textual/widgets/_digit_display.py
index fdbb8d9215d..c58769af294 100644
--- a/src/textual/widgets/_digit_display.py
+++ b/src/textual/widgets/_digit_display.py
@@ -199,6 +199,7 @@
class _SingleDigitDisplay(Static):
digit = reactive(" ", layout=True)
+ """The digit to display."""
DEFAULT_CSS = """
_SingleDigitDisplay {
@@ -212,10 +213,17 @@ def __init__(self, initial_value=" ", **kwargs):
super().__init__(**kwargs)
self.digit = initial_value
- def watch_digit(self, digit: str) -> None:
- """Called when the digit attribute changes."""
+ def validate_digit(self, digit: str) -> str:
+ """Sanitize and validate the digit input."""
if len(digit) > 1:
raise ValueError(f"Expected a single character, got {len(digit)}")
+ digit = digit.upper()
+ if digit not in _character_map:
+ raise ValueError(f"Unsupported character: {digit}")
+ return digit
+
+ def _watch_digit(self, digit: str) -> None:
+ """Called when the digit attribute changes and passes validation."""
self.update(_character_map[digit.upper()])
@@ -223,8 +231,10 @@ class DigitDisplay(Widget):
"""A widget to display digits and basic arithmetic operators using Unicode blocks."""
digits = reactive("", layout=True)
+ """The digits to display."""
supported_digits = frozenset(_character_map.keys())
+ """The digits and characters supported by this widget."""
DEFAULT_CSS = """
DigitDisplay {
@@ -242,27 +252,17 @@ def compose(self) -> ComposeResult:
for widget in self._displays:
yield widget
- def _add_digit_widget(self, digit: str) -> None:
- new_widget = _SingleDigitDisplay(digit)
- self._displays.append(new_widget)
- self.mount(new_widget)
-
- def watch_digits(self, digits: str) -> None:
+ def _watch_digits(self, digits: str) -> None:
"""
Called when the digits attribute changes.
Here we update the display widgets to match the input digits.
"""
- diff_digits_len = len(digits) - len(self._displays)
-
# Here we add or remove widgets to match the number of digits
- if diff_digits_len > 0:
- start = len(self._displays)
- for i in range(diff_digits_len):
- self._add_digit_widget(digits[start + i])
- elif diff_digits_len < 0:
- for display in self._displays[diff_digits_len:]:
- self._displays.remove(display)
- display.remove()
+ while len(self._displays) < len(digits):
+ self._displays.append(_SingleDigitDisplay(digits[len(self._displays)]))
+ self.mount(self._displays[-1])
+ while len(self._displays) > len(digits):
+ self._displays.pop().remove()
# At this point, the number of widgets matches the number of digits, and we can
# update the contents of the widgets that might need it
diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr
index 92ecbea4dbc..1611004818a 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-1756784214-matrix {
+ .terminal-4012950226-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
- .terminal-1756784214-title {
+ .terminal-4012950226-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
- .terminal-1756784214-r1 { fill: #e1e1e1 }
- .terminal-1756784214-r2 { fill: #c5c8c6 }
+ .terminal-4012950226-r1 { fill: #e1e1e1 }
+ .terminal-4012950226-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
+ ╻ ╻╻ ╻ ╻ ╺━┓╺━┓ ┓ ╻ ╻ ┓ ┏━╸┏━┓╻ ╻ ┓ ┏━┓
+ ╋ ╺━ ┳ ▝ ▘┏━┛╺╋╸ ━┫ ┃ ┗━┫ ┃ ┗━┓┗━┫ ✱ ┳ ╺╋╸ ┃ ┃╱┃
+ ╹ ╹╺━ ╹ ┗━╸╺━┛ •╺┻╸ ╹╺┻╸╺━┛╺━┛ ╹ ╺┻╸┗━┛
+
+
+
+
+
+
+
+
+
+
+