mirror of
https://github.com/ArthurSonzogni/FTXUI.git
synced 2025-06-24 16:21:12 +08:00
Added a option to set the style of the selection
This commit is contained in:
parent
d62dc6e305
commit
cbd28403af
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user