mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
key lines
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
from textual.app import App
|
||||
from textual.widgets import Placeholder
|
||||
from textual.widget import Widget
|
||||
|
||||
|
||||
class BasicApp(App):
|
||||
@@ -9,35 +9,51 @@ class BasicApp(App):
|
||||
|
||||
App > DockView {
|
||||
layout: dock;
|
||||
docks: sidebar=left/1 widgets=top;
|
||||
docks: side=left/1 header=top footer=bottom;
|
||||
layers: base panels;
|
||||
}
|
||||
|
||||
#sidebar {
|
||||
dock-group: sidebar;
|
||||
width: 40;
|
||||
text: bold #09312e on #3CAEA3;
|
||||
/* dock-group: header; */
|
||||
width: 30;
|
||||
height: 1fr;
|
||||
layer: panels;
|
||||
border-right: vkey #09312e;
|
||||
}
|
||||
|
||||
#widget1 {
|
||||
text: on blue;
|
||||
dock-group: widgets;
|
||||
height: 1fr;
|
||||
#header {
|
||||
text: on #173f5f;
|
||||
dock-group: header;
|
||||
height: 3;
|
||||
border: hkey white;
|
||||
|
||||
}
|
||||
|
||||
#widget2 {
|
||||
text: on red;
|
||||
dock-group: widgets;
|
||||
height: 1fr;
|
||||
#footer {
|
||||
dock-group: header;
|
||||
height: 3;
|
||||
border-top: hkey #0f2b41;
|
||||
text: #3a3009 on #f6d55c;
|
||||
}
|
||||
|
||||
#content {
|
||||
dock-group: header;
|
||||
text: on #20639B;
|
||||
}
|
||||
|
||||
|
||||
"""
|
||||
|
||||
async def on_mount(self) -> None:
|
||||
"""Build layout here."""
|
||||
await self.view.mount(
|
||||
sidebar=Placeholder(), widget1=Placeholder(), widget2=Placeholder()
|
||||
header=Widget(),
|
||||
content=Widget(),
|
||||
footer=Widget(),
|
||||
sidebar=Widget(),
|
||||
)
|
||||
self.panic(self.view.styles)
|
||||
|
||||
|
||||
BasicApp.run(log="textual.log")
|
||||
|
||||
@@ -17,6 +17,8 @@ BORDER_STYLES: dict[str, tuple[str, str, str]] = {
|
||||
"heavy": ("┏━┓", "┃ ┃", "┗━┛"),
|
||||
"inner": ("▗▄▖", "▐ ▌", "▝▀▘"),
|
||||
"outer": ("▛▀▜", "▌ ▐", "▙▄▟"),
|
||||
"hkey": ("▔▔▔", " ", "▁▁▁"),
|
||||
"vkey": ("▏ ▕", "▏ ▕", "▏ ▕"),
|
||||
}
|
||||
|
||||
|
||||
@@ -98,9 +100,9 @@ class Border:
|
||||
render_options = options.update_dimensions(width, height)
|
||||
|
||||
lines = console.render_lines(self.renderable, render_options)
|
||||
if len(lines) <= 2:
|
||||
yield SegmentLines(lines, new_lines=True)
|
||||
return
|
||||
# if len(lines) <= 2:
|
||||
# yield SegmentLines(lines, new_lines=True)
|
||||
# return
|
||||
if self.outline:
|
||||
self._crop_renderable(lines, options.max_width)
|
||||
|
||||
|
||||
@@ -305,7 +305,6 @@ class App(DOMNode):
|
||||
self.stylesheet.read(self.css_file)
|
||||
if self.css is not None:
|
||||
self.stylesheet.parse(self.css, path=f"<{self.__class__.__name__}>")
|
||||
print(self.stylesheet.css)
|
||||
except StylesheetParseError as error:
|
||||
self.panic(error)
|
||||
self._print_error_renderables()
|
||||
@@ -322,16 +321,14 @@ class App(DOMNode):
|
||||
# Wait for the load event to be processed, so we don't go in to application mode beforehand
|
||||
await load_event.wait()
|
||||
|
||||
await self.post_message(events.Mount(sender=self))
|
||||
|
||||
view = DockView()
|
||||
await self.mount(self, view)
|
||||
await self.push_view(view)
|
||||
|
||||
driver = self._driver = self.driver_class(self.console, self)
|
||||
|
||||
driver.start_application_mode()
|
||||
|
||||
try:
|
||||
mount_event = events.Mount(sender=self)
|
||||
await self.dispatch_message(mount_event)
|
||||
await mount_event.wait()
|
||||
|
||||
self.title = self._title
|
||||
self.refresh()
|
||||
await self.animator.start()
|
||||
@@ -339,8 +336,6 @@ class App(DOMNode):
|
||||
log("PROCESS END")
|
||||
await self.animator.stop()
|
||||
await self.close_all()
|
||||
except Exception:
|
||||
self.panic()
|
||||
finally:
|
||||
driver.stop_application_mode()
|
||||
except:
|
||||
@@ -376,13 +371,20 @@ class App(DOMNode):
|
||||
name_widgets: Iterable[tuple[str | None, Widget]]
|
||||
name_widgets = [*((None, widget) for widget in anon_widgets), *widgets.items()]
|
||||
apply_stylesheet = self.stylesheet.apply
|
||||
widget_events = []
|
||||
for widget_id, widget in name_widgets:
|
||||
if widget not in self.registry:
|
||||
if widget_id is not None:
|
||||
widget.id = widget_id
|
||||
self._register(parent, widget)
|
||||
apply_stylesheet(widget)
|
||||
widget.post_message_no_wait(events.Mount(sender=parent))
|
||||
mount_event = events.Mount(sender=parent)
|
||||
widget_events.append((widget, mount_event))
|
||||
# await widget.post_message(mount_event)
|
||||
# await mount_event.wait()
|
||||
for widget, event in widget_events:
|
||||
widget.post_message_no_wait(event)
|
||||
# await event.wait()
|
||||
|
||||
def is_mounted(self, widget: Widget) -> bool:
|
||||
return widget in self.registry
|
||||
@@ -471,7 +473,13 @@ class App(DOMNode):
|
||||
async def on_event(self, event: events.Event) -> None:
|
||||
# Handle input events that haven't been forwarded
|
||||
# If the event has been forwaded it may have bubbled up back to the App
|
||||
if isinstance(event, events.InputEvent) and not event.is_forwarded:
|
||||
if isinstance(event, events.Mount):
|
||||
view = DockView()
|
||||
await self.mount(self, view)
|
||||
await self.push_view(view)
|
||||
await super().on_event(event)
|
||||
|
||||
elif isinstance(event, events.InputEvent) and not event.is_forwarded:
|
||||
if isinstance(event, events.MouseEvent):
|
||||
# Record current mouse position on App
|
||||
self.mouse_position = Offset(event.x, event.y)
|
||||
|
||||
@@ -6,7 +6,7 @@ import rich.repr
|
||||
from rich.color import Color
|
||||
from rich.style import Style
|
||||
|
||||
from .scalar import Scalar, ScalarParseError
|
||||
from .scalar import get_symbols, UNIT_SYMBOL, Unit, Scalar, ScalarParseError
|
||||
from ..geometry import Offset, Spacing, SpacingDimensions
|
||||
from .constants import NULL_SPACING, VALID_EDGE
|
||||
from .errors import StyleTypeError, StyleValueError
|
||||
@@ -14,15 +14,16 @@ from ._error_tools import friendly_list
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .styles import Styles
|
||||
from .styles import DockSpecification
|
||||
from .styles import DockGroup
|
||||
|
||||
|
||||
class ScalarProperty:
|
||||
def __init__(self, units: set[str]) -> None:
|
||||
self.units = units
|
||||
def __init__(self, units: set[Unit] | None = None) -> None:
|
||||
self.units: set[Unit] = units or {*UNIT_SYMBOL}
|
||||
super().__init__()
|
||||
|
||||
def __set_name__(self, owner: Styles, name: str) -> None:
|
||||
self.name = name
|
||||
self.internal_name = f"_rule_{name}"
|
||||
|
||||
def __get__(
|
||||
@@ -38,7 +39,7 @@ class ScalarProperty:
|
||||
if value is None:
|
||||
new_value = None
|
||||
elif isinstance(value, float):
|
||||
new_value = Scalar(value, "")
|
||||
new_value = Scalar(value, Unit.CELLS)
|
||||
elif isinstance(value, Scalar):
|
||||
new_value = value
|
||||
elif isinstance(value, str):
|
||||
@@ -49,7 +50,9 @@ class ScalarProperty:
|
||||
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"units must be one of {friendly_list(self.units)}")
|
||||
raise StyleValueError(
|
||||
f"{self.name} units must be one of {friendly_list(get_symbols(self.units))}"
|
||||
)
|
||||
setattr(obj, self.internal_name, new_value)
|
||||
return value
|
||||
|
||||
@@ -224,12 +227,12 @@ class SpacingProperty:
|
||||
class DocksProperty:
|
||||
def __get__(
|
||||
self, obj: Styles, objtype: type[Styles] | None = None
|
||||
) -> tuple[DockSpecification, ...]:
|
||||
) -> tuple[DockGroup, ...]:
|
||||
return obj._rule_docks or ()
|
||||
|
||||
def __set__(
|
||||
self, obj: Styles, docks: Iterable[DockSpecification] | None
|
||||
) -> Iterable[DockSpecification] | None:
|
||||
self, obj: Styles, docks: Iterable[DockGroup] | None
|
||||
) -> Iterable[DockGroup] | None:
|
||||
if docks is None:
|
||||
obj._rule_docks = None
|
||||
else:
|
||||
|
||||
@@ -12,7 +12,7 @@ from ._error_tools import friendly_list
|
||||
from ..geometry import Offset, Spacing, SpacingDimensions
|
||||
from .model import Declaration
|
||||
from .scalar import Scalar
|
||||
from .styles import DockSpecification, Styles
|
||||
from .styles import DockGroup, Styles
|
||||
from .types import Edge, Display, Visibility
|
||||
from .tokenize import Token
|
||||
|
||||
@@ -138,7 +138,7 @@ class StylesBuilder:
|
||||
style_tokens: list[str] = []
|
||||
append = style_tokens.append
|
||||
for token in tokens:
|
||||
_, _, location, token_name, value = token
|
||||
token_name, value, _, _, _ = token
|
||||
if token_name == "token":
|
||||
if value in VALID_BORDER:
|
||||
border_type = value
|
||||
@@ -157,7 +157,7 @@ class StylesBuilder:
|
||||
|
||||
def _process_border(self, edge: str, name: str, tokens: list[Token]) -> None:
|
||||
border = self._parse_border("border", tokens)
|
||||
setattr(self.styles, f"_border_{edge}", border)
|
||||
setattr(self.styles, f"_rule_border_{edge}", border)
|
||||
|
||||
def process_border(self, name: str, tokens: list[Token]) -> None:
|
||||
border = self._parse_border("border", tokens)
|
||||
@@ -179,7 +179,7 @@ class StylesBuilder:
|
||||
|
||||
def _process_outline(self, edge: str, name: str, tokens: list[Token]) -> None:
|
||||
border = self._parse_border("outline", tokens)
|
||||
setattr(self.styles, f"_outline_{edge}", border)
|
||||
setattr(self.styles, f"_rule_outline_{edge}", border)
|
||||
|
||||
def process_outline(self, name: str, tokens: list[Token]) -> None:
|
||||
border = self._parse_border("outline", tokens)
|
||||
@@ -289,7 +289,7 @@ class StylesBuilder:
|
||||
self.styles._rule_dock_group = tokens[0].value if tokens else ""
|
||||
|
||||
def process_docks(self, name: str, tokens: list[Token]) -> None:
|
||||
docks: list[DockSpecification] = []
|
||||
docks: list[DockGroup] = []
|
||||
for token in tokens:
|
||||
if token.name == "key_value":
|
||||
key, edge_name = token.value.split("=")
|
||||
@@ -308,7 +308,7 @@ class StylesBuilder:
|
||||
token,
|
||||
f"edge must be one of 'top', 'right', 'bottom', or 'left'; found {edge_name!r}",
|
||||
)
|
||||
docks.append(DockSpecification(key.strip(), cast(Edge, edge_name), z))
|
||||
docks.append(DockGroup(key.strip(), cast(Edge, edge_name), z))
|
||||
elif token.name == "bar":
|
||||
pass
|
||||
else:
|
||||
|
||||
@@ -10,13 +10,15 @@ from ..geometry import Spacing
|
||||
VALID_VISIBILITY: Final = {"visible", "hidden"}
|
||||
VALID_DISPLAY: Final = {"block", "none"}
|
||||
VALID_BORDER: Final = {
|
||||
"rounded",
|
||||
"none" "round",
|
||||
"solid",
|
||||
"double",
|
||||
"dashed",
|
||||
"heavy",
|
||||
"inner",
|
||||
"outer",
|
||||
"hkey",
|
||||
"vkey",
|
||||
}
|
||||
VALID_EDGE: Final = {"top", "right", "bottom", "left"}
|
||||
VALID_LAYOUT: Final = {"dock", "vertical", "grid"}
|
||||
|
||||
@@ -1,10 +1,46 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from enum import Enum, unique
|
||||
import re
|
||||
from typing import NamedTuple
|
||||
from typing import Iterable, NamedTuple
|
||||
|
||||
|
||||
_MATCH_SCALAR = re.compile(r"^(\d+\.?\d*)(fr|%)?$").match
|
||||
@unique
|
||||
class Unit(Enum):
|
||||
CELLS = 1
|
||||
FRACTION = 2
|
||||
PERCENT = 3
|
||||
WIDTH = 4
|
||||
HEIGHT = 5
|
||||
VIEW_WIDTH = 6
|
||||
VIEW_HEIGHT = 7
|
||||
|
||||
|
||||
UNIT_SYMBOL = {
|
||||
Unit.CELLS: "",
|
||||
Unit.FRACTION: "fr",
|
||||
Unit.PERCENT: "%",
|
||||
Unit.WIDTH: "w",
|
||||
Unit.HEIGHT: "h",
|
||||
Unit.VIEW_WIDTH: "vw",
|
||||
Unit.VIEW_HEIGHT: "vh",
|
||||
}
|
||||
|
||||
SYMBOL_UNIT = {v: k for k, v in UNIT_SYMBOL.items()}
|
||||
|
||||
_MATCH_SCALAR = re.compile(r"^(\d+\.?\d*)(fr|%|w|h|vw|vh)?$").match
|
||||
|
||||
|
||||
def get_symbols(units: Iterable[Unit]) -> list[str]:
|
||||
"""Get symbols for an iterable of units.
|
||||
|
||||
Args:
|
||||
units (Iterable[Unit]): A number of units.
|
||||
|
||||
Returns:
|
||||
list[str]: List of symbols.
|
||||
"""
|
||||
return [UNIT_SYMBOL[unit] for unit in units]
|
||||
|
||||
|
||||
class ScalarParseError(Exception):
|
||||
@@ -15,36 +51,25 @@ class Scalar(NamedTuple):
|
||||
"""A numeric value and a unit."""
|
||||
|
||||
value: float
|
||||
unit: str
|
||||
unit: Unit
|
||||
|
||||
def __str__(self) -> str:
|
||||
value, unit = self
|
||||
return f"{int(value) if value.is_integer() else value}{unit}"
|
||||
value, _unit = self
|
||||
return f"{int(value) if value.is_integer() else value}{self.symbol}"
|
||||
|
||||
@property
|
||||
def cells(self) -> int | None:
|
||||
value, unit = self
|
||||
if unit:
|
||||
return None
|
||||
else:
|
||||
return int(value)
|
||||
return int(value) if unit == Unit.CELLS else None
|
||||
|
||||
@property
|
||||
def fraction(self) -> int | None:
|
||||
value, unit = self
|
||||
if unit == "fr":
|
||||
return int(value)
|
||||
else:
|
||||
return None
|
||||
return int(value) if unit == Unit.FRACTION else None
|
||||
|
||||
def resolve_size(self, total: int, total_fraction: int) -> int:
|
||||
value, unit = self
|
||||
if unit == "":
|
||||
return int(value)
|
||||
elif unit == "%":
|
||||
return int(total * value / 100.0)
|
||||
else: # if unit == "fr":
|
||||
return int((value / total_fraction) * total)
|
||||
@property
|
||||
def symbol(self) -> str:
|
||||
return UNIT_SYMBOL[self.unit]
|
||||
|
||||
@classmethod
|
||||
def parse(cls, token: str) -> Scalar:
|
||||
@@ -62,11 +87,14 @@ class Scalar(NamedTuple):
|
||||
match = _MATCH_SCALAR(token)
|
||||
if match is None:
|
||||
raise ScalarParseError(f"{token!r} is not a valid scalar")
|
||||
value, unit = match.groups()
|
||||
scalar = cls(float(value), unit or "")
|
||||
value, unit_name = match.groups()
|
||||
scalar = cls(float(value), SYMBOL_UNIT[unit_name or ""])
|
||||
return scalar
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
print(Scalar.parse("3.14"))
|
||||
print(Scalar.parse("3.14fr"))
|
||||
s = Scalar.parse("23")
|
||||
print(repr(s))
|
||||
print(repr(s.cells))
|
||||
|
||||
@@ -43,7 +43,7 @@ else:
|
||||
from typing_extensions import Literal
|
||||
|
||||
|
||||
class DockSpecification(NamedTuple):
|
||||
class DockGroup(NamedTuple):
|
||||
name: str
|
||||
edge: Edge
|
||||
z: int
|
||||
@@ -83,7 +83,7 @@ class Styles:
|
||||
_rule_layout: str | None = None
|
||||
|
||||
_rule_dock_group: str | None = None
|
||||
_rule_docks: tuple[DockSpecification, ...] | None = None
|
||||
_rule_docks: tuple[DockGroup, ...] | None = None
|
||||
|
||||
_rule_layers: tuple[str, ...] | None = None
|
||||
_rule_layer: str | None = None
|
||||
@@ -115,10 +115,10 @@ class Styles:
|
||||
outline_bottom = BoxProperty()
|
||||
outline_left = BoxProperty()
|
||||
|
||||
width = ScalarProperty({"", "fr"})
|
||||
height = ScalarProperty({"", "fr"})
|
||||
min_width = ScalarProperty({"", "fr"})
|
||||
min_height = ScalarProperty({"", "fr"})
|
||||
width = ScalarProperty()
|
||||
height = ScalarProperty()
|
||||
min_width = ScalarProperty()
|
||||
min_height = ScalarProperty()
|
||||
|
||||
dock_group = DockGroupProperty()
|
||||
docks = DocksProperty()
|
||||
@@ -251,8 +251,8 @@ class Styles:
|
||||
append_declaration(
|
||||
"docks",
|
||||
" ".join(
|
||||
(f"{key}={value}/{z}" if z else f"{key}={value}")
|
||||
for key, value, z in self._rule_docks
|
||||
(f"{name}={edge}/{z}" if z else f"{name}={edge}")
|
||||
for name, edge, z in self._rule_docks
|
||||
),
|
||||
)
|
||||
if self._rule_layers is not None:
|
||||
|
||||
@@ -134,7 +134,6 @@ class Stylesheet:
|
||||
for name, specificity_rules in rule_attributes.items()
|
||||
]
|
||||
node.styles.apply_rules(node_rules)
|
||||
log(node, node_rules)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -46,7 +46,7 @@ expect_declaration_content = Expect(
|
||||
comment_start=r"\/\*",
|
||||
percentage=r"\d+\%",
|
||||
scalar=r"\d+\.?\d*(?:fr|%)?",
|
||||
color=r"\#[0-9a-f]{6}|color\([0-9]{1,3}\)|rgb\(\d{1,3}\,\s?\d{1,3}\,\s?\d{1,3}\)",
|
||||
color=r"\#[0-9a-fA-F]{6}|color\([0-9]{1,3}\)|rgb\(\d{1,3}\,\s?\d{1,3}\,\s?\d{1,3}\)",
|
||||
key_value=r"[a-zA-Z_-][a-zA-Z0-9_-]*=[0-9a-zA-Z_\-\/]+",
|
||||
token="[a-zA-Z_-]+",
|
||||
string=r"\".*?\"",
|
||||
|
||||
@@ -67,7 +67,6 @@ class DockLayout(Layout):
|
||||
self, view: View, size: Size, scroll: Offset
|
||||
) -> Iterable[WidgetPlacement]:
|
||||
|
||||
map: LayoutMap = LayoutMap(size)
|
||||
width, height = size
|
||||
layout_region = Region(0, 0, width, height)
|
||||
layers: dict[int, Region] = defaultdict(lambda: layout_region)
|
||||
@@ -170,5 +169,3 @@ class DockLayout(Layout):
|
||||
region = Region(x, y, width - total, height)
|
||||
|
||||
layers[z] = region
|
||||
|
||||
return map
|
||||
|
||||
@@ -52,6 +52,9 @@ class Message:
|
||||
cls.bubble = bubble
|
||||
cls.verbosity = verbosity
|
||||
|
||||
def set_done(self) -> None:
|
||||
self._done_event.set()
|
||||
|
||||
@property
|
||||
def _done_event(self) -> Event:
|
||||
if self.__done_event is None:
|
||||
|
||||
@@ -225,14 +225,11 @@ class MessagePump:
|
||||
|
||||
async def dispatch_message(self, message: Message) -> bool | None:
|
||||
_rich_traceback_guard = True
|
||||
try:
|
||||
if isinstance(message, events.Event):
|
||||
if not isinstance(message, events.Null):
|
||||
await self.on_event(message)
|
||||
else:
|
||||
return await self.on_message(message)
|
||||
finally:
|
||||
message._done_event.set()
|
||||
if isinstance(message, events.Event):
|
||||
if not isinstance(message, events.Null):
|
||||
await self.on_event(message)
|
||||
else:
|
||||
return await self.on_message(message)
|
||||
return False
|
||||
|
||||
def _get_dispatch_methods(
|
||||
@@ -248,9 +245,12 @@ class MessagePump:
|
||||
async def on_event(self, event: events.Event) -> None:
|
||||
_rich_traceback_guard = True
|
||||
|
||||
for method in self._get_dispatch_methods(f"on_{event.name}", event):
|
||||
log(event, ">>>", self, verbosity=event.verbosity)
|
||||
await invoke(method, event)
|
||||
try:
|
||||
for method in self._get_dispatch_methods(f"on_{event.name}", event):
|
||||
log(event, ">>>", self, verbosity=event.verbosity)
|
||||
await invoke(method, event)
|
||||
finally:
|
||||
event.set_done()
|
||||
|
||||
if event.bubble and self._parent and not event._stop_propagation:
|
||||
if event.sender == self._parent:
|
||||
@@ -264,9 +264,12 @@ class MessagePump:
|
||||
method_name = f"handle_{message.name}"
|
||||
|
||||
method = getattr(self, method_name, None)
|
||||
if method is not None:
|
||||
log(message, ">>>", self, verbosity=message.verbosity)
|
||||
await invoke(method, message)
|
||||
try:
|
||||
if method is not None:
|
||||
log(message, ">>>", self, verbosity=message.verbosity)
|
||||
await invoke(method, message)
|
||||
finally:
|
||||
message.set_done()
|
||||
|
||||
if message.bubble and self._parent and not message._stop_propagation:
|
||||
if message.sender == self._parent:
|
||||
|
||||
@@ -118,6 +118,7 @@ class View(Widget):
|
||||
if cached_size == size and cached_scroll == scroll:
|
||||
return arrangement
|
||||
arrangement = list(self._layout.arrange(self, size, scroll))
|
||||
self.log(arrangement)
|
||||
self._cached_arrangement = (size, scroll, arrangement)
|
||||
return arrangement
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ from rich.padding import Padding
|
||||
from rich.pretty import Pretty
|
||||
from rich.style import Style
|
||||
from rich.styled import Styled
|
||||
from rich.text import TextType
|
||||
from rich.text import Text, TextType
|
||||
|
||||
from . import events
|
||||
from . import errors
|
||||
@@ -135,24 +135,28 @@ class Widget(DOMNode):
|
||||
Returns:
|
||||
RenderableType: A new renderable.
|
||||
"""
|
||||
renderable = Styled(self.render(), self.styles.text)
|
||||
|
||||
renderable = self.render()
|
||||
styles = self.styles
|
||||
if self.padding is not None:
|
||||
renderable = Padding(renderable, self.padding)
|
||||
if self.border not in ("", "none"):
|
||||
_border_style = self.console.get_style(self.border_style)
|
||||
renderable = Border(
|
||||
renderable,
|
||||
(
|
||||
("heavy", _border_style),
|
||||
("heavy", _border_style),
|
||||
("heavy", _border_style),
|
||||
("heavy", _border_style),
|
||||
),
|
||||
)
|
||||
|
||||
if styles.has_border:
|
||||
renderable = Border(renderable, styles.border)
|
||||
|
||||
# _border_style = self.console.get_style(self.border_style)
|
||||
# renderable = Border(
|
||||
# renderable,
|
||||
# (
|
||||
# ("heavy", _border_style),
|
||||
# ("heavy", _border_style),
|
||||
# ("heavy", _border_style),
|
||||
# ("heavy", _border_style),
|
||||
# ),
|
||||
# )
|
||||
if self.margin is not None:
|
||||
renderable = Padding(renderable, self.margin)
|
||||
if self.style:
|
||||
renderable = Styled(renderable, self.style)
|
||||
renderable = Styled(renderable, styles.text)
|
||||
return renderable
|
||||
|
||||
@property
|
||||
@@ -269,9 +273,7 @@ class Widget(DOMNode):
|
||||
Returns:
|
||||
RenderableType: Any renderable
|
||||
"""
|
||||
return Panel(
|
||||
Align.center(Pretty(self), vertical="middle"), title=self.__class__.__name__
|
||||
)
|
||||
return Align.center(Text(f"#{self.id}"), vertical="middle")
|
||||
|
||||
async def action(self, action: str, *params) -> None:
|
||||
await self.app.action(action, self)
|
||||
|
||||
@@ -10,7 +10,6 @@ import rich.repr
|
||||
from logging import getLogger
|
||||
|
||||
from .. import events
|
||||
from ..geometry import Offset
|
||||
from ..widget import Reactive, Widget
|
||||
|
||||
log = getLogger("rich")
|
||||
|
||||
Reference in New Issue
Block a user