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

Scrollable paragraph #519

Open
archydragon opened this issue Nov 27, 2022 · 3 comments
Open

Scrollable paragraph #519

archydragon opened this issue Nov 27, 2022 · 3 comments

Comments

@archydragon
Copy link

Hello. I sincerely apologize for using issues as helpdesk but cannot figure out how to make a thing which looks trivial: scrollable paragraph frame. Meaning, I need to display quite a wall of text and want to let user to scroll it with arrows/mouse wheel. I checked the other issues and the code of git-tui and chrome-log-beautifier, but they seem to operate with lists, not paragraphs. Or there is no easy builtin way to do that, and I need to write a component for this purpose from scratch?

image

Thanks in advance, the library is very neat and handy!

@ArthurSonzogni
Copy link
Owner

Hello,
Maybe you can try wrapping your component with the scroller from git-tui:
https://github.com/ArthurSonzogni/git-tui/blob/master/src/scroller.cpp

@archydragon
Copy link
Author

Thanks, I'll give it another shot today or later this week.

@archydragon
Copy link
Author

Still got no luck with paragraph, can't find an easy way to shift viewport there, as with a single paragraph element, the size is always 1. However, it works with just a list of strings which satisfies my needs for now:

class ScrollerBase : public ComponentBase {
public:
    explicit ScrollerBase(Component child) {
        Add(std::move(child));
    }

private:
    Element Render() final {
        auto focused = Focused() ? focus : ftxui::select;

        Element background = ComponentBase::Render();
        background->ComputeRequirement();
        size_ = background->requirement().min_y;

        // Values a bit hardcoded for bordered window, should be -0 and -2 if no border is used.
        min_selected_ = int(box_.y_max / 2) - 1;
        max_selected_ = size_ - int(box_.y_max / 2) - 1;
        if (selected_ == 0) {
            selected_ = min_selected_;
        }

        return dbox({
                   std::move(background),
                   vbox({
                       text("") | size(HEIGHT, EQUAL, selected_),
                       text("") | focused,
                   }),
               }) |
               vscroll_indicator | yframe | yflex | reflect(box_) | border;
    }

    bool OnEvent(Event event) final {
        if (event.is_mouse() && box_.Contain(event.mouse().x, event.mouse().y))
            TakeFocus();

        int selected_old = selected_;
        if (event == Event::ArrowUp || event == Event::Character('k') ||
            (event.is_mouse() && event.mouse().button == Mouse::WheelUp)) {
            selected_--;
        }
        if ((event == Event::ArrowDown || event == Event::Character('j') ||
             (event.is_mouse() && event.mouse().button == Mouse::WheelDown))) {
            selected_++;
        }
        if (event == Event::PageDown)
            selected_ += box_.y_max - box_.y_min;
        if (event == Event::PageUp)
            selected_ -= box_.y_max - box_.y_min;
        if (event == Event::Home)
            selected_ = 0;
        if (event == Event::End)
            selected_ = size_;

        if (selected_ < min_selected_) {
            selected_ = min_selected_;
        }
        if (selected_ > max_selected_) {
            selected_ = max_selected_;
        }

        selected_ = std::max(0, std::min(size_ - 1, selected_));
        return selected_old != selected_;
    }

    [[nodiscard]] bool Focusable() const final {
        return true;
    }

    int min_selected_ = 0;
    int max_selected_ = 0;
    int selected_ = 0;
    int size_ = 0;
    Box box_;
};

Something tells me that there should be an easier way to do that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants