Skip to content

using RichLog instead of ScrollView for TextScrollView #32

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 2, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 8 additions & 61 deletions ui/scrollable_area.py
Original file line number Diff line number Diff line change
@@ -1,81 +1,28 @@
from __future__ import annotations
from textual.widgets import RichLog

from textual.reactive import Reactive
from textual.widgets import Static
from textual.scroll_view import ScrollView
from textual.app import App, ComposeResult
from textual.geometry import Size
from rich.console import RenderableType
from textual.widgets import Markdown
from rich.text import Text


from textual.app import App, ComposeResult
from textual.geometry import Size
from textual.strip import Strip
from textual.scroll_view import ScrollView

from rich.segment import Segment

class TextScrollView(ScrollView):
class TextScrollView(RichLog):
COMPONENT_CLASSES = {
"box", # Class for the main text container
"rich-text--line", # Class for each line of text
}
DEFAULT_CSS = """
TextScrollView {
height: 100%;
scrollbar-size: 1 1;
}
"""

def __init__(self, title = "", lines: list[str] = None, component_id: str = None) -> None:
super().__init__()
def __init__(self, title: str = "", component_id: str = None) -> None:
super().__init__(name=title, auto_scroll=True, markup=True)
self.border_title = title
self.lines = lines if lines is not None else []
self.lines = lines
if lines:
self.virtual_size = Size(0, len(lines))
else:
self.virtual_size = Size(0, 5)

if component_id:
self.id = component_id

def update_virtual_size(self) -> None:
"""Update the virtual size based on the number of lines."""
self.virtual_size = Size(0, len(self.lines))

def render_line(self, y: int) -> Strip:
"""Render a line of the widget. y is relative to the top of the widget."""
scroll_x, scroll_y = self.scroll_offset
y += scroll_y

if self.lines:
if y >= len(self.lines):
return Strip.blank(self.size.width)

rich_text = Text.from_markup(self.lines[y])
segments = list(rich_text.render(self.app.console))

strip = Strip(segments, sum(segment.cell_length for segment in segments))
strip = strip.crop(scroll_x, scroll_x + self.size.width)
return strip
return Strip.blank(self.size.width)

def append(self, lines: list[str]):
if not self.lines:
self.lines = []

self.lines += lines
self.update_virtual_size()
self.refresh(layout=True)
self.scroll_to(y = self.max_scroll_y, speed=300)
self.write("\n".join(lines))

def text(self, lines: list[str]):
if not self.lines:
self.lines = []

self.lines = lines
self.update_virtual_size()
self.refresh(layout=True)
self.scroll_to(y = self.max_scroll_y, speed=300)
self.clear()
self.append(lines)