yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
dock_tree_renderer.cc
Go to the documentation of this file.
2
3#include <algorithm>
4#include <functional>
5#include <string>
6
8#include "imgui/imgui.h"
9#include "imgui/imgui_internal.h"
10
11namespace yaze {
12namespace editor {
13namespace layout_designer {
14namespace {
15
19
20void LayoutNodeRecursive(const DockNode* node, ImRect rect,
21 DockTreeLayout* out) {
22 if (node == nullptr)
23 return;
24 out->node_rects[node] = rect;
25 if (node->type != DockNode::Type::kSplit)
26 return;
27 if (node->child_a == nullptr || node->child_b == nullptr)
28 return;
29
30 const float width = rect.GetWidth();
31 const float height = rect.GetHeight();
32 const bool horizontal = IsHorizontalSplit(node->split_direction);
33 const float axis_size = horizontal ? width : height;
34 const float child_a_size = axis_size * node->split_ratio;
35 const float child_b_size = axis_size - child_a_size;
36
37 if (child_a_size < kMinCellSize || child_b_size < kMinCellSize) {
38 return;
39 }
40
41 ImRect r_a;
42 ImRect r_b;
43 if (horizontal) {
44 const float split_x = rect.Min.x + child_a_size;
45 r_a = ImRect(rect.Min.x, rect.Min.y, split_x, rect.Max.y);
46 r_b = ImRect(split_x, rect.Min.y, rect.Max.x, rect.Max.y);
47 } else {
48 const float split_y = rect.Min.y + child_a_size;
49 r_a = ImRect(rect.Min.x, rect.Min.y, rect.Max.x, split_y);
50 r_b = ImRect(rect.Min.x, split_y, rect.Max.x, rect.Max.y);
51 }
52
53 LayoutNodeRecursive(node->child_a.get(), r_a, out);
54 LayoutNodeRecursive(node->child_b.get(), r_b, out);
55}
56
57} // namespace
58
59DockTreeLayout ComputeLayout(const DockTree& tree, const ImRect& viewport) {
60 DockTreeLayout layout;
61 LayoutNodeRecursive(tree.root.get(), viewport, &layout);
62 return layout;
63}
64
65void RenderDockTree(const DockTree& tree, const DockTreeLayout& layout,
66 const DockNode* selected, ImDrawList* dl) {
67 if (dl == nullptr || tree.root == nullptr)
68 return;
69
70 const ImU32 cell_bg = ImGui::GetColorU32(ImGuiCol_FrameBg);
71 const ImU32 cell_border = ImGui::GetColorU32(ImGuiCol_Border);
72 const ImU32 split_gutter = cell_border;
73 const ImU32 text_color = ImGui::GetColorU32(ImGuiCol_Text);
74 const ImU32 selection = ImGui::ColorConvertFloat4ToU32(gui::GetAccentColor());
75
76 std::function<void(const DockNode*)> draw = [&](const DockNode* node) {
77 if (node == nullptr)
78 return;
79 const auto it = layout.node_rects.find(node);
80 if (it == layout.node_rects.end())
81 return;
82 const ImRect& rect = it->second;
83
84 const bool is_split = node->type == DockNode::Type::kSplit;
85 const bool children_expanded =
86 is_split && node->child_a != nullptr && node->child_b != nullptr &&
87 layout.node_rects.count(node->child_a.get()) > 0 &&
88 layout.node_rects.count(node->child_b.get()) > 0;
89
90 if (!is_split || !children_expanded) {
91 dl->AddRectFilled(rect.Min, rect.Max, cell_bg);
92 dl->AddRect(rect.Min, rect.Max, cell_border);
93
94 std::string label;
95 if (node->type == DockNode::Type::kLeaf && !node->panels.empty()) {
96 const int idx = std::clamp(node->active_tab_index, 0,
97 static_cast<int>(node->panels.size()) - 1);
98 label = node->panels[idx].display_name;
99 } else if (is_split) {
100 label = "(collapsed split)";
101 }
102
103 if (!label.empty() && rect.GetWidth() > 40.0f &&
104 rect.GetHeight() > 20.0f) {
105 dl->AddText(ImVec2(rect.Min.x + 6.0f, rect.Min.y + 6.0f), text_color,
106 label.c_str());
107 }
108 return;
109 }
110
111 const ImRect& a_rect = layout.node_rects.at(node->child_a.get());
112 if (IsHorizontalSplit(node->split_direction)) {
113 dl->AddLine(ImVec2(a_rect.Max.x, rect.Min.y),
114 ImVec2(a_rect.Max.x, rect.Max.y), split_gutter);
115 } else {
116 dl->AddLine(ImVec2(rect.Min.x, a_rect.Max.y),
117 ImVec2(rect.Max.x, a_rect.Max.y), split_gutter);
118 }
119 draw(node->child_a.get());
120 draw(node->child_b.get());
121 };
122
123 draw(tree.root.get());
124
125 if (selected != nullptr) {
126 const auto it = layout.node_rects.find(selected);
127 if (it != layout.node_rects.end()) {
128 dl->AddRect(it->second.Min, it->second.Max, selection, 0.0f, 0, 2.5f);
129 }
130 }
131}
132
133} // namespace layout_designer
134} // namespace editor
135} // namespace yaze
void LayoutNodeRecursive(const DockNode *node, ImRect rect, DockTreeLayout *out)
void RenderDockTree(const DockTree &tree, const DockTreeLayout &layout, const DockNode *selected, ImDrawList *dl)
DockTreeLayout ComputeLayout(const DockTree &tree, const ImRect &viewport)
ImVec4 GetAccentColor()
Definition ui_helpers.cc:69
Represents a dock node in the layout tree.
Definition dock_tree.h:61
std::unique_ptr< DockNode > child_a
Definition dock_tree.h:78
std::unique_ptr< DockNode > child_b
Definition dock_tree.h:79
absl::flat_hash_map< const DockNode *, ImRect > node_rects
std::unique_ptr< DockNode > root
Definition dock_tree.h:115