fix basic

This commit is contained in:
Will McGugan
2022-07-27 15:18:19 +01:00
parent 06bc566fec
commit 4f69516d8d
5 changed files with 4 additions and 216 deletions

View File

@@ -632,30 +632,6 @@ class StylesBuilder:
dock = tokens[0].value
self.styles._rules["dock"] = dock
def process_docks(self, name: str, tokens: list[Token]) -> None:
def docks_error(name, token):
self.error(name, token, docks_property_help_text(name, context="css"))
docks: list[DockGroup] = []
for token in tokens:
if token.name == "key_value":
key, edge_name = token.value.split("=")
edge_name = edge_name.strip().lower()
edge_name, _, number = edge_name.partition("/")
z = 0
if number:
if not number.isdigit():
docks_error(name, token)
z = int(number)
if edge_name not in VALID_EDGE:
docks_error(name, token)
docks.append(DockGroup(key.strip(), cast(Edge, edge_name), z))
elif token.name == "bar":
pass
else:
docks_error(name, token)
self.styles._rules["docks"] = tuple(docks + [DockGroup("_default", "top", 0)])
def process_layer(self, name: str, tokens: list[Token]) -> None:
if len(tokens) > 1:
self.error(name, tokens[1], f"unexpected tokens in dock-edge declaration")

View File

@@ -32,7 +32,7 @@ VALID_BORDER: Final[set[EdgeType]] = {
"wide",
}
VALID_EDGE: Final = {"top", "right", "bottom", "left"}
VALID_LAYOUT: Final = {"dock", "vertical", "horizontal"}
VALID_LAYOUT: Final = {"vertical", "horizontal"}
VALID_BOX_SIZING: Final = {"border-box", "content-box"}
VALID_OVERFLOW: Final = {"scroll", "hidden", "auto"}

View File

@@ -304,8 +304,6 @@ class Stylesheet:
animate (bool, optional): Animate changed rules. Defaults to ``False``.
"""
print(node)
# Dictionary of rule attribute names e.g. "text_background" to list of tuples.
# The tuples contain the rule specificity, and the value for that rule.
# We can use this to determine, for a given rule, whether we should apply it

View File

@@ -1,186 +0,0 @@
from __future__ import annotations
import sys
from collections import defaultdict
from dataclasses import dataclass
from operator import attrgetter
from typing import TYPE_CHECKING, NamedTuple, Sequence
from .._layout_resolve import layout_resolve
from ..css.types import Edge
from ..geometry import Region, Size
from .._layout import ArrangeResult, Layout, WidgetPlacement
from ..widget import Widget
if sys.version_info >= (3, 8):
from typing import Literal
else:
from typing_extensions import Literal
if TYPE_CHECKING:
from ..screen import Screen
DockEdge = Literal["top", "right", "bottom", "left"]
@dataclass
class DockOptions:
size: int | None = None
fraction: int | None = 1
min_size: int = 1
def __post_init__(self) -> None:
if self.size is None and self.fraction is None:
self.fraction = 1
class Dock(NamedTuple):
edge: Edge
widgets: Sequence[Widget]
z: int = 0
class DockLayout(Layout):
"""Dock Widgets to edge of screen."""
name = "dock"
def __init__(self) -> None:
super().__init__()
self._docks: list[Dock] | None = None
def __repr__(self):
return "<DockLayout>"
def get_docks(self, parent: Widget, children: list[Widget]) -> list[Dock]:
groups: dict[str, list[Widget]] = defaultdict(list)
for child in children:
assert isinstance(child, Widget)
groups[child.styles.dock].append(child)
docks: list[Dock] = []
append_dock = docks.append
for name, edge, z in parent.styles.docks:
append_dock(Dock(edge, groups[name], z))
return docks
def arrange(
self, parent: Widget, children: list[Widget], size: Size
) -> ArrangeResult:
width, height = size
layout_region = Region(0, 0, width, height)
layers: dict[int, Region] = defaultdict(lambda: layout_region)
docks = self.get_docks(parent, children)
def make_dock_options(widget: Widget, edge: Edge) -> DockOptions:
styles = widget.styles
has_rule = styles.has_rule
# TODO: This was written pre resolve_dimension, we should update this to use available units
return (
DockOptions(
styles.width.cells if has_rule("width") else None,
styles.width.fraction if has_rule("width") else 1,
styles.min_width.cells if has_rule("min_width") else 1,
)
if edge in ("left", "right")
else DockOptions(
styles.height.cells if has_rule("height") else None,
styles.height.fraction if has_rule("height") else 1,
styles.min_height.cells if has_rule("min_height") else 1,
)
)
placements: list[WidgetPlacement] = []
add_placement = placements.append
arranged_widgets: set[Widget] = set()
for z, (edge, widgets, _z) in enumerate(sorted(docks, key=attrgetter("z"))):
arranged_widgets.update(widgets)
dock_options = [make_dock_options(widget, edge) for widget in widgets]
region = layers[z]
if not region.area:
# No space left
continue
x, y, width, height = region
if edge == "top":
sizes = layout_resolve(height, dock_options)
render_y = y
remaining = region.height
total = 0
for widget, new_size in zip(widgets, sizes):
new_size = min(remaining, new_size)
if not new_size:
break
total += new_size
add_placement(
WidgetPlacement(Region(x, render_y, width, new_size), widget, z)
)
render_y += new_size
remaining = max(0, remaining - new_size)
region = Region(x, y + total, width, height - total)
elif edge == "bottom":
sizes = layout_resolve(height, dock_options)
render_y = y + height
remaining = region.height
total = 0
for widget, new_size in zip(widgets, sizes):
new_size = min(remaining, new_size)
if not new_size:
break
total += new_size
add_placement(
WidgetPlacement(
Region(x, render_y - new_size, width, new_size), widget, z
)
)
render_y -= new_size
remaining = max(0, remaining - new_size)
region = Region(x, y, width, height - total)
elif edge == "left":
sizes = layout_resolve(width, dock_options)
render_x = x
remaining = region.width
total = 0
for widget, new_size in zip(widgets, sizes):
new_size = min(remaining, new_size)
if not new_size:
break
total += new_size
add_placement(
WidgetPlacement(
Region(render_x, y, new_size, height), widget, z
)
)
render_x += new_size
remaining = max(0, remaining - new_size)
region = Region(x + total, y, width - total, height)
elif edge == "right":
sizes = layout_resolve(width, dock_options)
render_x = x + width
remaining = region.width
total = 0
for widget, new_size in zip(widgets, sizes):
new_size = min(remaining, new_size)
if not new_size:
break
total += new_size
add_placement(
WidgetPlacement(
Region(render_x - new_size, y, new_size, height), widget, z
)
)
render_x -= new_size
remaining = max(0, remaining - new_size)
region = Region(x, y, width - total, height)
layers[z] = region
return ArrangeResult(placements, arranged_widgets)

View File

@@ -1,12 +1,12 @@
import pytest
from textual.layouts.dock import DockLayout
from textual.layouts.vertical import VerticalLayout
from textual.layouts.factory import get_layout, MissingLayout
def test_get_layout_valid_layout():
layout = get_layout("dock")
assert type(layout) is DockLayout
layout = get_layout("vertical")
assert type(layout) is VerticalLayout
def test_get_layout_invalid_layout():