diff --git a/CHANGELOG.md b/CHANGELOG.md index 4410a7fbb..b9f38a6ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Added App.scroll_sensitivity_x and App.scroll_sensitivity_y to adjust how many lines the scroll wheel moves the scroll position https://github.com/Textualize/textual/issues/928 - Added Shift+scroll wheel and ctrl+scroll wheel to scroll horizontally - Added `Tree.action_toggle_node` to toggle a node without selecting, and bound it to Space https://github.com/Textualize/textual/issues/1433 -- Added the ability to set new root node label and/or data when calling `Tree.clear` https://github.com/Textualize/textual/issues/1437 +- Added `Tree.reset` to fully reset a `Tree` https://github.com/Textualize/textual/issues/1437 ### Changed diff --git a/src/textual/widgets/_tree.py b/src/textual/widgets/_tree.py index f299c0d99..4145e9eb0 100644 --- a/src/textual/widgets/_tree.py +++ b/src/textual/widgets/_tree.py @@ -560,20 +560,13 @@ class Tree(Generic[TreeDataType], ScrollView, can_focus=True): label = self.render_label(node, NULL_STYLE, NULL_STYLE) return label.cell_len - def clear(self, label: TextType | None = None, data: TreeDataType = ...) -> None: - """Clear all nodes under root. - - Args: - label: An optional new label for the root node. If not provided - the current root node's label will be used. - data: Optional new data for the root node. If not provided the - current root node's data will be used. - """ + def clear(self) -> None: + """Clear all nodes under root.""" self._line_cache.clear() self._tree_lines_cached = None self._current_id = 0 - root_label = self.root._label if label is None else label - root_data = self.root.data if data is ... else data + root_label = self.root._label + root_data = self.root.data self.root = TreeNode( self, None, @@ -585,6 +578,17 @@ class Tree(Generic[TreeDataType], ScrollView, can_focus=True): self._updates += 1 self.refresh() + def reset(self, label: TextType, data: TreeDataType | None = None) -> None: + """Clear the tree and reset the root node. + + Args: + label: The label for the root node. + data: Optional data for the root node. + """ + self.clear() + self.root.label = label + self.root.data = data + def select_node(self, node: TreeNode[TreeDataType] | None) -> None: """Move the cursor to the given node, or reset cursor. diff --git a/tests/tree/test_tree_clearing.py b/tests/tree/test_tree_clearing.py index 9b7762bbf..87543c4c8 100644 --- a/tests/tree/test_tree_clearing.py +++ b/tests/tree/test_tree_clearing.py @@ -41,7 +41,7 @@ class TreeClearApp(App[None]): async def test_tree_simple_clear() -> None: - """Clearing a tree should keep the old label and data.""" + """Clearing a tree should keep the old root label and data.""" async with TreeClearApp().run_test() as pilot: tree = pilot.app.query_one(VerseTree) assert len(tree.root.children) > 1 @@ -51,34 +51,23 @@ async def test_tree_simple_clear() -> None: assert isinstance(tree.root.data, VerseStar) -async def test_tree_new_label_clear() -> None: - """Clearing a tree with a new label should use the new label and keep the old data.""" +async def test_tree_reset_with_label() -> None: + """Resetting a tree with a new label should use the new label and set the data to None.""" async with TreeClearApp().run_test() as pilot: tree = pilot.app.query_one(VerseTree) assert len(tree.root.children) > 1 - pilot.app.query_one(VerseTree).clear(label="Jiangyin") + pilot.app.query_one(VerseTree).reset(label="Jiangyin") assert len(tree.root.children) == 0 assert str(tree.root.label) == "Jiangyin" - assert isinstance(tree.root.data, VerseStar) + assert tree.root.data is None -async def test_tree_new_data_clear() -> None: - """Clearing a tree with data should keep the old label and use the new data.""" +async def test_tree_reset_with_label_and_data() -> None: + """Resetting a tree with a label and data have that label and data used.""" async with TreeClearApp().run_test() as pilot: tree = pilot.app.query_one(VerseTree) assert len(tree.root.children) > 1 - pilot.app.query_one(VerseTree).clear(data=VersePlanet()) - assert len(tree.root.children) == 0 - assert str(tree.root.label) == "White Sun" - assert isinstance(tree.root.data, VersePlanet) - - -async def test_tree_new_labal_and_data_clear() -> None: - """Clearing a tree with label and data should replace the label and data.""" - async with TreeClearApp().run_test() as pilot: - tree = pilot.app.query_one(VerseTree) - assert len(tree.root.children) > 1 - pilot.app.query_one(VerseTree).clear(label="Jiangyin", data=VersePlanet()) + pilot.app.query_one(VerseTree).reset(label="Jiangyin", data=VersePlanet()) assert len(tree.root.children) == 0 assert str(tree.root.label) == "Jiangyin" assert isinstance(tree.root.data, VersePlanet)