yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
layout_manager.cc
Go to the documentation of this file.
2
5#include "imgui/imgui.h"
6#include "imgui/imgui_internal.h"
7#include "util/log.h"
8
9namespace yaze {
10namespace editor {
11
12namespace {
13
14// Helper function to show default cards from LayoutPresets
16 if (!registry) return;
17
18 auto default_panels = LayoutPresets::GetDefaultPanels(type);
19 for (const auto& panel_id : default_panels) {
20 registry->ShowPanel(panel_id);
21 }
22
23 LOG_INFO("LayoutManager", "Showing %zu default panels for editor type %d",
24 default_panels.size(), static_cast<int>(type));
25}
26
27} // namespace
28
30 ImGuiID dockspace_id) {
31 // Don't reinitialize if already set up
32 if (IsLayoutInitialized(type)) {
33 LOG_INFO("LayoutManager",
34 "Layout for editor type %d already initialized, skipping",
35 static_cast<int>(type));
36 return;
37 }
38
39 // Store dockspace ID and current editor type for potential rebuilds
40 last_dockspace_id_ = dockspace_id;
42
43 LOG_INFO("LayoutManager", "Initializing layout for editor type %d",
44 static_cast<int>(type));
45
46 // Clear existing layout for this dockspace
47 ImGui::DockBuilderRemoveNode(dockspace_id);
48 ImGui::DockBuilderAddNode(dockspace_id, ImGuiDockNodeFlags_DockSpace);
49 ImGui::DockBuilderSetNodeSize(dockspace_id, ImGui::GetMainViewport()->WorkSize);
50
51 // Build layout based on editor type using generic builder
52 BuildLayoutFromPreset(type, dockspace_id);
53
54 // Show default cards from LayoutPresets (single source of truth)
55 ShowDefaultPanelsForEditor(panel_manager_, type);
56
57 // Finalize the layout
58 ImGui::DockBuilderFinish(dockspace_id);
59
60 // Mark as initialized
62}
63
64void LayoutManager::RebuildLayout(EditorType type, ImGuiID dockspace_id) {
65 // Validate dockspace exists
66 ImGuiDockNode* node = ImGui::DockBuilderGetNode(dockspace_id);
67 if (!node) {
68 LOG_ERROR("LayoutManager",
69 "Cannot rebuild layout: dockspace ID %u not found", dockspace_id);
70 return;
71 }
72
73 LOG_INFO("LayoutManager", "Forcing rebuild of layout for editor type %d",
74 static_cast<int>(type));
75
76 // Store dockspace ID and current editor type
77 last_dockspace_id_ = dockspace_id;
79
80 // Clear the layout initialization flag to force rebuild
81 layouts_initialized_[type] = false;
82
83 // Clear existing layout for this dockspace
84 ImGui::DockBuilderRemoveNode(dockspace_id);
85 ImGui::DockBuilderAddNode(dockspace_id, ImGuiDockNodeFlags_DockSpace);
86 ImGui::DockBuilderSetNodeSize(dockspace_id, ImGui::GetMainViewport()->WorkSize);
87
88 // Build layout based on editor type using generic builder
89 BuildLayoutFromPreset(type, dockspace_id);
90
91 // Show default cards from LayoutPresets (single source of truth)
92 ShowDefaultPanelsForEditor(panel_manager_, type);
93
94 // Finalize the layout
95 ImGui::DockBuilderFinish(dockspace_id);
96
97 // Mark as initialized
99
100 LOG_INFO("LayoutManager", "Layout rebuild complete for editor type %d",
101 static_cast<int>(type));
102}
103
104namespace {
105
107 float left = 0.22f;
108 float right = 0.25f;
109 float bottom = 0.25f;
110 float top = 0.18f;
111 float vertical_split = 0.50f;
112
113 // Per-editor type configuration
115 DockSplitConfig cfg;
116 switch (type) {
117 case EditorType::kDungeon:
118 // Dungeon: narrower left panel for room list, right for object editor
119 cfg.left = 0.16f; // Room selector panel (narrower)
120 cfg.right = 0.22f; // Object editor panel
121 cfg.bottom = 0.20f; // Palette editor (shorter)
122 cfg.vertical_split = 0.45f; // Room matrix / Entrances split
123 break;
124 case EditorType::kOverworld:
125 cfg.left = 0.20f;
126 cfg.right = 0.25f;
127 cfg.bottom = 0.25f;
128 break;
129 default:
130 // Use defaults
131 break;
132 }
133 return cfg;
134 }
135};
136
138 ImGuiID center = 0;
139 ImGuiID left = 0;
140 ImGuiID right = 0;
141 ImGuiID bottom = 0;
142 ImGuiID top = 0;
143 ImGuiID left_top = 0;
144 ImGuiID left_bottom = 0;
145 ImGuiID right_top = 0;
146 ImGuiID right_bottom = 0;
147};
148
150 bool left = false;
151 bool right = false;
152 bool bottom = false;
153 bool top = false;
154 bool left_top = false;
155 bool left_bottom = false;
156 bool right_top = false;
157 bool right_bottom = false;
158};
159
161 DockSplitNeeds needs{};
162 for (const auto& [_, pos] : preset.panel_positions) {
163 switch (pos) {
165 needs.left = true;
166 break;
168 needs.right = true;
169 break;
171 needs.bottom = true;
172 break;
174 needs.top = true;
175 break;
177 needs.left = true;
178 needs.left_top = true;
179 break;
181 needs.left = true;
182 needs.left_bottom = true;
183 break;
185 needs.right = true;
186 needs.right_top = true;
187 break;
189 needs.right = true;
190 needs.right_bottom = true;
191 break;
193 default:
194 break;
195 }
196 }
197 return needs;
198}
199
200DockNodeIds BuildDockTree(ImGuiID dockspace_id, const DockSplitNeeds& needs,
201 const DockSplitConfig& cfg) {
202 DockNodeIds ids{};
203 ids.center = dockspace_id;
204
205 if (needs.left) {
206 ids.left = ImGui::DockBuilderSplitNode(ids.center, ImGuiDir_Left, cfg.left,
207 nullptr, &ids.center);
208 }
209 if (needs.right) {
210 ids.right = ImGui::DockBuilderSplitNode(ids.center, ImGuiDir_Right,
211 cfg.right, nullptr, &ids.center);
212 }
213 if (needs.bottom) {
214 ids.bottom = ImGui::DockBuilderSplitNode(ids.center, ImGuiDir_Down,
215 cfg.bottom, nullptr, &ids.center);
216 }
217 if (needs.top) {
218 ids.top = ImGui::DockBuilderSplitNode(ids.center, ImGuiDir_Up, cfg.top,
219 nullptr, &ids.center);
220 }
221
222 if (ids.left && (needs.left_top || needs.left_bottom)) {
223 ids.left_bottom = ImGui::DockBuilderSplitNode(
224 ids.left, ImGuiDir_Down, cfg.vertical_split, nullptr, &ids.left_top);
225 }
226
227 if (ids.right && (needs.right_top || needs.right_bottom)) {
228 ids.right_bottom = ImGui::DockBuilderSplitNode(
229 ids.right, ImGuiDir_Down, cfg.vertical_split, nullptr, &ids.right_top);
230 }
231
232 return ids;
233}
234
235} // namespace
236
237void LayoutManager::BuildLayoutFromPreset(EditorType type, ImGuiID dockspace_id) {
238 auto preset = LayoutPresets::GetDefaultPreset(type);
239
240 if (!panel_manager_) {
241 LOG_WARN("LayoutManager",
242 "PanelManager not available, skipping dock layout for type %d",
243 static_cast<int>(type));
244 return;
245 }
246
247 const size_t session_id =
249
250 DockSplitNeeds needs = ComputeSplitNeeds(preset);
251 DockSplitConfig cfg = DockSplitConfig::ForEditor(type);
252 DockNodeIds ids = BuildDockTree(dockspace_id, needs, cfg);
253
254 auto get_dock_id = [&](DockPosition pos) -> ImGuiID {
255 switch (pos) {
257 return ids.left ? ids.left : ids.center;
259 return ids.right ? ids.right : ids.center;
261 return ids.bottom ? ids.bottom : ids.center;
263 return ids.top ? ids.top : ids.center;
265 return ids.left_top ? ids.left_top
266 : (ids.left ? ids.left : ids.center);
268 return ids.left_bottom ? ids.left_bottom
269 : (ids.left ? ids.left : ids.center);
271 return ids.right_top ? ids.right_top
272 : (ids.right ? ids.right : ids.center);
274 return ids.right_bottom ? ids.right_bottom
275 : (ids.right ? ids.right : ids.center);
277 default:
278 return ids.center;
279 }
280 };
281
282 // Iterate through positioned panels and dock them
283 for (const auto& [panel_id, position] : preset.panel_positions) {
284 const PanelDescriptor* desc =
286 ? panel_manager_->GetPanelDescriptor(session_id, panel_id)
287 : nullptr;
288 if (!desc) {
289 LOG_WARN("LayoutManager",
290 "Preset references panel '%s' that is not registered (session "
291 "%zu)",
292 panel_id.c_str(), session_id);
293 continue;
294 }
295
296 std::string window_title = desc->GetWindowTitle();
297 if (window_title.empty()) {
298 LOG_WARN("LayoutManager",
299 "Cannot dock panel '%s': missing window title (session %zu)",
300 panel_id.c_str(), session_id);
301 continue;
302 }
303
304 ImGui::DockBuilderDockWindow(window_title.c_str(), get_dock_id(position));
305 }
306}
307
308// Deprecated individual build methods - redirected to generic or kept empty
320
321void LayoutManager::SaveCurrentLayout(const std::string& name) {
322 // TODO: [EditorManagerRefactor] Implement layout saving to file
323 // Use ImGui::SaveIniSettingsToMemory() and write to custom file
324 LOG_INFO("LayoutManager", "Saving layout: %s", name.c_str());
325}
326
327void LayoutManager::LoadLayout(const std::string& name) {
328 // TODO: [EditorManagerRefactor] Implement layout loading from file
329 // Use ImGui::LoadIniSettingsFromMemory() and read from custom file
330 LOG_INFO("LayoutManager", "Loading layout: %s", name.c_str());
331}
332
334 layouts_initialized_[type] = false;
335 LOG_INFO("LayoutManager", "Reset layout for editor type %d",
336 static_cast<int>(type));
337}
338
340 auto it = layouts_initialized_.find(type);
341 return it != layouts_initialized_.end() && it->second;
342}
343
345 layouts_initialized_[type] = true;
346 LOG_INFO("LayoutManager", "Marked layout for editor type %d as initialized",
347 static_cast<int>(type));
348}
349
351 layouts_initialized_.clear();
352 LOG_INFO("LayoutManager", "Cleared all layout initialization flags");
353}
354
355std::string LayoutManager::GetWindowTitle(const std::string& card_id) const {
356 if (!panel_manager_) {
357 return "";
358 }
359
360 const size_t session_id = panel_manager_->GetActiveSessionId();
361 // Look up the panel descriptor in the manager (session 0 by default)
362 auto* info = panel_manager_->GetPanelDescriptor(session_id, card_id);
363 if (info) {
364 return info->GetWindowTitle();
365 }
366 return "";
367}
368
369} // namespace editor
370} // namespace yaze
void LoadLayout(const std::string &name)
Load a saved layout by name.
std::string GetWindowTitle(const std::string &card_id) const
Get window title for a card ID from registry.
void BuildScreenLayout(ImGuiID dockspace_id)
void BuildPaletteLayout(ImGuiID dockspace_id)
void BuildDungeonLayout(ImGuiID dockspace_id)
void BuildGraphicsLayout(ImGuiID dockspace_id)
void RebuildLayout(EditorType type, ImGuiID dockspace_id)
Force rebuild of layout for a specific editor type.
void BuildEmulatorLayout(ImGuiID dockspace_id)
void BuildAssemblyLayout(ImGuiID dockspace_id)
void ClearInitializationFlags()
Clear all initialization flags (for testing)
void BuildMessageLayout(ImGuiID dockspace_id)
std::unordered_map< EditorType, bool > layouts_initialized_
bool IsLayoutInitialized(EditorType type) const
Check if a layout has been initialized for an editor.
void BuildSettingsLayout(ImGuiID dockspace_id)
void ResetToDefaultLayout(EditorType type)
Reset the layout for an editor to its default.
void BuildOverworldLayout(ImGuiID dockspace_id)
void MarkLayoutInitialized(EditorType type)
Mark a layout as initialized.
void InitializeEditorLayout(EditorType type, ImGuiID dockspace_id)
Initialize the default layout for a specific editor type.
void BuildLayoutFromPreset(EditorType type, ImGuiID dockspace_id)
void SaveCurrentLayout(const std::string &name)
Save the current layout with a custom name.
void BuildSpriteLayout(ImGuiID dockspace_id)
void BuildMusicLayout(ImGuiID dockspace_id)
static std::vector< std::string > GetDefaultPanels(EditorType type)
Get default visible panels for an editor.
static PanelLayoutPreset GetDefaultPreset(EditorType type)
Get the default layout preset for an editor type.
Central registry for all editor cards with session awareness and dependency injection.
const PanelDescriptor * GetPanelDescriptor(size_t session_id, const std::string &base_card_id) const
bool ShowPanel(size_t session_id, const std::string &base_card_id)
size_t GetActiveSessionId() const
#define LOG_ERROR(category, format,...)
Definition log.h:109
#define LOG_WARN(category, format,...)
Definition log.h:107
#define LOG_INFO(category, format,...)
Definition log.h:105
DockSplitNeeds ComputeSplitNeeds(const PanelLayoutPreset &preset)
void ShowDefaultPanelsForEditor(PanelManager *registry, EditorType type)
DockNodeIds BuildDockTree(ImGuiID dockspace_id, const DockSplitNeeds &needs, const DockSplitConfig &cfg)
DockPosition
Preferred dock position for a card in a layout.
Metadata for an editor panel (formerly PanelInfo)
std::string GetWindowTitle() const
Get the effective window title for DockBuilder.
Defines default panel visibility for an editor type.
std::unordered_map< std::string, DockPosition > panel_positions