mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
fix cropping on scroll
This commit is contained in:
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user