mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
virtual size
This commit is contained in:
@@ -29,7 +29,9 @@ class MyApp(App):
|
||||
|
||||
await self.view.dock(Header(), edge="top")
|
||||
await self.view.dock(Footer(), edge="bottom")
|
||||
await self.view.dock(self.directory, edge="left", size=32, name="sidebar")
|
||||
await self.view.dock(
|
||||
ScrollView(self.directory), edge="left", size=32, name="sidebar"
|
||||
)
|
||||
await self.view.dock(self.body, edge="right")
|
||||
|
||||
async def message_file_click(self, message: FileClick) -> None:
|
||||
|
||||
@@ -127,7 +127,7 @@ class Show(Event):
|
||||
|
||||
|
||||
class Hide(Event):
|
||||
"""Send when a widget has been hidden.
|
||||
"""Sent when a widget has been hidden.
|
||||
|
||||
A widget may be hidden by setting its `visible` flag to `False`, if it is no longer in a layout,
|
||||
or if it has been offset beyond the edges of the terminal.
|
||||
|
||||
@@ -17,12 +17,13 @@ class RenderRegion(NamedTuple):
|
||||
|
||||
class LayoutMap:
|
||||
def __init__(self, size: Dimensions) -> None:
|
||||
self.region = size.region
|
||||
self.size = size
|
||||
self.contents_region = Region(0, 0, 0, 0)
|
||||
self.widgets: dict[Widget, RenderRegion] = {}
|
||||
|
||||
@property
|
||||
def size(self) -> Dimensions:
|
||||
return self.region.size
|
||||
def virtual_size(self) -> Dimensions:
|
||||
return self.contents_region.size
|
||||
|
||||
def __getitem__(self, widget: Widget) -> RenderRegion:
|
||||
return self.widgets[widget]
|
||||
@@ -51,7 +52,7 @@ class LayoutMap:
|
||||
|
||||
region += widget.layout_offset
|
||||
self.widgets[widget] = RenderRegion(region, order, clip)
|
||||
self.region = self.region.union(region)
|
||||
self.contents_region = self.contents_region.union(region)
|
||||
|
||||
if isinstance(widget, View):
|
||||
sub_map = widget.layout.generate_map(
|
||||
|
||||
@@ -56,9 +56,11 @@ class View(Widget):
|
||||
def scroll(self) -> Offset:
|
||||
return Offset(self.scroll_x, self.scroll_y)
|
||||
|
||||
@property
|
||||
def virtual_size(self) -> Dimensions:
|
||||
return self.layout.map.size if self.layout.map else Dimensions(0, 0)
|
||||
virtual_size: Reactive[Dimensions] = Reactive(Dimensions(0, 0))
|
||||
|
||||
# @property
|
||||
# def virtual_size(self) -> Dimensions:
|
||||
# return self.layout.map.size if self.layout.map else Dimensions(0, 0)
|
||||
|
||||
# virtual_width: Reactive[int | None] = Reactive(None)
|
||||
# virtual_height: Reactive[int | None] = Reactive(None)
|
||||
@@ -157,6 +159,7 @@ class View(Widget):
|
||||
hidden, shown, resized = self.layout.reflow(
|
||||
self.console, width, height, self.scroll
|
||||
)
|
||||
self.virtual_size = self.layout.map.virtual_size
|
||||
self.app.refresh()
|
||||
|
||||
for widget in hidden:
|
||||
|
||||
@@ -2,12 +2,18 @@ from __future__ import annotations
|
||||
|
||||
from rich.console import RenderableType
|
||||
|
||||
from ..geometry import Offset, Dimensions
|
||||
from ..layouts.vertical import VerticalLayout
|
||||
from ..view import View
|
||||
from ..message import Message
|
||||
from ..widget import Widget
|
||||
from ..widgets import Static
|
||||
|
||||
|
||||
class VirtualSizeChange(Message):
|
||||
pass
|
||||
|
||||
|
||||
class WindowView(View, layout=VerticalLayout):
|
||||
def __init__(
|
||||
self,
|
||||
@@ -26,4 +32,8 @@ class WindowView(View, layout=VerticalLayout):
|
||||
assert isinstance(layout, VerticalLayout)
|
||||
layout.clear()
|
||||
layout.add(widget if isinstance(widget, Widget) else Static(widget))
|
||||
await self.refresh_layout()
|
||||
self.require_layout()
|
||||
|
||||
async def watch_virtual_size(self, size: Dimensions) -> None:
|
||||
await self.emit(VirtualSizeChange(self))
|
||||
|
||||
@@ -9,11 +9,11 @@ from .. import events
|
||||
from ..layouts.grid import GridLayout
|
||||
from ..message import Message
|
||||
from ..scrollbar import ScrollTo, ScrollBar
|
||||
from ..geometry import clamp
|
||||
from ..geometry import clamp, Offset, Dimensions
|
||||
from ..page import Page
|
||||
from ..reactive import watch
|
||||
from ..view import View
|
||||
from ..widgets import Placeholder
|
||||
|
||||
from ..widget import Widget
|
||||
|
||||
from ..reactive import Reactive
|
||||
|
||||
@@ -21,7 +21,7 @@ from ..reactive import Reactive
|
||||
class ScrollView(View):
|
||||
def __init__(
|
||||
self,
|
||||
renderable: RenderableType | None = None,
|
||||
contents: RenderableType | Widget | None = None,
|
||||
*,
|
||||
name: str | None = None,
|
||||
style: StyleType = "",
|
||||
@@ -32,7 +32,7 @@ class ScrollView(View):
|
||||
self.fluid = fluid
|
||||
self.vscroll = ScrollBar(vertical=True)
|
||||
self.hscroll = ScrollBar(vertical=False)
|
||||
self.window = WindowView("" if renderable is None else renderable)
|
||||
self.window = WindowView("" if contents is None else contents)
|
||||
layout = GridLayout()
|
||||
layout.add_column("main")
|
||||
layout.add_column("vscroll", size=1)
|
||||
@@ -70,9 +70,11 @@ class ScrollView(View):
|
||||
async def watch_y(self, new_value: float) -> None:
|
||||
self.window.scroll_y = round(new_value)
|
||||
self.vscroll.position = round(new_value)
|
||||
# self.window.require_repaint()
|
||||
self.window.require_layout()
|
||||
|
||||
async def update(self, renderabe: RenderableType) -> None:
|
||||
await self.window.update(renderabe)
|
||||
async def update(self, renderable: RenderableType) -> None:
|
||||
await self.window.update(renderable)
|
||||
|
||||
async def on_mount(self, event: events.Mount) -> None:
|
||||
assert isinstance(self.layout, GridLayout)
|
||||
@@ -172,19 +174,17 @@ class ScrollView(View):
|
||||
self.animate("x", self.target_x, speed=150, easing="out_cubic")
|
||||
self.animate("y", self.target_y, speed=150, easing="out_cubic")
|
||||
|
||||
async def message_page_update(self, message: Message) -> None:
|
||||
async def message_virtual_size_change(self, message: Message) -> None:
|
||||
virtual_size = self.window.virtual_size
|
||||
self.log("VIRTUAL_SIZE", self.size, virtual_size)
|
||||
self.x = self.validate_x(self.x)
|
||||
self.y = self.validate_y(self.y)
|
||||
self.vscroll.virtual_size = self.window.virtual_size.height
|
||||
self.vscroll.virtual_size = virtual_size.height
|
||||
self.vscroll.window_size = self.size.height
|
||||
|
||||
assert isinstance(self.layout, GridLayout)
|
||||
|
||||
if self.layout.show_column(
|
||||
"vscroll", self.window.virtual_size.height > self.size.height
|
||||
):
|
||||
if self.layout.show_column("vscroll", virtual_size.height > self.size.height):
|
||||
self.require_layout()
|
||||
if self.layout.show_row(
|
||||
"hscroll", self.window.virtual_size.width > self.size.width
|
||||
):
|
||||
if self.layout.show_row("hscroll", virtual_size.width > self.size.width):
|
||||
self.require_layout()
|
||||
|
||||
Reference in New Issue
Block a user