fix cropping on scroll

This commit is contained in:
Will McGugan
2021-07-28 21:04:25 +01:00
parent de81cf6860
commit ecc5d24b54
7 changed files with 39 additions and 30 deletions

View File

@@ -10,7 +10,9 @@ class GridTest(App):
async def on_mount(self, event: events.Mount) -> None:
grid = await self.view.dock_grid(edge="left", size=70, name="left")
left = self.view["left"]
self.view["left"].scroll_y = 5
self.view["left"].scroll_x = 5
grid.add_column(fraction=1, name="left", min_size=20)
grid.add_column(size=30, name="center")
@@ -27,18 +29,12 @@ class GridTest(App):
area4="right,top-start|middle-end",
)
def make_placeholder(name: str) -> Placeholder:
p = Placeholder(name=name)
p.layout_offset_x = 10
p.layout_offset_y = 0
return p
grid.place(
area1=make_placeholder(name="area1"),
area2=make_placeholder(name="area2"),
area3=make_placeholder(name="area3"),
area4=make_placeholder(name="area4"),
area1=Placeholder(name="area1"),
area2=Placeholder(name="area2"),
area3=Placeholder(name="area3"),
area4=Placeholder(name="area4"),
)
GridTest.run(title="Grid Test")
GridTest.run(title="Grid Test", log="textual.log")

View File

@@ -18,6 +18,7 @@ from rich.style import Style
from . import log
from ._loop import loop_last
from .layout_map import LayoutMap
from ._lines import crop_lines
from ._types import Lines
from .geometry import clamp, Region, Offset, Dimensions
@@ -95,11 +96,16 @@ class Layout(ABC):
self.renders.clear()
self._layout_map = None
def reflow(self, console: Console, width: int, height: int) -> ReflowResult:
def reflow(
self, console: Console, width: int, height: int, scroll: Offset
) -> ReflowResult:
self.reset()
map = self.generate_map(
console, Dimensions(width, height), Region(0, 0, width, height)
console,
Dimensions(width, height),
Region(0, 0, width, height),
scroll,
)
self._require_update = False
@@ -157,7 +163,7 @@ class Layout(ABC):
@abstractmethod
def generate_map(
self, console: Console, size: Dimensions, viewport: Region
self, console: Console, size: Dimensions, viewport: Region, scroll: Offset
) -> LayoutMap:
"""Generate a layout map that defines where on the screen the widgets will be drawn.
@@ -360,7 +366,6 @@ class Layout(ABC):
for region, clip, lines in chain(
renders, [(screen, screen, background_render)]
):
# region = region.intersection(clip)
for y, line in enumerate(lines, region.y):
if clip_y > y > clip_y2:
continue
@@ -396,6 +401,9 @@ class Layout(ABC):
)
self.renders[widget] = (region, clip, new_lines)
update_lines = self.render(console, region.intersection(clip)).lines
update_lines = self.render(console, region).lines
return LayoutUpdate(update_lines, region.x, region.y)
clipped_region = region.intersection(clip)
update = LayoutUpdate(update_lines, clipped_region.x, clipped_region.y)
return update

View File

@@ -54,7 +54,9 @@ class LayoutMap:
self.region = self.region.union(region.intersection(clip))
if isinstance(widget, View):
sub_map = widget.layout.generate_map(console, region.size, region)
sub_map = widget.layout.generate_map(
console, region.size, region, widget.scroll
)
for widget, (sub_region, sub_order, sub_clip) in sub_map.items():
sub_region += region.origin
sub_clip = sub_clip.intersection(clip)

View File

@@ -8,7 +8,7 @@ from typing import Iterable, TYPE_CHECKING, Sequence
from rich.console import Console
from .._layout_resolve import layout_resolve
from ..geometry import Region, Dimensions
from ..geometry import Offset, Region, Dimensions
from ..layout import Layout
from ..layout_map import LayoutMap
@@ -49,7 +49,7 @@ class DockLayout(Layout):
yield from dock.widgets
def generate_map(
self, console: Console, size: Dimensions, viewport: Region
self, console: Console, size: Dimensions, viewport: Region, scroll: Offset
) -> LayoutMap:
map: LayoutMap = LayoutMap(size)
@@ -90,7 +90,7 @@ class DockLayout(Layout):
add_widget(widget, Region(x, render_y, width, layout_size), order)
render_y += layout_size
remaining = max(0, remaining - layout_size)
region = Region(x, y + total, width, height - total)
region = Region(x, y + total, width, height - total) - scroll
elif dock.edge == "bottom":
sizes = layout_resolve(height, dock_options)
@@ -111,7 +111,7 @@ class DockLayout(Layout):
)
render_y -= layout_size
remaining = max(0, remaining - layout_size)
region = Region(x, y, width, height - total)
region = Region(x, y, width, height - total) - scroll
elif dock.edge == "left":
sizes = layout_resolve(width, dock_options)
@@ -128,7 +128,7 @@ class DockLayout(Layout):
add_widget(widget, Region(render_x, y, layout_size, height), order)
render_x += layout_size
remaining = max(0, remaining - layout_size)
region = Region(x + total, y, width - total, height)
region = Region(x + total, y, width - total, height) - scroll
elif dock.edge == "right":
sizes = layout_resolve(width, dock_options)
@@ -149,7 +149,7 @@ class DockLayout(Layout):
)
render_x -= layout_size
remaining = max(0, remaining - layout_size)
region = Region(x, y, width - total, height)
region = Region(x, y, width - total, height) - scroll
layers[dock.z] = region

View File

@@ -264,7 +264,7 @@ class GridLayout(Layout):
return self.widgets.keys()
def generate_map(
self, console: Console, size: Dimensions, viewport: Region
self, console: Console, size: Dimensions, viewport: Region, scroll: Offset
) -> LayoutMap:
"""Generate a map that associates widgets with their location on screen.
@@ -328,6 +328,7 @@ class GridLayout(Layout):
return names, tracks, len(spans), max_size
def add_widget(widget: Widget, region: Region, order: tuple[int, int]):
region -= scroll
map.add_widget(console, widget, region, order, viewport)
# region = region + widget.layout_offset
# map[widget] = RenderRegion(region, order, offset)

View File

@@ -28,7 +28,7 @@ class VerticalLayout(Layout):
return self._widgets
def generate_map(
self, console: Console, size: Dimensions, viewport: Region
self, console: Console, size: Dimensions, viewport: Region, scroll: Offset
) -> LayoutMap:
index = 0
width, height = size
@@ -54,7 +54,7 @@ class VerticalLayout(Layout):
else:
add_widget(
widget,
Region(x, y, region.width, region.height) - scroll_offset,
Region(x, y, region.width, region.height) - scroll,
clip,
)
y += region.height + gutter_height

View File

@@ -53,7 +53,7 @@ class View(Widget):
scroll_y: Reactive[int] = Reactive(0)
@property
def scroll_offset(self) -> Offset:
def scroll(self) -> Offset:
return Offset(self.scroll_x, self.scroll_y)
@property
@@ -154,7 +154,9 @@ class View(Widget):
width, height = self.console.size
# virtual_width, virtual_height = self.virtual_size
hidden, shown, resized = self.layout.reflow(self.console, width, height)
hidden, shown, resized = self.layout.reflow(
self.console, width, height, self.scroll
)
self.app.refresh()
for widget in hidden: