Skip to content

Commit c58abeb

Browse files
committed
Refactor TUITreeView to simplify component creation and enhance node interaction
1 parent de3357e commit c58abeb

2 files changed

Lines changed: 65 additions & 48 deletions

File tree

include/tuikit/widgets/TUITreeView.h

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,33 +7,34 @@
77
#include <memory>
88
#include "tuikit/layouts/TUIVBoxLayout.h"
99
#include "tuikit/widgets/TUICollapsible.h"
10-
#include "tuikit/widgets/TUIButton.h" // Added for clickable nodes
10+
#include "tuikit/widgets/TUIButton.h"
11+
#include <ftxui/component/component.hpp>
12+
#include <ftxui/dom/elements.hpp>
1113

1214
namespace TUIKIT {
1315

1416
struct TreeNode {
1517
std::string label;
1618
std::vector<TreeNode> children;
1719
bool is_expanded = false;
20+
ftxui::Component component;
1821
};
1922

2023
class TUITreeView : public TUIWidget {
2124
public:
2225
using OnSelectCallback = std::function<void(const std::string&)>;
2326

24-
TUITreeView(TreeNode root_node, TUIWidget* parent = nullptr);
27+
TUITreeView(TreeNode root_node);
2528
~TUITreeView() override = default;
2629

2730
void onSelect(OnSelectCallback cb);
2831

29-
std::shared_ptr<TUICollapsible> createCollapsibleNode(const TreeNode &node);
30-
3132
private:
33+
void buildComponent(TreeNode& node, int depth);
34+
ftxui::Element renderNode(const TreeNode& node, int depth);
35+
3236
TreeNode root_node_;
3337
OnSelectCallback on_select_;
34-
35-
std::shared_ptr<class TUIVBoxLayout> main_layout_;
36-
3738
};
3839

3940
} // namespace TUIKIT

src/widgets/TUITreeView.cpp

Lines changed: 57 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,72 @@
11
#include "tuikit/widgets/TUITreeView.h"
2-
#include "tuikit/layouts/TUIVBoxLayout.h"
3-
#include "tuikit/widgets/TUICollapsible.h"
4-
#include "tuikit/widgets/TUILabel.h"
5-
#include <ftxui/component/component.hpp>
2+
#include "ftxui/component/component.hpp"
3+
#include "ftxui/component/screen_interactive.hpp"
4+
#include "ftxui/dom/elements.hpp"
5+
#include "ftxui/component/component_options.hpp"
66

77
namespace TUIKIT {
88

9-
TUITreeView::TUITreeView(TreeNode root_node, TUIWidget* /*parent*/)
9+
TUITreeView::TUITreeView(TreeNode root_node)
1010
: TUIWidget(ftxui::Component()), root_node_(std::move(root_node)) {
11-
12-
main_layout_ = std::make_shared<TUIVBoxLayout>();
13-
component_ = main_layout_->get_ftxui_component();
14-
15-
// Create the root collapsible node
16-
auto root_collapsible = createCollapsibleNode(root_node_);
17-
main_layout_->addWidget(root_collapsible);
11+
buildComponent(root_node_, 0);
12+
component_ = root_node_.component;
1813
}
1914

2015
void TUITreeView::onSelect(OnSelectCallback cb) {
2116
on_select_ = std::move(cb);
2217
}
2318

24-
std::shared_ptr<TUICollapsible> TUITreeView::createCollapsibleNode(const TreeNode& node) {
25-
auto content_layout = std::make_shared<TUIVBoxLayout>();
26-
27-
// Create a label for the current node's content (or a button for selection)
28-
auto node_label = std::make_shared<TUILabel>(node.label);
29-
// Connect a click event to the label to simulate selection
30-
// This requires TUILabel to have an onClick or similar signal, which it currently doesn't.
31-
// For now, we'll just make it a label. If selection is critical, we might need a small button or a custom component.
32-
// For demonstration, we'll trigger on_select_ when the collapsible is expanded/collapsed.
33-
// A better approach would be to make the label itself clickable or add a small invisible button.
34-
35-
// Recursively create children
36-
for (const auto& child : node.children) {
37-
auto child_collapsible = createCollapsibleNode(child);
38-
content_layout->addWidget(child_collapsible);
39-
}
19+
void TUITreeView::buildComponent(TreeNode& node, int depth) {
20+
using namespace ftxui;
21+
22+
auto on_click = [this, &node] {
23+
node.is_expanded = !node.is_expanded;
24+
if (on_select_) {
25+
on_select_(node.label);
26+
}
27+
};
4028

41-
auto collapsible = std::make_shared<TUICollapsible>(node.label, content_layout);
42-
43-
// If a node is selected, trigger the callback
44-
// This is a placeholder. A proper selection mechanism would involve a clickable element inside the collapsible.
45-
// For now, we'll just use the collapsible's title as the selected item.
46-
// This part needs refinement based on how selection is truly intended.
47-
// For now, let's assume expanding/collapsing implies a form of interaction.
48-
// A better way would be to add a small button next to the label or make the label itself interactive.
49-
// Since TUILabel doesn't have an onClick, we'll rely on the user clicking the collapsible title.
50-
// If the user clicks the collapsible title, we can consider it "selected".
51-
// This is a simplification for the refactoring.
52-
53-
return collapsible;
29+
if (node.children.empty()) {
30+
auto option = ButtonOption();
31+
option.transform = [=, &node](const EntryState& state) {
32+
std::string indentation = std::string(depth * 3, ' ');
33+
auto element = hbox({
34+
text(indentation + " " + node.label)
35+
});
36+
if (state.focused) {
37+
element = element | inverted;
38+
}
39+
return element;
40+
};
41+
node.component = Button(&node.label, on_click, option);
42+
} else {
43+
std::vector<Component> children_components;
44+
for (auto& child : node.children) {
45+
buildComponent(child, depth + 1);
46+
children_components.push_back(child.component);
47+
}
48+
auto children_container = Container::Vertical(children_components);
49+
50+
auto header_button = Button(&node.label, on_click);
51+
52+
auto combined = Container::Vertical({header_button, children_container});
53+
54+
node.component = Renderer(combined, [=, &node] {
55+
std::string indentation = std::string(depth * 3, ' ');
56+
std::string icon = node.is_expanded ? "" : "";
57+
auto header_element = hbox({
58+
text(indentation + icon + node.label)
59+
});
60+
if (header_button->Focused()) {
61+
header_element = header_element | inverted;
62+
}
63+
64+
if (node.is_expanded) {
65+
return vbox({header_element, children_container->Render()});
66+
}
67+
return header_element;
68+
});
69+
}
5470
}
5571

5672
} // namespace TUIKIT

0 commit comments

Comments
 (0)