Add TreeNode.tree

Currently, in the various TreeNode messages, and the handlers you'd write to
handle them, there's no way to easily know *which* tree sent the message and
so which tree the node belongs to.

This commit adds public access to the tree reference to the nodes, so that
in an event handler the developer can check the tree involved in the event.

See #2413.
This commit is contained in:
Dave Pearson
2023-04-28 10:22:11 +01:00
parent 730f78757a
commit 02ed90c633
3 changed files with 38 additions and 9 deletions

View File

@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## Unreleased
### Added
- Added `TreeNode.tree` as a read-only public attribute https://github.com/Textualize/textual/issues/2413
## [0.22.0] - 2023-04-27
### Fixed

View File

@@ -125,6 +125,11 @@ class TreeNode(Generic[TreeDataType]):
self._selected_ = False
self._updates += 1
@property
def tree(self) -> Tree[TreeDataType]:
"""The tree that this node is attached to."""
return self._tree
@property
def children(self) -> TreeNodes[TreeDataType]:
"""The child nodes of a TreeNode."""

View File

@@ -16,18 +16,26 @@ class TreeApp(App[None]):
def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
self.messages: list[str] = []
self.messages: list[tuple[str, str]] = []
def compose(self) -> ComposeResult:
"""Compose the child widgets."""
yield MyTree("Root")
yield MyTree("Root", id="test-tree")
def on_mount(self) -> None:
self.query_one(MyTree).root.add("Child")
self.query_one(MyTree).focus()
def record(self, event: Message) -> None:
self.messages.append(event.__class__.__name__)
def record(
self,
event: Tree.NodeSelected[None]
| Tree.NodeExpanded[None]
| Tree.NodeCollapsed[None]
| Tree.NodeHighlighted[None],
) -> None:
self.messages.append(
(event.__class__.__name__, event.node.tree.id or "Unknown")
)
def on_tree_node_selected(self, event: Tree.NodeSelected[None]) -> None:
self.record(event)
@@ -47,7 +55,10 @@ async def test_tree_node_selected_message() -> None:
async with TreeApp().run_test() as pilot:
await pilot.press("enter")
await pilot.pause()
assert pilot.app.messages == ["NodeExpanded", "NodeSelected"]
assert pilot.app.messages == [
("NodeExpanded", "test-tree"),
("NodeSelected", "test-tree"),
]
async def test_tree_node_selected_message_no_auto() -> None:
@@ -56,7 +67,7 @@ async def test_tree_node_selected_message_no_auto() -> None:
pilot.app.query_one(MyTree).auto_expand = False
await pilot.press("enter")
await pilot.pause()
assert pilot.app.messages == ["NodeSelected"]
assert pilot.app.messages == [("NodeSelected", "test-tree")]
async def test_tree_node_expanded_message() -> None:
@@ -64,7 +75,7 @@ async def test_tree_node_expanded_message() -> None:
async with TreeApp().run_test() as pilot:
await pilot.press("space")
await pilot.pause()
assert pilot.app.messages == ["NodeExpanded"]
assert pilot.app.messages == [("NodeExpanded", "test-tree")]
async def test_tree_node_collapsed_message() -> None:
@@ -72,7 +83,10 @@ async def test_tree_node_collapsed_message() -> None:
async with TreeApp().run_test() as pilot:
await pilot.press("space", "space")
await pilot.pause()
assert pilot.app.messages == ["NodeExpanded", "NodeCollapsed"]
assert pilot.app.messages == [
("NodeExpanded", "test-tree"),
("NodeCollapsed", "test-tree"),
]
async def test_tree_node_highlighted_message() -> None:
@@ -80,4 +94,8 @@ async def test_tree_node_highlighted_message() -> None:
async with TreeApp().run_test() as pilot:
await pilot.press("enter", "down")
await pilot.pause()
assert pilot.app.messages == ["NodeExpanded", "NodeSelected", "NodeHighlighted"]
assert pilot.app.messages == [
("NodeExpanded", "test-tree"),
("NodeSelected", "test-tree"),
("NodeHighlighted", "test-tree"),
]