Skip to content

Commit

Permalink
Allow setting a toggle button's label (#3765)
Browse files Browse the repository at this point in the history
* Allow setting a toggle button's label

Until now CheckBox and RadioButton labels have been fixed after the widgets
have been created. Prompted by #3764 and seeing no reasonable reason to not
allow updating the labels later on, this adds that ability.

* Link the CHANGELOG entries to the PR

* Ensure the setter enforces the first-line-only rule too
  • Loading branch information
davep authored Nov 28, 2023
1 parent 4058e59 commit 2f86ee4
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 2 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Added experimental Canvas class https://github.com/Textualize/textual/pull/3669/
- Added `keyline` rule https://github.com/Textualize/textual/pull/3669/
- Widgets can now have an ALLOW_CHILDREN (bool) classvar to disallow adding children to a widget https://github.com/Textualize/textual/pull/3758
- Added the ability to set the `label` property of a `Checkbox` https://github.com/Textualize/textual/pull/3765
- Added the ability to set the `label` property of a `RadioButton` https://github.com/Textualize/textual/pull/3765

### Changed

Expand Down
21 changes: 19 additions & 2 deletions src/textual/widgets/_toggle_button.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,18 +149,35 @@ def __init__(
# NOTE: Don't send a Changed message in response to the initial set.
with self.prevent(self.Changed):
self.value = value
self._label = Text.from_markup(label) if isinstance(label, str) else label
self._label = self._make_label(label)

def _make_label(self, label: TextType) -> Text:
"""Make a `Text` label from a `TextType` value.
Args:
label: The source value for the label.
Returns:
A `Text` rendering of the label for use in the button.
"""
label = Text.from_markup(label) if isinstance(label, str) else label
try:
# Only use the first line if it's a multi-line label.
self._label = self._label.split()[0]
label = label.split()[0]
except IndexError:
pass
return label

@property
def label(self) -> Text:
"""The label associated with the button."""
return self._label

@label.setter
def label(self, label: TextType) -> None:
self._label = self._make_label(label)
self.refresh(layout=True)

@property
def _button(self) -> Text:
"""The button, reflecting the current value."""
Expand Down
36 changes: 36 additions & 0 deletions tests/toggles/test_labels.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""Test that setting a toggle button's label has the desired effect."""

from rich.text import Text

from textual.app import App, ComposeResult
from textual.widgets import Checkbox, RadioButton, RadioSet


class LabelChangeApp(App[None]):
def compose(self) -> ComposeResult:
yield Checkbox("Before")
yield RadioButton("Before")
yield RadioSet("Before")


async def test_change_labels() -> None:
"""It should be possible to change the labels of toggle buttons."""
async with LabelChangeApp().run_test() as pilot:
assert pilot.app.query_one(Checkbox).label == Text("Before")
assert pilot.app.query_one("Screen > RadioButton", RadioButton).label == Text(
"Before"
)
assert pilot.app.query_one("RadioSet > RadioButton", RadioButton).label == Text(
"Before"
)
pilot.app.query_one(Checkbox).label = "After"
pilot.app.query_one("Screen > RadioButton", RadioButton).label = "After"
pilot.app.query_one("RadioSet > RadioButton", RadioButton).label = "After"
await pilot.pause()
assert pilot.app.query_one(Checkbox).label == Text("After")
assert pilot.app.query_one("Screen > RadioButton", RadioButton).label == Text(
"After"
)
assert pilot.app.query_one("RadioSet > RadioButton", RadioButton).label == Text(
"After"
)

0 comments on commit 2f86ee4

Please sign in to comment.