Merge pull request #795 from Textualize/remove-docks

Remove `docks` references & other tidying
This commit is contained in:
Will McGugan
2022-09-22 15:39:26 +01:00
committed by GitHub
35 changed files with 6 additions and 1261 deletions

3
.gitignore vendored
View File

@@ -113,3 +113,6 @@ venv.bak/
# mypy # mypy
.mypy_cache/ .mypy_cache/
# Snapshot testing report output directory
tests/snapshot_tests/output

View File

@@ -1,3 +1,5 @@
from __future__ import annotations
import asyncio import asyncio
from typing import Any from typing import Any

View File

@@ -1,3 +0,0 @@
# Dev Sandbox
This directory contains test code for Textual devs to experiment with new features. None of the .py files here are guaranteed to run or do anything useful, but you are welcome to look around.

View File

@@ -1,48 +0,0 @@
Screen {
layout: vertical;
overflow: auto;
}
Widget {
margin:1;
}
#thing {
width: auto;
height: auto;
background:magenta;
margin: 1;
padding: 1;
border: solid white;
box-sizing: border-box;
border: solid white;
align-horizontal: center;
}
#thing2 {
border: solid white;
/* outline: heavy blue; */
height: 10;
padding: 1 2;
box-sizing: border-box;
max-height: 100vh;
background:green;
align-horizontal: center;
color:white;
}
#thing3 {
height: 10;
margin: 1;
background:blue;
color: white 50%;
border: white;
align-horizontal: center;
}

View File

@@ -1,30 +0,0 @@
from rich.style import Style
from textual.app import App, ComposeResult
from textual.widget import Widget
from textual.widgets import Static
class Thing(Widget):
def render(self):
return "Hello, 3434 World.\n[b]Lorem impsum."
class AlignApp(App):
CSS_PATH = "align.css"
def on_load(self):
self.bind("t", "log_tree")
def compose(self) -> ComposeResult:
yield Thing(id="thing")
yield Static("foo", id="thing2")
yield Widget(id="thing3")
def action_log_tree(self):
self.log(self.screen.tree)
if __name__ == "__main__":
app = AlignApp(css_path="align.css")
app.run()

View File

@@ -1,16 +0,0 @@
Vertical {
background: red 50%;
}
.test {
width: auto;
height: auto;
background: white 50%;
border:solid green;
padding: 0;
margin:3;
align: center middle;
box-sizing: border-box;
}

View File

@@ -1,21 +0,0 @@
from textual.app import App, ComposeResult
from textual.widgets import Static
from textual.layout import Vertical
from rich.text import Text
TEXT = Text.from_markup(" ".join(str(n) * 5 for n in range(12)))
class AutoApp(App):
CSS_PATH = "auto_test.css"
def compose(self) -> ComposeResult:
yield Vertical(
Static(TEXT, classes="test"), Static(TEXT, id="test", classes="test")
)
if __name__ == "__main__":
app = AutoApp()
app.run()

View File

@@ -1,66 +0,0 @@
from rich.console import RenderableType
from rich.text import Text
from textual.app import App, ComposeResult
from textual.css.types import EdgeType
from textual.widget import Widget
from textual.widgets import Placeholder
class VerticalContainer(Widget):
DEFAULT_CSS = """
VerticalContainer {
layout: vertical;
overflow: hidden auto;
background: darkblue;
}
VerticalContainer Placeholder {
margin: 1 0;
height: auto;
align: center top;
}
"""
class Introduction(Widget):
DEFAULT_CSS = """
Introduction {
background: indigo;
color: white;
height: 3;
padding: 1 0;
}
"""
def render(self) -> RenderableType:
return Text("Here are the color edge types we support.", justify="center")
class BorderDemo(Widget):
def __init__(self, name: str):
super().__init__(name=name)
def render(self) -> RenderableType:
return Text(self.name, style="black on yellow", justify="center")
class MyTestApp(App):
def compose(self) -> ComposeResult:
border_demo_widgets = []
for border_edge_type in EdgeType.__args__:
border_demo = BorderDemo(f'"border: {border_edge_type} white"')
border_demo.styles.height = "auto"
border_demo.styles.margin = (1, 0)
border_demo.styles.border = (border_edge_type, "white")
border_demo_widgets.append(border_demo)
yield VerticalContainer(Introduction(), *border_demo_widgets, id="root")
def on_mount(self):
self.bind("q", "quit")
if __name__ == "__main__":
app = MyTestApp()
app.run()

View File

@@ -1,6 +0,0 @@
Button {
box-sizing: border-box;
margin: 1;
width: 100%;
}

View File

@@ -1,33 +0,0 @@
from textual import layout, events
from textual.app import App, ComposeResult
from textual.widgets import Button
class ButtonsApp(App[str]):
def compose(self) -> ComposeResult:
yield layout.Vertical(
Button("default", id="foo"),
Button.success("success", id="bar"),
Button.warning("warning", id="baz"),
Button.error("error", id="baz"),
)
def on_button_pressed(self, event: Button.Pressed) -> None:
self.app.bell()
async def on_key(self, event: events.Key) -> None:
await self.dispatch_key(event)
def key_d(self):
self.dark = not self.dark
app = ButtonsApp(
log_path="textual.log",
css_path="buttons.css",
watch_css=True,
)
if __name__ == "__main__":
result = app.run()
print(repr(result))

View File

@@ -1,46 +0,0 @@
import rich.repr
from rich.align import Align
from rich.console import RenderableType
from rich.panel import Panel
from rich.pretty import Pretty
from textual._color_constants import COLOR_NAME_TO_RGB
from textual.app import App, ComposeResult
from textual.widget import Widget
from textual.widgets import Placeholder
@rich.repr.auto(angular=False)
class ColorDisplay(Widget, can_focus=True):
def render(self) -> RenderableType:
return Panel(
Align.center(
Pretty(self, no_wrap=True, overflow="ellipsis"), vertical="middle"
),
title=self.name,
border_style="none",
)
class ColorNames(App):
DEFAULT_CSS = """
ColorDisplay {
height: 1;
}
"""
def on_mount(self):
self.bind("q", "quit")
def compose(self) -> ComposeResult:
for color_name, color in COLOR_NAME_TO_RGB.items():
color_placeholder = ColorDisplay(name=color_name)
is_dark_color = sum(color) < 400
color_placeholder.styles.color = "white" if is_dark_color else "black"
color_placeholder.styles.background = color_name
yield color_placeholder
if __name__ == "__main__":
color_name_app = ColorNames()
color_name_app.run()

View File

@@ -1,54 +0,0 @@
from textual.app import App
from textual.widget import Widget
from textual.widgets import Static
class FocusKeybindsApp(App):
dark = True
def on_load(self) -> None:
self.bind("1", "focus('widget1')")
self.bind("2", "focus('widget2')")
self.bind("3", "focus('widget3')")
self.bind("4", "focus('widget4')")
self.bind("q", "focus('widgetq')")
self.bind("w", "focus('widgetw')")
self.bind("e", "focus('widgete')")
self.bind("r", "focus('widgetr')")
def on_mount(self) -> None:
info = Static(
"Use keybinds to shift focus between the widgets in the lists below",
)
self.mount(info=info)
self.mount(
body=Widget(
Widget(
Static("Press 1 to focus", id="widget1", classes="list-item"),
Static("Press 2 to focus", id="widget2", classes="list-item"),
Static("Press 3 to focus", id="widget3", classes="list-item"),
Static("Press 4 to focus", id="widget4", classes="list-item"),
classes="list",
id="left_list",
),
Widget(
Static("Press Q to focus", id="widgetq", classes="list-item"),
Static("Press W to focus", id="widgetw", classes="list-item"),
Static("Press E to focus", id="widgete", classes="list-item"),
Static("Press R to focus", id="widgetr", classes="list-item"),
classes="list",
id="right_list",
),
),
)
self.mount(footer=Static("No widget focused"))
def on_descendant_focus(self):
self.get_child("footer").update(
f"Focused: {self.focused.id}" or "No widget focused"
)
app = FocusKeybindsApp(css_path="focus_keybindings.scss", watch_css=True)
app.run()

View File

@@ -1,57 +0,0 @@
App > Screen {
layout: dock;
docks: left=left top=top;
}
#info {
background: $primary;
dock: top;
height: 3;
padding: 1;
}
#body {
dock: top;
layout: dock;
docks: bodylhs=left;
}
#left_list {
dock: bodylhs;
padding: 2;
}
#right_list {
dock: bodylhs;
padding: 2;
}
#footer {
height: 1;
background: $secondary;
padding: 0 1;
dock: top;
}
.list {
background: $surface;
border-top: hkey $surface-darken-1;
}
.list:focus-within {
background: $primary-darken-1;
outline-top: $accent-lighten-1;
outline-bottom: $accent-lighten-1;
}
.list-item {
background: $surface;
height: auto;
border: $surface-darken-1 tall;
padding: 0 1;
}
.list-item:focus {
background: $surface-darken-1;
outline: $accent tall;
}

View File

@@ -1,38 +0,0 @@
from rich.console import RenderableType
from rich.panel import Panel
from rich.style import Style
from textual.app import App
from textual.widget import Widget
class PanelWidget(Widget):
def render(self) -> RenderableType:
return Panel("hello world!", title="Title")
class BasicApp(App):
"""Sandbox application used for testing/development by Textual developers"""
def on_load(self):
"""Bind keys here."""
self.bind("tab", "toggle_class('#sidebar', '-active')")
self.bind("a", "toggle_class('#header', '-visible')")
self.bind("c", "toggle_class('#content', '-content-visible')")
self.bind("d", "toggle_class('#footer', 'dim')")
self.bind("x", "dump")
def on_mount(self):
"""Build layout here."""
self.mount(
header=Widget(),
content=PanelWidget(),
footer=Widget(),
sidebar=Widget(),
)
def action_dump(self):
self.panic(self.tree)
BasicApp.run(css_path="dev_sandbox.scss", watch_css=True, log_path="textual.log")

View File

@@ -1,66 +0,0 @@
/* CSS file for dev_sandbox.py */
$text: #f0f0f0;
$primary: #021720;
$secondary: #95d52a;
$background: #262626;
$animatitext-speed: 500ms;
$animation: offset $animatitext-speed in_out_cubic;
App > View {
docks: side=left/1;
background: $background;
}
Widget:hover {
outline: heavy;
text-style: bold !important;
}
#sidebar {
color: $text;
background: $background;
dock: side;
width: 30;
offset-x: -100%;
transition: $animation;
border-right: outer $secondary;
}
#sidebar.-active {
offset-x: 0;
}
#header {
color: $text;
background: $primary;
height: 3;
border-bottom: hkey $secondary;
}
#header.-visible {
visibility: hidden;
}
#content {
color: $text;
background: $background;
offset-y: -3;
}
#content.-content-visible {
visibility: hidden;
}
#footer {
text-opacity: 1;
color: $text;
background: $background;
height: 3;
border-top: hkey $secondary;
}
#footer.dim {
text-opacity: 0.5;
}

View File

@@ -1,30 +0,0 @@
from textual.app import App
from textual import layout
from textual.widget import Widget
class FiftyApp(App):
DEFAULT_CSS = """
Screen {
layout: vertical;
}
Horizontal {
height: 50%;
}
Widget {
width: 50%;
outline: white;
background: blue;
}
"""
def compose(self):
yield layout.Horizontal(Widget(), Widget())
yield layout.Horizontal(Widget(), Widget())
app = FiftyApp()
if __name__ == "__main__":
app.run()

View File

@@ -1,18 +0,0 @@
Horizontal {
background: red 50%;
overflow-x: auto;
/* width: auto */
}
.test {
width: auto;
height: auto;
background: white 50%;
border:solid green;
padding: 0;
margin:3;
align: center middle;
box-sizing: content-box;
}

View File

@@ -1,26 +0,0 @@
from textual.app import App, ComposeResult
from textual.widgets import Static
from textual import layout
from rich.text import Text
TEXT = Text.from_markup(" ".join(str(n) * 5 for n in range(10)))
class AutoApp(App):
def on_mount(self) -> None:
self.bind("t", "tree")
def compose(self) -> ComposeResult:
yield layout.Horizontal(
Static(TEXT, classes="test"), Static(TEXT, id="test", classes="test")
)
def action_tree(self):
self.log(self.screen.tree)
app = AutoApp(css_path="horizontal.css")
if __name__ == "__main__":
app.run()

View File

@@ -1,67 +0,0 @@
from __future__ import annotations
from pathlib import Path
from textual.app import App
from textual.widget import Widget
from textual.widgets.text_input import TextInput, TextWidgetBase, TextArea
def celsius_to_fahrenheit(celsius: float) -> float:
return celsius * 1.8 + 32
def fahrenheit_to_celsius(fahrenheit: float) -> float:
return (fahrenheit - 32) / 1.8
words = set(Path("/usr/share/dict/words").read_text().splitlines())
def word_autocompleter(value: str) -> str | None:
# An example autocompleter that uses the Unix dictionary to suggest
# word completions
for word in words:
if word.startswith(value):
return word
return None
class InputApp(App[str]):
def on_mount(self) -> None:
self.fahrenheit = TextInput(placeholder="Fahrenheit", id="fahrenheit")
self.celsius = TextInput(placeholder="Celsius", id="celsius")
self.fahrenheit.focus()
text_boxes = Widget(self.fahrenheit, self.celsius)
self.mount(inputs=text_boxes)
self.mount(spacer=Widget())
self.mount(
top_search=Widget(
TextInput(autocompleter=word_autocompleter, id="topsearchbox")
)
)
self.mount(
footer=TextInput(
placeholder="Footer Search Bar", autocompleter=word_autocompleter
)
)
self.mount(text_area=TextArea())
def on_text_input_changed_changed(self, event: TextInput.Changed) -> None:
try:
value = float(event.value)
except ValueError:
return
if event.sender == self.celsius:
fahrenheit = celsius_to_fahrenheit(value)
self.fahrenheit.value = f"{fahrenheit:.1f}"
elif event.sender == self.fahrenheit:
celsius = fahrenheit_to_celsius(value)
self.celsius.value = f"{celsius:.1f}"
app = InputApp(log_path="textual.log", css_path="input.scss", watch_css=True)
if __name__ == "__main__":
result = app.run()

View File

@@ -1,53 +0,0 @@
App {
background: $secondary;
}
#spacer {
height: 1;
background: $primary-darken-2;
dock: top;
}
Screen {
layout: dock;
docks: top=top bottom=bottom;
background: $background;
}
#fahrenheit {
width: 50%;
}
#celsius {
width: 50%;
}
#celsius :focus {
border: heavy darkgoldenrod;
}
#inputs {
dock: top;
background: $primary;
height: 3;
layout: horizontal;
}
#text_area {
dock: bottom;
}
#top_search {
dock: top;
}
#topsearchbox {
width: 10%;
}
#footer {
background: $primary-darken-2;
dock: bottom;
height: 1;
border: ;
}

View File

@@ -1,11 +0,0 @@
App > View {
layout: dock;
}
Widget {
text: on blue;
}
Widget.-highlight {
outline: heavy red;
}

View File

@@ -1,36 +0,0 @@
from textual import events
from textual.app import App
from textual.widget import Widget
from textual.widgets import Placeholder
class BasicApp(App):
"""Sandbox application used for testing/development by Textual developers"""
def on_mount(self):
"""Build layout here."""
self.mount(
header=Widget(),
content=Placeholder(),
footer=Widget(),
sidebar=Widget(),
)
async def on_key(self, event: events.Key) -> None:
await self.dispatch_key(event)
def key_a(self) -> None:
footer = self.get_child("footer")
footer.set_styles(text="on magenta")
def key_b(self) -> None:
footer = self.get_child("footer")
footer.set_styles("text: on green")
def key_c(self) -> None:
header = self.get_child("header")
header.toggle_class("-highlight")
self.log(header.styles)
BasicApp.run(css_path="local_styles.css", log_path="textual.log")

View File

@@ -1,25 +0,0 @@
Vertical {
background: blue;
}
#container {
width:50%;
height: auto;
align-horizontal: center;
padding: 1;
border: heavy white;
background: white 50%;
overflow-y: auto
}
TextWidget {
/* width: 50%; */
height: auto;
padding: 2;
background: green 30%;
border: yellow;
box-sizing: border-box;
}

View File

@@ -1,32 +0,0 @@
from textual.app import App, ComposeResult
from textual.widget import Widget
from textual import layout
from rich.text import Text
lorem = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
TEXT = Text.from_markup(lorem)
class TextWidget(Widget):
def render(self):
return TEXT
class AutoApp(App, css_path="nest.css"):
def on_mount(self) -> None:
self.bind("t", "tree")
def compose(self) -> ComposeResult:
yield layout.Vertical(
Widget(
TextWidget(classes="test"),
id="container",
),
)
def action_tree(self):
self.log(self.screen.tree)

View File

@@ -1,72 +0,0 @@
from rich.console import RenderableType
from rich.text import Text
from textual.app import App, ComposeResult
from textual.widget import Widget
from textual.widgets import Placeholder
placeholders_count = 12
class VerticalContainer(Widget):
DEFAULT_CSS = """
VerticalContainer {
layout: vertical;
overflow: hidden auto;
background: darkblue;
}
VerticalContainer Placeholder {
margin: 1 0;
height: 5;
border: solid lime;
align: center top;
}
"""
class Introduction(Widget):
DEFAULT_CSS = """
Introduction {
background: indigo;
color: white;
height: 3;
padding: 1 0;
}
"""
def render(self) -> RenderableType:
return Text(
"Press keys 0 to 9 to scroll to the Placeholder with that ID.",
justify="center",
)
class MyTestApp(App):
def compose(self) -> ComposeResult:
placeholders = [
Placeholder(id=f"placeholder_{i}", name=f"Placeholder #{i}")
for i in range(placeholders_count)
]
yield VerticalContainer(Introduction(), *placeholders, id="root")
def on_mount(self):
self.bind("q", "quit")
self.bind("t", "tree")
for widget_index in range(placeholders_count):
self.bind(str(widget_index), f"scroll_to('placeholder_{widget_index}')")
def action_tree(self):
self.log(self.tree)
async def action_scroll_to(self, target_placeholder_id: str):
target_placeholder = self.query(f"#{target_placeholder_id}").first()
target_placeholder_container = self.query("#root").first()
target_placeholder_container.scroll_to_widget(target_placeholder, animate=True)
app = MyTestApp()
if __name__ == "__main__":
app.run()

View File

@@ -1,3 +0,0 @@
from textual.app import App
app = App()

View File

@@ -1,28 +0,0 @@
App.-show-focus *:focus {
tint: #8bc34a 20%;
}
#uber1 {
layout: vertical;
background: green;
overflow: hidden auto;
border: heavy white;
text-style: underline;
/* box-sizing: content-box; */
}
#uber1:focus-within {
background: darkslateblue;
}
#child2 {
text-style: underline;
background: red 10%;
}
.list-item {
height: 10;
/* display: none; */
color: #12a0;
background: #ffffff00;
}

View File

@@ -1,83 +0,0 @@
import random
import sys
from textual import events
from textual.app import App
from textual.widget import Widget
from textual.widgets import Placeholder
class BasicApp(App):
"""Sandbox application used for testing/development by Textual developers"""
def on_load(self):
self.bind("q", "quit", "Quit")
self.bind("d", "dump")
self.bind("t", "log_tree")
self.bind("p", "print")
self.bind("v", "toggle_visibility")
self.bind("x", "toggle_display")
self.bind("f", "modify_focussed")
self.bind("b", "toggle_border")
async def on_mount(self):
"""Build layout here."""
first_child = Placeholder(id="child1", classes="list-item")
uber1 = Widget(
first_child,
Placeholder(id="child2", classes="list-item"),
Placeholder(id="child3", classes="list-item"),
Placeholder(classes="list-item"),
Placeholder(classes="list-item"),
Placeholder(classes="list-item"),
)
self.mount(uber1=uber1)
uber1.focus()
self.first_child = first_child
self.uber = uber1
async def on_key(self, event: events.Key) -> None:
await self.dispatch_key(event)
def action_quit(self):
self.panic(self.app.tree)
def action_dump(self):
self.panic(str(self.app._registry))
def action_log_tree(self):
self.log(self.screen.tree)
def action_print(self):
print(
"Focused widget is:",
self.focused,
)
self.app.set_focus(None)
def action_modify_focussed(self):
"""Increment height of focussed child, randomise border and bg color"""
previous_height = self.focused.styles.height.value
new_height = previous_height + 1
self.focused.styles.height = self.focused.styles.height.copy_with(
value=new_height
)
color = random.choice(["red", "green", "blue"])
self.focused.styles.background = color
self.focused.styles.border = ("dashed", color)
def action_toggle_visibility(self):
self.focused.visible = not self.focused.visible
def action_toggle_display(self):
# TODO: Doesn't work
self.focused.display = not self.focused.display
def action_toggle_border(self):
self.focused.styles.border_top = ("solid", "invalid-color")
app = BasicApp(css_path="uber.css")
if __name__ == "__main__":
app.run()

View File

@@ -1,22 +0,0 @@
Screen {
background:blue;
}
Vertical {
background: red 50%;
overflow: auto;
/* width: auto */
}
.test {
/* width: auto; */
/* height: 50vh; */
background: white 50%;
border:solid green;
padding: 0;
margin:3;
align: center middle;
box-sizing: border-box;
}

View File

@@ -1,29 +0,0 @@
from textual.app import App, ComposeResult
from textual.widgets import Static
from textual import layout
from rich.text import Text
TEXT = Text.from_markup(" ".join(str(n) * 5 for n in range(10)))
class AutoApp(App):
def on_mount(self) -> None:
self.bind("t", "tree")
def compose(self) -> ComposeResult:
yield layout.Horizontal(
layout.Vertical(
Static(TEXT, classes="test"),
Static(TEXT, id="test", classes="test"),
)
)
def action_tree(self):
self.log(self.screen.tree)
app = AutoApp(css_path="vertical.css")
if __name__ == "__main__":
app.run()

View File

@@ -1,94 +0,0 @@
from rich.console import RenderableType
from rich.text import Text
from textual.app import App, ComposeResult
from textual.widget import Widget
from textual.widgets import Placeholder
root_container_style = "border: solid white;"
initial_placeholders_count = 4
class VerticalContainer(Widget):
DEFAULT_CSS = """
VerticalContainer {
layout: vertical;
overflow: hidden auto;
background: darkblue;
${root_container_style}
}
VerticalContainer Placeholder {
margin: 1 0;
height: 5;
border: solid lime;
align: center top;
}
""".replace(
"${root_container_style}", root_container_style
)
class Introduction(Widget):
DEFAULT_CSS = """
Introduction {
background: indigo;
color: white;
height: 3;
padding: 1 0;
}
"""
def render(self, styles) -> RenderableType:
return Text(
"Press '-' and '+' to add or remove placeholders.", justify="center"
)
class MyTestApp(App):
def compose(self) -> ComposeResult:
# yield Introduction()
placeholders = [
Placeholder(id=f"placeholder_{i}", name=f"Placeholder #{i}")
for i in range(initial_placeholders_count)
]
yield VerticalContainer(Introduction(), *placeholders, id="root")
def on_mount(self):
self.bind("q", "quit")
self.bind("t", "tree")
self.bind("-", "remove_placeholder")
self.bind("+", "add_placeholder")
def action_tree(self):
self.log(self.tree)
async def action_remove_placeholder(self):
placeholders = self.query("Placeholder")
placeholders_count = len(placeholders)
for i, placeholder in enumerate(placeholders):
if i == placeholders_count - 1:
await self.remove(placeholder)
placeholder.parent.children._nodes.remove(placeholder)
self.refresh(repaint=True, layout=True)
self.refresh_css()
async def action_add_placeholder(self):
placeholders = self.query("Placeholder")
placeholders_count = len(placeholders)
placeholder = Placeholder(
id=f"placeholder_{placeholders_count}",
name=f"Placeholder #{placeholders_count}",
)
root = self.get_child("root")
root.mount(placeholder)
self.refresh(repaint=True, layout=True)
self.refresh_css()
app = MyTestApp()
if __name__ == "__main__":
app.run()

View File

@@ -98,7 +98,7 @@ def arrange(
) )
dock_spacing = Spacing(top, right, bottom, left) dock_spacing = Spacing(top, right, bottom, left)
region = size.region.shrink(dock_spacing) region = region.shrink(dock_spacing)
layout_placements, arranged_layout_widgets = widget._layout.arrange( layout_placements, arranged_layout_widgets = widget._layout.arrange(
widget, layout_widgets, region.size widget, layout_widgets, region.size
) )

View File

@@ -511,45 +511,6 @@ class SpacingProperty:
obj.refresh(layout=True) obj.refresh(layout=True)
class DocksProperty:
"""Descriptor for getting and setting the docks property. This property
is used to define docks and their location on screen.
"""
def __get__(
self, obj: StylesBase, objtype: type[StylesBase] | None = None
) -> tuple[DockGroup, ...]:
"""Get the Docks property
Args:
obj (Styles): The ``Styles`` object.
objtype (type[Styles]): The ``Styles`` class.
Returns:
tuple[DockGroup, ...]: A ``tuple`` containing the defined docks.
"""
if obj.has_rule("docks"):
return obj.get_rule("docks")
from .styles import DockGroup
return (DockGroup("_default", "top", 1),)
def __set__(self, obj: StylesBase, docks: Iterable[DockGroup] | None):
"""Set the Docks property
Args:
obj (Styles): The ``Styles`` object.
docks (Iterable[DockGroup]): Iterable of DockGroups
"""
_rich_traceback_omit = True
if docks is None:
if obj.clear_rule("docks"):
obj.refresh(layout=True)
else:
if obj.set_rule("docks", tuple(docks)):
obj.refresh(layout=True)
class DockProperty: class DockProperty:
"""Descriptor for getting and setting the dock property. The dock property """Descriptor for getting and setting the dock property. The dock property
allows you to specify which edge you want to fix a Widget to. allows you to specify which edge you want to fix a Widget to.

View File

@@ -21,7 +21,6 @@ from ._style_properties import (
BoxProperty, BoxProperty,
ColorProperty, ColorProperty,
DockProperty, DockProperty,
DocksProperty,
FractionalProperty, FractionalProperty,
IntegerProperty, IntegerProperty,
LayoutProperty, LayoutProperty,
@@ -115,7 +114,6 @@ class RulesMap(TypedDict, total=False):
max_height: Scalar max_height: Scalar
dock: str dock: str
docks: tuple[DockGroup, ...]
overflow_x: Overflow overflow_x: Overflow
overflow_y: Overflow overflow_y: Overflow
@@ -238,7 +236,6 @@ class StylesBase(ABC):
max_height = ScalarProperty(percent_unit=Unit.HEIGHT, allow_auto=False) max_height = ScalarProperty(percent_unit=Unit.HEIGHT, allow_auto=False)
dock = DockProperty() dock = DockProperty()
docks = DocksProperty()
overflow_x = StringEnumProperty(VALID_OVERFLOW, "hidden") overflow_x = StringEnumProperty(VALID_OVERFLOW, "hidden")
overflow_y = StringEnumProperty(VALID_OVERFLOW, "hidden") overflow_y = StringEnumProperty(VALID_OVERFLOW, "hidden")
@@ -722,14 +719,6 @@ class Styles(StylesBase):
append_declaration("offset", f"{x} {y}") append_declaration("offset", f"{x} {y}")
if has_rule("dock"): if has_rule("dock"):
append_declaration("dock", rules["dock"]) append_declaration("dock", rules["dock"])
if has_rule("docks"):
append_declaration(
"docks",
" ".join(
(f"{name}={edge}/{z}" if z else f"{name}={edge}")
for name, edge, z in rules["docks"]
),
)
if has_rule("layers"): if has_rule("layers"):
append_declaration("layers", " ".join(self.layers)) append_declaration("layers", " ".join(self.layers))
if has_rule("layer"): if has_rule("layer"):
@@ -946,7 +935,6 @@ if __name__ == "__main__":
styles.visibility = "hidden" styles.visibility = "hidden"
styles.border = ("solid", "rgb(10,20,30)") styles.border = ("solid", "rgb(10,20,30)")
styles.outline_right = ("solid", "red") styles.outline_right = ("solid", "red")
styles.docks = "foo bar"
styles.text_style = "italic" styles.text_style = "italic"
styles.dock = "bar" styles.dock = "bar"
styles.layers = "foo bar" styles.layers = "foo bar"

View File

@@ -504,99 +504,3 @@ class Stylesheet:
apply(node.horizontal_scrollbar) apply(node.horizontal_scrollbar)
if node.show_horizontal_scrollbar and node.show_vertical_scrollbar: if node.show_horizontal_scrollbar and node.show_vertical_scrollbar:
apply(node.scrollbar_corner) apply(node.scrollbar_corner)
if __name__ == "__main__":
from rich.traceback import install
install(show_locals=True)
class Widget(DOMNode):
pass
class View(DOMNode):
pass
class App(DOMNode):
pass
app = App()
main_view = View(id="main")
help_view = View(id="help")
app._add_child(main_view)
app._add_child(help_view)
widget1 = Widget(id="widget1")
widget2 = Widget(id="widget2")
sidebar = Widget(id="sidebar")
sidebar.add_class("float")
helpbar = Widget(id="helpbar")
helpbar.add_class("float")
main_view._add_child(widget1)
main_view._add_child(widget2)
main_view._add_child(sidebar)
sub_view = View(id="sub")
sub_view.add_class("-subview")
main_view._add_child(sub_view)
tooltip = Widget(id="tooltip")
tooltip.add_class("float", "transient")
sub_view._add_child(tooltip)
help = Widget(id="markdown")
help_view._add_child(help)
help_view._add_child(helpbar)
from rich import print
print(app.tree)
print()
DEFAULT_CSS = """
App > View {
layout: dock;
docks: sidebar=left | widgets=top;
}
#sidebar {
dock-group: sidebar;
}
#widget1 {
text: on blue;
dock-group: widgets;
}
#widget2 {
text: on red;
dock-group: widgets;
}
"""
stylesheet = Stylesheet()
stylesheet.add_source(CSS)
print(stylesheet.css)
# print(stylesheet.error_renderable)
# print(widget1.styles)
# stylesheet.apply(widget1)
# print(widget1.styles)
# print(stylesheet.css)
# from .query import DOMQuery
# tests = ["View", "App > View", "Widget.float", ".float.transient", "*"]
# for test in tests:
# print("")
# print(f"[b]{test}")
# print(app.query(test))