Making dynamic element scrollable? #930
Replies: 1 comment
-
You are missing For fun, I also added mouse click and scroll event handling. Notice how A common pattern is to have a final // includes ....
using namespace ftxui;
using owner_t = std::string;
using payload_t = std::string;
using message_t = std::pair<owner_t, payload_t>;
class chatHistory : public ComponentBase {
public:
explicit chatHistory(owner_t owner, std::vector<message_t>& messages) : m_owner(owner), m_messages(messages) {}
int focused = 0;
// Mouse click support:
std::vector<Box> boxes_;
Box box_;
bool Focusable() const final { return true; }
Element Render() noexcept final {
const int size = m_messages.size();
boxes_.resize(size);
focused = clamp(focused, 0, size - 1);
const bool is_chat_focused = Focused();
Elements messageElements;
for (int index = 0; index < size; index++) {
const auto& message = m_messages[index];
auto focus_management = (focused != index) ? nothing : is_chat_focused ? focus : select;
if (message.first == m_owner) {
messageElements.push_back(hbox({
filler(),
hbox({
text(message.first + ": ") | bold | color(Color::White),
text(message.second)
}) | border | color(Color::Yellow)
}) | focus_management | reflect(boxes_[index]));
} else {
messageElements.push_back(hbox({
hbox({
text(message.first + ": ") | bold | color(Color::White),
text(message.second)
}) | border | color(Color::Cyan),
filler()
}) | focus_management | reflect(boxes_[index]));
}
if ((focused == index) && is_chat_focused) { messageElements.back() = messageElements.back() | bgcolor(Color::GrayDark); }
}
return vbox(messageElements);
}
bool OnEvent(Event event) override {
if (!CaptureMouse(event)) { return false; }
if (event.is_mouse()) {
if (event.mouse().button == Mouse::WheelDown || event.mouse().button == Mouse::WheelUp) {
const int old_focused = focused;
if (event.mouse().button == Mouse::WheelUp) { focused--; }
if (event.mouse().button == Mouse::WheelDown) { focused++; }
focused = clamp(focused, 0, (int)m_messages.size() - 1);
return true;
}
if (event.mouse().button != Mouse::Left) { return false; }
for (int i = 0; i < m_messages.size(); ++i) {
if (!boxes_[i].Contain(event.mouse().x, event.mouse().y)) { continue; }
TakeFocus();
focused = i;
}
return false;
}
if (Focused()) {
const int old_focused = focused;
if (event == Event::ArrowUp) focused--;
if (event == Event::ArrowDown) focused++;
focused = clamp(focused, 0, (int)m_messages.size() - 1);
if (focused != old_focused) { return true; }
}
return false;
}
private:
owner_t m_owner;
std::vector<message_t>& m_messages;
};
int main() {
std::vector<message_t> messages = {{"Morpheus", "Wake up, Neo..."}, {"Morpheus", "The Matrix has you..."}, {"Neo", " What the hell?"}, {"Morpheus", " Follow the white rabbit."}, {"Neo", " Follow the what rabbit."}, {"Morpheus", " Knock, knock, Neo."}};
for (size_t i = 0; i < 100; ++i) { messages.push_back(messages[i % messages.size()]); }
auto screen = ScreenInteractive::Fullscreen();
auto chat_history = std::make_shared<chatHistory>("Neo", messages); // single
screen.Loop(Renderer(chat_history, [&]() -> Element { return chat_history->Render() | vscroll_indicator | yframe; }));
} |
Beta Was this translation helpful? Give feedback.
-
Hi I'm just getting familiar with FTXUI. I'm trying to implement a
Component
class which is actually responsible to present chat history for basic chat program. I'm struggling with making it scrollable. I think I'm missing some fundamental points, so here is a snippet from my code:Beta Was this translation helpful? Give feedback.
All reactions