diff --git a/sandbox/uber.css b/sandbox/uber.css index 5099412f7..bb848e433 100644 --- a/sandbox/uber.css +++ b/sandbox/uber.css @@ -2,8 +2,8 @@ /* border: heavy green;*/ layout: vertical; text: on dark_green; - overflow: auto auto; - /*border: heavy white;*/ + overflow: hidden auto; + border: heavy white; } .list-item { diff --git a/src/textual/_animator.py b/src/textual/_animator.py index 4accb9312..e16b34f09 100644 --- a/src/textual/_animator.py +++ b/src/textual/_animator.py @@ -232,7 +232,7 @@ class Animator: animation = self._animations[animation_key] if animation(animation_time): del self._animations[animation_key] - self.on_animation_frame() + self.on_animation_frame() def on_animation_frame(self) -> None: # TODO: We should be able to do animation without refreshing everything diff --git a/src/textual/_compositor.py b/src/textual/_compositor.py index 180c54ed3..0caa8cab3 100644 --- a/src/textual/_compositor.py +++ b/src/textual/_compositor.py @@ -196,7 +196,6 @@ class Compositor: order: tuple[int, ...], clip: Region, ) -> None: - widget.pre_render() widgets.add(widget) styles_offset = widget.styles.offset layout_offset = ( @@ -205,21 +204,21 @@ class Compositor: else ORIGIN ) + # Container region is minus border + container_region = region.shrink(widget.styles.gutter) + if widget.layout is not None: scroll = widget.scroll - # Container region is minus border - container_region = region.shrink(widget.styles.gutter) - # The region that contains the content (container region minus scrollbars) child_region = widget._arrange_container(container_region) sub_clip = clip.intersection(child_region) - total_region = child_region.reset_origin - + arrange_region = child_region + total_region = arrange_region.reset_origin placements, arranged_widgets = widget.layout.arrange( - widget, child_region.size, scroll + widget, arrange_region.size, scroll ) widgets.update(arranged_widgets) placements = sorted(placements, key=attrgetter("order")) @@ -234,13 +233,13 @@ class Compositor: sub_clip, ) - map[widget] = RenderRegion( - child_region + layout_offset, - order, - sub_clip, - total_region.size, - container_region.size, - ) + # map[widget] = RenderRegion( + # child_region + layout_offset, + # order, + # sub_clip, + # total_region.size, + # container_region.size, + # ) for chrome_widget, chrome_region in widget._arrange_scrollbars( container_region.size @@ -249,10 +248,18 @@ class Compositor: chrome_region + container_region.origin + layout_offset, order, clip, - chrome_region.size, - chrome_region.size, + container_region.size, + container_region.size, ) + map[widget] = RenderRegion( + region + layout_offset, + order, + clip, + total_region.size, + container_region.size, + ) + else: map[widget] = RenderRegion( @@ -260,7 +267,7 @@ class Compositor: order, clip, region.size, - region.size, + container_region.size, ) add_widget(root, size.region, (), size.region) diff --git a/src/textual/messages.py b/src/textual/messages.py index 8ebfe0eae..12def496f 100644 --- a/src/textual/messages.py +++ b/src/textual/messages.py @@ -27,6 +27,7 @@ class Update(Message, verbosity=3): return NotImplemented def can_replace(self, message: Message) -> bool: + # Update messages can replace update for the same widget return isinstance(message, Update) and self == message diff --git a/src/textual/widget.py b/src/textual/widget.py index 95c334c48..bb110010c 100644 --- a/src/textual/widget.py +++ b/src/textual/widget.py @@ -124,11 +124,11 @@ class Widget(DOMNode): @property def max_scroll_x(self) -> float: - return max(0, self.virtual_size.width - self.size.width) + return max(0, self.virtual_size.width - self.container_size.width) @property def max_scroll_y(self) -> float: - return max(0, self.virtual_size.height - self.size.height) + return max(0, self.virtual_size.height - self.container_size.height) @property def vscroll(self) -> ScrollBar: @@ -174,6 +174,8 @@ class Widget(DOMNode): overflow_x = styles.overflow_x overflow_y = styles.overflow_y + self.log(virtual=self.virtual_size, container=self.container_size) + width, height = self.container_size show_horizontal = self.show_horizontal_scrollbar @@ -192,16 +194,18 @@ class Widget(DOMNode): elif overflow_y == "auto": show_vertical = self.virtual_size.height > height + self.log(horizontal=show_horizontal, vertical=show_vertical) + self.show_horizontal_scrollbar = show_horizontal self.show_vertical_scrollbar = show_vertical - self.log( - "REFRESH_SCROLLBARS", - widget=self, - virtual_size=self.virtual_size, - size=self.size, - container_size=self.container_size, - ) + # self.log( + # "REFRESH_SCROLLBARS", + # widget=self, + # virtual_size=self.virtual_size, + # size=self.size, + # container_size=self.container_size, + # ) # return changed @property @@ -216,7 +220,6 @@ class Widget(DOMNode): return False, False enabled = self.show_vertical_scrollbar, self.show_horizontal_scrollbar - self.log(enabled) return enabled def scroll_to( @@ -234,10 +237,6 @@ class Widget(DOMNode): animate (bool, optional): Animate to new scroll position. Defaults to False. """ - self.log( - "scroll_to", x=x, y=y, max_x=self.max_scroll_x, max_y=self.max_scroll_y - ) - if animate: # TODO: configure animation speed if x is not None: @@ -277,16 +276,24 @@ class Widget(DOMNode): self.scroll_to(y=self.scroll_target_y - 1.5, animate=animate) def scroll_page_up(self, animate: bool = True) -> None: - self.scroll_to(y=self.scroll_target_y - self.size.height, animate=animate) + self.scroll_to( + y=self.scroll_target_y - self.container_size.height, animate=animate + ) def scroll_page_down(self, animate: bool = True) -> None: - self.scroll_to(y=self.scroll_target_y + self.size.height, animate=animate) + self.scroll_to( + y=self.scroll_target_y + self.container_size.height, animate=animate + ) def scroll_page_left(self, animate: bool = True) -> None: - self.scroll_to(x=self.scroll_target_x - self.size.width, animate=animate) + self.scroll_to( + x=self.scroll_target_x - self.container_size.width, animate=animate + ) def scroll_page_right(self, animate: bool = True) -> None: - self.scroll_to(x=self.scroll_target_x + self.size.width, animate=animate) + self.scroll_to( + x=self.scroll_target_x + self.container_size.width, animate=animate + ) def __init_subclass__(cls, can_focus: bool = True) -> None: super().__init_subclass__() @@ -491,16 +498,16 @@ class Widget(DOMNode): if self.show_vertical_scrollbar: self.vscroll.window_virtual_size = virtual_size.height self.vscroll.window_size = height - self.vscroll.refresh() + # self.vscroll.refresh() if self.show_horizontal_scrollbar: self.hscroll.window_virtual_size = virtual_size.width self.hscroll.window_size = width - self.hscroll.refresh() + # self.hscroll.refresh() # self.scroll_to(self.scroll_x, self.scroll_y) self.refresh(layout=True) self._refresh_scrollbars() - self.call_later(self.scroll_to, 0, 0) + self.call_later(self.scroll_to, self.scroll_x, self.scroll_y) # self.call_later(self._refresh_scrollbars) else: self.refresh() @@ -567,9 +574,6 @@ class Widget(DOMNode): self._repaint_required = True self.check_idle() - def pre_render(self) -> None: - self._refresh_scrollbars() - def render(self) -> RenderableType: """Get renderable for widget. diff --git a/src/textual/widgets/_placeholder.py b/src/textual/widgets/_placeholder.py index d6d8f81f2..c43b3100d 100644 --- a/src/textual/widgets/_placeholder.py +++ b/src/textual/widgets/_placeholder.py @@ -14,13 +14,6 @@ from ..reactive import Reactive from ..widget import Widget -class TPanel(Panel): - def __rich_console__(self, console, options): - - log("*", options) - return super().__rich_console__(console, options) - - @rich.repr.auto(angular=False) class Placeholder(Widget, can_focus=True): @@ -34,7 +27,7 @@ class Placeholder(Widget, can_focus=True): yield "mouse_over", self.mouse_over, False def render(self) -> RenderableType: - return TPanel( + return Panel( Align.center( Pretty(self, no_wrap=True, overflow="ellipsis"), vertical="middle" ),