yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
panel_manager.h
Go to the documentation of this file.
1#ifndef APP_EDITOR_SYSTEM_PANEL_MANAGER_H_
2#define APP_EDITOR_SYSTEM_PANEL_MANAGER_H_
3
4#include <algorithm>
5#include <cstdint>
6#include <functional>
7#include <list>
8#include <memory>
9#include <string>
10#include <unordered_map>
11#include <unordered_set>
12#include <vector>
13
18
19#ifndef YAZE_ENABLE_CARD_SHIM_DEPRECATION
20#define YAZE_ENABLE_CARD_SHIM_DEPRECATION 1
21#endif
22
23#if YAZE_ENABLE_CARD_SHIM_DEPRECATION && defined(__has_cpp_attribute)
24#if __has_cpp_attribute(deprecated)
25#define YAZE_CARD_SHIM_DEPRECATED(msg) [[deprecated(msg)]]
26#else
27#define YAZE_CARD_SHIM_DEPRECATED(msg)
28#endif
29#else
30#define YAZE_CARD_SHIM_DEPRECATED(msg)
31#endif
32
33namespace yaze {
34
35namespace gui {
36class PanelWindow;
37} // namespace gui
38
39namespace editor {
40
41// Forward declarations
42enum class EditorType;
43class Editor;
44
50 std::string card_id; // Unique identifier (e.g., "dungeon.room_selector")
51 std::string display_name; // Human-readable name (e.g., "Room Selector")
52 std::string window_title; // ImGui window title for DockBuilder (e.g., " Rooms List")
53 std::string icon; // Material icon
54 std::string category; // Category (e.g., "Dungeon", "Graphics", "Palette")
55
56 // Lifecycle behavior on editor switches (default: EditorBound).
58
59 // Optional context binding (default: none).
61
63 enum class ShortcutScope {
64 kGlobal, // Available regardless of active editor
65 kEditor, // Only active within the owning editor
66 kPanel // Panel visibility/within-panel actions
67 };
68 std::string shortcut_hint; // Display hint (e.g., "Ctrl+Shift+R")
70 bool* visibility_flag; // Pointer to bool controlling visibility
71 std::function<void()> on_show; // Callback when card is shown
72 std::function<void()> on_hide; // Callback when card is hidden
73 int priority; // Display priority for menus (lower = higher)
74
75 // Disabled state support for IDE-like behavior
76 std::function<bool()> enabled_condition; // Returns true if card is enabled (nullptr = always enabled)
77 std::string disabled_tooltip; // Tooltip shown when hovering disabled card
78
83 std::string GetWindowTitle() const {
84 if (!window_title.empty()) {
85 return window_title;
86 }
87 // Generate from icon + display_name if window_title not explicitly set
88 return icon + " " + display_name;
89 }
90
97 std::string GetImGuiWindowName() const {
98 const std::string label =
99 icon.empty() ? display_name : (icon + " " + display_name);
100 if (!card_id.empty()) {
101 return label + "##" + card_id;
102 }
103 return label;
104 }
105};
106
113 public:
114 PanelManager() = default;
115 ~PanelManager() = default;
116
117 // Non-copyable, non-movable
118 PanelManager(const PanelManager&) = delete;
122
123 // Special category for dashboard/welcome screen - suppresses panel drawing
124 static constexpr const char* kDashboardCategory = "Dashboard";
125
126 // ============================================================================
127 // Session Lifecycle Management
128 // ============================================================================
129
130 void RegisterSession(size_t session_id);
131 void UnregisterSession(size_t session_id);
132 void SetActiveSession(size_t session_id);
133
134 // ============================================================================
135 // Context Keys (Optional Policy Engine)
136 // ============================================================================
137
144 void SetContextKey(size_t session_id, PanelContextScope scope,
145 std::string key);
146 std::string GetContextKey(size_t session_id, PanelContextScope scope) const;
147
148 // ============================================================================
149 // Panel Registration
150 // ============================================================================
151
152 void RegisterPanel(size_t session_id, const PanelDescriptor& base_info);
153
160 void RegisterPanelAlias(const std::string& legacy_base_id,
161 const std::string& canonical_base_id);
162
167 std::string ResolvePanelAlias(const std::string& panel_id) const;
168
169 void RegisterPanel(size_t session_id, const std::string& card_id,
170 const std::string& display_name, const std::string& icon,
171 const std::string& category,
172 const std::string& shortcut_hint = "", int priority = 50,
173 std::function<void()> on_show = nullptr,
174 std::function<void()> on_hide = nullptr,
175 bool visible_by_default = false);
176
177 void UnregisterPanel(size_t session_id, const std::string& base_card_id);
178 void UnregisterPanelsWithPrefix(const std::string& prefix);
179 void ClearAllPanels();
180
181 // ============================================================================
182 // EditorPanel Instance Management (Phase 4)
183 // ============================================================================
184
192 void RegisterRegistryPanel(std::unique_ptr<EditorPanel> panel);
193
200 void RegisterRegistryPanelsForSession(size_t session_id);
201
203 size_t GetRegistryPanelCount() const { return registry_panel_ids_.size(); }
204
214 void RegisterEditorPanel(std::unique_ptr<EditorPanel> panel);
215
220 void UnregisterEditorPanel(const std::string& panel_id);
221
227 EditorPanel* GetEditorPanel(const std::string& panel_id);
228
237
248 void OnEditorSwitch(const std::string& from_category,
249 const std::string& to_category);
250
251 // ============================================================================
252 // Panel Control (Programmatic)
253 // ============================================================================
254
255 bool ShowPanel(size_t session_id, const std::string& base_card_id);
256 bool HidePanel(size_t session_id, const std::string& base_card_id);
257 bool TogglePanel(size_t session_id, const std::string& base_card_id);
258 bool IsPanelVisible(size_t session_id, const std::string& base_card_id) const;
259 bool* GetVisibilityFlag(size_t session_id, const std::string& base_card_id);
260
261 // ============================================================================
262 // Batch Operations
263 // ============================================================================
264
265 void ShowAllPanelsInSession(size_t session_id);
266 void HideAllPanelsInSession(size_t session_id);
267 void ShowAllPanelsInCategory(size_t session_id, const std::string& category);
268 void HideAllPanelsInCategory(size_t session_id, const std::string& category);
269 void ShowOnlyPanel(size_t session_id, const std::string& base_card_id);
270
271 // ============================================================================
272 // Query Methods
273 // ============================================================================
274
275 std::vector<std::string> GetPanelsInSession(size_t session_id) const;
276 std::vector<PanelDescriptor> GetPanelsInCategory(size_t session_id,
277 const std::string& category) const;
278 std::vector<std::string> GetAllCategories(size_t session_id) const;
279 const PanelDescriptor* GetPanelDescriptor(size_t session_id,
280 const std::string& base_card_id) const;
281
286 const std::unordered_map<std::string, PanelDescriptor>& GetAllPanelDescriptors() const {
287 return cards_;
288 }
289
290 std::vector<std::string> GetAllCategories() const;
291
292 // ============================================================================
293 // State Persistence
294 // ============================================================================
295
301 std::vector<std::string> GetVisiblePanelIds(size_t session_id) const;
302
308 void SetVisiblePanels(size_t session_id,
309 const std::vector<std::string>& panel_ids);
310
316 std::unordered_map<std::string, bool> SerializeVisibilityState(
317 size_t session_id) const;
318
325 size_t session_id, const std::unordered_map<std::string, bool>& state,
326 bool publish_events = false);
327
332 std::unordered_map<std::string, bool> SerializePinnedState() const;
333
338 void RestorePinnedState(const std::unordered_map<std::string, bool>& state);
339
344 std::string GetPanelWindowName(size_t session_id,
345 const std::string& base_card_id) const;
346
350 std::string GetPanelWindowName(const PanelDescriptor& descriptor) const;
351
352 static constexpr float GetSidebarWidth() { return 48.0f; }
353 static constexpr float GetSidePanelWidth() { return 300.0f; }
357 };
358 static SidePanelWidthBounds GetSidePanelWidthBounds(float viewport_width);
359 static float GetSidePanelWidthForViewport(float viewport_width) {
360 if (viewport_width <= 0.0f) {
361 return GetSidePanelWidth();
362 }
363
364 // Keep side panel useful on compact/touch widths while preserving
365 // desktop defaults on large displays.
366 if (viewport_width < 900.0f) {
367 const float preferred = viewport_width * 0.50f;
368 const float min_width = std::max(220.0f, viewport_width * 0.40f);
369 const float max_width =
370 std::max(min_width, std::min(380.0f, viewport_width * 0.58f));
371 return std::clamp(preferred, min_width, max_width);
372 }
373
374 if (viewport_width < 1200.0f) {
375 const float preferred = viewport_width * 0.34f;
376 const float min_width = 300.0f;
377 const float max_width = std::min(420.0f, viewport_width * 0.42f);
378 return std::clamp(preferred, min_width, max_width);
379 }
380
381 // iPad Pro landscape sits in this range; avoid falling back to a narrow
382 // desktop sidebar width that feels cramped for touch navigation.
383 if (viewport_width < 1400.0f) {
384 const float preferred = viewport_width * 0.25f;
385 const float min_width = 300.0f;
386 const float max_width = 380.0f;
387 return std::clamp(preferred, min_width, max_width);
388 }
389
390 float width = GetSidePanelWidth();
391 const float max_width = viewport_width * 0.30f;
392 if (max_width > 0.0f && width > max_width) {
393 width = max_width;
394 }
395 return width;
396 }
397 float GetActiveSidePanelWidth(float viewport_width) const;
398 void SetActiveSidePanelWidth(float width, float viewport_width = 0.0f,
399 bool notify = true);
400 void ResetSidePanelWidth(bool notify = true);
402 void SetStoredSidePanelWidth(float width, bool notify = false) {
403 SetActiveSidePanelWidth(width, 0.0f, notify);
404 }
405 void SetSidePanelWidthChangedCallback(std::function<void(float)> cb) {
406 on_side_panel_width_changed_ = std::move(cb);
407 }
408
412 void SetPanelBrowserCategoryWidth(float width, bool notify = true);
414 std::function<void(float)> cb) {
416 }
417 static constexpr float GetDefaultPanelBrowserCategoryWidth() {
418 return 260.0f;
419 }
420
421 static constexpr float GetCollapsedSidebarWidth() { return 16.0f; }
422
423 static std::string GetCategoryIcon(const std::string& category);
424
431 float r, g, b, a; // Icon color when active
432 float glow_r, glow_g, glow_b; // Glow/accent color (same hue)
433 };
434 static CategoryTheme GetCategoryTheme(const std::string& category);
435
439 void HandleSidebarKeyboardNav(size_t session_id,
440 const std::vector<PanelDescriptor>& cards);
441
442 bool SidebarHasFocus() const { return sidebar_has_focus_; }
444
451
452 void SetSidebarVisible(bool visible, bool notify = true) {
453 if (sidebar_visible_ != visible) {
454 sidebar_visible_ = visible;
455 if (notify && on_sidebar_state_changed_) {
457 }
458 }
459 }
460
461 bool IsSidebarVisible() const { return sidebar_visible_; }
462
469
470 void SetPanelExpanded(bool expanded, bool notify = true) {
471 if (panel_expanded_ != expanded) {
472 panel_expanded_ = expanded;
473 if (notify && on_sidebar_state_changed_) {
475 }
476 }
477 }
478
479 bool IsPanelExpanded() const { return panel_expanded_; }
480
481 // ============================================================================
482 // EventBus Integration
483 // ============================================================================
484
485 void SetEventBus(EventBus* event_bus) { event_bus_ = event_bus; }
486
487 // ============================================================================
488 // Triggers (exposed for ActivityBar) - prefer EventBus, fallback to callbacks
489 // ============================================================================
490
512 void TriggerUndo() {
513 if (event_bus_) {
515 }
516 }
517 void TriggerRedo() {
518 if (event_bus_) {
520 }
521 }
566 void TriggerPanelClicked(const std::string& category) {
567 if (on_card_clicked_) on_card_clicked_(category);
568 }
569 void TriggerCategorySelected(const std::string& category) {
571 }
572
573 // ============================================================================
574 // Utility Icon Callbacks (DEPRECATED: subscribe to UIActionRequestEvent instead)
575 // ============================================================================
576
578 std::function<void(bool, bool)> cb) {
579 on_sidebar_state_changed_ = std::move(cb);
580 }
581
582 // ============================================================================
583 // Unified Visibility Management (single source of truth)
584 // ============================================================================
585
586 bool IsEmulatorVisible() const { return emulator_visible_; }
587 void SetEmulatorVisible(bool visible) {
588 if (emulator_visible_ != visible) {
589 emulator_visible_ = visible;
592 }
593 }
594 }
596 void SetEmulatorVisibilityChangedCallback(std::function<void(bool)> cb) {
597 on_emulator_visibility_changed_ = std::move(cb);
598 }
599 void SetCategoryChangedCallback(std::function<void(const std::string&)> cb) {
600 on_category_changed_ = std::move(cb);
601 }
602
603 // ============================================================================
604 // Workspace Presets
605 // ============================================================================
606
608 std::string name;
609 std::vector<std::string> visible_cards; // Panel IDs
610 std::string description;
611 };
612
613 void SavePreset(const std::string& name, const std::string& description = "");
614 bool LoadPreset(const std::string& name);
615 void DeletePreset(const std::string& name);
616 std::vector<WorkspacePreset> GetPresets() const;
617
618 // ============================================================================
619 // Panel Validation (for catching ImGui window-name mismatches)
620 // ============================================================================
621
623 std::string card_id;
624 std::string expected_title; // Exact ImGui window name for docking/focus
625 bool found_in_imgui; // Whether ImGui found a window with this title
626 std::string message; // Human-readable status
627 };
628
629 std::vector<PanelValidationResult> ValidatePanels() const;
630 PanelValidationResult ValidatePanel(const std::string& card_id) const;
631
632 // ============================================================================
633 // Quick Actions
634 // ============================================================================
635
636 void ShowAll(size_t session_id);
637 void HideAll(size_t session_id);
638 void ResetToDefaults(size_t session_id);
639 void ResetToDefaults(size_t session_id, EditorType editor_type);
640
641 // ============================================================================
642 // Statistics
643 // ============================================================================
644
645 size_t GetPanelCount() const { return cards_.size(); }
646 size_t GetVisiblePanelCount(size_t session_id) const;
647 size_t GetSessionCount() const { return session_count_; }
648
649 // ============================================================================
650 // Session Prefixing Utilities
651 // ============================================================================
652
653 std::string MakePanelId(size_t session_id, const std::string& base_id) const;
654 std::string MakePanelId(size_t session_id, const std::string& base_id,
655 PanelScope scope) const;
656 bool ShouldPrefixPanels() const { return session_count_ > 1; }
657
658 // ============================================================================
659 // Convenience Methods (for EditorManager direct usage without session_id)
660 // ============================================================================
661
662 void RegisterPanel(const PanelDescriptor& base_info) {
663 RegisterPanel(active_session_, base_info);
664 }
665 void UnregisterPanel(const std::string& base_card_id) {
666 UnregisterPanel(active_session_, base_card_id);
667 }
668 bool ShowPanel(const std::string& base_card_id) {
669 return ShowPanel(active_session_, base_card_id);
670 }
671 bool HidePanel(const std::string& base_card_id) {
672 return HidePanel(active_session_, base_card_id);
673 }
674 bool IsPanelVisible(const std::string& base_card_id) const {
675 return IsPanelVisible(active_session_, base_card_id);
676 }
677 void HideAllPanelsInCategory(const std::string& category) {
679 }
680 std::string GetActiveCategory() const { return active_category_; }
681 void SetActiveCategory(const std::string& category, bool notify = true) {
682 if (active_category_ != category) {
683 active_category_ = category;
684 if (notify && on_category_changed_) {
685 on_category_changed_(category);
686 }
687 }
688 }
689 void ShowAllPanelsInCategory(const std::string& category) {
691 }
692 bool* GetVisibilityFlag(const std::string& base_card_id) {
693 return GetVisibilityFlag(active_session_, base_card_id);
694 }
697 void SetOnPanelClickedCallback(std::function<void(const std::string&)> callback) {
698 on_card_clicked_ = std::move(callback);
699 }
700 void SetOnCategorySelectedCallback(std::function<void(const std::string&)> callback) {
701 on_category_selected_ = std::move(callback);
702 }
703 void SetEditorResolver(std::function<Editor*(const std::string&)> resolver) {
704 editor_resolver_ = std::move(resolver);
705 }
706
707 size_t GetActiveSessionId() const { return active_session_; }
708
709 // ============================================================================
710 // File Browser Integration
711 // ============================================================================
712
713 FileBrowser* GetFileBrowser(const std::string& category);
714 void EnableFileBrowser(const std::string& category,
715 const std::string& root_path = "");
716 void DisableFileBrowser(const std::string& category);
717 bool HasFileBrowser(const std::string& category) const;
718 void SetFileBrowserPath(const std::string& category, const std::string& path);
720 std::function<void(const std::string& category, const std::string& path)>
721 callback) {
722 on_file_clicked_ = std::move(callback);
723 }
724
725 // ============================================================================
726 // Favorites (delegates to Pinned) and Recent
727 // ============================================================================
728
729 // Favorites are now aliases for pinned panels
730 void ToggleFavorite(const std::string& card_id) {
731 SetPanelPinned(card_id, !IsPanelPinned(card_id));
732 }
733 bool IsFavorite(const std::string& card_id) const {
734 return IsPanelPinned(card_id);
735 }
736
738 void MarkPanelRecentlyUsed(const std::string& card_id);
739
741 std::vector<PanelDescriptor> GetPanelsSortedByMRU(
742 size_t session_id, const std::string& category) const;
743
745 uint64_t GetPanelMRUTime(const std::string& card_id) const {
746 auto iter = last_used_at_.find(card_id);
747 return (iter != last_used_at_.end()) ? iter->second : 0;
748 }
749
750 // ============================================================================
751 // Pinning (Phase 3 scaffold)
752 // ============================================================================
753
754 void SetPanelPinned(size_t session_id, const std::string& base_card_id, bool pinned);
755 bool IsPanelPinned(size_t session_id, const std::string& base_card_id) const;
756 std::vector<std::string> GetPinnedPanels(size_t session_id) const;
757
758 void SetPanelPinned(const std::string& base_card_id, bool pinned);
759 bool IsPanelPinned(const std::string& base_card_id) const;
760 std::vector<std::string> GetPinnedPanels() const;
761
762 // ============================================================================
763 // Resource Management (Phase 6)
764 // ============================================================================
765
773 void EnforceResourceLimits(const std::string& resource_type);
774
779 void MarkPanelUsed(const std::string& panel_id);
780
781 EditorPanel* FindPanelInstance(const std::string& prefixed_panel_id,
782 const std::string& base_panel_id);
783 const EditorPanel* FindPanelInstance(const std::string& prefixed_panel_id,
784 const std::string& base_panel_id) const;
785
786 private:
788 size_t operator()(PanelContextScope scope) const noexcept {
789 return static_cast<size_t>(scope);
790 }
791 };
792
793 void ApplyContextPolicy(size_t session_id, PanelContextScope scope,
794 const std::string& old_key,
795 const std::string& new_key);
796 std::string ResolveBasePanelId(const std::string& panel_id) const;
797 std::string GetBaseIdForPrefixedId(size_t session_id,
798 const std::string& prefixed_id) const;
799
800 // ... existing private members ...
801
802 // Resource panel tracking: type -> list of panel_ids (front = LRU, back = MRU)
803 std::unordered_map<std::string, std::list<std::string>> resource_panels_;
804
805 // Map panel_id -> resource_type for quick lookups
806 std::unordered_map<std::string, std::string> panel_resource_types_;
807
808 // ... existing private members ...
809 // Core card storage (prefixed IDs → PanelDescriptor)
810 std::unordered_map<std::string, PanelDescriptor> cards_;
811
812 // EditorPanel instance storage (panel_id → EditorPanel)
813 // Panels with instances are drawn by DrawAllVisiblePanels()
814 std::unordered_map<std::string, std::unique_ptr<EditorPanel>> panel_instances_;
815 std::unordered_set<std::string> registry_panel_ids_;
816 std::unordered_set<std::string> global_panel_ids_;
817
818 // MRU timestamp tracking (panel_id -> monotonic counter)
819 std::unordered_map<std::string, uint64_t> last_used_at_;
820 uint64_t mru_counter_ = 0;
821
822 // Centralized visibility flags for cards without external flags
823 std::unordered_map<std::string, bool> centralized_visibility_;
824 // Pinned state tracking (prefixed ID → pinned)
825 std::unordered_map<std::string, bool> pinned_panels_;
826
827 // Session tracking
828 size_t session_count_ = 0;
829 size_t active_session_ = 0;
830
831 // Maps session_id → vector of prefixed card IDs registered for that session
832 std::unordered_map<size_t, std::vector<std::string>> session_cards_;
833
834 // Maps session_id → (base_card_id → prefixed_card_id)
835 std::unordered_map<size_t, std::unordered_map<std::string, std::string>>
837
838 // Maps session_id → (prefixed_card_id → base_card_id)
839 std::unordered_map<size_t, std::unordered_map<std::string, std::string>>
841
842 // Backward compatibility aliases for renamed panel IDs.
843 // Maps legacy base_id -> canonical base_id.
844 std::unordered_map<std::string, std::string> panel_id_aliases_;
845
846 // Context keys per session (used by SetContextKey/GetContextKey).
847 std::unordered_map<size_t,
848 std::unordered_map<PanelContextScope, std::string,
851
852 // Workspace presets
853 std::unordered_map<std::string, WorkspacePreset> presets_;
854
855 // Active category tracking
856 std::string active_category_;
857 std::vector<std::string> recent_categories_;
858 static constexpr size_t kMaxRecentCategories = 5;
859
860 // Sidebar state
861 bool sidebar_visible_ = false; // Controls Activity Bar visibility (0px vs 48px)
862 bool panel_expanded_ = false; // Controls Side Panel visibility (0px vs 250px) - starts collapsed
863 float side_panel_width_ = 0.0f; // 0 = use responsive default
866
867 // Keyboard navigation state (click-to-focus modal)
868 int focused_card_index_ = -1; // Currently focused card index (-1 = none)
869 bool sidebar_has_focus_ = false; // Whether sidebar has keyboard focus
870
871 // Unified visibility state (single source of truth)
872 bool emulator_visible_ = false; // Emulator window visibility
873
874 // EventBus for action events (preferred over callbacks)
876
877 // State change callbacks
878 std::function<void(bool visible, bool expanded)> on_sidebar_state_changed_;
879 std::function<void(float width)> on_side_panel_width_changed_;
880 std::function<void(float width)> on_panel_browser_category_width_changed_;
881 std::function<void(const std::string&)> on_category_changed_;
882 std::function<void(const std::string&)> on_card_clicked_;
883 std::function<void(const std::string&)> on_category_selected_; // Activity Bar icon clicked
884 std::function<void(bool)> on_emulator_visibility_changed_;
885 std::function<void(const std::string&, const std::string&)> on_file_clicked_;
886 std::function<Editor*(const std::string&)> editor_resolver_;
887
888 // File browser for categories that support it (e.g., Assembly)
889 std::unordered_map<std::string, std::unique_ptr<FileBrowser>>
891
892 // Tracking active editor categories for visual feedback
893 std::unordered_set<std::string> active_editor_categories_;
894
895 // Helper methods
896 void UpdateSessionCount();
897 std::string GetPrefixedPanelId(size_t session_id,
898 const std::string& base_id) const;
899 void RegisterPanelDescriptorForSession(size_t session_id,
900 const EditorPanel& panel);
901 void TrackPanelForSession(size_t session_id, const std::string& base_id,
902 const std::string& panel_id);
903 void UnregisterSessionPanels(size_t session_id);
904 void SavePresetsToFile();
905 void LoadPresetsFromFile();
906};
907
908} // namespace editor
909} // namespace yaze
910
911#undef YAZE_CARD_SHIM_DEPRECATED
912
913#endif // APP_EDITOR_SYSTEM_PANEL_MANAGER_H_
void Publish(const T &event)
Definition event_bus.h:35
Base interface for all logical panel components.
Interface for editor classes.
Definition editor.h:236
File system browser for the sidebar.
Central registry for all editor cards with session awareness and dependency injection.
std::unordered_map< std::string, bool > SerializeVisibilityState(size_t session_id) const
Serialize panel visibility state for persistence.
std::vector< std::string > GetPinnedPanels() const
float GetPanelBrowserCategoryWidth() const
void ApplyContextPolicy(size_t session_id, PanelContextScope scope, const std::string &old_key, const std::string &new_key)
std::function< void(bool visible, bool expanded)> on_sidebar_state_changed_
size_t GetVisiblePanelCount(size_t session_id) const
void ShowOnlyPanel(size_t session_id, const std::string &base_card_id)
std::unordered_map< std::string, bool > centralized_visibility_
void SetPanelExpanded(bool expanded, bool notify=true)
void SetEmulatorVisibilityChangedCallback(std::function< void(bool)> cb)
void SetOnCategorySelectedCallback(std::function< void(const std::string &)> callback)
void SetSidebarStateChangedCallback(std::function< void(bool, bool)> cb)
std::unordered_map< std::string, std::unique_ptr< EditorPanel > > panel_instances_
bool * GetVisibilityFlag(const std::string &base_card_id)
std::function< void(const std::string &) on_category_selected_)
void ShowAllPanelsInCategory(const std::string &category)
void RegisterSession(size_t session_id)
void SetFileBrowserPath(const std::string &category, const std::string &path)
void TriggerCategorySelected(const std::string &category)
EditorPanel * GetEditorPanel(const std::string &panel_id)
Get an EditorPanel instance by ID.
void SetSidebarVisible(bool visible, bool notify=true)
void OnEditorSwitch(const std::string &from_category, const std::string &to_category)
Handle editor/category switching for panel visibility.
void UnregisterSessionPanels(size_t session_id)
void SetActiveSession(size_t session_id)
bool TogglePanel(size_t session_id, const std::string &base_card_id)
const PanelDescriptor * GetPanelDescriptor(size_t session_id, const std::string &base_card_id) const
void SetCategoryChangedCallback(std::function< void(const std::string &)> cb)
void HideAllPanelsInCategory(const std::string &category)
std::unordered_map< std::string, std::string > panel_resource_types_
uint64_t GetPanelMRUTime(const std::string &card_id) const
Get MRU timestamp for a panel (0 if never used)
void TriggerPanelClicked(const std::string &category)
std::unordered_map< size_t, std::vector< std::string > > session_cards_
PanelManager & operator=(PanelManager &&)=delete
void SetActiveSidePanelWidth(float width, float viewport_width=0.0f, bool notify=true)
void ResetSidePanelWidth(bool notify=true)
std::vector< std::string > GetPanelsInSession(size_t session_id) const
void HandleSidebarKeyboardNav(size_t session_id, const std::vector< PanelDescriptor > &cards)
Handle keyboard navigation in sidebar (click-to-focus modal)
void RestorePinnedState(const std::unordered_map< std::string, bool > &state)
Restore pinned panel state from persistence.
void RestoreVisibilityState(size_t session_id, const std::unordered_map< std::string, bool > &state, bool publish_events=false)
Restore panel visibility state from persistence.
std::unordered_map< size_t, std::unordered_map< std::string, std::string > > session_reverse_card_mapping_
std::unordered_map< std::string, bool > SerializePinnedState() const
Serialize pinned panel state for persistence.
void SetActiveCategory(const std::string &category, bool notify=true)
std::vector< std::string > GetAllCategories() const
std::string GetContextKey(size_t session_id, PanelContextScope scope) const
bool * GetVisibilityFlag(size_t session_id, const std::string &base_card_id)
void UnregisterSession(size_t session_id)
void HideAllPanelsInSession(size_t session_id)
std::string GetBaseIdForPrefixedId(size_t session_id, const std::string &prefixed_id) const
bool HasFileBrowser(const std::string &category) const
PanelManager & operator=(const PanelManager &)=delete
void RegisterPanelAlias(const std::string &legacy_base_id, const std::string &canonical_base_id)
Register a legacy panel ID alias that resolves to a canonical ID.
static float GetSidePanelWidthForViewport(float viewport_width)
std::vector< PanelDescriptor > GetPanelsSortedByMRU(size_t session_id, const std::string &category) const
Get panels in category sorted by: pinned first, then MRU.
std::function< void(bool)> on_emulator_visibility_changed_
void UnregisterPanelsWithPrefix(const std::string &prefix)
void SetOnPanelClickedCallback(std::function< void(const std::string &)> callback)
void SetEditorResolver(std::function< Editor *(const std::string &)> resolver)
std::function< void(const std::string &, const std::string &) on_file_clicked_)
std::vector< PanelDescriptor > GetPanelsInCategory(size_t session_id, const std::string &category) const
std::unordered_map< size_t, std::unordered_map< PanelContextScope, std::string, PanelContextScopeHash > > session_context_keys_
bool ShowPanel(size_t session_id, const std::string &base_card_id)
std::string MakePanelId(size_t session_id, const std::string &base_id) const
std::function< void(float width)> on_side_panel_width_changed_
std::unordered_map< std::string, PanelDescriptor > cards_
void UnregisterPanel(const std::string &base_card_id)
std::unordered_map< std::string, bool > pinned_panels_
static CategoryTheme GetCategoryTheme(const std::string &category)
void RegisterPanel(size_t session_id, const PanelDescriptor &base_info)
std::string GetActiveCategory() const
bool IsPanelVisible(size_t session_id, const std::string &base_card_id) const
bool LoadPreset(const std::string &name)
void EnableFileBrowser(const std::string &category, const std::string &root_path="")
PanelManager(const PanelManager &)=delete
void SetEventBus(EventBus *event_bus)
static constexpr float GetCollapsedSidebarWidth()
PanelValidationResult ValidatePanel(const std::string &card_id) const
std::unordered_map< size_t, std::unordered_map< std::string, std::string > > session_card_mapping_
void DeletePreset(const std::string &name)
std::vector< std::string > recent_categories_
std::string ResolveBasePanelId(const std::string &panel_id) const
size_t GetRegistryPanelCount() const
Returns the number of panels registered via ContentRegistry.
PanelManager(PanelManager &&)=delete
void DisableFileBrowser(const std::string &category)
void RegisterRegistryPanelsForSession(size_t session_id)
Register descriptors for all registry panels in a session.
std::function< void(const std::string &) on_card_clicked_)
std::unordered_map< std::string, std::unique_ptr< FileBrowser > > category_file_browsers_
std::string GetPrefixedPanelId(size_t session_id, const std::string &base_id) const
static constexpr float GetSidebarWidth()
std::unordered_set< std::string > active_editor_categories_
void SetPanelBrowserCategoryWidth(float width, bool notify=true)
std::string GetPanelWindowName(size_t session_id, const std::string &base_card_id) const
Resolve the exact ImGui window name for a panel by base ID.
void UnregisterPanel(size_t session_id, const std::string &base_card_id)
void DrawAllVisiblePanels()
Draw all visible EditorPanel instances (central drawing)
float GetStoredSidePanelWidth() const
void ResetToDefaults(size_t session_id)
static constexpr size_t kMaxRecentCategories
std::unordered_set< std::string > global_panel_ids_
void UnregisterEditorPanel(const std::string &panel_id)
Unregister and destroy an EditorPanel instance.
bool IsPanelVisible(const std::string &base_card_id) const
void ShowAllPanelsInCategory(size_t session_id, const std::string &category)
std::vector< PanelValidationResult > ValidatePanels() const
void MarkPanelUsed(const std::string &panel_id)
Mark a panel as recently used (for LRU)
void SetEmulatorVisible(bool visible)
std::unordered_map< std::string, std::list< std::string > > resource_panels_
void SetStoredSidePanelWidth(float width, bool notify=false)
void MarkPanelRecentlyUsed(const std::string &card_id)
Record that a panel was used (for MRU ordering in sidebar)
void SetContextKey(size_t session_id, PanelContextScope scope, std::string key)
Set a string key for a given context scope (room/selection/etc)
void EnforceResourceLimits(const std::string &resource_type)
Enforce limits on resource panels (LRU eviction)
static std::string GetCategoryIcon(const std::string &category)
EditorPanel * FindPanelInstance(const std::string &prefixed_panel_id, const std::string &base_panel_id)
static constexpr const char * kDashboardCategory
static SidePanelWidthBounds GetSidePanelWidthBounds(float viewport_width)
void SetVisiblePanels(size_t session_id, const std::vector< std::string > &panel_ids)
Set which panels should be visible for a session.
void TrackPanelForSession(size_t session_id, const std::string &base_id, const std::string &panel_id)
static constexpr float GetSidePanelWidth()
void RegisterRegistryPanel(std::unique_ptr< EditorPanel > panel)
Register a ContentRegistry-managed EditorPanel instance.
std::unordered_map< std::string, std::string > panel_id_aliases_
float GetActiveSidePanelWidth(float viewport_width) const
std::function< void(float width)> on_panel_browser_category_width_changed_
static constexpr float GetDefaultPanelBrowserCategoryWidth()
bool IsPanelPinned(size_t session_id, const std::string &base_card_id) const
const std::unordered_map< std::string, PanelDescriptor > & GetAllPanelDescriptors() const
Get all panel descriptors (for layout designer, panel browser, etc.)
void RegisterPanel(const PanelDescriptor &base_info)
void SetPanelBrowserCategoryWidthChangedCallback(std::function< void(float)> cb)
bool HidePanel(const std::string &base_card_id)
FileBrowser * GetFileBrowser(const std::string &category)
void ToggleFavorite(const std::string &card_id)
std::unordered_map< std::string, uint64_t > last_used_at_
bool ShowPanel(const std::string &base_card_id)
void RegisterEditorPanel(std::unique_ptr< EditorPanel > panel)
Register an EditorPanel instance for central drawing.
void SavePreset(const std::string &name, const std::string &description="")
bool HidePanel(size_t session_id, const std::string &base_card_id)
std::unordered_set< std::string > registry_panel_ids_
void SetSidePanelWidthChangedCallback(std::function< void(float)> cb)
void SetFileClickedCallback(std::function< void(const std::string &category, const std::string &path)> callback)
std::vector< WorkspacePreset > GetPresets() const
std::function< Editor *(const std::string &) editor_resolver_)
size_t GetActiveSessionId() const
void SetPanelPinned(size_t session_id, const std::string &base_card_id, bool pinned)
bool IsFavorite(const std::string &card_id) const
void HideAllPanelsInCategory(size_t session_id, const std::string &category)
std::unordered_map< std::string, WorkspacePreset > presets_
void RegisterPanelDescriptorForSession(size_t session_id, const EditorPanel &panel)
std::function< void(const std::string &) on_category_changed_)
std::vector< std::string > GetVisiblePanelIds(size_t session_id) const
Get list of currently visible panel IDs for a session.
void ShowAllPanelsInSession(size_t session_id)
std::string ResolvePanelAlias(const std::string &panel_id) const
Resolve a panel ID through the alias table.
Draggable, dockable panel for editor sub-windows.
PanelCategory
Defines lifecycle behavior for editor panels.
@ EditorBound
Hidden when switching editors (default)
PanelScope
Defines whether a panel is session-scoped or global.
PanelContextScope
Optional context binding for a panel's behavior within an editor.
Metadata for an editor panel (formerly PanelInfo)
std::string GetImGuiWindowName() const
Build the exact ImGui window name used by PanelWindow::Begin.
std::function< void()> on_show
std::string GetWindowTitle() const
Get the effective window title for DockBuilder.
PanelContextScope context_scope
std::function< bool()> enabled_condition
std::function< void()> on_hide
Get the expressive theme color for a category.
size_t operator()(PanelContextScope scope) const noexcept
static UIActionRequestEvent Redo(size_t session=0)
static UIActionRequestEvent ShowCommandPalette(size_t session=0)
static UIActionRequestEvent SaveRom(size_t session=0)
static UIActionRequestEvent Create(Action act, size_t session=0)
static UIActionRequestEvent Undo(size_t session=0)
static UIActionRequestEvent ShowSettings(size_t session=0)
static UIActionRequestEvent ShowAgentProposalsSidebar(size_t session=0)
static UIActionRequestEvent ShowAgentChatSidebar(size_t session=0)
static UIActionRequestEvent OpenRom(size_t session=0)
static UIActionRequestEvent ShowEmulator(size_t session=0)