This commit is contained in:
Will McGugan
2022-04-14 16:55:58 +01:00
parent 8e76e524a8
commit cecbf655ab
11 changed files with 84 additions and 33 deletions

View File

@@ -1,19 +1,39 @@
Screen {
layout: horizontal;
}
Widget#thing {
Widget {
margin:1;
}
#thing {
width: 20;
height: 10;
align: center middle;
background:magenta;
margin: 1;
padding: 1;
/* border: solid white; */
align-vertical: middle;
}
Widget#thing2 {
width: 30;
height: 8;
align: center middle;
background: green;
}
#thing2 {
width: 20;
height: 10;
background:green;
align-vertical: middle;
}
#thing3 {
width: 20;
height: 10;
background:blue;
align-vertical: bottom;
}

View File

@@ -1,14 +1,21 @@
from rich.text import Text
from textual.app import App
from textual.widget import Widget
class Thing(Widget):
def render(self):
return Text.from_markup("Hello, World. [b magenta]Lorem impsum.")
class AlignApp(App):
def on_load(self):
self.bind("t", "log_tree")
def on_mount(self) -> None:
self.log("MOUNTED")
self.mount(thing=Widget(), thing2=Widget())
self.mount(thing=Thing(), thing2=Widget(), thing3=Widget())
def action_log_tree(self):
self.log(self.screen.tree)

View File

@@ -21,6 +21,7 @@ App > Screen {
color: $text-background;
}
#sidebar {
color: $text-primary;
background: $primary;
@@ -81,7 +82,8 @@ Tweet {
/* border: outer $primary; */
padding: 1;
border: wide $panel-darken-2;
overflow-y: scroll
overflow-y: scroll;
align-horizontal: center;
}
@@ -168,6 +170,7 @@ Error {
margin: 1 3;
text-style: bold;
align-horizontal: center;
}
Warning {
@@ -179,6 +182,7 @@ Warning {
border-bottom: hkey $warning-darken-2;
margin: 1 2;
text-style: bold;
align-horizontal: center;
}
Success {
@@ -190,4 +194,5 @@ Success {
border-bottom: hkey $success;
margin: 1 2;
text-style: bold;
align-horizontal: center;
}

View File

@@ -8,6 +8,7 @@ when setting and getting.
"""
from __future__ import annotations
from tkinter.tix import AUTO
from typing import Iterable, NamedTuple, TYPE_CHECKING, cast
@@ -47,10 +48,14 @@ class ScalarProperty:
"""Descriptor for getting and setting scalar properties. Scalars are numeric values with a unit, e.g. "50vh"."""
def __init__(
self, units: set[Unit] | None = None, percent_unit: Unit = Unit.WIDTH
self,
units: set[Unit] | None = None,
percent_unit: Unit = Unit.WIDTH,
allow_auto: bool = True,
) -> None:
self.units: set[Unit] = units or {*UNIT_SYMBOL}
self.percent_unit = percent_unit
self.allow_auto = allow_auto
super().__init__()
def __set_name__(self, owner: Styles, name: str) -> None:
@@ -90,7 +95,7 @@ class ScalarProperty:
if value is None:
obj.clear_rule(self.name)
return
if isinstance(value, float):
if isinstance(value, (int, float)):
new_value = Scalar(float(value), Unit.CELLS, Unit.WIDTH)
elif isinstance(value, Scalar):
new_value = value
@@ -101,12 +106,23 @@ class ScalarProperty:
raise StyleValueError("unable to parse scalar from {value!r}")
else:
raise StyleValueError("expected float, Scalar, or None")
if new_value is not None and new_value.unit not in self.units:
raise StyleValueError(
f"{self.name} units must be one of {friendly_list(get_symbols(self.units))}"
)
if new_value is not None and new_value.is_percent:
new_value = Scalar(float(new_value.value), self.percent_unit, Unit.WIDTH)
if (
new_value is not None
and new_value.unit == Unit.AUTO
and not self.allow_auto
):
raise StyleValueError("'auto' not allowed here")
if new_value.unit != Unit.AUTO:
if new_value is not None and new_value.unit not in self.units:
raise StyleValueError(
f"{self.name} units must be one of {friendly_list(get_symbols(self.units))}"
)
if new_value is not None and new_value.is_percent:
new_value = Scalar(
float(new_value.value), self.percent_unit, Unit.WIDTH
)
if obj.set_rule(self.name, new_value):
obj.refresh()

View File

@@ -625,7 +625,9 @@ class StylesBuilder:
self.styles._rules["align_vertical"] = token_vertical.value
def process_align_horizontal(self, name: str, tokens: list[Token]) -> None:
self._process_enum(name, tokens, VALID_ALIGN_HORIZONTAL)
value = self._process_enum(name, tokens, VALID_ALIGN_HORIZONTAL)
self.styles._rules["align_horizontal"] = value
def process_align_vertical(self, name: str, tokens: list[Token]) -> None:
self._process_enum(name, tokens, VALID_ALIGN_VERTICAL)
value = self._process_enum(name, tokens, VALID_ALIGN_VERTICAL)
self.styles._rules["align_vertical"] = value

View File

@@ -152,6 +152,7 @@ class Scalar(NamedTuple):
float: _description_
"""
value, unit, percent_unit = self
if unit == Unit.PERCENT:
unit = percent_unit
try:

View File

@@ -418,8 +418,8 @@ class StylesBase(ABC):
margin = self.margin
else: # border-box
if has_rule("padding"):
size -= self.padding.totals
# if has_rule("padding"):
# size -= self.padding.totals
if has_rule("border"):
size -= self.border.spacing.totals
if has_rule("margin"):
@@ -458,7 +458,7 @@ class StylesBase(ABC):
"""
offset_y = 0
align_vertical = self.align_vertical
if align_vertical != "left":
if align_vertical != "top":
if align_vertical == "middle":
offset_y = (parent_height - height) // 2
else:

View File

@@ -3,6 +3,7 @@ from __future__ import annotations
import sys
from collections import defaultdict
from dataclasses import dataclass
from operator import attrgetter
from typing import Iterable, TYPE_CHECKING, NamedTuple, Sequence
from .._layout_resolve import layout_resolve
@@ -91,7 +92,7 @@ class DockLayout(Layout):
add_placement = placements.append
arranged_widgets: set[Widget] = set()
for edge, widgets, z in docks:
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]

View File

@@ -29,7 +29,9 @@ class HorizontalLayout(Layout):
(content_width, content_height), margin = widget.styles.get_box_model(
size, parent_size
)
offset_y = styles.align_height(content_height, parent_size.height)
offset_y = styles.align_height(
content_height + margin.height, parent_size.height
)
region = Region(
margin.left + x, margin.top + offset_y, content_width, content_height
)

View File

@@ -31,7 +31,9 @@ class VerticalLayout(Layout):
(content_width, content_height), margin = styles.get_box_model(
size, parent_size
)
offset_x = styles.align_width(content_width, parent_size.width)
offset_x = styles.align_width(
content_width + margin.width, parent_size.width
)
region = Region(
margin.left + offset_x, y + margin.top, content_width, content_height

View File

@@ -6,7 +6,6 @@ from typing import (
Awaitable,
TYPE_CHECKING,
Callable,
ClassVar,
Iterable,
NamedTuple,
cast,
@@ -16,10 +15,9 @@ import rich.repr
from rich.align import Align
from rich.console import Console, RenderableType
from rich.padding import Padding
from rich.pretty import Pretty
from rich.style import Style
from rich.styled import Styled
from rich.text import Text
from . import errors, log
from . import events
@@ -394,10 +392,7 @@ class Widget(DOMNode):
if renderable_text_style:
renderable = Styled(renderable, renderable_text_style)
if styles.padding:
renderable = Padding(
renderable, styles.padding, style=renderable_text_style
)
renderable = Padding(renderable, styles.padding, style=renderable_text_style)
if styles.border:
renderable = Border(