fix refresh

This commit is contained in:
Will McGugan
2021-12-13 10:18:01 +00:00
parent f40b339888
commit 485c1bdfe1
12 changed files with 42 additions and 18 deletions

View File

@@ -11,10 +11,14 @@ App > DockView {
height: 1fr;
layer: panels;
border-right: outer #09312e;
offset-x: -50%;
offset-x: -100%;
transition: offset-x 1.2s in_cubic 200ms, offset-y 1s linear;
}
#sidebar.-active {
offset-x: 0;
}
#header {
text: on #173f5f;
dock-group: header;

View File

@@ -5,16 +5,17 @@ from textual.widget import Widget
class BasicApp(App):
"""A basic app demonstrating CSS"""
def on_mount(self) -> None:
"""Build layout here."""
def on_load(self):
self.bind("t", "toggle('#sidebar', '-active')")
self.view.mount(
def on_mount(self):
"""Build layout here."""
self.mount(
header=Widget(),
content=Widget(),
footer=Widget(),
sidebar=Widget(),
)
self.panic(self.query("#sidebar").first().styles)
BasicApp.run(log="textual.log", css_file="basic.css")
BasicApp.run(log="textual.log", css_file="basic.css", log_verbosity=3)

View File

@@ -31,6 +31,7 @@ from .driver import Driver
from .layouts.dock import DockLayout, Dock
from ._linux_driver import LinuxDriver
from ._types import MessageTarget
from . import messages
from .message_pump import MessagePump
from ._profile import timer
from .view import View
@@ -66,8 +67,6 @@ class ActionError(Exception):
class App(DOMNode):
"""The base class for Textual Applications"""
KEYS: ClassVar[dict[str, str]] = {}
css = ""
def __init__(
@@ -215,6 +214,10 @@ class App(DOMNode):
asyncio.run(run_app())
def mount(self, *anon_widgets: Widget, **widgets: Widget) -> None:
self.register(self.view, *anon_widgets, **widgets)
self.view.refresh()
async def push_view(self, view: ViewType) -> ViewType:
self._view_stack.append(view)
return view
@@ -354,7 +357,9 @@ class App(DOMNode):
return True
return False
def mount(self, parent: DOMNode, *anon_widgets: Widget, **widgets: Widget) -> None:
def register(
self, parent: DOMNode, *anon_widgets: Widget, **widgets: Widget
) -> None:
"""Mount widget(s) so they may receive events.
Args:
@@ -467,7 +472,7 @@ class App(DOMNode):
# If the event has been forwarded it may have bubbled up back to the App
if isinstance(event, events.Mount):
view = DockView()
self.mount(self, view)
self.register(self, view)
await self.push_view(view)
await super().on_event(event)
@@ -567,6 +572,7 @@ class App(DOMNode):
async def action_toggle(self, selector: str, class_name: str) -> None:
self.view.query(selector).toggle_class(class_name)
self.view.refresh(layout=True)
if __name__ == "__main__":

View File

@@ -14,8 +14,8 @@ from .scalar import (
ScalarOffset,
ScalarParseError,
)
from ..geometry import Offset, Spacing, SpacingDimensions
from .constants import NULL_SPACING, VALID_EDGE
from ..geometry import Spacing, SpacingDimensions
from .constants import NULL_SPACING
from .errors import StyleTypeError, StyleValueError
from .transition import Transition
from ._error_tools import friendly_list

View File

@@ -7,6 +7,7 @@ from dataclasses import dataclass, field
from enum import Enum
from typing import Iterable
from .. import log
from ..dom import DOMNode
from .styles import Styles
from .tokenize import Token

View File

@@ -64,6 +64,5 @@ class DOMQuery:
node.remove_class(*class_names)
def toggle_class(self, *class_names: str) -> None:
for node in self._nodes:
node.remove_class(*class_names)
node.toggle_class(*class_names)

View File

@@ -55,6 +55,7 @@ class DockGroup(NamedTuple):
@dataclass
class Styles:
_changed: float = 0
_rule_display: Display | None = None
_rule_visibility: Visibility | None = None
_rule_layout: str | None = None

View File

@@ -122,10 +122,14 @@ class Stylesheet:
rule_attributes[key].append((rule_specificity, value))
get_first_item = itemgetter(0)
log(rule_attributes.get("offset"))
node_rules = [
(name, max(specificity_rules, key=get_first_item)[1])
for name, specificity_rules in rule_attributes.items()
]
node.styles.apply_rules(node_rules)

View File

@@ -172,6 +172,8 @@ class DOMNode(MessagePump):
def toggle_class(self, *class_names: str) -> None:
"""Toggle class names"""
self._classes.symmetric_difference_update(class_names)
self.app.stylesheet.apply(self)
self.log(self.styles.css)
def has_psuedo_class(self, *class_names: str) -> bool:
"""Check for psuedo class (such as hover, focus etc)"""

View File

@@ -29,6 +29,9 @@ if TYPE_CHECKING:
ReactiveType = TypeVar("ReactiveType")
T = TypeVar("T")
class Reactive(Generic[ReactiveType]):
"""Reactive descriptor."""

View File

@@ -139,7 +139,7 @@ class View(Widget):
self.app.refresh()
def mount(self, *anon_widgets: Widget, **widgets: Widget) -> None:
self.app.mount(self, *anon_widgets, **widgets)
self.app.register(self, *anon_widgets, **widgets)
self.refresh()
async def refresh_layout(self) -> None:
@@ -170,7 +170,7 @@ class View(Widget):
widget.post_message_no_wait(
events.Resize(self, unclipped_region.size)
)
except:
except Exception:
self.app.panic()
async def on_resize(self, event: events.Resize) -> None:

View File

@@ -285,15 +285,18 @@ class Widget(DOMNode):
self.refresh()
async def on_idle(self, event: events.Idle) -> None:
self.log("Widget.on_idle")
if self.check_layout():
self.log("layout required")
self.render_cache = None
self.reset_check_repaint()
self.reset_check_layout()
await self.emit(Layout(self))
await self.post_message(Layout(self))
elif self.check_repaint():
self.log("repaint required")
self.render_cache = None
self.reset_check_repaint()
await self.emit(Update(self, self))
await self.post_message(Update(self, self))
async def focus(self) -> None:
await self.app.set_focus(self)