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(Header(), edge="top")
await self.view.dock(Footer(), edge="bottom") 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") await self.view.dock(self.body, edge="right")
async def message_file_click(self, message: FileClick) -> None: async def message_file_click(self, message: FileClick) -> None:

View File

@@ -127,7 +127,7 @@ class Show(Event):
class Hide(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, 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. or if it has been offset beyond the edges of the terminal.

View File

@@ -17,12 +17,13 @@ class RenderRegion(NamedTuple):
class LayoutMap: class LayoutMap:
def __init__(self, size: Dimensions) -> None: 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] = {} self.widgets: dict[Widget, RenderRegion] = {}
@property @property
def size(self) -> Dimensions: def virtual_size(self) -> Dimensions:
return self.region.size return self.contents_region.size
def __getitem__(self, widget: Widget) -> RenderRegion: def __getitem__(self, widget: Widget) -> RenderRegion:
return self.widgets[widget] return self.widgets[widget]
@@ -51,7 +52,7 @@ class LayoutMap:
region += widget.layout_offset region += widget.layout_offset
self.widgets[widget] = RenderRegion(region, order, clip) 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): if isinstance(widget, View):
sub_map = widget.layout.generate_map( sub_map = widget.layout.generate_map(

View File

@@ -56,9 +56,11 @@ class View(Widget):
def scroll(self) -> Offset: def scroll(self) -> Offset:
return Offset(self.scroll_x, self.scroll_y) return Offset(self.scroll_x, self.scroll_y)
@property virtual_size: Reactive[Dimensions] = Reactive(Dimensions(0, 0))
def virtual_size(self) -> Dimensions:
return self.layout.map.size if self.layout.map else 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_width: Reactive[int | None] = Reactive(None)
# virtual_height: 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( hidden, shown, resized = self.layout.reflow(
self.console, width, height, self.scroll self.console, width, height, self.scroll
) )
self.virtual_size = self.layout.map.virtual_size
self.app.refresh() self.app.refresh()
for widget in hidden: for widget in hidden:

View File

@@ -2,12 +2,18 @@ from __future__ import annotations
from rich.console import RenderableType from rich.console import RenderableType
from ..geometry import Offset, Dimensions
from ..layouts.vertical import VerticalLayout from ..layouts.vertical import VerticalLayout
from ..view import View from ..view import View
from ..message import Message
from ..widget import Widget from ..widget import Widget
from ..widgets import Static from ..widgets import Static
class VirtualSizeChange(Message):
pass
class WindowView(View, layout=VerticalLayout): class WindowView(View, layout=VerticalLayout):
def __init__( def __init__(
self, self,
@@ -26,4 +32,8 @@ class WindowView(View, layout=VerticalLayout):
assert isinstance(layout, VerticalLayout) assert isinstance(layout, VerticalLayout)
layout.clear() layout.clear()
layout.add(widget if isinstance(widget, Widget) else Static(widget)) layout.add(widget if isinstance(widget, Widget) else Static(widget))
await self.refresh_layout()
self.require_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 ..layouts.grid import GridLayout
from ..message import Message from ..message import Message
from ..scrollbar import ScrollTo, ScrollBar from ..scrollbar import ScrollTo, ScrollBar
from ..geometry import clamp from ..geometry import clamp, Offset, Dimensions
from ..page import Page from ..page import Page
from ..reactive import watch
from ..view import View from ..view import View
from ..widgets import Placeholder from ..widget import Widget
from ..reactive import Reactive from ..reactive import Reactive
@@ -21,7 +21,7 @@ from ..reactive import Reactive
class ScrollView(View): class ScrollView(View):
def __init__( def __init__(
self, self,
renderable: RenderableType | None = None, contents: RenderableType | Widget | None = None,
*, *,
name: str | None = None, name: str | None = None,
style: StyleType = "", style: StyleType = "",
@@ -32,7 +32,7 @@ class ScrollView(View):
self.fluid = fluid self.fluid = fluid
self.vscroll = ScrollBar(vertical=True) self.vscroll = ScrollBar(vertical=True)
self.hscroll = ScrollBar(vertical=False) 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 = GridLayout()
layout.add_column("main") layout.add_column("main")
layout.add_column("vscroll", size=1) layout.add_column("vscroll", size=1)
@@ -70,9 +70,11 @@ class ScrollView(View):
async def watch_y(self, new_value: float) -> None: async def watch_y(self, new_value: float) -> None:
self.window.scroll_y = round(new_value) self.window.scroll_y = round(new_value)
self.vscroll.position = round(new_value) self.vscroll.position = round(new_value)
# self.window.require_repaint()
self.window.require_layout()
async def update(self, renderabe: RenderableType) -> None: async def update(self, renderable: RenderableType) -> None:
await self.window.update(renderabe) await self.window.update(renderable)
async def on_mount(self, event: events.Mount) -> None: async def on_mount(self, event: events.Mount) -> None:
assert isinstance(self.layout, GridLayout) 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("x", self.target_x, speed=150, easing="out_cubic")
self.animate("y", self.target_y, 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.x = self.validate_x(self.x)
self.y = self.validate_y(self.y) 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 self.vscroll.window_size = self.size.height
assert isinstance(self.layout, GridLayout) assert isinstance(self.layout, GridLayout)
if self.layout.show_column( if self.layout.show_column("vscroll", virtual_size.height > self.size.height):
"vscroll", self.window.virtual_size.height > self.size.height
):
self.require_layout() self.require_layout()
if self.layout.show_row( if self.layout.show_row("hscroll", virtual_size.width > self.size.width):
"hscroll", self.window.virtual_size.width > self.size.width
):
self.require_layout() self.require_layout()