yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
layout_manager.h
Go to the documentation of this file.
1#ifndef YAZE_APP_EDITOR_LAYOUT_LAYOUT_MANAGER_H_
2#define YAZE_APP_EDITOR_LAYOUT_LAYOUT_MANAGER_H_
3
4#include <string>
5#include <unordered_map>
6#include <unordered_set>
7#include <vector>
8
9#include "absl/status/status.h"
10#include "absl/status/statusor.h"
11#include "app/editor/editor.h"
13#include "imgui/imgui.h"
14
15namespace yaze {
16namespace editor {
17
18// Forward declaration
19class WorkspaceWindowManager;
20class UserSettings;
21
27
32 std::string id; // Stable id (e.g. "code", "debug")
33 std::string label; // UI-facing label
34 std::string description; // Short profile summary
35 std::string preset_name; // Backing LayoutPresets name
36 bool open_agent_chat = false;
37};
38
55 public:
56 LayoutManager() = default;
58
64 window_manager_ = manager;
65 }
66
72
78 void InitializeEditorLayout(EditorType type, ImGuiID dockspace_id);
79
88 void RebuildLayout(EditorType type, ImGuiID dockspace_id);
89
100 bool DockDefaultPositionOnFirstOpen(size_t session_id,
101 const std::string& panel_id);
102
113 bool DockPresetPositionOnPanelOpen(size_t session_id,
114 const std::string& panel_id);
115
121 void SaveCurrentLayout(const std::string& name, bool persist = true);
122
127 void LoadLayout(const std::string& name);
128
134 void CaptureTemporarySessionLayout(size_t session_id);
135
140 bool RestoreTemporarySessionLayout(size_t session_id,
141 bool clear_after_restore = false);
142
147
152
160 bool SaveNamedSnapshot(const std::string& name, size_t session_id);
161
165 bool RestoreNamedSnapshot(const std::string& name, size_t session_id,
166 bool remove_after_restore = false);
167
171 bool DeleteNamedSnapshot(const std::string& name);
172
176 std::vector<std::string> ListNamedSnapshots(size_t session_id) const;
177
181 bool HasNamedSnapshot(const std::string& name) const;
182
188 bool DeleteLayout(const std::string& name);
189
193 static std::vector<LayoutProfile> GetBuiltInProfiles();
194
203 bool ApplyBuiltInProfile(const std::string& profile_id, size_t session_id,
204 EditorType editor_type,
205 LayoutProfile* out_profile = nullptr);
206
211 std::vector<std::string> GetSavedLayoutNames() const;
212
218 bool HasLayout(const std::string& name) const;
219
223 void LoadLayoutsFromDisk();
224
229 void SetProjectLayoutKey(const std::string& key);
230
234 void UseGlobalLayouts();
235
240
246
252 bool IsLayoutInitialized(EditorType type) const;
253
259
264
269
273 bool IsRebuildRequested() const { return rebuild_requested_; }
274
279
285 std::string GetWindowTitle(const std::string& card_id) const;
286
287 // ==========================================================================
288 // DockTree integration (Layout Designer)
289 // ==========================================================================
290
315 absl::Status ApplyDockTree(const layout_designer::DockTree& tree,
316 ImGuiID dockspace_id);
317
318 // Finish one-time saved tab selection after ImGui registers the windows.
320
328 void SetMainDockspaceId(ImGuiID id) { main_dockspace_id_ = id; }
329
335 ImGuiID GetMainDockspaceId() const;
336
337 // ==========================================================================
338 // Per-editor dockspaces (B2)
339 // ==========================================================================
340
348 static ImGuiID OuterDockspaceId();
349
357 static ImGuiID EditorDockspaceId(EditorType type);
358
360 ImGuiID ActiveEditorDockspaceId() const;
361
364
373 void DrawEditorHost();
374
376 ImGuiID FindPinNode() const;
377
380 ImGuiDir pin_dir() const { return pin_dir_; }
381 float pin_size() const { return pin_size_; }
382
383 // ==========================================================================
384 // imgui.ini persistence (B2 layout revision)
385 // ==========================================================================
386
388 static constexpr int kLayoutIniRevision = 1;
389
392
394 void ReadLayoutIniLine(const char* line);
396 void WriteLayoutIniSettings(ImGuiTextBuffer* buf) const;
397
417
454 absl::Status MaybeReapplyStartupLayout(UserSettings* settings);
455
472 absl::StatusOr<layout_designer::DockTree> CaptureDockTree(
473 ImGuiID dockspace_id) const;
474
475 private:
476 // DockBuilder layout implementations for each editor type
477 void BuildLayoutFromPreset(EditorType type, ImGuiID dockspace_id);
479 void RefreshLazyDefaultDockingContext(EditorType type, ImGuiID dockspace_id);
481 bool DockPresetPositionOnFirstOpen(size_t session_id,
482 const std::string& panel_id,
483 bool include_default_visible,
484 bool allow_redock = false);
485 void MarkLazyDefaultDockAttempted(const std::string& panel_id);
487 bool RestoreLazyDefaultDockState(EditorType type, ImGuiID dockspace_id);
488 ImGuiID EnsurePinNode();
489 void RecordPinSpot();
490 // Puts the pin node on side `dir` (size in pixels, 0 keeps the saved one)
491 // and moves the panels already pinned there. Returns the pin node.
492 ImGuiID MovePinSpot(ImGuiDir dir, float size);
493 ImVec2 EditorDockspaceSize() const;
494 void EnforcePinnedPanels(ImGuiID pin_node);
496
497 void LoadLayoutsFromDiskInternal(LayoutScope scope, bool merge);
498 void SaveLayoutsToDisk(LayoutScope scope) const;
499
500 // Track which layouts have been initialized
501 std::unordered_map<EditorType, bool> layouts_initialized_;
502
504 ImGuiID node_id = 0;
505 ImGuiID selected_id = 0;
507 std::vector<ImGuiID> tab_ids;
508 size_t session_id = 0;
510 };
511 std::vector<PendingDockTabSelection> pending_dock_tab_selections_;
512
513 // Panel manager for window title lookups
515
516 // Rebuild flag
517 bool rebuild_requested_ = false;
518
519 // Last used dockspace ID (for rebuild operations)
521
522 // Main dockspace ID captured from the authoritative scope (see
523 // `SetMainDockspaceId`). 0 until the controller has rendered at least
524 // one DockSpaceWindow frame.
526
527 // True after `MaybeReapplyStartupLayout` has fired for this session
528 // (whether successfully or with a logged error). Guards the one-shot
529 // semantics across the per-frame call cadence.
531
532 // Set by `MaybeReapplyStartupLayout` after a successful apply, then
533 // consumed by the very next `InitializeEditorLayout` call (any
534 // editor type). Phase 8.2 review (2026-04-25): without this flag the
535 // first editor activation post-startup would blow away the
536 // freshly-reapplied custom layout via lazy preset init. The flag is
537 // intentionally global-one-shot rather than per-editor because at
538 // startup we don't know which editor the user will activate first;
539 // the very first lazy init is always the dangerous one.
541
542 // Current editor type being displayed
544
545 // Editor whose dockspace the editor host submits as active. Synced each
546 // frame by LayoutCoordinator::ProcessLayoutRebuild.
548
549 // Content size of the editor host from the last frame; zero before it draws.
550 ImVec2 editor_host_size_ = ImVec2(0.0f, 0.0f);
551
552 // Parsed [YazeLayout][Data] section from imgui.ini.
554 bool section_seen = false;
555 int revision = 0;
556 std::vector<EditorType> initialized;
557 ImGuiDir pin_dir = ImGuiDir_None;
558 float pin_size = 0.0f;
559 };
562
563 // Where the shared pin node goes when it is (re)built. The node is deleted
564 // when its last panel leaves, so the user's drag is kept here.
565 ImGuiDir pin_dir_ = ImGuiDir_Right;
566 float pin_size_ = 0.0f;
567
568 // Window names of the panels pinned at the last EnforcePinnedPanels. Tells
569 // a drag of a pinned panel apart from a panel pinned where it already sat.
570 std::unordered_set<std::string> pinned_last_frame_;
571
572 // Default presets may omit hidden panels from the initial dock tree. Keep
573 // enough state to create their preferred region lazily on first open.
575 bool enabled = false;
576 bool compact = false;
578 size_t session_id = 0;
579 ImGuiID dockspace = 0;
580 ImGuiID center = 0;
581 ImGuiID left = 0;
582 ImGuiID right = 0;
583 ImGuiID bottom = 0;
584 ImGuiID top = 0;
585 ImGuiID left_top = 0;
586 ImGuiID left_bottom = 0;
587 ImGuiID right_top = 0;
588 ImGuiID right_bottom = 0;
589 float left_ratio = 0.17f;
590 float right_ratio = 0.24f;
591 float bottom_ratio = 0.22f;
592 float top_ratio = 0.12f;
593 float vertical_split = 0.52f;
594 std::unordered_set<std::string> attempted_panels;
595 };
597 // Lazy state stashed per editor so a switch back resumes first-open docking.
598 std::unordered_map<EditorType, LazyDefaultDockState> lazy_states_by_type_;
599 std::unordered_map<
600 size_t, std::unordered_map<EditorType, std::unordered_set<std::string>>>
602
603 // Saved layouts (panel visibility state)
604 std::unordered_map<std::string, std::unordered_map<std::string, bool>>
606
607 // In-memory temporary session snapshot (never persisted).
610 std::unordered_map<std::string, bool> temp_session_visibility_;
611 std::unordered_map<std::string, bool> temp_session_pinned_;
613
614 // Multi-slot named session snapshots (in-memory only, never persisted).
615 // The user-supplied name is the stable key; duplicate saves overwrite.
617 size_t session_id = 0;
618 std::unordered_map<std::string, bool> visibility;
619 std::unordered_map<std::string, bool> pinned;
620 std::string imgui_layout;
621 };
622 std::unordered_map<std::string, SessionSnapshot> named_snapshots_;
623
624 // Saved ImGui docking layouts (INI data)
625 std::unordered_map<std::string, std::string> saved_imgui_layouts_;
626
627 // Saved pinned panel state for layouts
628 std::unordered_map<std::string, std::unordered_map<std::string, bool>>
630
631 // Layout scope tracking
632 std::unordered_map<std::string, LayoutScope> layout_scopes_;
633
634 // Project storage key for project-scoped layouts
636};
637
638} // namespace editor
639} // namespace yaze
640
641#endif // YAZE_APP_EDITOR_LAYOUT_LAYOUT_MANAGER_H_
Manages ImGui DockBuilder layouts for each editor type.
void DrawEditorHost()
Draw the editor host window and enforce the pin node.
void DockOpenPresetPanels(EditorType type)
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.
std::unordered_set< std::string > pinned_last_frame_
bool RestoreNamedSnapshot(const std::string &name, size_t session_id, bool remove_after_restore=false)
Restore a named snapshot by name.
std::vector< PendingDockTabSelection > pending_dock_tab_selections_
bool DockPresetPositionOnPanelOpen(size_t session_id, const std::string &panel_id)
Rebind any preset panel when a visibility event opens it.
WorkspaceWindowManager * window_manager() const
Get the window manager.
WorkspaceWindowManager * window_manager_
void ProtectRestoredLayoutFromDefaultInitialization()
ImGuiID FindPinNode() const
Pin node under the outer root, or 0 before the first split.
void CaptureTemporarySessionLayout(size_t session_id)
Capture the current workspace as a temporary session layout.
void SetProjectLayoutKey(const std::string &key)
Set the active project layout key (enables project scope)
bool DeleteNamedSnapshot(const std::string &name)
Delete a named snapshot. Returns true if an entry was removed.
bool SaveNamedSnapshot(const std::string &name, size_t session_id)
Capture the current workspace under a named, session-scoped slot.
std::unordered_map< std::string, std::unordered_map< std::string, bool > > saved_layouts_
std::unordered_map< size_t, std::unordered_map< EditorType, std::unordered_set< std::string > > > lazy_default_dock_attempts_
void SaveLayoutsToDisk(LayoutScope scope) const
absl::Status ApplyDockTree(const layout_designer::DockTree &tree, ImGuiID dockspace_id)
Apply a DockTree to the given dockspace.
void RebuildLayout(EditorType type, ImGuiID dockspace_id)
Force rebuild of layout for a specific editor type.
std::unordered_map< std::string, SessionSnapshot > named_snapshots_
void LoadLayoutsFromDisk()
Load layouts for the active scope (global + optional project)
static ImGuiID EditorDockspaceId(EditorType type)
Dockspace that holds one editor's panels.
void UseGlobalLayouts()
Clear project scope and return to global layouts only.
LazyDefaultDockState lazy_default_dock_state_
void ClearInitializationFlags()
Clear all initialization flags (for testing)
bool DockPresetPositionOnFirstOpen(size_t session_id, const std::string &panel_id, bool include_default_visible, bool allow_redock=false)
bool HasTemporarySessionLayout() const
Whether a temporary session layout is available.
bool startup_reapply_pending_protection_for_test() const
void set_current_editor_type_for_test(EditorType type)
bool DeleteLayout(const std::string &name)
Delete a saved layout by name.
bool HasNamedSnapshot(const std::string &name) const
Whether a named snapshot with the given name exists.
absl::StatusOr< layout_designer::DockTree > CaptureDockTree(ImGuiID dockspace_id) const
Capture the current docking state into a DockTree.
std::unordered_map< std::string, std::string > saved_imgui_layouts_
void reset_startup_layout_consumed_for_test()
Test-only: reset the one-shot startup-reapply guard so a single test fixture can drive MaybeReapplySt...
std::vector< std::string > GetSavedLayoutNames() const
Get list of all saved layout names.
std::unordered_map< EditorType, bool > layouts_initialized_
static ImGuiID OuterDockspaceId()
Outer dockspace hosted by DockSpaceWindow.
void RefreshLazyDefaultDockingContext(EditorType type, ImGuiID dockspace_id)
void LoadLayoutsFromDiskInternal(LayoutScope scope, bool merge)
bool IsLayoutInitialized(EditorType type) const
Check if a layout has been initialized for an editor.
ImGuiID MovePinSpot(ImGuiDir dir, float size)
bool RestoreTemporarySessionLayout(size_t session_id, bool clear_after_restore=false)
Restore the temporary session layout if one has been captured.
EditorType active_editor_type() const
void EnforcePinnedPanels(ImGuiID pin_node)
std::unordered_map< EditorType, LazyDefaultDockState > lazy_states_by_type_
std::unordered_map< std::string, std::unordered_map< std::string, bool > > saved_pinned_layouts_
bool RestoreLazyDefaultDockState(EditorType type, ImGuiID dockspace_id)
void ResetToDefaultLayout(EditorType type)
Reset the layout for an editor to its default.
void SetMainDockspaceId(ImGuiID id)
Record the outer dockspace ID (OuterDockspaceId() in the app).
void set_editor_host_size_for_test(ImVec2 size)
LayoutScope GetActiveScope() const
Get the active layout scope.
void WriteLayoutIniSettings(ImGuiTextBuffer *buf) const
void ClearRebuildRequest()
Clear rebuild request flag.
static constexpr int kLayoutIniRevision
Layout revision written to imgui.ini. A mismatch resets dock trees.
void ClearTemporarySessionLayout()
Clear temporary session layout snapshot state.
void MarkLayoutInitialized(EditorType type)
Mark a layout as initialized.
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.
void SetWindowManager(WorkspaceWindowManager *manager)
Set the window manager for window title lookups.
ImGuiID ActiveEditorDockspaceId() const
Dockspace of the editor shown in the editor host, or 0 for kUnknown.
static std::vector< LayoutProfile > GetBuiltInProfiles()
Get built-in layout profiles.
bool DockDefaultPositionOnFirstOpen(size_t session_id, const std::string &panel_id)
Dock a hidden-by-default panel at its preset position on first open.
void ReadLayoutIniLine(const char *line)
void InitializeEditorLayout(EditorType type, ImGuiID dockspace_id)
Initialize the default layout for a specific editor type.
void SetActiveEditorType(EditorType type)
void RegisterLayoutIniHandler()
Register the "YazeLayout" ImGui settings handler on the current context.
bool IsRebuildRequested() const
Check if rebuild was requested.
bool HasLayout(const std::string &name) const
Check if a layout exists.
std::unordered_map< std::string, LayoutScope > layout_scopes_
void BuildLayoutFromPreset(EditorType type, ImGuiID dockspace_id)
bool startup_layout_consumed_for_test() const
bool ApplyBuiltInProfile(const std::string &profile_id, size_t session_id, EditorType editor_type, LayoutProfile *out_profile=nullptr)
Apply a built-in layout profile by profile ID.
std::vector< std::string > ListNamedSnapshots(size_t session_id) const
List all named snapshots for the given session.
std::unordered_map< std::string, bool > temp_session_pinned_
absl::Status MaybeReapplyStartupLayout(UserSettings *settings)
One-shot startup hook that re-applies the user's last applied named layout, if any.
void MarkLazyDefaultDockAttempted(const std::string &panel_id)
ImGuiID GetMainDockspaceId() const
Get the cached main dockspace ID.
std::unordered_map< std::string, bool > temp_session_visibility_
Manages user preferences and settings persistence.
Central registry for all editor cards with session awareness and dependency injection.
LayoutScope
Storage scope for saved layouts.
std::unordered_set< std::string > attempted_panels
std::unordered_map< std::string, bool > visibility
std::unordered_map< std::string, bool > pinned
Built-in workflow-oriented layout profiles.