mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
declaration parser
This commit is contained in:
@@ -1,4 +1,13 @@
|
|||||||
App > DockView {
|
App > View {
|
||||||
|
docks: main=top;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar {
|
||||||
|
dock-group: main;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
App > View {
|
||||||
layout: dock;
|
layout: dock;
|
||||||
docks: side=left/1 header=top footer=bottom;
|
docks: side=left/1 header=top footer=bottom;
|
||||||
layers: base panels;
|
layers: base panels;
|
||||||
@@ -37,3 +46,4 @@ App > DockView {
|
|||||||
dock-group: header;
|
dock-group: header;
|
||||||
text: on #20639b;
|
text: on #20639b;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ class BasicApp(App):
|
|||||||
"""A basic app demonstrating CSS"""
|
"""A basic app demonstrating CSS"""
|
||||||
|
|
||||||
def on_load(self):
|
def on_load(self):
|
||||||
self.bind("t", "toggle_class('#sidebar', '-active')")
|
self.bind("tab", "toggle_class('#sidebar', '-active')")
|
||||||
|
|
||||||
def on_mount(self):
|
def on_mount(self):
|
||||||
"""Build layout here."""
|
"""Build layout here."""
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ ANSI_SEQUENCES: Dict[str, Tuple[Keys, ...]] = {
|
|||||||
"\x06": (Keys.ControlF,), # Control-F (cursor forward)
|
"\x06": (Keys.ControlF,), # Control-F (cursor forward)
|
||||||
"\x07": (Keys.ControlG,), # Control-G
|
"\x07": (Keys.ControlG,), # Control-G
|
||||||
"\x08": (Keys.ControlH,), # Control-H (8) (Identical to '\b')
|
"\x08": (Keys.ControlH,), # Control-H (8) (Identical to '\b')
|
||||||
"\x09": (Keys.ControlI,), # Control-I (9) (Identical to '\t')
|
"\x09": (Keys.Tab,), # Control-I (9) (Identical to '\t')
|
||||||
"\x0a": (Keys.ControlJ,), # Control-J (10) (Identical to '\n')
|
"\x0a": (Keys.ControlJ,), # Control-J (10) (Identical to '\n')
|
||||||
"\x0b": (Keys.ControlK,), # Control-K (delete until end of line; vertical tab)
|
"\x0b": (Keys.ControlK,), # Control-K (delete until end of line; vertical tab)
|
||||||
"\x0c": (Keys.ControlL,), # Control-L (clear; form feed)
|
"\x0c": (Keys.ControlL,), # Control-L (clear; form feed)
|
||||||
|
|||||||
@@ -498,7 +498,7 @@ class App(DOMNode):
|
|||||||
# Handle input events that haven't been forwarded
|
# Handle input events that haven't been forwarded
|
||||||
# If the event has been forwarded it may have bubbled up back to the App
|
# If the event has been forwarded it may have bubbled up back to the App
|
||||||
if isinstance(event, events.Mount):
|
if isinstance(event, events.Mount):
|
||||||
view = DockView()
|
view = View()
|
||||||
self.register(self, view)
|
self.register(self, view)
|
||||||
await self.push_view(view)
|
await self.push_view(view)
|
||||||
await super().on_event(event)
|
await super().on_event(event)
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ class ScalarProperty:
|
|||||||
if new_value is not None and new_value.is_percent:
|
if new_value is not None and new_value.is_percent:
|
||||||
new_value = Scalar(float(new_value.value), self.percent_unit, Unit.WIDTH)
|
new_value = Scalar(float(new_value.value), self.percent_unit, Unit.WIDTH)
|
||||||
setattr(obj, self.internal_name, new_value)
|
setattr(obj, self.internal_name, new_value)
|
||||||
|
obj.refresh()
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
@@ -100,6 +101,7 @@ class BoxProperty:
|
|||||||
else:
|
else:
|
||||||
new_value = (_type, Style.from_color(Color.parse(color)))
|
new_value = (_type, Style.from_color(Color.parse(color)))
|
||||||
setattr(obj, self.internal_name, new_value)
|
setattr(obj, self.internal_name, new_value)
|
||||||
|
obj.refresh()
|
||||||
return border
|
return border
|
||||||
|
|
||||||
|
|
||||||
@@ -151,6 +153,7 @@ class BorderProperty:
|
|||||||
| None,
|
| None,
|
||||||
) -> None:
|
) -> None:
|
||||||
top, right, bottom, left = self._properties
|
top, right, bottom, left = self._properties
|
||||||
|
obj.refresh()
|
||||||
if border is None:
|
if border is None:
|
||||||
setattr(obj, top, None)
|
setattr(obj, top, None)
|
||||||
setattr(obj, right, None)
|
setattr(obj, right, None)
|
||||||
@@ -207,6 +210,7 @@ class StyleProperty:
|
|||||||
return style
|
return style
|
||||||
|
|
||||||
def __set__(self, obj: Styles, style: Style | str | None) -> Style | str | None:
|
def __set__(self, obj: Styles, style: Style | str | None) -> Style | str | None:
|
||||||
|
obj.refresh()
|
||||||
if style is None:
|
if style is None:
|
||||||
setattr(obj, self._color_name, None)
|
setattr(obj, self._color_name, None)
|
||||||
setattr(obj, self._bgcolor_name, None)
|
setattr(obj, self._bgcolor_name, None)
|
||||||
@@ -232,6 +236,7 @@ class SpacingProperty:
|
|||||||
return getattr(obj, self._internal_name) or NULL_SPACING
|
return getattr(obj, self._internal_name) or NULL_SPACING
|
||||||
|
|
||||||
def __set__(self, obj: Styles, spacing: SpacingDimensions) -> Spacing:
|
def __set__(self, obj: Styles, spacing: SpacingDimensions) -> Spacing:
|
||||||
|
obj.refresh(True)
|
||||||
spacing = Spacing.unpack(spacing)
|
spacing = Spacing.unpack(spacing)
|
||||||
setattr(obj, self._internal_name, spacing)
|
setattr(obj, self._internal_name, spacing)
|
||||||
return spacing
|
return spacing
|
||||||
@@ -246,6 +251,7 @@ class DocksProperty:
|
|||||||
def __set__(
|
def __set__(
|
||||||
self, obj: Styles, docks: Iterable[DockGroup] | None
|
self, obj: Styles, docks: Iterable[DockGroup] | None
|
||||||
) -> Iterable[DockGroup] | None:
|
) -> Iterable[DockGroup] | None:
|
||||||
|
obj.refresh(True)
|
||||||
if docks is None:
|
if docks is None:
|
||||||
obj._rule_docks = None
|
obj._rule_docks = None
|
||||||
else:
|
else:
|
||||||
@@ -258,6 +264,7 @@ class DockGroupProperty:
|
|||||||
return obj._rule_dock_group or ""
|
return obj._rule_dock_group or ""
|
||||||
|
|
||||||
def __set__(self, obj: Styles, spacing: str | None) -> str | None:
|
def __set__(self, obj: Styles, spacing: str | None) -> str | None:
|
||||||
|
obj.refresh(True)
|
||||||
obj._rule_dock_group = spacing
|
obj._rule_dock_group = spacing
|
||||||
return spacing
|
return spacing
|
||||||
|
|
||||||
@@ -274,6 +281,7 @@ class OffsetProperty:
|
|||||||
def __set__(
|
def __set__(
|
||||||
self, obj: Styles, offset: tuple[int | str, int | str]
|
self, obj: Styles, offset: tuple[int | str, int | str]
|
||||||
) -> tuple[int | str, int | str]:
|
) -> tuple[int | str, int | str]:
|
||||||
|
obj.refresh(True)
|
||||||
x, y = offset
|
x, y = offset
|
||||||
scalar_x = (
|
scalar_x = (
|
||||||
Scalar.parse(x, Unit.WIDTH)
|
Scalar.parse(x, Unit.WIDTH)
|
||||||
@@ -299,6 +307,7 @@ class IntegerProperty:
|
|||||||
return getattr(obj, self._internal_name, 0)
|
return getattr(obj, self._internal_name, 0)
|
||||||
|
|
||||||
def __set__(self, obj: Styles, value: int | None) -> int | None:
|
def __set__(self, obj: Styles, value: int | None) -> int | None:
|
||||||
|
obj.refresh()
|
||||||
if not isinstance(value, int):
|
if not isinstance(value, int):
|
||||||
raise StyleTypeError(f"{self._name} must be a str")
|
raise StyleTypeError(f"{self._name} must be a str")
|
||||||
setattr(obj, self._internal_name, value)
|
setattr(obj, self._internal_name, value)
|
||||||
@@ -318,6 +327,7 @@ class StringProperty:
|
|||||||
return getattr(obj, self._internal_name, None) or self._default
|
return getattr(obj, self._internal_name, None) or self._default
|
||||||
|
|
||||||
def __set__(self, obj: Styles, value: str | None = None) -> str | None:
|
def __set__(self, obj: Styles, value: str | None = None) -> str | None:
|
||||||
|
obj.refresh()
|
||||||
if value is not None:
|
if value is not None:
|
||||||
if value not in self._valid_values:
|
if value not in self._valid_values:
|
||||||
raise StyleValueError(
|
raise StyleValueError(
|
||||||
@@ -336,6 +346,7 @@ class NameProperty:
|
|||||||
return getattr(obj, self._internal_name) or ""
|
return getattr(obj, self._internal_name) or ""
|
||||||
|
|
||||||
def __set__(self, obj: Styles, name: str | None) -> str | None:
|
def __set__(self, obj: Styles, name: str | None) -> str | None:
|
||||||
|
obj.refresh(True)
|
||||||
if not isinstance(name, str):
|
if not isinstance(name, str):
|
||||||
raise StyleTypeError(f"{self._name} must be a str")
|
raise StyleTypeError(f"{self._name} must be a str")
|
||||||
setattr(obj, self._internal_name, name)
|
setattr(obj, self._internal_name, name)
|
||||||
@@ -355,6 +366,7 @@ class NameListProperty:
|
|||||||
def __set__(
|
def __set__(
|
||||||
self, obj: Styles, names: str | tuple[str] | None = None
|
self, obj: Styles, names: str | tuple[str] | None = None
|
||||||
) -> str | tuple[str] | None:
|
) -> str | tuple[str] | None:
|
||||||
|
obj.refresh(True)
|
||||||
names_value: tuple[str, ...] | None = None
|
names_value: tuple[str, ...] | None = None
|
||||||
if isinstance(names, str):
|
if isinstance(names, str):
|
||||||
names_value = tuple(name.strip().lower() for name in names.split(" "))
|
names_value = tuple(name.strip().lower() for name in names.split(" "))
|
||||||
@@ -375,6 +387,7 @@ class ColorProperty:
|
|||||||
return getattr(obj, self._internal_name, None) or Color.default()
|
return getattr(obj, self._internal_name, None) or Color.default()
|
||||||
|
|
||||||
def __set__(self, obj: Styles, color: Color | str | None) -> Color | str | None:
|
def __set__(self, obj: Styles, color: Color | str | None) -> Color | str | None:
|
||||||
|
obj.refresh()
|
||||||
if color is None:
|
if color is None:
|
||||||
setattr(self, self._internal_name, None)
|
setattr(self, self._internal_name, None)
|
||||||
else:
|
else:
|
||||||
@@ -409,6 +422,7 @@ class StyleFlagsProperty:
|
|||||||
return getattr(obj, self._internal_name, None) or Style.null()
|
return getattr(obj, self._internal_name, None) or Style.null()
|
||||||
|
|
||||||
def __set__(self, obj: Styles, style_flags: str | None) -> str | None:
|
def __set__(self, obj: Styles, style_flags: str | None) -> str | None:
|
||||||
|
obj.refresh()
|
||||||
if style_flags is None:
|
if style_flags is None:
|
||||||
setattr(self, self._internal_name, None)
|
setattr(self, self._internal_name, None)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ from rich import print
|
|||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
from typing import Iterator, Iterable
|
from typing import Iterator, Iterable
|
||||||
|
|
||||||
from .tokenize import tokenize, Token
|
from .styles import Styles
|
||||||
|
from .tokenize import tokenize, tokenize_declarations, Token
|
||||||
from .tokenizer import EOFError
|
from .tokenizer import EOFError
|
||||||
|
|
||||||
from .model import (
|
from .model import (
|
||||||
@@ -157,6 +158,44 @@ def parse_rule_set(tokens: Iterator[Token], token: Token) -> Iterable[RuleSet]:
|
|||||||
yield rule_set
|
yield rule_set
|
||||||
|
|
||||||
|
|
||||||
|
def parse_declarations(css: str, path: str) -> Styles:
|
||||||
|
|
||||||
|
tokens = iter(tokenize_declarations(css, path))
|
||||||
|
styles_builder = StylesBuilder()
|
||||||
|
|
||||||
|
declaration: Declaration | None = None
|
||||||
|
errors: list[tuple[Token, str]] = []
|
||||||
|
|
||||||
|
while True:
|
||||||
|
token = next(tokens, None)
|
||||||
|
if token is None:
|
||||||
|
break
|
||||||
|
token_name = token.name
|
||||||
|
if token_name in ("whitespace", "declaration_end", "eof"):
|
||||||
|
continue
|
||||||
|
if token_name == "declaration_name":
|
||||||
|
if declaration and declaration.tokens:
|
||||||
|
try:
|
||||||
|
styles_builder.add_declaration(declaration)
|
||||||
|
except DeclarationError as error:
|
||||||
|
errors.append((error.token, error.message))
|
||||||
|
declaration = Declaration(token, "")
|
||||||
|
declaration.name = token.value.rstrip(":")
|
||||||
|
elif token_name == "declaration_set_end":
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
if declaration:
|
||||||
|
declaration.tokens.append(token)
|
||||||
|
|
||||||
|
if declaration and declaration.tokens:
|
||||||
|
try:
|
||||||
|
styles_builder.add_declaration(declaration)
|
||||||
|
except DeclarationError as error:
|
||||||
|
errors.append((error.token, error.message))
|
||||||
|
|
||||||
|
return styles_builder.styles
|
||||||
|
|
||||||
|
|
||||||
def parse(css: str, path: str) -> Iterable[RuleSet]:
|
def parse(css: str, path: str) -> Iterable[RuleSet]:
|
||||||
|
|
||||||
tokens = iter(tokenize(css, path))
|
tokens = iter(tokenize(css, path))
|
||||||
@@ -206,3 +245,10 @@ def parse(css: str, path: str) -> Iterable[RuleSet]:
|
|||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
print(parse_selectors("Foo > Bar.baz { foo: bar"))
|
print(parse_selectors("Foo > Bar.baz { foo: bar"))
|
||||||
|
|
||||||
|
CSS = """
|
||||||
|
text: on red;
|
||||||
|
docks: main=top;
|
||||||
|
"""
|
||||||
|
|
||||||
|
print(parse_declarations(CSS, "foo"))
|
||||||
|
|||||||
@@ -91,6 +91,9 @@ class Styles:
|
|||||||
|
|
||||||
_rule_transitions: dict[str, Transition] | None = None
|
_rule_transitions: dict[str, Transition] | None = None
|
||||||
|
|
||||||
|
_layout_required: bool = False
|
||||||
|
_repaint_required: bool = False
|
||||||
|
|
||||||
important: set[str] = field(default_factory=set)
|
important: set[str] = field(default_factory=set)
|
||||||
|
|
||||||
display = StringProperty(VALID_DISPLAY, "block")
|
display = StringProperty(VALID_DISPLAY, "block")
|
||||||
@@ -130,6 +133,15 @@ class Styles:
|
|||||||
layers = NameListProperty()
|
layers = NameListProperty()
|
||||||
transitions = TransitionsProperty()
|
transitions = TransitionsProperty()
|
||||||
|
|
||||||
|
def refresh(self, layout: bool = False) -> None:
|
||||||
|
self._repaint_required = True
|
||||||
|
self._layout_required = layout
|
||||||
|
|
||||||
|
def check_refresh(self) -> tuple[bool, bool]:
|
||||||
|
result = (self._repaint_required, self._layout_required)
|
||||||
|
self._repaint_required = self._layout_required = False
|
||||||
|
return result
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def has_border(self) -> bool:
|
def has_border(self) -> bool:
|
||||||
"""Check in a border is present."""
|
"""Check in a border is present."""
|
||||||
|
|||||||
@@ -40,6 +40,13 @@ expect_declaration = Expect(
|
|||||||
declaration_set_end=r"\}",
|
declaration_set_end=r"\}",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
expect_declaration_solo = Expect(
|
||||||
|
whitespace=r"\s+",
|
||||||
|
comment_start=r"\/\*",
|
||||||
|
declaration_name=r"[a-zA-Z_\-]+\:",
|
||||||
|
declaration_set_end=r"\}",
|
||||||
|
).expect_eof(True)
|
||||||
|
|
||||||
expect_declaration_content = Expect(
|
expect_declaration_content = Expect(
|
||||||
declaration_end=r"\n|;",
|
declaration_end=r"\n|;",
|
||||||
whitespace=r"\s+",
|
whitespace=r"\s+",
|
||||||
@@ -55,34 +62,65 @@ expect_declaration_content = Expect(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
_STATES = {
|
class StateTokenizer:
|
||||||
"selector_start": expect_selector_continue,
|
EXPECT = expect_selector
|
||||||
"selector_start_id": expect_selector_continue,
|
STATE_MAP = {
|
||||||
"selector_start_class": expect_selector_continue,
|
"selector_start": expect_selector_continue,
|
||||||
"selector_start_universal": expect_selector_continue,
|
"selector_start_id": expect_selector_continue,
|
||||||
"selector_id": expect_selector_continue,
|
"selector_start_class": expect_selector_continue,
|
||||||
"selector_class": expect_selector_continue,
|
"selector_start_universal": expect_selector_continue,
|
||||||
"selector_universal": expect_selector_continue,
|
"selector_id": expect_selector_continue,
|
||||||
"declaration_set_start": expect_declaration,
|
"selector_class": expect_selector_continue,
|
||||||
"declaration_name": expect_declaration_content,
|
"selector_universal": expect_selector_continue,
|
||||||
"declaration_end": expect_declaration,
|
"declaration_set_start": expect_declaration,
|
||||||
"declaration_set_end": expect_selector,
|
"declaration_name": expect_declaration_content,
|
||||||
}
|
"declaration_end": expect_declaration,
|
||||||
|
"declaration_set_end": expect_selector,
|
||||||
|
}
|
||||||
|
|
||||||
|
def __call__(self, code: str, path: str) -> Iterable[Token]:
|
||||||
|
tokenizer = Tokenizer(code, path=path)
|
||||||
|
expect = self.EXPECT
|
||||||
|
get_token = tokenizer.get_token
|
||||||
|
get_state = self.STATE_MAP.get
|
||||||
|
while True:
|
||||||
|
token = get_token(expect)
|
||||||
|
name = token.name
|
||||||
|
if name == "comment_start":
|
||||||
|
tokenizer.skip_to(expect_comment_end)
|
||||||
|
continue
|
||||||
|
elif name == "eof":
|
||||||
|
break
|
||||||
|
expect = get_state(name, expect)
|
||||||
|
yield token
|
||||||
|
|
||||||
|
|
||||||
def tokenize(code: str, path: str) -> Iterable[Token]:
|
class DeclarationStateTokenizer(StateTokenizer):
|
||||||
tokenizer = Tokenizer(code, path=path)
|
EXPECT = expect_declaration_solo
|
||||||
expect = expect_selector
|
STATE_MAP = {
|
||||||
get_token = tokenizer.get_token
|
"declaration_name": expect_declaration_content,
|
||||||
get_state = _STATES.get
|
"declaration_end": expect_declaration_solo,
|
||||||
while True:
|
}
|
||||||
token = get_token(expect)
|
|
||||||
|
|
||||||
name = token.name
|
|
||||||
if name == "comment_start":
|
tokenize = StateTokenizer()
|
||||||
tokenizer.skip_to(expect_comment_end)
|
tokenize_declarations = DeclarationStateTokenizer()
|
||||||
continue
|
|
||||||
elif name == "eof":
|
|
||||||
break
|
# def tokenize(
|
||||||
expect = get_state(name, expect)
|
# code: str, path: str, *, expect: Expect = expect_selector
|
||||||
yield token
|
# ) -> Iterable[Token]:
|
||||||
|
# tokenizer = Tokenizer(code, path=path)
|
||||||
|
# # expect = expect_selector
|
||||||
|
# get_token = tokenizer.get_token
|
||||||
|
# get_state = _STATES.get
|
||||||
|
# while True:
|
||||||
|
# token = get_token(expect)
|
||||||
|
# name = token.name
|
||||||
|
# if name == "comment_start":
|
||||||
|
# tokenizer.skip_to(expect_comment_end)
|
||||||
|
# continue
|
||||||
|
# elif name == "eof":
|
||||||
|
# break
|
||||||
|
# expect = get_state(name, expect)
|
||||||
|
# yield token
|
||||||
|
|||||||
@@ -39,12 +39,15 @@ class LayoutProperty:
|
|||||||
@rich.repr.auto
|
@rich.repr.auto
|
||||||
class View(Widget):
|
class View(Widget):
|
||||||
|
|
||||||
layout_factory: ClassVar[Callable[[], Layout]]
|
CSS = """
|
||||||
|
docks: main=top
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(self, name: str | None = None, id: str | None = None) -> None:
|
||||||
self, layout: Layout = None, name: str | None = None, id: str | None = None
|
|
||||||
) -> None:
|
from .layouts.dock import DockLayout
|
||||||
self._layout: Layout = layout or self.layout_factory()
|
|
||||||
|
self._layout: Layout = DockLayout()
|
||||||
|
|
||||||
self.mouse_over: Widget | None = None
|
self.mouse_over: Widget | None = None
|
||||||
self.widgets: set[Widget] = set()
|
self.widgets: set[Widget] = set()
|
||||||
@@ -56,7 +59,6 @@ class View(Widget):
|
|||||||
Offset(),
|
Offset(),
|
||||||
[],
|
[],
|
||||||
)
|
)
|
||||||
|
|
||||||
super().__init__(name=name, id=id)
|
super().__init__(name=name, id=id)
|
||||||
|
|
||||||
def __init_subclass__(
|
def __init_subclass__(
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ class RenderCache(NamedTuple):
|
|||||||
@property
|
@property
|
||||||
def cursor_line(self) -> int | None:
|
def cursor_line(self) -> int | None:
|
||||||
for index, line in enumerate(self.lines):
|
for index, line in enumerate(self.lines):
|
||||||
for text, style, control in line:
|
for _text, style, _control in line:
|
||||||
if style and style._meta and style.meta.get("cursor", False):
|
if style and style._meta and style.meta.get("cursor", False):
|
||||||
return index
|
return index
|
||||||
return None
|
return None
|
||||||
@@ -59,6 +59,10 @@ class Widget(DOMNode):
|
|||||||
_counts: ClassVar[dict[str, int]] = {}
|
_counts: ClassVar[dict[str, int]] = {}
|
||||||
can_focus: bool = False
|
can_focus: bool = False
|
||||||
|
|
||||||
|
CSS = """
|
||||||
|
dock-group: main;
|
||||||
|
"""
|
||||||
|
|
||||||
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__
|
||||||
@@ -279,13 +283,14 @@ class Widget(DOMNode):
|
|||||||
self.refresh()
|
self.refresh()
|
||||||
|
|
||||||
async def on_idle(self, event: events.Idle) -> None:
|
async def on_idle(self, event: events.Idle) -> None:
|
||||||
if self.check_layout():
|
repaint, layout = self.styles.check_refresh()
|
||||||
|
if layout or self.check_layout():
|
||||||
self.log("layout required")
|
self.log("layout required")
|
||||||
self.render_cache = None
|
self.render_cache = None
|
||||||
self.reset_check_repaint()
|
self.reset_check_repaint()
|
||||||
self.reset_check_layout()
|
self.reset_check_layout()
|
||||||
await self.emit(Layout(self))
|
await self.emit(Layout(self))
|
||||||
elif self.check_repaint():
|
elif repaint or self.check_repaint():
|
||||||
self.log("repaint required")
|
self.log("repaint required")
|
||||||
self.render_cache = None
|
self.render_cache = None
|
||||||
self.reset_check_repaint()
|
self.reset_check_repaint()
|
||||||
|
|||||||
Reference in New Issue
Block a user