border improvement

This commit is contained in:
Will McGugan
2022-09-13 14:27:29 +01:00
parent fc414a0b10
commit 45d1e1c7e1
7 changed files with 115 additions and 24 deletions

21
offset.css Normal file
View File

@@ -0,0 +1,21 @@
Screen {
layout: center;
}
#parent {
width: 32;
height: 8;
background: $panel;
}
#tag {
color: $text;
background: $success;
padding: 1 2;
width: auto;
/* offset: -8 -4; */
}
#child {
background: red;
}

17
offset.py Normal file
View File

@@ -0,0 +1,17 @@
from textual import layout
from textual.app import App, ComposeResult
from textual.widgets import Static
class OffsetExample(App):
def compose(self) -> ComposeResult:
yield layout.Vertical(
Static("Child", id="child"),
id="parent"
)
yield Static("Tag", id="tag")
app = OffsetExample(css_path="offset.css")
if __name__ == "__main__":
app.run()

21
sandbox/will/offset.css Normal file
View File

@@ -0,0 +1,21 @@
Screen {
layout: center;
}
#parent {
width: 32;
height: 8;
background: $panel;
}
#tag {
color: $text;
background: $success;
padding: 2 4;
width: auto;
offset: -8 -4;
}
#child {
background: red;
}

17
sandbox/will/offset.py Normal file
View File

@@ -0,0 +1,17 @@
from textual import layout
from textual.app import App, ComposeResult
from textual.widgets import Static
class OffsetExample(App):
def compose(self) -> ComposeResult:
yield layout.Vertical(
Static("Child", id="child"),
id="parent"
)
yield Static("Tag", id="tag")
app = OffsetExample(css_path="offset.css")
if __name__ == "__main__":
app.run()

View File

@@ -39,8 +39,8 @@ BORDER_CHARS: dict[EdgeType, tuple[str, str, str]] = {
"outer": ("▛▀▜", "▌ ▐", "▙▄▟"), "outer": ("▛▀▜", "▌ ▐", "▙▄▟"),
"hkey": ("▔▔▔", " ", "▁▁▁"), "hkey": ("▔▔▔", " ", "▁▁▁"),
"vkey": ("▏ ▕", "▏ ▕", "▏ ▕"), "vkey": ("▏ ▕", "▏ ▕", "▏ ▕"),
"tall": ("▕▔▏", "▕ ▏", "▕▁▏"), "tall": ("▊▔▎", "▊ ▎", "▊▁▎"),
"wide": ("▁▁▁", "▏ ▕", "▔▔▔"), "wide": ("▁▁▁", "▎ ▋", "▔▔▔"),
} }
# Some of the borders are on the widget background and some are on the background of the parent # Some of the borders are on the widget background and some are on the background of the parent
@@ -62,8 +62,8 @@ BORDER_LOCATIONS: dict[
"outer": ((0, 0, 0), (0, 0, 0), (0, 0, 0)), "outer": ((0, 0, 0), (0, 0, 0), (0, 0, 0)),
"hkey": ((0, 0, 0), (0, 0, 0), (0, 0, 0)), "hkey": ((0, 0, 0), (0, 0, 0), (0, 0, 0)),
"vkey": ((0, 0, 0), (0, 0, 0), (0, 0, 0)), "vkey": ((0, 0, 0), (0, 0, 0), (0, 0, 0)),
"tall": ((1, 0, 1), (1, 0, 1), (1, 0, 1)), "tall": ((2, 0, 1), (2, 0, 1), (2, 0, 1)),
"wide": ((1, 1, 1), (0, 1, 0), (1, 1, 1)), "wide": ((1, 1, 1), (3, 1, 4), (1, 1, 1)),
} }
INVISIBLE_EDGE_TYPES = cast("frozenset[EdgeType]", frozenset(("", "none", "hidden"))) INVISIBLE_EDGE_TYPES = cast("frozenset[EdgeType]", frozenset(("", "none", "hidden")))
@@ -81,7 +81,10 @@ Borders: TypeAlias = Tuple[EdgeStyle, EdgeStyle, EdgeStyle, EdgeStyle]
@lru_cache(maxsize=1024) @lru_cache(maxsize=1024)
def get_box( def get_box(
name: EdgeType, inner_style: Style, outer_style: Style, style: Style name: EdgeType,
inner_style: Style,
outer_style: Style,
style: Style,
) -> BoxSegments: ) -> BoxSegments:
"""Get segments used to render a box. """Get segments used to render a box.
@@ -107,23 +110,29 @@ def get_box(
(lbottom1, lbottom2, lbottom3), (lbottom1, lbottom2, lbottom3),
) = BORDER_LOCATIONS[name] ) = BORDER_LOCATIONS[name]
styles = (inner_style, outer_style) styles: tuple[Style, ...] = (inner_style + style, outer_style + style)
styles += (
Style.from_color(styles[1].bgcolor, styles[0].color),
Style.from_color(styles[0].color, styles[0].bgcolor),
Style.from_color(styles[0].bgcolor, styles[1].color),
)
return ( return (
( (
_Segment(top1, styles[ltop1] + style), _Segment(top1, styles[ltop1]),
_Segment(top2, styles[ltop2] + style), _Segment(top2, styles[ltop2]),
_Segment(top3, styles[ltop3] + style), _Segment(top3, styles[ltop3]),
), ),
( (
_Segment(mid1, styles[lmid1] + style), _Segment(mid1, styles[lmid1]),
_Segment(mid2, styles[lmid2] + style), _Segment(mid2, styles[lmid2]),
_Segment(mid3, styles[lmid3] + style), _Segment(mid3, styles[lmid3]),
), ),
( (
_Segment(bottom1, styles[lbottom1] + style), _Segment(bottom1, styles[lbottom1]),
_Segment(bottom2, styles[lbottom2] + style), _Segment(bottom2, styles[lbottom2]),
_Segment(bottom3, styles[lbottom3] + style), _Segment(bottom3, styles[lbottom3]),
), ),
) )

View File

@@ -14,7 +14,7 @@ without having to render the entire screen.
from __future__ import annotations from __future__ import annotations
from itertools import chain from itertools import chain
from operator import attrgetter, itemgetter from operator import itemgetter
import sys import sys
from typing import Callable, cast, Iterator, Iterable, NamedTuple, TYPE_CHECKING from typing import Callable, cast, Iterator, Iterable, NamedTuple, TYPE_CHECKING
@@ -26,7 +26,7 @@ from rich.segment import Segment
from rich.style import Style from rich.style import Style
from . import errors from . import errors
from .geometry import Region, Offset, Size, Spacing from .geometry import Region, Offset, Size
from ._cells import cell_len from ._cells import cell_len
from ._profile import timer from ._profile import timer
@@ -55,7 +55,7 @@ class MapGeometry(NamedTuple):
"""Defines the absolute location of a Widget.""" """Defines the absolute location of a Widget."""
region: Region # The (screen) region occupied by the widget region: Region # The (screen) region occupied by the widget
order: tuple[int, ...] # A tuple of ints defining the painting order order: tuple[tuple[int, ...], ...] # A tuple of ints defining the painting order
clip: Region # A region to clip the widget by (if a Widget is within a container) clip: Region # A region to clip the widget by (if a Widget is within a container)
virtual_size: Size # The virtual size (scrollable region) of a widget if it is a container virtual_size: Size # The virtual size (scrollable region) of a widget if it is a container
container_size: Size # The container size (area not occupied by scrollbars) container_size: Size # The container size (area not occupied by scrollbars)
@@ -344,12 +344,14 @@ class Compositor:
map: CompositorMap = {} map: CompositorMap = {}
widgets: set[Widget] = set() widgets: set[Widget] = set()
layer_order: int = 0
def add_widget( def add_widget(
widget: Widget, widget: Widget,
virtual_region: Region, virtual_region: Region,
region: Region, region: Region,
order: tuple[int, ...], order: tuple[tuple[int, ...], ...],
layer_order: int,
clip: Region, clip: Region,
) -> None: ) -> None:
"""Called recursively to place a widget and its children in the map. """Called recursively to place a widget and its children in the map.
@@ -413,15 +415,19 @@ class Compositor:
) )
widget_region = sub_region + placement_scroll_offset widget_region = sub_region + placement_scroll_offset
widget_order = order + (get_layer_index(sub_widget.layer, 0), z) widget_order = order + (
(get_layer_index(sub_widget.layer, 0), z, layer_order),
)
add_widget( add_widget(
sub_widget, sub_widget,
sub_region, sub_region,
widget_region, widget_region,
widget_order, widget_order,
layer_order,
sub_clip, sub_clip,
) )
layer_order -= 1
# Add any scrollbars # Add any scrollbars
for chrome_widget, chrome_region in widget._arrange_scrollbars( for chrome_widget, chrome_region in widget._arrange_scrollbars(
@@ -457,7 +463,7 @@ class Compositor:
) )
# Add top level (root) widget # Add top level (root) widget
add_widget(root, size.region, size.region, (0,), size.region) add_widget(root, size.region, size.region, ((0,),), layer_order, size.region)
return map, widgets return map, widgets
@property @property

View File

@@ -124,13 +124,13 @@ class ColorSystem:
background = self.background or Color.parse(DEFAULT_LIGHT_BACKGROUND) background = self.background or Color.parse(DEFAULT_LIGHT_BACKGROUND)
surface = self.surface or Color.parse(DEFAULT_LIGHT_SURFACE) surface = self.surface or Color.parse(DEFAULT_LIGHT_SURFACE)
boost = self.boost or background.get_contrast_text(1.0).with_alpha(0.07)
if self.panel is None: if self.panel is None:
panel = surface.blend(primary, luminosity_spread) panel = surface.blend(primary, luminosity_spread) + boost
else: else:
panel = self.panel panel = self.panel
boost = self.boost or background.get_contrast_text(1.0).with_alpha(0.07)
colors: dict[str, str] = {} colors: dict[str, str] = {}
def luminosity_range(spread) -> Iterable[tuple[str, float]]: def luminosity_range(spread) -> Iterable[tuple[str, float]]: