Skip to content

Commit

Permalink
Ensure that TreeNode messages are posted when via-API changes are made
Browse files Browse the repository at this point in the history
Until now the Tree.NodeExpanded and Tree.NodeCollapsed messages were only
sent out when changes were made to the tree by user interaction. This meant
that if any changes were made with the TreeNode expand, expand_all,
collapse, collapse_all, toggle or toggle_all API calls no messages would be
sent.

This PR corrects this.

The work here is, in part, required for Textualize#2456 (DirectoryTree lazy-loads
directory information on node expansion so if someone is expanding nodes
under code control the DirectoryTree never gets to know that it should load
a directory's content) and will build on Textualize#1644, essentially adding a missing
aspect to the latter PR.
  • Loading branch information
davep committed May 10, 2023
1 parent 8855471 commit c7fc66f
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 2 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ 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

### Fixed

- Fixed `TreeNode.expand` and `TreeNode.expand_all` not posting a `Tree.NodeExpanded` message https://github.com/Textualize/textual/issues/2535
- Fixed `TreeNode.collapse` and `TreeNode.collapse_all` not posting a `Tree.NodeCollapsed` message https://github.com/Textualize/textual/issues/2535
- Fixed `TreeNode.toggle` and `TreeNode.toggle_all` not posting a `Tree.NodeExpanded` or `Tree.NodeCollapsed` message https://github.com/Textualize/textual/issues/2535

## [0.24.1] - 2023-05-08

### Fixed
Expand Down
4 changes: 2 additions & 2 deletions src/textual/widgets/_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ def _expand(self, expand_all: bool) -> None:
"""
self._expanded = True
self._updates += 1
self._tree.post_message(Tree.NodeExpanded(self._tree, self))
if expand_all:
for child in self.children:
child._expand(expand_all)
Expand Down Expand Up @@ -239,6 +240,7 @@ def _collapse(self, collapse_all: bool) -> None:
"""
self._expanded = False
self._updates += 1
self._tree.post_message(Tree.NodeCollapsed(self._tree, self))
if collapse_all:
for child in self.children:
child._collapse(collapse_all)
Expand Down Expand Up @@ -1157,10 +1159,8 @@ def _toggle_node(self, node: TreeNode[TreeDataType]) -> None:
return
if node.is_expanded:
node.collapse()
self.post_message(self.NodeCollapsed(self, node))
else:
node.expand()
self.post_message(self.NodeExpanded(self, node))

async def _on_click(self, event: events.Click) -> None:
meta = event.style.meta
Expand Down
54 changes: 54 additions & 0 deletions tests/tree/test_tree_messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,20 @@ async def test_tree_node_expanded_message() -> None:
assert pilot.app.messages == [("NodeExpanded", "test-tree")]


async def tree_node_expanded_by_code_message() -> None:
"""Expanding a node via the API should result in an expanded message being posted."""
async with TreeApp().run_test() as pilot:
pilot.app.query_one(Tree).root.children[0].expand()
assert pilot.app.messages == [("NodeExpanded", "test-tree")]


async def tree_node_all_expanded_by_code_message() -> None:
"""Expanding all nodes via the API should result in expanded messages being posted."""
async with TreeApp().run_test() as pilot:
pilot.app.query_one(Tree).root.children[0].expand_all()
assert pilot.app.messages == [("NodeExpanded", "test-tree")]


async def test_tree_node_collapsed_message() -> None:
"""Collapsing a node should result in a collapsed message being emitted."""
async with TreeApp().run_test() as pilot:
Expand All @@ -89,6 +103,46 @@ async def test_tree_node_collapsed_message() -> None:
]


async def tree_node_collapsed_by_code_message() -> None:
"""Collapsing a node via the API should result in a collapsed message being posted."""
async with TreeApp().run_test() as pilot:
pilot.app.query_one(Tree).root.children[0].expand().collapse()
assert pilot.app.messages == [
("NodeExpanded", "test-tree"),
("NodeCollapsed", "test-tree"),
]


async def tree_node_all_collapsed_by_code_message() -> None:
"""Collapsing all nodes via the API should result in collapsed messages being posted."""
async with TreeApp().run_test() as pilot:
pilot.app.query_one(Tree).root.children[0].expand_all().collapse_all()
assert pilot.app.messages == [
("NodeExpanded", "test-tree"),
("NodeCollapsed", "test-tree"),
]


async def tree_node_toggled_by_code_message() -> None:
"""Toggling a node twice via the API should result in expanded and collapsed messages."""
async with TreeApp().run_test() as pilot:
pilot.app.query_one(Tree).root.children[0].toggle().toggle()
assert pilot.app.messages == [
("NodeExpanded", "test-tree"),
("NodeCollapsed", "test-tree"),
]


async def tree_node_all_toggled_by_code_message() -> None:
"""Toggling all nodes twice via the API should result in expanded and collapsed messages."""
async with TreeApp().run_test() as pilot:
pilot.app.query_one(Tree).root.children[0].toggle_all().toggle_all()
assert pilot.app.messages == [
("NodeExpanded", "test-tree"),
("NodeCollapsed", "test-tree"),
]


async def test_tree_node_highlighted_message() -> None:
"""Highlighting a node should result in a highlighted message being emitted."""
async with TreeApp().run_test() as pilot:
Expand Down

0 comments on commit c7fc66f

Please sign in to comment.