Skip to content

Commit 527dc45

Browse files
authored
Merge pull request #7 from davep/multiple-playgrounds
✨ Add support for multiple playgrounds in the sandbox
2 parents 473ea5c + fa89819 commit 527dc45

File tree

2 files changed

+106
-19
lines changed

2 files changed

+106
-19
lines changed

textual_query_sandbox/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
__credits__ = ["Dave Pearson"]
88
__maintainer__ = "Dave Pearson"
99
__email__ = "[email protected]"
10-
__version__ = "0.3.0"
10+
__version__ = "0.4.0"
1111
__licence__ = "GPLv3+"
1212

1313
### __init__.py ends here

textual_query_sandbox/sandbox.py

Lines changed: 105 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,15 @@
22

33
from __future__ import annotations
44

5+
from itertools import cycle
6+
57
from textual import on
68
from textual.app import App, ComposeResult
9+
from textual.binding import Binding
710
from textual.containers import Horizontal, Vertical, VerticalScroll
11+
from textual.message import Message
812
from textual.widget import Widget
9-
from textual.widgets import Button, Input, Pretty, Static
13+
from textual.widgets import Button, Input, Pretty, Static, TabbedContent, TabPane, Label
1014

1115

1216
class Playground(Vertical, inherit_css=False):
@@ -43,6 +47,58 @@ def title(widget: Widget, main_title: str | None = None) -> Widget:
4347
return widget
4448

4549

50+
class NestedContainers(Playground):
51+
"""A Playground made of nested containers."""
52+
53+
def compose(self) -> ComposeResult:
54+
"""Compose the playground."""
55+
with title(Vertical(id="one", classes="foo bar")):
56+
with title(Vertical(id="two")):
57+
with title(Horizontal(id="three", classes="baz")):
58+
for n in range(3):
59+
yield title(
60+
Vertical(id=f"three-{n}", classes=f"wibble wobble-{n}")
61+
)
62+
with title(Vertical(id="four")):
63+
yield title(Vertical(id="innermost", classes="foo baz"))
64+
65+
66+
class VariousWidgets(Playground):
67+
"""A playground made of some widgets."""
68+
69+
DEFAULT_CSS = """
70+
VariousWidgets Label{
71+
width: 1fr;
72+
}
73+
"""
74+
75+
def compose(self) -> ComposeResult:
76+
"""Compose the playground."""
77+
with title(Horizontal()):
78+
classes = cycle(("foo", "bar"))
79+
with title(Vertical(id="input-widgets")):
80+
for n in range(5):
81+
yield title(
82+
Input(
83+
placeholder=f"Example input {n}",
84+
id=f"input-{n}",
85+
classes=next(classes),
86+
)
87+
)
88+
with title(Vertical(id="static-and-labels")):
89+
for n in range(3):
90+
yield title(
91+
Static(
92+
"Can you find me?", id=f"static-{n}", classes=next(classes)
93+
)
94+
)
95+
yield title(
96+
Label(
97+
"Can you find me?", id=f"label-{n}", classes=next(classes)
98+
)
99+
)
100+
101+
46102
class QuerySandboxApp(App[None]):
47103
"""A Textual CSS query sandbox application."""
48104

@@ -55,12 +111,16 @@ class QuerySandboxApp(App[None]):
55111
height: 4;
56112
}
57113
114+
TabbedContent {
115+
height: 2fr;
116+
}
117+
58118
Playground * {
59119
margin: 1;
60120
border: panel red 40%;
61121
}
62122
63-
.hit {
123+
Playground .hit {
64124
border: panel green;
65125
background: green 10%;
66126
}
@@ -76,6 +136,10 @@ class QuerySandboxApp(App[None]):
76136
border: panel cornflowerblue;
77137
}
78138
139+
#output {
140+
height: 1fr;
141+
}
142+
79143
#results {
80144
width: 3fr;
81145
}
@@ -85,44 +149,67 @@ class QuerySandboxApp(App[None]):
85149
}
86150
"""
87151

152+
BINDINGS = [
153+
Binding("f1", "playground('tab-1')", "Nested Containers"),
154+
Binding("f2", "playground('tab-2')", "Various Widgets"),
155+
]
156+
88157
def compose(self) -> ComposeResult:
89158
"""Compose the DOM for the application."""
90159
with Horizontal(id="input"):
91160
yield Input()
92161
yield Button("Query")
93-
with Playground():
94-
with title(Vertical(id="one", classes="foo bar")):
95-
with title(Vertical(id="two")):
96-
with title(Horizontal(id="three", classes="baz")):
97-
for n in range(3):
98-
yield title(
99-
Vertical(id=f"three-{n}", classes=f"wibble wobble-{n}")
100-
)
101-
with title(Vertical(id="four")):
102-
yield title(Vertical(id="innermost", classes="foo baz"))
103-
with Horizontal():
162+
with TabbedContent():
163+
with TabPane("Nested Containers (F1)"):
164+
yield NestedContainers()
165+
with TabPane("Various Widgets (F2)"):
166+
yield VariousWidgets()
167+
with Horizontal(id="output"):
104168
with title(VerticalScroll(id="results"), "Query Results"):
105169
yield Pretty([])
106170
with title(VerticalScroll(id="tree"), "Playground DOM Tree"):
107171
yield Static("")
108172

109-
def on_mount(self) -> None:
110-
self.query_one("#tree > Static", Static).update(self.query_one(Playground).tree)
173+
@property
174+
def input(self) -> Input:
175+
"""The main input widget."""
176+
return self.query_one("#input Input", Input)
177+
178+
@property
179+
def playground(self) -> Playground:
180+
"""The current playground widget."""
181+
return self.query_one(
182+
f"TabPane#{self.query_one(TabbedContent).active} Playground", Playground
183+
)
111184

112185
@on(Input.Submitted)
113186
@on(Button.Pressed)
114-
def do_query(self) -> None:
187+
@on(TabbedContent.TabActivated)
188+
def do_query(self, event: Message | None = None) -> None:
115189
"""Perform the query and show the result."""
116190
self.query("Playground *").remove_class("hit")
117191
result: list[Widget] | Exception
118192
try:
119-
hits = self.query_one(Playground).query(self.query_one(Input).value)
193+
hits = self.playground.query(self.input.value)
120194
hits.add_class("hit")
121195
result = list(hits)
122196
except Exception as error: # pylint:disable=broad-exception-caught
123197
result = error
124198
self.query_one("#results > Pretty", Pretty).update(result)
125-
self.query_one(Input).focus()
199+
self.query_one("#tree > Static", Static).update(
200+
self.playground.children[0].tree
201+
)
202+
if not isinstance(event, TabbedContent.TabActivated):
203+
self.input.focus()
204+
205+
def action_playground(self, playground: str) -> None:
206+
"""Switch between different playgrounds.
207+
208+
Args:
209+
playground: The playground to switch to.
210+
"""
211+
self.query_one(TabbedContent).active = playground
212+
self.do_query()
126213

127214

128215
### sandbox.py ends here

0 commit comments

Comments
 (0)