mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
css render
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
App > View {
|
App > View {
|
||||||
layout: dock;
|
layout: dock;
|
||||||
docks: side=left/1 header=top footer=bottom;
|
docks: side=left/1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sidebar {
|
#sidebar {
|
||||||
@@ -16,24 +16,21 @@ App > View {
|
|||||||
#sidebar.-active {
|
#sidebar.-active {
|
||||||
offset-x: 0;
|
offset-x: 0;
|
||||||
transition: offset 400ms in_out_cubic;
|
transition: offset 400ms in_out_cubic;
|
||||||
text: on red;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#header {
|
#header {
|
||||||
text: on #173f5f;
|
text: on #173f5f;
|
||||||
dock: header;
|
|
||||||
height: 3;
|
height: 3;
|
||||||
border: hkey white;
|
border: hkey white;
|
||||||
}
|
}
|
||||||
|
|
||||||
#footer {
|
#footer {
|
||||||
dock: header;
|
|
||||||
height: 3;
|
height: 3;
|
||||||
border-top: hkey #0f2b41;
|
border-top: hkey #0f2b41;
|
||||||
text: #3a3009 on #f6d55c;
|
text: #3a3009 on #f6d55c;
|
||||||
}
|
}
|
||||||
|
|
||||||
#content {
|
#content {
|
||||||
dock: header;
|
|
||||||
text: bold on #20639b;
|
text: bold on #20639b;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,10 +28,12 @@ class Border:
|
|||||||
renderable: RenderableType,
|
renderable: RenderableType,
|
||||||
edge_styles: tuple[EdgeStyle, EdgeStyle, EdgeStyle, EdgeStyle],
|
edge_styles: tuple[EdgeStyle, EdgeStyle, EdgeStyle, EdgeStyle],
|
||||||
outline: bool = False,
|
outline: bool = False,
|
||||||
|
style: StyleType = "",
|
||||||
):
|
):
|
||||||
self.renderable = renderable
|
self.renderable = renderable
|
||||||
self.edge_styles = edge_styles
|
self.edge_styles = edge_styles
|
||||||
self.outline = outline
|
self.outline = outline
|
||||||
|
self.style = style
|
||||||
|
|
||||||
(
|
(
|
||||||
(top, top_style),
|
(top, top_style),
|
||||||
@@ -75,7 +77,13 @@ class Border:
|
|||||||
self, console: "Console", options: "ConsoleOptions"
|
self, console: "Console", options: "ConsoleOptions"
|
||||||
) -> "RenderResult":
|
) -> "RenderResult":
|
||||||
top, right, bottom, left = self._sides
|
top, right, bottom, left = self._sides
|
||||||
|
style = console.get_style(self.style)
|
||||||
top_style, right_style, bottom_style, left_style = self._styles
|
top_style, right_style, bottom_style, left_style = self._styles
|
||||||
|
if style:
|
||||||
|
top_style = style + top_style
|
||||||
|
right_style = style + right_style
|
||||||
|
bottom_style = style + bottom_style
|
||||||
|
left_style = style + left_style
|
||||||
BOX = BORDER_STYLES
|
BOX = BORDER_STYLES
|
||||||
|
|
||||||
has_left = left != "none"
|
has_left = left != "none"
|
||||||
|
|||||||
@@ -52,8 +52,8 @@ class LinuxDriver(Driver):
|
|||||||
write("\x1b[?1015h") # SET_VT200_HIGHLIGHT_MOUSE
|
write("\x1b[?1015h") # SET_VT200_HIGHLIGHT_MOUSE
|
||||||
write("\x1b[?1006h") # SET_SGR_EXT_MODE_MOUSE
|
write("\x1b[?1006h") # SET_SGR_EXT_MODE_MOUSE
|
||||||
|
|
||||||
# write("\x1b[?1007h")
|
write("\x1b[?1007h")
|
||||||
# self.console.file.flush()
|
self.console.file.flush()
|
||||||
|
|
||||||
# Note: E.g. lxterminal understands 1000h, but not the urxvt or sgr
|
# Note: E.g. lxterminal understands 1000h, but not the urxvt or sgr
|
||||||
# extensions.
|
# extensions.
|
||||||
@@ -64,7 +64,7 @@ class LinuxDriver(Driver):
|
|||||||
write("\x1b[?1003l") #
|
write("\x1b[?1003l") #
|
||||||
write("\x1b[?1015l")
|
write("\x1b[?1015l")
|
||||||
write("\x1b[?1006l")
|
write("\x1b[?1006l")
|
||||||
# self.console.file.flush()
|
self.console.file.flush()
|
||||||
|
|
||||||
def start_application_mode(self):
|
def start_application_mode(self):
|
||||||
|
|
||||||
|
|||||||
@@ -224,8 +224,7 @@ class App(DOMNode):
|
|||||||
asyncio.run(run_app())
|
asyncio.run(run_app())
|
||||||
|
|
||||||
async def _on_css_change(self) -> None:
|
async def _on_css_change(self) -> None:
|
||||||
self.log("CSS changed")
|
|
||||||
self.log("css_file", self.css_file)
|
|
||||||
if self.css_file is not None:
|
if self.css_file is not None:
|
||||||
stylesheet = Stylesheet()
|
stylesheet = Stylesheet()
|
||||||
try:
|
try:
|
||||||
@@ -235,11 +234,10 @@ class App(DOMNode):
|
|||||||
self.log(error)
|
self.log(error)
|
||||||
self.console.bell()
|
self.console.bell()
|
||||||
else:
|
else:
|
||||||
self.log("reseting stylesheet")
|
|
||||||
self.reset_styles()
|
self.reset_styles()
|
||||||
self.stylesheet = stylesheet
|
self.stylesheet = stylesheet
|
||||||
self.stylesheet.update(self)
|
self.stylesheet.update(self)
|
||||||
self.refresh(layout=True)
|
self.view.refresh(layout=True)
|
||||||
|
|
||||||
def mount(self, *anon_widgets: Widget, **widgets: Widget) -> None:
|
def mount(self, *anon_widgets: Widget, **widgets: Widget) -> None:
|
||||||
self.register(self.view, *anon_widgets, **widgets)
|
self.register(self.view, *anon_widgets, **widgets)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ from typing import Any, cast, Iterable, Iterator, TYPE_CHECKING
|
|||||||
from rich.highlighter import ReprHighlighter
|
from rich.highlighter import ReprHighlighter
|
||||||
import rich.repr
|
import rich.repr
|
||||||
from rich.pretty import Pretty
|
from rich.pretty import Pretty
|
||||||
|
from rich.style import Style
|
||||||
from rich.tree import Tree
|
from rich.tree import Tree
|
||||||
|
|
||||||
from .css.styles import Styles
|
from .css.styles import Styles
|
||||||
@@ -50,7 +51,7 @@ class DOMNode(MessagePump):
|
|||||||
@property
|
@property
|
||||||
def parent(self) -> DOMNode:
|
def parent(self) -> DOMNode:
|
||||||
if self._parent is None:
|
if self._parent is None:
|
||||||
raise NoParent(f"{self._parent} has no parent")
|
raise NoParent(f"{self} has no parent")
|
||||||
assert isinstance(self._parent, DOMNode)
|
assert isinstance(self._parent, DOMNode)
|
||||||
return self._parent
|
return self._parent
|
||||||
|
|
||||||
@@ -121,6 +122,19 @@ class DOMNode(MessagePump):
|
|||||||
node = node.parent
|
node = node.parent
|
||||||
return tuple(reversed(indexes))
|
return tuple(reversed(indexes))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def text_style(self) -> Style:
|
||||||
|
"""Get the text style (added to parent style).
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Style: Rich Style object.
|
||||||
|
"""
|
||||||
|
return (
|
||||||
|
self.parent.text_style + self.styles.text
|
||||||
|
if self.has_parent
|
||||||
|
else self.styles.text
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def tree(self) -> Tree:
|
def tree(self) -> Tree:
|
||||||
highlighter = ReprHighlighter()
|
highlighter = ReprHighlighter()
|
||||||
@@ -141,7 +155,7 @@ class DOMNode(MessagePump):
|
|||||||
for node in self.walk_children():
|
for node in self.walk_children():
|
||||||
node.styles = Styles(node=node)
|
node.styles = Styles(node=node)
|
||||||
if isinstance(node, Widget):
|
if isinstance(node, Widget):
|
||||||
node.clear_render_cache()
|
# node.clear_render_cache()
|
||||||
node._repaint_required = True
|
node._repaint_required = True
|
||||||
node._layout_required = True
|
node._layout_required = True
|
||||||
|
|
||||||
|
|||||||
@@ -65,12 +65,12 @@ class Widget(DOMNode):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name: str | None = None, id: str | None = None) -> None:
|
def __init__(self, name: str | None = None, id: str | None = None) -> None:
|
||||||
if name is None:
|
# if name is None:
|
||||||
class_name = self.__class__.__name__
|
# class_name = self.__class__.__name__
|
||||||
Widget._counts.setdefault(class_name, 0)
|
# Widget._counts.setdefault(class_name, 0)
|
||||||
Widget._counts[class_name] += 1
|
# Widget._counts[class_name] += 1
|
||||||
_count = self._counts[class_name]
|
# _count = self._counts[class_name]
|
||||||
name = f"{class_name}{_count}"
|
# name = f"{class_name}{_count}"
|
||||||
|
|
||||||
self._size = Size(0, 0)
|
self._size = Size(0, 0)
|
||||||
self._repaint_required = False
|
self._repaint_required = False
|
||||||
@@ -108,7 +108,10 @@ class Widget(DOMNode):
|
|||||||
|
|
||||||
def __rich_repr__(self) -> rich.repr.Result:
|
def __rich_repr__(self) -> rich.repr.Result:
|
||||||
yield "id", self.id, None
|
yield "id", self.id, None
|
||||||
yield "name", self.name
|
if self.name:
|
||||||
|
yield "name", self.name
|
||||||
|
if self.classes:
|
||||||
|
yield "classes", self.classes
|
||||||
|
|
||||||
def __rich__(self) -> RenderableType:
|
def __rich__(self) -> RenderableType:
|
||||||
renderable = self.render_styled()
|
renderable = self.render_styled()
|
||||||
@@ -138,20 +141,27 @@ class Widget(DOMNode):
|
|||||||
renderable = self.render()
|
renderable = self.render()
|
||||||
styles = self.styles
|
styles = self.styles
|
||||||
|
|
||||||
|
parent_text_style = self.parent.text_style
|
||||||
|
text_style = styles.text
|
||||||
|
renderable_text_style = parent_text_style + text_style
|
||||||
|
if renderable_text_style:
|
||||||
|
renderable = Styled(renderable, renderable_text_style)
|
||||||
|
|
||||||
if styles.has_padding:
|
if styles.has_padding:
|
||||||
renderable = Padding(renderable, styles.padding)
|
renderable = Padding(
|
||||||
|
renderable, styles.padding, style=renderable_text_style
|
||||||
|
)
|
||||||
|
|
||||||
if styles.has_border:
|
if styles.has_border:
|
||||||
renderable = Border(renderable, styles.border)
|
renderable = Border(renderable, styles.border, style=renderable_text_style)
|
||||||
|
|
||||||
if styles.has_margin:
|
if styles.has_margin:
|
||||||
renderable = Padding(renderable, styles.margin)
|
renderable = Padding(renderable, styles.margin, style=parent_text_style)
|
||||||
|
|
||||||
if styles.has_outline:
|
if styles.has_outline:
|
||||||
renderable = Border(renderable, styles.outline, outline=True)
|
renderable = Border(
|
||||||
|
renderable, styles.outline, outline=True, style=parent_text_style
|
||||||
if styles.text:
|
)
|
||||||
renderable = Styled(renderable, styles.text)
|
|
||||||
|
|
||||||
return renderable
|
return renderable
|
||||||
|
|
||||||
@@ -263,6 +273,7 @@ class Widget(DOMNode):
|
|||||||
elif repaint:
|
elif repaint:
|
||||||
self.clear_render_cache()
|
self.clear_render_cache()
|
||||||
self._repaint_required = True
|
self._repaint_required = True
|
||||||
|
self.log("refresh", repaint, layout)
|
||||||
self.post_message_no_wait(events.Null(self))
|
self.post_message_no_wait(events.Null(self))
|
||||||
|
|
||||||
def render(self) -> RenderableType:
|
def render(self) -> RenderableType:
|
||||||
|
|||||||
Reference in New Issue
Block a user