Skip to content

ScrollViewState: Add helper interface #72

Open
@Teufelchen1

Description

@Teufelchen1

Hello 🐦

In my app I want the following behavior while using ScrollViewState under the hood:
A user runs the app and sees e.g. a log. The log is rendered using ScrollView+ScrollViewState.
The log regularly gets updates and grows.
Because I can call .scroll_to_bottom() during each render, the user always sees the latest log entries.

Now, the user scrolls up the log and observes older entries. Even though new entries get added to the log, the view remains fixed on the position the user scrolled to.

Later, the user scrolls back down to end of the scroll view, seeing the latest entries again.
When new entries are added, the view remains at the bottom as before.

Here are some options that I believe make ScrollView easier to use. Let me know if you have further questions. Should you accept my proposal, I would love to file a PR.

My current solution

The current solution works fine but feels a bit unclean. I manually keep track on the scroll position, replicating work that is already been done inside ScrollViewState iirc.

event_loop(..) {
    MouseEventKind::ScrollDown => {
        self.scroll_position = self.scroll_position.saturating_sub(1);
        self.follow_the_bottom = self.scroll_position == 0;
        self.scroll_state.scroll_down();
    }
    MouseEventKind::ScrollUp => {
        self.follow_the_bottom = false;
        if self.scroll_state.offset().y != 0 {
            self.scroll_position = self.scroll_position.saturating_add(1);
        }
        self.scroll_state.scroll_up();
    }
}

/* ... */
fn draw(...) {
    if self.follow_the_bottom {
        self.scroll_state.scroll_to_bottom()
    }
}

Proposed solution

The ScrollViewState can just tell me where the scroll position is.

event_loop(..) {
    MouseEventKind::ScrollDown => {
        self.scroll_state.scroll_down();
        self.follow_the_bottom = self.scroll_state.is_at_bottom();
    }
    MouseEventKind::ScrollUp => {
        self.follow_the_bottom = false;
        self.scroll_state.scroll_up();
    }
}

/* ... */
fn draw(...) {
    if self.follow_the_bottom {
        self.scroll_state.scroll_to_bottom()
    }
}

Alternative solution

Let me ask for the size of the scroll view. Theoretically, I could calculate this info myself but in practice, that leads to code in the event loop (or where ever you have your "business" logic) reasoning about the ui layout. It's not too bad but it feels wrong to me.

The ScrollViewState can just tell me where the scroll position is.

event_loop(..) {
    MouseEventKind::ScrollDown => {
        self.scroll_state.scroll_down();
        self.follow_the_bottom =  self.scroll_state.offset().y == self.scroll_state.size.height();
    }
    MouseEventKind::ScrollUp => {
        self.follow_the_bottom = false;
        self.scroll_state.scroll_up();
    }
}

/* ... */
fn draw(...) {
    if self.follow_the_bottom {
        self.scroll_state.scroll_to_bottom()
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions