How would one go about scrollable table? #757
-
Hi, I want to make a scrollable table where the row contents are scrollable, but wasn't able to get it to work after trying to add a frame & scroll_indicator. Do you have suggestions on how to go about this? Or any examples to help? // Copyright 2022 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.
#include <memory> // for allocator, __shared_ptr_access, shared_ptr
#include <string> // for to_string, operator+
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Button, Renderer, Vertical
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/component_options.hpp" // for ButtonOption
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
#include "ftxui/dom/elements.hpp" // for operator|, text, Element, hbox, separator, size, vbox, border, frame, vscroll_indicator, HEIGHT, LESS_THAN
#include "ftxui/screen/color.hpp" // for Color, Color::Default, Color::GrayDark, Color::White
#include "ftxui/dom/table.hpp" // for Table
using namespace ftxui;
Component MakeOne() {
class Impl : public ComponentBase {
Element Render() final {
return hbox({
text("Hello!")
});
}
bool OnEvent(Event event) final {
return true;
}
};
return Make<Impl>();
}
int main() {
auto container = Container::Vertical({});
for (int i = 0 ;i < 30; i++) {
container->Add(MakeOne());
}
auto screen = ScreenInteractive::FitComponent();
auto renderer = Renderer(container, [&] {
return vbox({
container->Render() | vscroll_indicator | frame |
size(HEIGHT, LESS_THAN, 20),
}) |
border;
});
auto component = CatchEvent(renderer, [&](Event event) {
if (event == Event::Character('q')) {
screen.ExitLoopClosure()();
return true;
}
return false;
});
screen.Loop(component);
return 0;
} |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
I think there is a bug. I can get RadioButton, Menus, and Buttons to scroll, but not much else. Even there official code here that should support vscroll does not from i can see - https://github.com/ArthurSonzogni/FTXUI/blob/main/examples/component/homescreen.cpp |
Beta Was this translation helpful? Give feedback.
-
Hello @bqle Here's a breakdown of the necessary steps, based on your example: Focusable:The inner components (the ones you want to scroll through) must declare themselves as Focusable. This lets the parent container know that these components can receive focus. bool Focusable() const final { return true; } Visual Feedback:When an inner component has focus (is currently Active()/Selected()), it needs to provide visual feedback. Event Handling:The inner components shouldn't consume arrow key or mouse events by immediately returning true from their Here is the solution based on your example. // Copyright 2022 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.
#include <memory> // for allocator, __shared_ptr_access, shared_ptr
#include <string> // for to_string, operator+
#include "ftxui/component/captured_mouse.hpp" // for ftxui
#include "ftxui/component/component.hpp" // for Button, Renderer, Vertical
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/component_options.hpp" // for ButtonOption
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
#include "ftxui/dom/elements.hpp" // for operator|, text, Element, hbox, separator, size, vbox, border, frame, vscroll_indicator, HEIGHT, LESS_THAN
#include "ftxui/screen/color.hpp" // for Color, Color::Default, Color::GrayDark, Color::White
#include "ftxui/dom/table.hpp" // for Table
using namespace ftxui;
Component MakeOne() {
class Impl : public ComponentBase {
Element Render() final {
auto element = text("Hello!");
if (Focused()) {
element = focus(element);
element |= inverted;
} else if (Active()) {
element = select(element);
element |= inverted;
}
return element;
}
bool Focusable() const final { return true; }
};
return Make<Impl>();
}
int main() {
auto container = Container::Vertical({});
for (int i = 0 ;i < 30; i++) {
container->Add(MakeOne());
}
auto screen = ScreenInteractive::FitComponent();
auto renderer = Renderer(container, [&] {
return container->Render()
| vscroll_indicator
| frame
| size(HEIGHT, LESS_THAN, 20)
| border;
});
auto component = CatchEvent(renderer, [&](Event event) {
if (event == Event::Character('q')) {
screen.Exit();
return true;
}
return false;
});
screen.Loop(component);
return 0;
}
|
Beta Was this translation helpful? Give feedback.
Hello @bqle
Here's a breakdown of the necessary steps, based on your example:
Focusable:
The inner components (the ones you want to scroll through) must declare themselves as Focusable. This lets the parent container know that these components can receive focus.
In your example, this is achieved with:
Visual Feedback:
When an inner component has focus (is currently Active()/Selected()), it needs to provide visual feedback.
Use decorators like
focus
orselect
in the component's Render() method to give theframe
the location of the element to focus.You can also use
inverted
to provide visual feedback.Event Handling:
The inner components should…