Merge branch 'css' into invisible-widgets

This commit is contained in:
Will McGugan
2022-09-02 14:02:18 +01:00
committed by GitHub
61 changed files with 572 additions and 360 deletions

View File

@@ -8,7 +8,7 @@ from textual.widgets import Placeholder
class VerticalContainer(Widget):
CSS = """
DEFAULT_CSS = """
VerticalContainer {
layout: vertical;
overflow: hidden auto;
@@ -24,7 +24,7 @@ class VerticalContainer(Widget):
class Introduction(Widget):
CSS = """
DEFAULT_CSS = """
Introduction {
background: indigo;
color: white;

View File

@@ -23,7 +23,9 @@ class ButtonsApp(App[str]):
app = ButtonsApp(
log_path="textual.log", css_path="buttons.css", watch_css=True, log_verbosity=2
log_path="textual.log",
css_path="buttons.css",
watch_css=True,
)
if __name__ == "__main__":

View File

@@ -23,7 +23,7 @@ class ColorDisplay(Widget, can_focus=True):
class ColorNames(App):
CSS = """
DEFAULT_CSS = """
ColorDisplay {
height: 1;
}

View File

@@ -23,7 +23,9 @@ class ButtonsApp(App[str]):
app = ButtonsApp(
log_path="textual.log", css_path="buttons.css", watch_css=True, log_verbosity=2
log_path="textual.log",
css_path="buttons.css",
watch_css=True,
)
if __name__ == "__main__":

View File

@@ -62,9 +62,7 @@ class FileSearchApp(App):
self.file_table.filter = event.value
app = FileSearchApp(
log_path="textual.log", css_path="file_search.scss", watch_css=True, log_verbosity=2
)
app = FileSearchApp(log_path="textual.log", css_path="file_search.scss", watch_css=True)
if __name__ == "__main__":
result = app.run()

View File

@@ -5,7 +5,7 @@ from textual.widget import Widget
class FiftyApp(App):
CSS = """
DEFAULT_CSS = """
Screen {
layout: vertical;
}
@@ -24,6 +24,7 @@ class FiftyApp(App):
yield layout.Horizontal(Widget(), Widget())
yield layout.Horizontal(Widget(), Widget())
app = FiftyApp()
if __name__ == "__main__":
app.run()

View File

@@ -61,9 +61,7 @@ class InputApp(App[str]):
self.celsius.value = f"{celsius:.1f}"
app = InputApp(
log_path="textual.log", css_path="input.scss", watch_css=True, log_verbosity=2
)
app = InputApp(log_path="textual.log", css_path="input.scss", watch_css=True)
if __name__ == "__main__":
result = app.run()

View File

@@ -9,7 +9,7 @@ placeholders_count = 12
class VerticalContainer(Widget):
CSS = """
DEFAULT_CSS = """
VerticalContainer {
layout: vertical;
overflow: hidden auto;
@@ -26,7 +26,7 @@ class VerticalContainer(Widget):
class Introduction(Widget):
CSS = """
DEFAULT_CSS = """
Introduction {
background: indigo;
color: white;

View File

@@ -10,7 +10,7 @@ initial_placeholders_count = 4
class VerticalContainer(Widget):
CSS = """
DEFAULT_CSS = """
VerticalContainer {
layout: vertical;
overflow: hidden auto;
@@ -30,7 +30,7 @@ class VerticalContainer(Widget):
class Introduction(Widget):
CSS = """
DEFAULT_CSS = """
Introduction {
background: indigo;
color: white;

View File

@@ -11,7 +11,7 @@ class Thing(Static):
class AddRemoveApp(App):
CSS = """
DEFAULT_CSS = """
#buttons {
dock: top;
height: auto;

View File

@@ -9,8 +9,8 @@ Screen {
table-columns: 1fr;
table-rows: 2fr 1fr 1fr 1fr 1fr 1fr;
margin: 1 2;
min-height:26;
min-width: 50;
min-height:25;
min-width: 26;
}
Button {
@@ -18,18 +18,15 @@ Button {
height: 100%;
}
.display {
#numbers {
column-span: 4;
content-align: right middle;
padding: 0 1;
height: 100%;
background: $panel-darken-2;
background: $primary-lighten-2;
color: $text-primary-lighten-2;
}
.special {
tint: $text-panel 20%;
}
.zero {
#number-0 {
column-span: 2;
}

View File

@@ -1,35 +1,143 @@
from textual.app import App
from decimal import Decimal
from textual.app import App, ComposeResult
from textual import events
from textual.layout import Container
from textual.reactive import Reactive
from textual.widgets import Button, Static
class CalculatorApp(App):
def compose(self):
"""A working 'desktop' calculator."""
numbers = Reactive.var("0")
show_ac = Reactive.var(True)
left = Reactive.var(Decimal("0"))
right = Reactive.var(Decimal("0"))
value = Reactive.var("")
operator = Reactive.var("plus")
KEY_MAP = {
"+": "plus",
"-": "minus",
".": "point",
"*": "multiply",
"/": "divide",
"_": "plus-minus",
"%": "percent",
"=": "equals",
}
def watch_numbers(self, value: str) -> None:
"""Called when numbers is updated."""
# Update the Numbers widget
self.query_one("#numbers", Static).update(value)
def compute_show_ac(self) -> bool:
"""Compute switch to show AC or C button"""
return self.value in ("", "0") and self.numbers == "0"
def watch_show_ac(self, show_ac: bool) -> None:
"""Called when show_ac changes."""
self.query_one("#c").display = not show_ac
self.query_one("#ac").display = show_ac
def compose(self) -> ComposeResult:
"""Add our buttons."""
yield Container(
Static("0", classes="display"),
Button("AC", classes="special"),
Button("+/-", classes="special"),
Button("%", classes="special"),
Button("÷", variant="warning"),
Button("7"),
Button("8"),
Button("9"),
Button("×", variant="warning"),
Button("4"),
Button("5"),
Button("6"),
Button("-", variant="warning"),
Button("1"),
Button("2"),
Button("3"),
Button("+", variant="warning"),
Button("0", classes="operator zero"),
Button("."),
Button("=", variant="warning"),
Static(id="numbers"),
Button("AC", id="ac", variant="primary"),
Button("C", id="c", variant="primary"),
Button("+/-", id="plus-minus", variant="primary"),
Button("%", id="percent", variant="primary"),
Button("÷", id="divide", variant="warning"),
Button("7", id="number-7"),
Button("8", id="number-8"),
Button("9", id="number-9"),
Button("×", id="multiply", variant="warning"),
Button("4", id="number-4"),
Button("5", id="number-5"),
Button("6", id="number-6"),
Button("-", id="minus", variant="warning"),
Button("1", id="number-1"),
Button("2", id="number-2"),
Button("3", id="number-3"),
Button("+", id="plus", variant="warning"),
Button("0", id="number-0"),
Button(".", id="point"),
Button("=", id="equals", variant="warning"),
id="calculator",
)
def on_key(self, event: events.Key) -> None:
"""Called when the user presses a key."""
print(f"KEY {event} was pressed!")
def press(button_id: str) -> None:
self.query_one(f"#{button_id}", Button).press()
self.set_focus(None)
key = event.key
if key.isdecimal():
press(f"number-{key}")
elif key == "c":
press("c")
press("ac")
elif key in self.KEY_MAP:
press(self.KEY_MAP[key])
def on_button_pressed(self, event: Button.Pressed) -> None:
"""Called when a button is pressed."""
button_id = event.button.id
assert button_id is not None
self.bell() # Terminal bell
def do_math() -> None:
"""Does the math: LEFT OPERATOR RIGHT"""
try:
if self.operator == "plus":
self.left += self.right
elif self.operator == "minus":
self.left -= self.right
elif self.operator == "divide":
self.left /= self.right
elif self.operator == "multiply":
self.left *= self.right
self.numbers = str(self.left)
self.value = ""
except Exception:
self.numbers = "Error"
if button_id.startswith("number-"):
number = button_id.partition("-")[-1]
self.numbers = self.value = self.value.lstrip("0") + number
elif button_id == "plus-minus":
self.numbers = self.value = str(Decimal(self.value or "0") * -1)
elif button_id == "percent":
self.numbers = self.value = str(Decimal(self.value or "0") / Decimal(100))
elif button_id == "point":
if "." not in self.value:
self.numbers = self.value = (self.value or "0") + "."
elif button_id == "ac":
self.value = ""
self.left = self.right = Decimal(0)
self.operator = "plus"
self.numbers = "0"
elif button_id == "c":
self.value = ""
self.numbers = "0"
elif button_id in ("plus", "minus", "divide", "multiply"):
self.right = Decimal(self.value or "0")
do_math()
self.operator = button_id
elif button_id == "equals":
if self.value:
self.right = Decimal(self.value)
do_math()
app = CalculatorApp(css_path="calculator.css")
if __name__ == "__main__":

View File

@@ -3,7 +3,7 @@ from textual.widgets import Static
class CenterApp(App):
CSS = """
DEFAULT_CSS = """
CenterApp Screen {
layout: center;

View File

@@ -4,7 +4,7 @@ from textual.widgets import Static
class CenterApp(App):
CSS = """
DEFAULT_CSS = """
#sidebar {
dock: left;
@@ -52,4 +52,4 @@ class CenterApp(App):
)
app = CenterApp(log_verbosity=3)
app = CenterApp()

View File

@@ -10,7 +10,7 @@ from textual.widget import Widget
class Box(Widget, can_focus=True):
CSS = "#box {background: blue;}"
DEFAULT_CSS = "#box {background: blue;}"
def render(self) -> RenderableType:
return Panel("Box")

View File

@@ -21,7 +21,7 @@ class NewScreen(Screen):
class ScreenApp(App):
CSS = """
DEFAULT_CSS = """
ScreenApp Screen {
background: #111144;
color: white;

View File

@@ -37,9 +37,7 @@ class ButtonsApp(App[str]):
self.dark = not self.dark
app = ButtonsApp(
log_path="textual.log", css_path="buttons.css", watch_css=True, log_verbosity=3
)
app = ButtonsApp(log_path="textual.log", css_path="buttons.css", watch_css=True)
if __name__ == "__main__":
result = app.run()

View File

@@ -8,6 +8,6 @@ Static {
background: blue 20%;
height: 100%;
margin: 2 4;
min-width: 30;
visibility: hidden;
min-width: 80;
min-height: 40;
}

View File

@@ -5,7 +5,7 @@ from textual.widgets import DirectoryTree
class TreeApp(App):
CSS = """
DEFAULT_CSS = """
Screen {
overflow: auto;