mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
Fixing vertical layout
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -13,7 +13,6 @@ from typing import (
|
||||
TYPE_CHECKING,
|
||||
)
|
||||
|
||||
from . import log
|
||||
from . import events
|
||||
|
||||
from ._callback import count_parameters, invoke
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user