css render

This commit is contained in:
Will McGugan
2021-12-26 22:19:36 +00:00
parent c5e1d76cfd
commit ddd1a10840
6 changed files with 56 additions and 28 deletions

View File

@@ -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;
} }

View File

@@ -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"

View File

@@ -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):

View File

@@ -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)

View File

@@ -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

View File

@@ -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: