mirror of
https://github.com/ArthurSonzogni/FTXUI.git
synced 2025-09-21 11:08:09 +08:00
Feature: Selection
Add support for selection content in the dom.
This commit is contained in:
@@ -576,6 +576,18 @@ void ScreenInteractive::ForceHandleCtrlZ(bool force) {
|
||||
force_handle_ctrl_z_ = force;
|
||||
}
|
||||
|
||||
/// @brief Returns the content of the current selection
|
||||
std::string ScreenInteractive::GetSelection() {
|
||||
if (!selection_) {
|
||||
return "";
|
||||
}
|
||||
return selection_->GetParts();
|
||||
}
|
||||
|
||||
void ScreenInteractive::SelectionChange(std::function<void()> callback) {
|
||||
selection_on_change_ = std::move(callback);
|
||||
}
|
||||
|
||||
/// @brief Return the currently active screen, or null if none.
|
||||
// static
|
||||
ScreenInteractive* ScreenInteractive::Active() {
|
||||
@@ -751,6 +763,14 @@ void ScreenInteractive::RunOnce(Component component) {
|
||||
ExecuteSignalHandlers();
|
||||
}
|
||||
Draw(std::move(component));
|
||||
|
||||
if (selection_data_previous_ != selection_data_) {
|
||||
selection_data_previous_ = selection_data_;
|
||||
if (selection_on_change_) {
|
||||
selection_on_change_();
|
||||
Post(Event::Custom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// private
|
||||
@@ -781,7 +801,9 @@ void ScreenInteractive::HandleTask(Component component, Task& task) {
|
||||
|
||||
arg.screen_ = this;
|
||||
|
||||
const bool handled = component->OnEvent(arg);
|
||||
bool handled = component->OnEvent(arg);
|
||||
|
||||
handled = HandleSelection(handled, arg);
|
||||
|
||||
if (arg == Event::CtrlC && (!handled || force_handle_ctrl_c_)) {
|
||||
RecordSignal(SIGABRT);
|
||||
@@ -824,6 +846,59 @@ void ScreenInteractive::HandleTask(Component component, Task& task) {
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
// private
|
||||
bool ScreenInteractive::HandleSelection(bool handled, Event event) {
|
||||
if (handled) {
|
||||
selection_pending_ = nullptr;
|
||||
selection_data_.empty = false;
|
||||
selection_ = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!event.is_mouse()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& mouse = event.mouse();
|
||||
if (mouse.button != Mouse::Left) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mouse.motion == Mouse::Pressed) {
|
||||
selection_pending_ = CaptureMouse();
|
||||
selection_data_.start_x = mouse.x;
|
||||
selection_data_.start_y = mouse.y;
|
||||
selection_data_.end_x = mouse.x;
|
||||
selection_data_.end_y = mouse.y;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!selection_pending_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mouse.motion == Mouse::Moved) {
|
||||
if ((mouse.x != selection_data_.end_x) ||
|
||||
(mouse.y != selection_data_.end_y)) {
|
||||
selection_data_.end_x = mouse.x;
|
||||
selection_data_.end_y = mouse.y;
|
||||
selection_data_.empty = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mouse.motion == Mouse::Released) {
|
||||
selection_pending_ = nullptr;
|
||||
selection_data_.end_x = mouse.x;
|
||||
selection_data_.end_y = mouse.y;
|
||||
selection_data_.empty = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// private
|
||||
// NOLINTNEXTLINE
|
||||
void ScreenInteractive::Draw(Component component) {
|
||||
@@ -899,7 +974,12 @@ void ScreenInteractive::Draw(Component component) {
|
||||
#endif
|
||||
previous_frame_resized_ = resized;
|
||||
|
||||
Render(*this, document);
|
||||
selection_ = selection_data_.empty
|
||||
? std::make_unique<Selection>()
|
||||
: std::make_unique<Selection>(
|
||||
selection_data_.start_x, selection_data_.start_y, //
|
||||
selection_data_.end_x, selection_data_.end_y);
|
||||
Render(*this, document.get(), *selection_);
|
||||
|
||||
// Set cursor position for user using tools to insert CJK characters.
|
||||
{
|
||||
@@ -988,4 +1068,21 @@ void ScreenInteractive::Signal(int signal) {
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ScreenInteractive::SelectionData::operator==(
|
||||
const ScreenInteractive::SelectionData& other) const {
|
||||
if (empty && other.empty) {
|
||||
return true;
|
||||
}
|
||||
if (empty || other.empty) {
|
||||
return false;
|
||||
}
|
||||
return start_x == other.start_x && start_y == other.start_y &&
|
||||
end_x == other.end_x && end_y == other.end_y;
|
||||
}
|
||||
|
||||
bool ScreenInteractive::SelectionData::operator!=(
|
||||
const ScreenInteractive::SelectionData& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
} // namespace ftxui.
|
||||
|
Reference in New Issue
Block a user