virtual size

This commit is contained in:
Will McGugan
2021-07-29 21:20:15 +01:00
parent 4ad342d9f2
commit 72b3b58ef5
6 changed files with 40 additions and 24 deletions

View File

@@ -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:

View File

@@ -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.

View File

@@ -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(

View File

@@ -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:

View File

@@ -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))

View File

@@ -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()