Skip to content

Commit 1c6087f

Browse files
committed
feat: add tabs for the left panel
Signed-off-by: Henry Schreiner <[email protected]>
1 parent d63da54 commit 1c6087f

File tree

6 files changed

+67
-37
lines changed

6 files changed

+67
-37
lines changed

src/uproot_browser/tui/README.md

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,28 @@ something to plot. Press `spacebar` to open/close a directory or tree. You can
99
also use the VIM keys: `j` to move down, `k` to move up, `l` to open a folder,
1010
and `h` to close a folder.
1111

12+
You can also open the command palette with `ctrl-p`, which gives you some
13+
options like changing the theme, writing out an SVG, or quitting the program.
14+
1215
## Plotting
1316

1417
Histograms, rectangular simple data (e.g. TTree's), and jagged arrays can
1518
be plotted. Click on an item or press `enter` to plot. If something can't
1619
be plotted, you'll see a scrollable error traceback. If you think it should
1720
be plottable, feel free to open an issue. 2D plots are not yet supported.
1821

19-
## Themes
22+
## Tools
23+
24+
The panel on the left (which can be hidden/shown with `b` has tabs; the `Tree`
25+
tab is the default, but you can also select `Tools`, which has a theme
26+
selector, and an Info tab, which gives the versions of installed packages.
2027

21-
You can press `t` to toggle light and dark mode.
2228

2329
## Leaving
2430

25-
You can press `q` to quit. You can also press `d` to quit with a dump of the
26-
current plot and how to get the object being plotted in Python uproot code.
31+
You can press `q` or `esc` to quit. You can also press `d` to quit with a dump
32+
of the current plot and how to get the object being plotted in Python uproot
33+
code.
2734

2835
## Exiting the help.
2936

src/uproot_browser/tui/browser.css

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Browser Widget {
88
scrollbar-size: 1 1;
99
}
1010

11-
#tree-view {
11+
#left-view {
1212
display: none;
1313
overflow: auto;
1414
width: 25%;
@@ -21,7 +21,7 @@ Tree > .tree--cursor {
2121
text-style: bold;
2222
}
2323

24-
Browser.-show-tree #tree-view {
24+
Browser.-show-panel #left-view {
2525
display: block;
2626
max-width: 50%;
2727
}
@@ -50,6 +50,14 @@ ContentSwitcher#main-view {
5050
content-align: center middle;
5151
}
5252

53+
Info {
54+
overflow: scroll;
55+
}
56+
57+
Tools {
58+
overflow: scroll;
59+
}
60+
5361
Footer > .footer--highlight {
5462
background: $secondary-darken-2;
5563
}

src/uproot_browser/tui/browser.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
PlotWidget,
4747
make_plot,
4848
)
49+
from .tools import Info, Tools
4950

5051

5152
class Browser(textual.app.App[object]):
@@ -58,13 +59,13 @@ class Browser(textual.app.App[object]):
5859
textual.binding.Binding("b", "toggle_files", "Navbar"),
5960
textual.binding.Binding("q", "quit", "Quit"),
6061
textual.binding.Binding("d", "quit_with_dump", "Dump & Quit"),
61-
textual.binding.Binding("t", "toggle_theme", "Theme"),
6262
textual.binding.Binding("f1", "help", "Help"),
6363
textual.binding.Binding("?", "help", "Help", show=False),
6464
textual.binding.Binding("escape", "quit", "Quit", show=False),
6565
]
6666

6767
show_tree = var(True)
68+
show_tools = var(False)
6869

6970
def __init__(self, path: str, **kwargs: Any) -> None:
7071
self.path = path
@@ -78,8 +79,14 @@ def compose(self) -> textual.app.ComposeResult:
7879
yield Header("uproot-browser")
7980
with textual.containers.Container():
8081
# left_panel
81-
yield UprootTree(self.path, id="tree-view")
82-
# right_panel
82+
with textual.widgets.TabbedContent(id="left-view"):
83+
with textual.widgets.TabPane("Tree"):
84+
yield UprootTree(self.path, id="tree-view")
85+
with textual.widgets.TabPane("Tools"):
86+
yield Tools()
87+
with textual.widgets.TabPane("Info"):
88+
yield Info()
89+
# main_panel
8390
with textual.widgets.ContentSwitcher(id="main-view", initial="logo"):
8491
yield LogoWidget(id="logo")
8592
yield self.plot_widget
@@ -88,11 +95,11 @@ def compose(self) -> textual.app.ComposeResult:
8895
yield textual.widgets.Footer()
8996

9097
def on_mount(self, _event: textual.events.Mount) -> None:
91-
self.query_one("#tree-view", UprootTree).focus()
98+
self.query_one("#tree-view").focus()
9299

93100
def watch_show_tree(self, show_tree: bool) -> None:
94101
"""Called when show_tree is modified."""
95-
self.set_class(show_tree, "-show-tree")
102+
self.set_class(show_tree, "-show-panel")
96103

97104
def action_help(self) -> None:
98105
self.push_screen(HelpScreen())
@@ -131,14 +138,10 @@ def action_quit_with_dump(self) -> None:
131138

132139
self.exit(message=results)
133140

134-
def action_toggle_theme(self) -> None:
135-
"""An action to toggle dark mode."""
136-
dark = self.theme != "textual-light"
137-
theme = "textual-light" if dark else "textual-dark"
138-
141+
def watch_theme(self, _old: str, new: str) -> None:
142+
dark = not new.endswith("-light")
139143
if self.plot_widget.item:
140-
self.plot_widget.item.theme = "default" if dark else "dark"
141-
self.theme = theme
144+
self.plot_widget.item.theme = "dark" if dark else "default"
142145

143146
def on_uproot_selected(self, message: UprootSelected) -> None:
144147
"""A message sent by the tree when a file is clicked."""

src/uproot_browser/tui/help.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ class HelpScreen(textual.screen.ModalScreen[None]):
2222
textual.binding.Binding("b", "", "Nothing", show=False),
2323
textual.binding.Binding("f1", "", "Nothing", show=False),
2424
textual.binding.Binding("q", "done", "Done", show=True),
25-
textual.binding.Binding("esc", "done", "Done", show=True),
26-
textual.binding.Binding("t", "toggle_theme", "Theme", show=True),
25+
textual.binding.Binding("escape", "done", "Done", show=True),
2726
]
2827

2928
app: Browser
@@ -43,6 +42,3 @@ def on_button_pressed(self, _event: textual.widgets.Button.Pressed) -> None:
4342

4443
def action_done(self) -> None:
4544
self.app.pop_screen()
46-
47-
def action_toggle_theme(self) -> None:
48-
self.app.action_toggle_theme()

src/uproot_browser/tui/tools.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import importlib.metadata
2+
3+
import textual.containers
4+
import textual.widgets
5+
6+
from .. import __version__
7+
8+
9+
class Tools(textual.containers.Container):
10+
def compose(self) -> textual.app.ComposeResult:
11+
yield textual.widgets.Label("Tools")
12+
with textual.widgets.Collapsible(title="Theme", collapsed=False):
13+
themes = self.app.available_themes
14+
yield textual.widgets.Select([(t, t) for t in themes])
15+
16+
@textual.on(textual.widgets.Select.Changed)
17+
def select_changed(self, event: textual.widgets.Select.Changed) -> None:
18+
self.app.theme = str(event.value)
19+
20+
21+
class Info(textual.containers.Container):
22+
def compose(self) -> textual.app.ComposeResult:
23+
yield textual.widgets.Label("Info")
24+
with textual.widgets.Collapsible(title="uproot-browser", collapsed=False):
25+
yield textual.widgets.Label(f"Version: [green]{__version__}[/green]")
26+
with textual.widgets.Collapsible(title="Packages", collapsed=False):
27+
for dist in importlib.metadata.distributions():
28+
yield textual.widgets.Label(
29+
f"{dist.metadata['Name']} == [green]{dist.version}[/green]"
30+
)

tests/test_tui.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,6 @@ async def test_browse_plot() -> None:
1818
assert pilot.app.query_one("#main-view").current == "plot"
1919

2020

21-
async def test_theme_switch() -> None:
22-
async with Browser(
23-
skhep_testdata.data_path("uproot-Event.root")
24-
).run_test() as pilot:
25-
await pilot.press("down", "down", "down", "enter")
26-
browser_theme = pilot.app.theme
27-
plot_theme = pilot.app.theme
28-
await pilot.press("t")
29-
new_browser_theme = pilot.app.theme
30-
new_plot_theme = pilot.app.theme
31-
assert browser_theme != new_browser_theme
32-
assert plot_theme != new_plot_theme
33-
34-
3521
async def test_browse_empty() -> None:
3622
async with Browser(
3723
skhep_testdata.data_path("uproot-empty.root")

0 commit comments

Comments
 (0)