yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
layout_definition.cc
Go to the documentation of this file.
2
3#include <chrono>
4
5namespace yaze {
6namespace editor {
7namespace layout_designer {
8
9// ============================================================================
10// DockNode Implementation
11// ============================================================================
12
13void DockNode::AddPanel(const LayoutPanel& panel) {
15 // Can only add panels to leaf/root nodes
16 return;
17 }
18 panels.push_back(panel);
19}
20
21void DockNode::Split(ImGuiDir direction, float ratio) {
23 // Already split
24 return;
25 }
26
28 split_dir = direction;
29 split_ratio = ratio;
30
31 // Move existing panels to left child
32 child_left = std::make_unique<DockNode>();
34 child_left->panels = std::move(panels);
35 panels.clear();
36
37 // Create empty right child
38 child_right = std::make_unique<DockNode>();
40}
41
42LayoutPanel* DockNode::FindPanel(const std::string& panel_id) {
43 if (type == DockNodeType::Leaf) {
44 for (auto& panel : panels) {
45 if (panel.panel_id == panel_id) {
46 return &panel;
47 }
48 }
49 return nullptr;
50 }
51
52 // Search children
53 if (child_left) {
54 if (auto* found = child_left->FindPanel(panel_id)) {
55 return found;
56 }
57 }
58 if (child_right) {
59 if (auto* found = child_right->FindPanel(panel_id)) {
60 return found;
61 }
62 }
63
64 return nullptr;
65}
66
67size_t DockNode::CountPanels() const {
69 return panels.size();
70 }
71
72 size_t count = 0;
73 if (child_left) {
74 count += child_left->CountPanels();
75 }
76 if (child_right) {
77 count += child_right->CountPanels();
78 }
79 return count;
80}
81
82std::unique_ptr<DockNode> DockNode::Clone() const {
83 auto clone = std::make_unique<DockNode>();
84 clone->type = type;
85 clone->node_id = node_id;
86 clone->split_dir = split_dir;
87 clone->split_ratio = split_ratio;
88 clone->flags = flags;
89 clone->panels = panels;
90
91 if (child_left) {
92 clone->child_left = child_left->Clone();
93 }
94 if (child_right) {
95 clone->child_right = child_right->Clone();
96 }
97
98 return clone;
99}
100
101// ============================================================================
102// LayoutDefinition Implementation
103// ============================================================================
104
106 LayoutDefinition layout;
107 layout.name = name;
108 layout.description = "Empty layout";
109 layout.root = std::make_unique<DockNode>();
110 layout.root->type = DockNodeType::Root;
111
112 auto now = std::chrono::system_clock::now();
113 layout.created_timestamp = std::chrono::duration_cast<std::chrono::seconds>(
114 now.time_since_epoch()).count();
116
117 return layout;
118}
119
120std::unique_ptr<LayoutDefinition> LayoutDefinition::Clone() const {
121 auto clone = std::make_unique<LayoutDefinition>();
122 clone->name = name;
123 clone->description = description;
124 clone->editor_type = editor_type;
125 clone->canvas_size = canvas_size;
126 clone->author = author;
127 clone->version = version;
128 clone->created_timestamp = created_timestamp;
129 clone->modified_timestamp = modified_timestamp;
130
131 if (root) {
132 clone->root = root->Clone();
133 }
134
135 return clone;
136}
137
138LayoutPanel* LayoutDefinition::FindPanel(const std::string& panel_id) const {
139 if (!root) {
140 return nullptr;
141 }
142 return root->FindPanel(panel_id);
143}
144
145std::vector<LayoutPanel*> LayoutDefinition::GetAllPanels() const {
146 std::vector<LayoutPanel*> result;
147
148 if (!root) {
149 return result;
150 }
151
152 // Recursive helper to collect panels
153 std::function<void(DockNode*)> collect = [&](DockNode* node) {
154 if (!node) return;
155
156 if (node->type == DockNodeType::Leaf) {
157 for (auto& panel : node->panels) {
158 result.push_back(&panel);
159 }
160 } else {
161 collect(node->child_left.get());
162 collect(node->child_right.get());
163 }
164 };
165
166 collect(root.get());
167 return result;
168}
169
170bool LayoutDefinition::Validate(std::string* error_message) const {
171 if (name.empty()) {
172 if (error_message) {
173 *error_message = "Layout name cannot be empty";
174 }
175 return false;
176 }
177
178 if (!root) {
179 if (error_message) {
180 *error_message = "Layout must have a root node";
181 }
182 return false;
183 }
184
185 // Validate that split nodes have both children
186 std::function<bool(const DockNode*)> validate_node =
187 [&](const DockNode* node) -> bool {
188 if (!node) {
189 if (error_message) {
190 *error_message = "Null node found in tree";
191 }
192 return false;
193 }
194
195 if (node->type == DockNodeType::Split) {
196 if (!node->child_left || !node->child_right) {
197 if (error_message) {
198 *error_message = "Split node must have both children";
199 }
200 return false;
201 }
202
203 if (node->split_ratio <= 0.0f || node->split_ratio >= 1.0f) {
204 if (error_message) {
205 *error_message = "Split ratio must be between 0.0 and 1.0";
206 }
207 return false;
208 }
209
210 if (!validate_node(node->child_left.get())) {
211 return false;
212 }
213 if (!validate_node(node->child_right.get())) {
214 return false;
215 }
216 }
217
218 return true;
219 };
220
221 return validate_node(root.get());
222}
223
225 auto now = std::chrono::system_clock::now();
226 modified_timestamp = std::chrono::duration_cast<std::chrono::seconds>(
227 now.time_since_epoch()).count();
228}
229
230} // namespace layout_designer
231} // namespace editor
232} // namespace yaze
Represents a dock node in the layout tree.
void AddPanel(const LayoutPanel &panel)
void Split(ImGuiDir direction, float ratio)
LayoutPanel * FindPanel(const std::string &panel_id)
std::unique_ptr< DockNode > Clone() const
std::unique_ptr< DockNode > child_left
std::unique_ptr< DockNode > child_right
Complete layout definition with metadata.
std::unique_ptr< LayoutDefinition > Clone() const
Clone the layout definition.
std::vector< LayoutPanel * > GetAllPanels() const
Get all panels in the layout.
bool Validate(std::string *error_message=nullptr) const
Validate the layout structure.
static LayoutDefinition CreateEmpty(const std::string &name)
Create a default empty layout.
void Touch()
Update the modified timestamp to current time.
LayoutPanel * FindPanel(const std::string &panel_id) const
Find a panel by ID anywhere in the layout.
Represents a single panel in a layout.