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() {
auto screen = ScreenInteractive::TerminalOutput();
int counter = 0;
screen.onSelectionModified([&]{
counter++;
});
int selectionChangeCounter = 0;
std::string selection = "";
auto quit = Button("Quit", screen.ExitLoopClosure());
// The components:
auto renderer = Renderer(quit, [&] {
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({
LoremIpsum(),
separator(),
@ -75,5 +73,10 @@ int main() {
});
});
screen.onSelectionModified([&] {
selectionChangeCounter++;
selection = screen.GetSelectedContent(renderer);
});
screen.Loop(renderer);
}

View File

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

View File

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

View File

@ -577,9 +577,12 @@ void ScreenInteractive::ForceHandleCtrlZ(bool force) {
}
/// @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

View File

@ -57,6 +57,17 @@ void Node::Check(Status* status) {
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.
/// @ingroup dom
void Render(Screen& screen, const Element& element) {
@ -105,4 +116,35 @@ void Render(Screen& screen, Node* node, Selection& selection) {
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

View File

@ -44,6 +44,7 @@ class Text : public Node {
void Render(Screen& screen) override {
int x = box_.x_min;
const int y = box_.y_min;
if (y > box_.y_max) {
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:
std::string text_;
bool has_selection = false;