yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
layout_coordinator.cc
Go to the documentation of this file.
2
3#include <algorithm>
4#include <filesystem>
5
6#include "absl/strings/str_format.h"
13#include "imgui/imgui.h"
14#include "imgui/imgui_internal.h"
15#include "util/log.h"
16#include "util/platform_paths.h"
17
18namespace yaze {
19namespace editor {
20
29
30// ==========================================================================
31// Layout Offset Calculations
32// ==========================================================================
33
36 float viewport_width, float activity_bar_width, float left_side_panel_width,
37 float right_sidebar_width, float right_sidebar_budget_width,
38 float min_canvas_width) {
39 const float activity = std::max(0.0f, activity_bar_width);
40 const float left_panel = std::max(0.0f, left_side_panel_width);
41 const float right_panel = std::max(0.0f, right_sidebar_width);
42 const float right_budget = right_sidebar_budget_width >= 0.0f
43 ? right_sidebar_budget_width
44 : right_panel;
45 const float desired_left = activity + left_panel;
46
47 if (viewport_width > 0.0f && viewport_width - desired_left - right_budget <
48 std::max(0.0f, min_canvas_width)) {
49 return {
50 .left_offset = activity,
51 .right_offset = 0.0f,
52 .side_panels_overlay = left_panel > 0.0f || right_panel > 0.0f,
53 };
54 }
55
56 return {
57 .left_offset = desired_left,
58 .right_offset = right_panel,
59 .side_panels_overlay = false,
60 };
61}
62
65 float viewport_width = 0.0f;
66 if (ImGui::GetCurrentContext()) {
67 const ImGuiViewport* viewport = ImGui::GetMainViewport();
68 viewport_width = viewport ? viewport->WorkSize.x : 0.0f;
69 }
70
71 float activity_width = 0.0f;
72 float left_panel_width = 0.0f;
73 const bool show_left_chrome =
77 if (show_left_chrome) {
80 left_panel_width =
82 }
83 }
84
85 const float right_sidebar_width =
87 const float right_sidebar_budget_width =
89 : 0.0f;
90 return ResolveWorkspaceChromeBudget(viewport_width, activity_width,
91 left_panel_width, right_sidebar_width,
92 right_sidebar_budget_width);
93}
94
98
102
107
108// ==========================================================================
109// Layout Operations
110// ==========================================================================
111
113 if (!layout_manager_) {
114 return;
115 }
116
117 if (ImGui::GetCurrentContext()) {
118 static const char kEmptyIni[] = "\n";
119 ImGui::LoadIniSettingsFromMemory(kEmptyIni, sizeof(kEmptyIni) - 1);
120 }
121
122 if (auto ini_path = util::PlatformPaths::GetImGuiIniPath(); ini_path.ok()) {
123 std::error_code ec;
124 std::filesystem::remove(*ini_path, ec);
125 if (ec) {
126 LOG_WARN("LayoutCoordinator", "Failed to remove ImGui ini: %s",
127 ec.message().c_str());
128 }
129 }
130
133
134 // Force immediate rebuild for active context
135 ImGuiContext* imgui_ctx = ImGui::GetCurrentContext();
136 if (imgui_ctx && imgui_ctx->WithinFrameScope) {
137 ImGuiID dockspace_id = ImGui::GetID("MainDockSpace");
138
139 // Determine which layout to rebuild based on emulator visibility
142 LOG_INFO("LayoutCoordinator", "Emulator layout reset complete");
143 }
144 // Note: Current editor check would need to be passed in or stored
145 } else {
146 // Not in frame scope - rebuild will happen on next tick via RequestRebuild()
147 LOG_INFO("LayoutCoordinator", "Layout reset queued for next frame");
148 }
149}
150
151void LayoutCoordinator::ApplyLayoutPreset(const std::string& preset_name,
152 size_t session_id) {
153 if (!window_manager_) {
154 return;
155 }
156
157 PanelLayoutPreset preset;
158
159 // Get the preset by name
160 if (preset_name == "Minimal") {
162 } else if (preset_name == "Developer") {
164 } else if (preset_name == "Designer") {
166 } else if (preset_name == "Modder") {
168 } else if (preset_name == "Overworld Expert") {
170 } else if (preset_name == "Dungeon Expert") {
172 } else if (preset_name == "Testing") {
174 } else if (preset_name == "Audio") {
176 } else {
177 LOG_WARN("LayoutCoordinator", "Unknown layout preset: %s",
178 preset_name.c_str());
179 if (toast_manager_) {
180 toast_manager_->Show(absl::StrFormat("Unknown preset: %s", preset_name),
182 }
183 return;
184 }
185
186 // Hide all panels first
188
189 // Show only the panels defined in the preset
190 for (const auto& panel_id : preset.default_visible_panels) {
191 window_manager_->OpenWindow(session_id, panel_id);
192 }
193
194 // Request a dock rebuild so the preset positions are applied
195 if (layout_manager_) {
197 }
198
199 LOG_INFO("LayoutCoordinator", "Applied layout preset: %s",
200 preset_name.c_str());
201 if (toast_manager_) {
202 toast_manager_->Show(absl::StrFormat("Layout: %s", preset_name),
204 }
205}
206
208 return "Before default: " + EditorRegistry::GetEditorCategory(type);
209}
210
215
217 if (!HasPreviousEditorLayout(type))
218 return false;
219 const std::string backup = DefaultLayoutBackupName(type);
223 if (toast_manager_) {
224 toast_manager_->Show("Previous layout restored", ToastType::kSuccess);
225 }
226 return true;
227}
228
230 size_t session_id) {
231 if (!window_manager_) {
232 if (toast_manager_) {
233 toast_manager_->Show("No active editor to reset", ToastType::kWarning);
234 }
235 return;
236 }
237
238 // Keep the first pre-reset workspace until it is explicitly restored.
239 // Repeated default-layout tests must not overwrite the user's recovery copy.
240 if (layout_manager_) {
241 const std::string backup = DefaultLayoutBackupName(editor_type);
242 if (!layout_manager_->HasLayout(backup)) {
244 }
245 }
246
247 // Reset panels to defaults
248 window_manager_->ResetToDefaults(session_id, editor_type);
249
250 // Rebuild dock layout for this editor on next frame
251 if (layout_manager_) {
254 }
255
256 LOG_INFO("LayoutCoordinator", "Reset editor layout to defaults for type %d",
257 static_cast<int>(editor_type));
258 if (toast_manager_) {
259 toast_manager_->Show("Default layout applied; previous layout saved",
261 }
262}
263
264// ==========================================================================
265// Layout Rebuild Handling
266// ==========================================================================
267
269 bool is_emulator_visible) {
271 return;
272 }
273
274 // Only rebuild if we're in a valid ImGui frame with dockspace
275 ImGuiContext* imgui_ctx = ImGui::GetCurrentContext();
276 if (!imgui_ctx || !imgui_ctx->WithinFrameScope) {
277 return;
278 }
279
280 ImGuiID dockspace_id = ImGui::GetID("MainDockSpace");
281
282 // Determine which editor layout to rebuild
283 EditorType rebuild_type = EditorType::kUnknown;
284 if (is_emulator_visible) {
285 rebuild_type = EditorType::kEmulator;
286 } else if (current_editor_type != EditorType::kUnknown) {
287 rebuild_type = current_editor_type;
288 }
289
290 // Execute rebuild if we have a valid editor type
291 if (rebuild_type != EditorType::kUnknown) {
292 layout_manager_->RebuildLayout(rebuild_type, dockspace_id);
293 LOG_INFO("LayoutCoordinator", "Layout rebuilt for editor type %d",
294 static_cast<int>(rebuild_type));
295 }
296
298}
299
301 if (!layout_manager_) {
302 return;
303 }
304
306 return;
307 }
308
309 // Defer layout initialization to ensure we are in the correct scope
310 QueueDeferredAction([this, type]() {
312 ImGuiID dockspace_id = ImGui::GetID("MainDockSpace");
313 layout_manager_->InitializeEditorLayout(type, dockspace_id);
314 }
315 });
316}
317
318void LayoutCoordinator::QueueDeferredAction(std::function<void()> action) {
319 deferred_actions_.push_back(std::move(action));
320 pending_deferred_actions_.fetch_add(1, std::memory_order_relaxed);
321}
322
324 if (deferred_actions_.empty()) {
325 return;
326 }
327
328 std::vector<std::function<void()>> actions_to_execute;
329 actions_to_execute.swap(deferred_actions_);
330 const int processed_count = static_cast<int>(actions_to_execute.size());
331
332 for (auto& action : actions_to_execute) {
333 action();
334 }
335
336 if (processed_count > 0) {
337 const int remaining = pending_deferred_actions_.fetch_sub(
338 processed_count, std::memory_order_relaxed) -
339 processed_count;
340 if (remaining < 0) {
341 pending_deferred_actions_.store(0, std::memory_order_relaxed);
342 }
343 }
344}
345
346} // namespace editor
347} // namespace yaze
static std::string GetEditorCategory(EditorType type)
bool RestorePreviousEditorLayout(EditorType type)
std::vector< std::function< void()> > deferred_actions_
void QueueDeferredAction(std::function< void()> action)
Queue an action to be executed on the next frame.
static std::string DefaultLayoutBackupName(EditorType type)
void ProcessDeferredActions()
Process all queued deferred actions.
WorkspaceChromeBudget GetWorkspaceChromeBudget() const
float GetBottomLayoutOffset() const
Get the bottom margin needed for status bar.
static WorkspaceChromeBudget ResolveWorkspaceChromeBudget(float viewport_width, float activity_bar_width, float left_side_panel_width, float right_sidebar_width, float right_sidebar_budget_width=-1.0f, float min_canvas_width=640.0f)
bool HasPreviousEditorLayout(EditorType type) const
void ResetWorkspaceLayout()
Reset the workspace layout to defaults.
void ProcessLayoutRebuild(EditorType current_editor_type, bool is_emulator_visible)
Process pending layout rebuild requests.
RightDrawerManager * right_drawer_manager_
WorkspaceWindowManager * window_manager_
std::atomic< int > pending_deferred_actions_
void InitializeEditorLayout(EditorType type)
Initialize layout for an editor type on first activation.
float GetRightLayoutOffset() const
Get the right margin needed for drawers.
void ResetCurrentEditorLayout(EditorType editor_type, size_t session_id)
Reset current editor layout to its default configuration.
void ApplyLayoutPreset(const std::string &preset_name, size_t session_id)
Apply a named layout preset.
void Initialize(const Dependencies &deps)
Initialize with all dependencies.
float GetLeftLayoutOffset() const
Get the left margin needed for sidebar (Activity Bar + Side Panel)
void LoadLayout(const std::string &name)
Load a saved layout by name.
void RebuildLayout(EditorType type, ImGuiID dockspace_id)
Force rebuild of layout for a specific editor type.
void ClearInitializationFlags()
Clear all initialization flags (for testing)
bool DeleteLayout(const std::string &name)
Delete a saved layout by name.
bool IsLayoutInitialized(EditorType type) const
Check if a layout has been initialized for an editor.
void ResetToDefaultLayout(EditorType type)
Reset the layout for an editor to its default.
void ClearRebuildRequest()
Clear rebuild request flag.
void SaveCurrentLayout(const std::string &name, bool persist=true)
Save the current layout with a custom name.
void RequestRebuild()
Request a layout rebuild on next frame.
bool IsRebuildRequested() const
Check if rebuild was requested.
bool HasLayout(const std::string &name) const
Check if a layout exists.
static PanelLayoutPreset GetLogicDebuggerPreset()
Get the "logic debugger" workspace preset (QA and debug focused)
static PanelLayoutPreset GetDungeonMasterPreset()
Get the "dungeon master" workspace preset.
static PanelLayoutPreset GetAudioEngineerPreset()
Get the "audio engineer" workspace preset (music focused)
static PanelLayoutPreset GetDesignerPreset()
Get the "designer" workspace preset (visual-focused)
static PanelLayoutPreset GetOverworldArtistPreset()
Get the "overworld artist" workspace preset.
static PanelLayoutPreset GetModderPreset()
Get the "modder" workspace preset (full-featured)
static PanelLayoutPreset GetMinimalPreset()
Get the "minimal" workspace preset (minimal cards)
static PanelLayoutPreset GetDeveloperPreset()
Get the "developer" workspace preset (debug-focused)
bool IsEnabled() const
Definition status_bar.h:72
float GetHeight() const
Get the height of the status bar.
Definition status_bar.cc:81
void Show(const std::string &message, ToastType type=ToastType::kInfo, float ttl_seconds=3.0f, std::string action_label={}, std::function< void()> on_action=nullptr)
float GetActiveSidePanelWidth(float viewport_width) const
bool OpenWindow(size_t session_id, const std::string &base_window_id)
static absl::StatusOr< std::filesystem::path > GetImGuiIniPath()
Get the ImGui ini path for YAZE.
#define LOG_WARN(category, format,...)
Definition log.h:138
#define LOG_INFO(category, format,...)
Definition log.h:136
All dependencies required by LayoutCoordinator.
Defines default panel visibility for an editor type.
std::vector< std::string > default_visible_panels