We can retrieve the content of the selection

This commit is contained in:
Clement Roblot 2024-12-02 16:47:13 +07:00 committed by ArthurSonzogni
parent dc70091203
commit 307d8b51bf
No known key found for this signature in database
GPG Key ID: 41D98248C074CD6C
6 changed files with 83 additions and 9 deletions

View File

@ -27,18 +27,16 @@ Element LoremIpsum() {
int main() { int main() {
auto screen = ScreenInteractive::TerminalOutput(); auto screen = ScreenInteractive::TerminalOutput();
int counter = 0; int selectionChangeCounter = 0;
std::string selection = "";
screen.onSelectionModified([&]{
counter++;
});
auto quit = Button("Quit", screen.ExitLoopClosure()); auto quit = Button("Quit", screen.ExitLoopClosure());
// The components: // The components:
auto renderer = Renderer(quit, [&] { auto renderer = Renderer(quit, [&] {
return vbox({ return vbox({
text("Select: " + std::to_string(counter)), text("Select changed: " + std::to_string(selectionChangeCounter) + " times"),
text("Currently selected: " + selection),
window(text("Horizontal split"), hbox({ window(text("Horizontal split"), hbox({
LoremIpsum(), LoremIpsum(),
separator(), separator(),
@ -75,5 +73,10 @@ int main() {
}); });
}); });
screen.onSelectionModified([&] {
selectionChangeCounter++;
selection = screen.GetSelectedContent(renderer);
});
screen.Loop(renderer); screen.Loop(renderer);
} }

View File

@ -69,8 +69,7 @@ class ScreenInteractive : public Screen {
void ForceHandleCtrlZ(bool force); void ForceHandleCtrlZ(bool force);
// Selection API. // Selection API.
// TODO: Implement somethings here. std::string GetSelectedContent(Component component);
std::string GetSelectedContent(void);
void onSelectionModified(std::function<void(void)> callback); void onSelectionModified(std::function<void(void)> callback);
private: private:

View File

@ -48,6 +48,8 @@ class Node {
// Step 4: Draw this element. // Step 4: Draw this element.
virtual void Render(Screen& screen); virtual void Render(Screen& screen);
virtual std::string GetSelectedContent(Selection& selection);
// Layout may not resolve within a single iteration for some elements. This // Layout may not resolve within a single iteration for some elements. This
// allows them to request additionnal iterations. This signal must be // allows them to request additionnal iterations. This signal must be
// forwarded to children at least once. // forwarded to children at least once.
@ -66,6 +68,7 @@ class Node {
void Render(Screen& screen, const Element& element); void Render(Screen& screen, const Element& element);
void Render(Screen& screen, Node* node); void Render(Screen& screen, Node* node);
void Render(Screen& screen, Node* node, Selection& selection); void Render(Screen& screen, Node* node, Selection& selection);
std::string GetNodeSelectedContent(Screen& screen, Node* node, Selection& selection);
} // namespace ftxui } // namespace ftxui

View File

@ -577,9 +577,12 @@ void ScreenInteractive::ForceHandleCtrlZ(bool force) {
} }
/// @brief Returns the content of the current selection /// @brief Returns the content of the current selection
std::string ScreenInteractive::GetSelectedContent(void) std::string ScreenInteractive::GetSelectedContent(Component component)
{ {
Selection selection(selection_start_x_, selection_start_y_, //
selection_end_x_, selection_end_y_);
return GetNodeSelectedContent(*this, component->Render().get(), selection);
} }
/// @brief Sets a callback on modifications of the selection /// @brief Sets a callback on modifications of the selection

View File

@ -57,6 +57,17 @@ void Node::Check(Status* status) {
status->need_iteration |= (status->iteration == 0); status->need_iteration |= (status->iteration == 0);
} }
std::string Node::GetSelectedContent(Selection& selection) {
std::string content;
for (auto& child : children_) {
content += child->GetSelectedContent(selection);
}
return content;
}
/// @brief Display an element on a ftxui::Screen. /// @brief Display an element on a ftxui::Screen.
/// @ingroup dom /// @ingroup dom
void Render(Screen& screen, const Element& element) { void Render(Screen& screen, const Element& element) {
@ -105,4 +116,35 @@ void Render(Screen& screen, Node* node, Selection& selection) {
screen.ApplyShader(); screen.ApplyShader();
} }
std::string GetNodeSelectedContent(Screen& screen, Node* node, Selection& selection) {
Box box;
box.x_min = 0;
box.y_min = 0;
box.x_max = screen.dimx() - 1;
box.y_max = screen.dimy() - 1;
Node::Status status;
node->Check(&status);
const int max_iterations = 20;
while (status.need_iteration && status.iteration < max_iterations) {
// Step 1: Find what dimension this elements wants to be.
node->ComputeRequirement();
// Step 2: Assign a dimension to the element.
node->SetBox(box);
// Check if the element needs another iteration of the layout algorithm.
status.need_iteration = false;
status.iteration++;
node->Check(&status);
}
// Step 3: Selection
node->Select(selection);
// Step 4: get the selected content.
return node->GetSelectedContent(selection);
}
} // namespace ftxui } // namespace ftxui

View File

@ -44,6 +44,7 @@ class Text : public Node {
void Render(Screen& screen) override { void Render(Screen& screen) override {
int x = box_.x_min; int x = box_.x_min;
const int y = box_.y_min; const int y = box_.y_min;
if (y > box_.y_max) { if (y > box_.y_max) {
return; return;
} }
@ -67,6 +68,29 @@ class Text : public Node {
} }
} }
std::string GetSelectedContent(Selection& selection) {
int x = box_.x_min;
std::string selected_text = "";
if (has_selection == false) {
return "";
}
for (const auto& cell : Utf8ToGlyphs(text_)) {
if (x > box_.x_max) {
break;
}
if ((x >= selection_start_) && (x <= selection_end_)) {
selected_text += cell;
}
++x;
}
return selected_text;
}
private: private:
std::string text_; std::string text_;
bool has_selection = false; bool has_selection = false;