Files
textual/examples/json_tree.py
2023-03-27 14:26:55 +01:00

94 lines
2.7 KiB
Python

import json
from pathlib import Path
from rich.text import Text
from textual.app import App, ComposeResult
from textual.widgets import Header, Footer, Tree
from textual.widgets.tree import TreeNode
class TreeApp(App):
BINDINGS = [
("a", "add", "Add node"),
("c", "clear", "Clear"),
("t", "toggle_root", "Toggle root"),
]
def compose(self) -> ComposeResult:
yield Header()
yield Footer()
yield Tree("Root")
@classmethod
def add_json(cls, node: TreeNode, json_data: object) -> None:
"""Adds JSON data to a node.
Args:
node (TreeNode): A Tree node.
json_data (object): An object decoded from JSON.
"""
from rich.highlighter import ReprHighlighter
highlighter = ReprHighlighter()
def add_node(name: str, node: TreeNode, data: object) -> None:
"""Adds a node to the tree.
Args:
name (str): Name of the node.
node (TreeNode): Parent node.
data (object): Data associated with the node.
"""
if isinstance(data, dict):
node.set_label(Text(f"{{}} {name}"))
for key, value in data.items():
new_node = node.add("")
add_node(key, new_node, value)
elif isinstance(data, list):
node.set_label(Text(f"[] {name}"))
for index, value in enumerate(data):
new_node = node.add("")
add_node(str(index), new_node, value)
else:
node.allow_expand = False
if name:
label = Text.assemble(
Text.from_markup(f"[b]{name}[/b]="), highlighter(repr(data))
)
else:
label = Text(repr(data))
node.set_label(label)
add_node("JSON", node, json_data)
def on_mount(self) -> None:
"""Load some JSON when the app starts."""
file_path = Path(__file__).parent / "food.json"
with open(file_path) as data_file:
self.json_data = json.load(data_file)
def action_add(self) -> None:
"""Add a node to the tree."""
tree = self.query_one(Tree)
json_node = tree.root.add("JSON")
self.add_json(json_node, self.json_data)
tree.root.expand()
def action_clear(self) -> None:
"""Clear the tree (remove all nodes)."""
tree = self.query_one(Tree)
tree.clear()
def action_toggle_root(self) -> None:
"""Toggle the root node."""
tree = self.query_one(Tree)
tree.show_root = not tree.show_root
if __name__ == "__main__":
app = TreeApp()
app.run()