Skip to content
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

Horizontal scrolling #77

Closed
samuelcolvin opened this issue Aug 27, 2021 · 9 comments
Closed

Horizontal scrolling #77

samuelcolvin opened this issue Aug 27, 2021 · 9 comments
Labels
bug Something isn't working

Comments

@samuelcolvin
Copy link

(hope you don't mind me opening an issue to ask a question, I've tried hard to get to the bottom of this myself)

I'm trying to get horizontal scrolling working with textual and a rich table, but no luck

Below is what I have so far.

It seems like the table is refusing to exceed the width of the terminal, thus the horizontal scroll bar of ScrollView is not coming into play.

Vertical scrolling is working great.

What am I doing wrong?

(ref: https://twitter.com/samuel_colvin/status/1426289617632960515)

from rich.table import Table

from textual import events
from textual.app import App
from textual.widgets import Header, Footer, ScrollView


class MyApp(App):
    """An example of a very simple Textual App"""

    async def on_load(self, event: events.Load) -> None:
        await self.bind("q", "quit", "Quit")

    async def on_mount(self, event: events.Mount) -> None:

        self.body = body = ScrollView()
        body.virtual_size.width = 300

        await self.view.dock(body)

        async def add_content():
            table = Table(title="Demo", width=300, min_width=300)

            for i in range(40):
                table.add_column(f'Col {i + 1}', style='magenta')

            for i in range(40):
                table.add_row(*[f'cell {i},{j}' for j in range(40)])

            await body.update(table)

        await self.call_later(add_content)


MyApp.run(title="Simple App", log="textual.log")

Versions:

python 3.9.5
textual==0.1.10
rich==10.7.0
OS: Ubuntu 21.04 with standard terminal
@willmcgugan
Copy link
Collaborator

Hi Samuel,

Thanks for the bug report. The horizontal scroll bar should show automatically if he renderable is wider than the widget size, but I can see from a quick test that it isn't. Will fix that in the next update.

@willmcgugan willmcgugan added the bug Something isn't working label Aug 27, 2021
@samuelcolvin
Copy link
Author

Thanks so much, not sure if it's part of the same problem, but horizontal scrolling didn't seem to be working at all - e.g. if I used the left and right arrows, no scrolling occurred.

@willmcgugan
Copy link
Collaborator

Yeah, they aren't showing anywhere. It was working at one point. But they haven't been as well tested as vertical scrollbars.

@willmcgugan
Copy link
Collaborator

Hi @samuelcolvin Horizontal scrolling should be fixed in v0.1.11 (just released)

@samuelcolvin
Copy link
Author

thanks so much. I'll test now.

@samuelcolvin
Copy link
Author

samuelcolvin commented Sep 12, 2021

Thanks so much, works brilliantly.

The only small problem I found was that by default I could scroll vertically with the arrow keys, but not horizontally.

I fixed that fairly easily as follows:

from rich.table import Table

from textual import events
from textual.app import App
from textual.widgets import ScrollView


class CustomScrollView(ScrollView):
    def move_left(self) -> None:
        self.target_x -= 2
        self.animate("x", self.target_x, speed=80, easing="out_cubic")

    def move_right(self) -> None:
        self.target_x += 2
        self.animate("x", self.target_x, speed=80, easing="out_cubic")


class MyApp(App):
    """An example of a very simple Textual App"""

    async def on_load(self, event: events.Load) -> None:
        await self.bind("q", "quit", "Quit")

    def on_key(self, event: events.Key):
        if event.key == 'left':
            self.body.move_left()
        elif event.key == 'right':
            self.body.move_right()

    async def on_mount(self, event: events.Mount) -> None:

        self.body = body = CustomScrollView(auto_width=True)

        await self.view.dock(body)

        async def add_content():
            table = Table(title="Demo")

            for i in range(40):
                table.add_column(f"Col {i + 1}", style="magenta")
            for i in range(200):
                table.add_row(*[f"cell {i},{j}" for j in range(40)])

            await body.update(table)

        await self.call_later(add_content)
        self.log('HELLO')


MyApp.run(title="Simple App", log="textual.log")

Happy to add that to the example if you don't think it should work out of the box?

@samuelcolvin
Copy link
Author

the other thing I noticed is that rendering the table is relatively slow, even for this modest table. Any idea what's causing that slow down and if it can be solved?

I'm thinking of a tool that can easily show a table thousands of rows a hundred columns, if I extrapolated the current performance to that it would get very slow to load.

@willmcgugan
Copy link
Collaborator

The scroll view widget should probably handle the left/right keys. I'll add that in the next update.

Large tables will be slow to render in a ScrollView, since it renders everything up front. There will eventually be a datatable widget that is optimized to only render the visible area.

@github-actions
Copy link

Did I solve your problem?

Consider sponsoring my work on Textual with a monthly donation.

Or buy me a coffee to say thanks.

Will McGugan

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants