Tabbed content activated message (#2260)

* Add a message for the tabbed content activated

* Add a docstring

* Testing tabbed content activated message

* Update changelog

* Add reference to the docs about TabbedContent.TabActivated
This commit is contained in:
darrenburns
2023-04-12 10:55:14 +01:00
committed by GitHub
parent 6352ceb61b
commit f95e30870b
5 changed files with 63 additions and 4 deletions

View File

@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Added `DataTable.remove_row` method https://github.com/Textualize/textual/pull/2253
- `Widget.scroll_to_center` now scrolls the widget to the center of the screen https://github.com/Textualize/textual/pull/2255
- Added `TabActivated` message to `TabbedContent` https://github.com/Textualize/textual/pull/2260
## [0.19.1] - 2023-04-10

View File

@@ -101,6 +101,10 @@ The following example contains a `TabbedContent` with three tabs.
| `active` | `str` | `""` | The `id` attribute of the active tab. Set this to switch tabs. |
## Messages
- [TabbedContent.TabActivated][textual.widgets.TabbedContent.TabActivated]
## See also

View File

@@ -61,7 +61,7 @@ The following example adds a `Tabs` widget above a text label. Press ++a++ to ad
## Messages
- [Tabs.TabActivate][textual.widgets.Tabs.TabActivated]
- [Tabs.TabActivated][textual.widgets.Tabs.TabActivated]
- [Tabs.Cleared][textual.widgets.Tabs.Cleared]
## Bindings

View File

@@ -2,9 +2,11 @@ from __future__ import annotations
from itertools import zip_longest
from rich.repr import Result
from rich.text import Text, TextType
from ..app import ComposeResult
from ..message import Message
from ..reactive import reactive
from ..widget import Widget
from ._content_switcher import ContentSwitcher
@@ -84,6 +86,24 @@ class TabbedContent(Widget):
active: reactive[str] = reactive("", init=False)
"""The ID of the active tab, or empty string if none are active."""
class TabActivated(Message):
"""Posted when the active tab changes."""
def __init__(self, tabbed_content: TabbedContent, tab: Tab) -> None:
"""Initialize message.
Args:
tabbed_content: The TabbedContent widget.
tab: The Tab widget that was selected (contains the tab label).
"""
self.tabbed_content = tabbed_content
self.tab = tab
super().__init__()
def __rich_repr__(self) -> Result:
yield self.tabbed_content
yield self.tab
def __init__(self, *titles: TextType, initial: str = "") -> None:
"""Initialize a TabbedContent widgets.
@@ -167,6 +187,12 @@ class TabbedContent(Widget):
assert isinstance(event.tab, ContentTab)
switcher.current = event.tab.id
self.active = event.tab.id
self.post_message(
TabbedContent.TabActivated(
tabbed_content=self,
tab=event.tab,
)
)
def _on_tabs_cleared(self, event: Tabs.Cleared) -> None:
"""All tabs were removed."""

View File

@@ -14,7 +14,7 @@ async def test_tabbed_content_switch():
yield Label("Foo", id="foo-label")
with TabPane("bar", id="bar"):
yield Label("Bar", id="bar-label")
with TabPane("baz`", id="baz"):
with TabPane("baz", id="baz"):
yield Label("Baz", id="baz-label")
app = TabbedApp()
@@ -73,11 +73,11 @@ async def test_tabbed_content_initial():
yield Label("Foo", id="foo-label")
with TabPane("bar", id="bar"):
yield Label("Bar", id="bar-label")
with TabPane("baz`", id="baz"):
with TabPane("baz", id="baz"):
yield Label("Baz", id="baz-label")
app = TabbedApp()
async with app.run_test() as pilot:
async with app.run_test():
tabbed_content = app.query_one(TabbedContent)
assert tabbed_content.active == "bar"
@@ -85,3 +85,31 @@ async def test_tabbed_content_initial():
assert not app.query_one("#foo-label").region
assert app.query_one("#bar-label").region
assert not app.query_one("#baz-label").region
async def test_tabbed_content_messages():
class TabbedApp(App):
message = None
def compose(self) -> ComposeResult:
with TabbedContent(initial="bar"):
with TabPane("foo", id="foo"):
yield Label("Foo", id="foo-label")
with TabPane("bar", id="bar"):
yield Label("Bar", id="bar-label")
with TabPane("baz", id="baz"):
yield Label("Baz", id="baz-label")
def on_tabbed_content_tab_activated(
self, event: TabbedContent.TabActivated
) -> None:
self.message = event
app = TabbedApp()
async with app.run_test() as pilot:
tabbed_content = app.query_one(TabbedContent)
tabbed_content.active = "bar"
await pilot.pause()
assert isinstance(app.message, TabbedContent.TabActivated)
assert app.message.tab.label.plain == "bar"