From dc70091203c37535a4411aec0f893d36b3f3de18 Mon Sep 17 00:00:00 2001 From: Clement Roblot Date: Mon, 2 Dec 2024 15:40:50 +0700 Subject: [PATCH] Added a callback on selection change --- examples/component/selectable_input.cpp | 6 ++++ .../ftxui/component/screen_interactive.hpp | 4 +++ src/ftxui/component/screen_interactive.cpp | 35 +++++++++++++++++-- 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/examples/component/selectable_input.cpp b/examples/component/selectable_input.cpp index 0546cd9b..779e3283 100644 --- a/examples/component/selectable_input.cpp +++ b/examples/component/selectable_input.cpp @@ -27,12 +27,18 @@ Element LoremIpsum() { int main() { auto screen = ScreenInteractive::TerminalOutput(); + int counter = 0; + + screen.onSelectionModified([&]{ + counter++; + }); auto quit = Button("Quit", screen.ExitLoopClosure()); // The components: auto renderer = Renderer(quit, [&] { return vbox({ + text("Select: " + std::to_string(counter)), window(text("Horizontal split"), hbox({ LoremIpsum(), separator(), diff --git a/include/ftxui/component/screen_interactive.hpp b/include/ftxui/component/screen_interactive.hpp index 38d2e50a..1c0f8685 100644 --- a/include/ftxui/component/screen_interactive.hpp +++ b/include/ftxui/component/screen_interactive.hpp @@ -70,6 +70,8 @@ class ScreenInteractive : public Screen { // Selection API. // TODO: Implement somethings here. + std::string GetSelectedContent(void); + void onSelectionModified(std::function callback); private: void ExitNow(); @@ -141,6 +143,8 @@ class ScreenInteractive : public Screen { int selection_start_y_ = 0; int selection_end_x_ = 0; int selection_end_y_ = 0; + bool selection_changed = false; + std::function selection_changed_callback_ = nullptr; friend class Loop; diff --git a/src/ftxui/component/screen_interactive.cpp b/src/ftxui/component/screen_interactive.cpp index 2b474933..dab73ecb 100644 --- a/src/ftxui/component/screen_interactive.cpp +++ b/src/ftxui/component/screen_interactive.cpp @@ -576,6 +576,21 @@ void ScreenInteractive::ForceHandleCtrlZ(bool force) { force_handle_ctrl_z_ = force; } +/// @brief Returns the content of the current selection +std::string ScreenInteractive::GetSelectedContent(void) +{ + +} + +/// @brief Sets a callback on modifications of the selection +/// This callback is called when the start of end of the selection moved. +/// Not when the content/characters inside of the selection change. +/// @param callback The function to callback on modifications of the selection. +void ScreenInteractive::onSelectionModified(std::function callback) +{ + selection_changed_callback_ = std::move(callback); +} + /// @brief Return the currently active screen, or null if none. // static ScreenInteractive* ScreenInteractive::Active() { @@ -828,6 +843,8 @@ void ScreenInteractive::HandleTask(Component component, Task& task) { // private bool ScreenInteractive::HandleSelection(Event event) { + selection_changed = false; + if (!event.is_mouse()) { return false; } @@ -843,6 +860,8 @@ bool ScreenInteractive::HandleSelection(Event event) { selection_start_y_ = mouse.y; selection_end_x_ = mouse.x; selection_end_y_ = mouse.y; + + selection_changed = true; } if (!selection_pending_) { @@ -850,8 +869,13 @@ bool ScreenInteractive::HandleSelection(Event event) { } if (mouse.motion == Mouse::Moved) { - selection_end_x_ = mouse.x; - selection_end_y_ = mouse.y; + if((mouse.x != selection_end_x_) || (mouse.y != selection_end_y_)) { + selection_end_x_ = mouse.x; + selection_end_y_ = mouse.y; + + selection_changed = true; + } + return true; } @@ -859,6 +883,8 @@ bool ScreenInteractive::HandleSelection(Event event) { selection_pending_ = nullptr; selection_end_x_ = mouse.x; selection_end_y_ = mouse.y; + + selection_changed = true; return true; } @@ -944,6 +970,11 @@ void ScreenInteractive::Draw(Component component) { selection_end_x_, selection_end_y_); Render(*this, document.get(), selection); + if((selection_changed == true) && (selection_changed_callback_ != nullptr)) + { + selection_changed_callback_(); + } + // Set cursor position for user using tools to insert CJK characters. { const int dx = dimx_ - 1 - cursor_.x + int(dimx_ != terminal.dimx);