From 19d0a2b097521d8481df8763a4d6cb251ce95cde Mon Sep 17 00:00:00 2001 From: Darren Burns Date: Tue, 25 Jan 2022 15:20:14 +0000 Subject: [PATCH] Fixing vertical layout --- examples/dev_sandbox.css | 4 +-- examples/dev_sandbox.py | 12 +++---- src/textual/app.py | 55 ++------------------------------- src/textual/layout.py | 6 ++-- src/textual/layouts/vertical.py | 19 +++--------- src/textual/reactive.py | 1 - src/textual/view.py | 1 - 7 files changed, 16 insertions(+), 82 deletions(-) diff --git a/examples/dev_sandbox.css b/examples/dev_sandbox.css index 2e348e134..30e37d779 100644 --- a/examples/dev_sandbox.css +++ b/examples/dev_sandbox.css @@ -1,8 +1,8 @@ /* CSS file for dev_sandbox.py */ App > View { - docks: side=left/1; - text: on #20639b; + layout: vertical; + text: on #6e06c2; } Widget:hover { diff --git a/examples/dev_sandbox.py b/examples/dev_sandbox.py index d53946fb3..1782695fc 100644 --- a/examples/dev_sandbox.py +++ b/examples/dev_sandbox.py @@ -7,7 +7,7 @@ from textual.widget import Widget class PanelWidget(Widget): def render(self) -> RenderableType: - return Panel("hello world!", title="Title") + return Panel("hello world!", title="Title", height=4) class BasicApp(App): @@ -21,12 +21,8 @@ class BasicApp(App): def on_mount(self): """Build layout here.""" - self.mount( - header=Widget(), - content=PanelWidget(), - footer=Widget(), - sidebar=Widget(), - ) + self.mount(header=PanelWidget(), content=PanelWidget(), footer=PanelWidget()) + self.view.refresh_layout() -BasicApp.run(css_file="test_app.css", watch_css=True, log="textual.log") +BasicApp.run(log="textual.log") diff --git a/src/textual/app.py b/src/textual/app.py index 8708bf5ab..a6094995d 100644 --- a/src/textual/app.py +++ b/src/textual/app.py @@ -254,7 +254,6 @@ class App(DOMNode): Args: widget (Widget): [description] """ - log("set_focus", widget) if widget == self.focused: # Widget is already focused return @@ -380,7 +379,7 @@ class App(DOMNode): if self.log_file is not None: self.log_file.close() - def _register(self, parent: DOMNode, child: DOMNode) -> bool: + def _register_child(self, parent: DOMNode, child: DOMNode) -> bool: if child not in self.registry: parent.children._append(child) self.registry.add(child) @@ -409,7 +408,7 @@ class App(DOMNode): if widget not in self.registry: if widget_id is not None: widget.id = widget_id - self._register(parent, widget) + self._register_child(parent, child=widget) apply_stylesheet(widget) for _widget_id, widget in name_widgets: @@ -432,7 +431,7 @@ class App(DOMNode): driver.disable_input() await self.close_messages() - def refresh(self, repaint: bool = True, layout: bool = False) -> None: + def refresh(self) -> None: sync_available = os.environ.get("TERM_PROGRAM", "") != "Apple_Terminal" if not self._closed: console = self.console @@ -627,51 +626,3 @@ class App(DOMNode): self.reset_styles() self.stylesheet.update(self) self.view.refresh(layout=True) - - -if __name__ == "__main__": - import asyncio - - from .widgets import Header - from .widgets import Footer - - from .widgets import Placeholder - - # from .widgets.scroll_view import ScrollView - - import os - - class MyApp(App): - """Just a test app.""" - - async def on_load(self, event: events.Load) -> None: - await self.bind("ctrl+c", "quit", show=False) - await self.bind("q", "quit", "Quit") - await self.bind("x", "bang", "Test error handling") - await self.bind("b", "toggle_sidebar", "Toggle sidebar") - - show_bar: Reactive[bool] = Reactive(False) - - async def watch_show_bar(self, show_bar: bool) -> None: - self.animator.animate(self.bar, "layout_offset_x", 0 if show_bar else -40) - - async def action_toggle_sidebar(self) -> None: - self.show_bar = not self.show_bar - - async def on_mount(self, event: events.Mount) -> None: - view = await self.push_view(DockView()) - - header = Header() - footer = Footer() - self.bar = Placeholder(name="left") - - await view.dock(header, edge="top") - await view.dock(footer, edge="bottom") - await view.dock(self.bar, edge="left", size=40, z=1) - self.bar.layout_offset_x = -40 - - sub_view = DockView() - await sub_view.dock(Placeholder(), Placeholder(), edge="top") - await view.dock(sub_view, edge="left") - - MyApp.run(log="textual.log") diff --git a/src/textual/layout.py b/src/textual/layout.py index 8542e5942..2a0576bf1 100644 --- a/src/textual/layout.py +++ b/src/textual/layout.py @@ -159,9 +159,9 @@ class Layout(ABC): """Generate a layout map that defines where on the screen the widgets will be drawn. Args: - console (Console): Console instance. - size (Dimensions): Size of container. - viewport (Region): Screen relative viewport. + view (View): The View instance. + size (Size): Size of container. + scroll (Offset): Offset to apply to the Widget placements. Returns: Iterable[WidgetPlacement]: An iterable of widget location diff --git a/src/textual/layouts/vertical.py b/src/textual/layouts/vertical.py index 75a54df73..aabb88f80 100644 --- a/src/textual/layouts/vertical.py +++ b/src/textual/layouts/vertical.py @@ -22,25 +22,15 @@ class VerticalLayout(Layout): self.auto_width = auto_width self.z = z self.gutter = Spacing.unpack(gutter) - self._widgets: list[Widget] = [] self._max_widget_width = 0 super().__init__() - def add(self, widget: Widget) -> None: - self._widgets.append(widget) - self._max_widget_width = max(widget.app.measure(widget), self._max_widget_width) - - def clear(self) -> None: - del self._widgets[:] - self._max_widget_width = 0 - - def get_widgets(self) -> Iterable[Widget]: - return self._widgets + def get_widgets(self, view: View) -> Iterable[Widget]: + return view.children def arrange( self, view: View, size: Size, scroll: Offset ) -> Iterable[WidgetPlacement]: - index = 0 width, _height = size gutter = self.gutter x, y = self.gutter.top_left @@ -51,10 +41,9 @@ class VerticalLayout(Layout): ) total_width = render_width - gutter_height = max(gutter.top, gutter.bottom) - for last, widget in loop_last(self._widgets): + for last, widget in loop_last(view.children): if ( not widget.render_cache or widget.render_cache.size.width != render_width @@ -63,7 +52,7 @@ class VerticalLayout(Layout): assert widget.render_cache is not None render_height = widget.render_cache.size.height region = Region(x, y, render_width, render_height) - yield WidgetPlacement(region, widget, (self.z, index)) + yield WidgetPlacement(region, widget, self.z) y += render_height + (gutter.bottom if last else gutter_height) yield WidgetPlacement(Region(0, 0, total_width + gutter.width, y)) diff --git a/src/textual/reactive.py b/src/textual/reactive.py index d8421408e..dbf7de699 100644 --- a/src/textual/reactive.py +++ b/src/textual/reactive.py @@ -13,7 +13,6 @@ from typing import ( TYPE_CHECKING, ) -from . import log from . import events from ._callback import count_parameters, invoke diff --git a/src/textual/view.py b/src/textual/view.py index b16645f10..74602c3dc 100644 --- a/src/textual/view.py +++ b/src/textual/view.py @@ -22,7 +22,6 @@ class View(Widget): def __init__(self, name: str | None = None, id: str | None = None) -> None: self.mouse_over: Widget | None = None - self.widgets: set[Widget] = set() self._mouse_style: Style = Style() self._mouse_widget: Widget | None = None