Added a option to set the style of the selection

This commit is contained in:
Clement Roblot 2024-12-02 19:34:27 +07:00 committed by ArthurSonzogni
parent d62dc6e305
commit cbd28403af
No known key found for this signature in database
GPG Key ID: 41D98248C074CD6C
6 changed files with 63 additions and 20 deletions

View File

@ -73,9 +73,14 @@ int main() {
});
});
screen.onSelectionModified([&] {
selectionChangeCounter++;
selection = screen.GetSelectedContent(renderer);
screen.setSelectionOptions({
.transform = [](Pixel& pixel) {
pixel.underlined_double = true;
},
.on_change = [&] {
selectionChangeCounter++;
selection = screen.GetSelectedContent(renderer);
}
});
screen.Loop(renderer);

View File

@ -15,6 +15,7 @@
#include "ftxui/component/animation.hpp" // for TimePoint
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
#include "ftxui/component/event.hpp" // for Event
#include "ftxui/dom/selection.hpp" // for SelectionOption
#include "ftxui/component/task.hpp" // for Task, Closure
#include "ftxui/screen/screen.hpp" // for Screen
@ -70,7 +71,7 @@ class ScreenInteractive : public Screen {
// Selection API.
std::string GetSelectedContent(Component component);
void onSelectionModified(std::function<void(void)> callback);
void setSelectionOptions(SelectionOption option);
private:
void ExitNow();
@ -143,7 +144,7 @@ class ScreenInteractive : public Screen {
int selection_end_x_ = 0;
int selection_end_y_ = 0;
bool selection_changed = false;
std::function<void(void)> selection_changed_callback_ = nullptr;
SelectionOption selection_options_ = SelectionOption::Simple();
friend class Loop;

View File

@ -5,15 +5,33 @@
#ifndef FTXUI_DOM_SELECTION_HPP
#define FTXUI_DOM_SELECTION_HPP
#include <functional>
#include "ftxui/screen/box.hpp" // for Box
#include "ftxui/screen/pixel.hpp" // for Pixel
namespace ftxui {
/// @brief Option for the selection of content.
/// @ingroup component
struct SelectionOption {
/// @brief Selection is simply inverted:
static SelectionOption Simple();
// Style:
std::function<void(Pixel& pixel)> transform ;
// Observers:
/// Called when the selection changed.
std::function<void()> on_change = [] {};
};
/// @brief Represent a selection in the terminal.
class Selection {
public:
Selection(int start_x, int start_y, int end_x, int end_y);
Selection(int start_x, int start_y, int end_x, int end_y, SelectionOption option = SelectionOption::Simple());
const Box& GetBox() const;
const SelectionOption& GetOption() const;
Selection SaturateHorizontal(Box box);
Selection SaturateVertical(Box box);
@ -25,6 +43,7 @@ class Selection {
const int end_x_;
const int end_y_;
const Box box_;
const SelectionOption option;
};
} // namespace ftxui

View File

@ -580,18 +580,14 @@ void ScreenInteractive::ForceHandleCtrlZ(bool force) {
std::string ScreenInteractive::GetSelectedContent(Component component)
{
Selection selection(selection_start_x_, selection_start_y_, //
selection_end_x_, selection_end_y_);
selection_end_x_, selection_end_y_, selection_options_);
return GetNodeSelectedContent(*this, component->Render().get(), selection);
}
/// @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<void(void)> callback)
void ScreenInteractive::setSelectionOptions(SelectionOption option)
{
selection_changed_callback_ = std::move(callback);
selection_options_ = std::move(option);
}
/// @brief Return the currently active screen, or null if none.
@ -970,12 +966,12 @@ void ScreenInteractive::Draw(Component component) {
previous_frame_resized_ = resized;
Selection selection(selection_start_x_, selection_start_y_, //
selection_end_x_, selection_end_y_);
selection_end_x_, selection_end_y_, selection_options_);
Render(*this, document.get(), selection);
if((selection_changed == true) && (selection_changed_callback_ != nullptr))
if(selection_changed == true)
{
selection_changed_callback_();
selection_options_.on_change();
}
// Set cursor position for user using tools to insert CJK characters.

View File

@ -26,11 +26,12 @@ class Unselectable : public NodeDecorator {
/// @param start_y The y coordinate of the start of the selection.
/// @param end_x The x coordinate of the end of the selection.
/// @param end_y The y coordinate of the end of the selection.
Selection::Selection(int start_x, int start_y, int end_x, int end_y)
Selection::Selection(int start_x, int start_y, int end_x, int end_y, SelectionOption option)
: start_x_(start_x),
start_y_(start_y),
end_x_(end_x),
end_y_(end_y),
option(option),
box_{
std::min(start_x, end_x),
std::max(start_x, end_x),
@ -44,6 +45,12 @@ const Box& Selection::GetBox() const {
return box_;
}
/// @brief Get the options of the selection.
/// @return The options of the selection.
const SelectionOption& Selection::GetOption() const {
return option;
}
/// @brief Saturate the selection to be inside the box.
/// This is called by `hbox` to propagate the selection to its children.
/// @param box The box to saturate the selection in.
@ -77,7 +84,7 @@ Selection Selection::SaturateHorizontal(Box box) {
end_y = box.y_min;
}
}
return Selection(start_x, start_y, end_x, end_y);
return Selection(start_x, start_y, end_x, end_y, option);
}
/// @brief Saturate the selection to be inside the box.
@ -114,7 +121,7 @@ Selection Selection::SaturateVertical(Box box) {
end_y = box.y_min;
}
}
return Selection(start_x, start_y, end_x, end_y);
return Selection(start_x, start_y, end_x, end_y, option);
}
/// @brief Add a filter that will invert the foreground and the background
@ -124,4 +131,16 @@ Element unselectable(Element child) {
return std::make_shared<Unselectable>(std::move(child));
}
/// @brief Create a SelectionOption, inverting the selection.
/// @ingroup component
// static
SelectionOption SelectionOption::Simple() {
SelectionOption option;
option.transform = [](Pixel& pixel) {
pixel.inverted = true;
};
return option;
}
} // namespace ftxui

View File

@ -39,6 +39,8 @@ class Text : public Node {
has_selection = true;
selection_start_ = selection_saturated.GetBox().x_min;
selection_end_ = selection_saturated.GetBox().x_max;
selectionTransform = selection.GetOption().transform;
}
void Render(Screen& screen) override {
@ -60,7 +62,7 @@ class Text : public Node {
if (has_selection) {
if ((x >= selection_start_) && (x <= selection_end_)) {
screen.PixelAt(x, y).inverted = true;
selectionTransform(screen.PixelAt(x, y));
}
}
@ -96,6 +98,7 @@ class Text : public Node {
bool has_selection = false;
int selection_start_ = 0;
int selection_end_ = 10;
std::function<void(Pixel& pixel)> selectionTransform;
};
class VText : public Node {