501 lines
16 KiB
C++
501 lines
16 KiB
C++
#ifndef YAZE_APP_EDITOR_SYSTEM_EDITOR_CARD_REGISTRY_H_
|
|
#define YAZE_APP_EDITOR_SYSTEM_EDITOR_CARD_REGISTRY_H_
|
|
|
|
#include <functional>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
#include "imgui/imgui.h"
|
|
|
|
namespace yaze {
|
|
namespace editor {
|
|
|
|
// Forward declaration
|
|
class EditorCard;
|
|
|
|
/**
|
|
* @struct CardInfo
|
|
* @brief Metadata for an editor card
|
|
*
|
|
* Describes a registerable UI card that can be shown/hidden,
|
|
* organized by category, and controlled programmatically.
|
|
*/
|
|
struct CardInfo {
|
|
std::string card_id; // Unique identifier (e.g., "dungeon.room_selector")
|
|
std::string display_name; // Human-readable name (e.g., "Room Selector")
|
|
std::string icon; // Material icon
|
|
std::string category; // Category (e.g., "Dungeon", "Graphics", "Palette")
|
|
std::string shortcut_hint; // Display hint (e.g., "Ctrl+Shift+R")
|
|
bool* visibility_flag; // Pointer to bool controlling visibility
|
|
EditorCard* card_instance; // Pointer to actual card (optional)
|
|
std::function<void()> on_show; // Callback when card is shown
|
|
std::function<void()> on_hide; // Callback when card is hidden
|
|
int priority; // Display priority for menus (lower = higher)
|
|
};
|
|
|
|
/**
|
|
* @class EditorCardRegistry
|
|
* @brief Central registry for all editor cards with session awareness and dependency injection
|
|
*
|
|
* This class combines the functionality of EditorCardManager (global card management)
|
|
* and SessionCardRegistry (session-aware prefixing) into a single, dependency-injected
|
|
* component that can be passed to editors.
|
|
*
|
|
* Design Philosophy:
|
|
* - Dependency injection (no singleton pattern)
|
|
* - Session-aware card ID prefixing for multi-session support
|
|
* - Centralized visibility management
|
|
* - View menu integration
|
|
* - Workspace preset system
|
|
* - No direct GUI dependency in registration logic
|
|
*
|
|
* Session-Aware Card IDs:
|
|
* - Single session: "dungeon.room_selector"
|
|
* - Multiple sessions: "s0.dungeon.room_selector", "s1.dungeon.room_selector"
|
|
*
|
|
* Usage:
|
|
* ```cpp
|
|
* // In EditorManager:
|
|
* EditorCardRegistry card_registry;
|
|
* EditorDependencies deps;
|
|
* deps.card_registry = &card_registry;
|
|
*
|
|
* // In Editor:
|
|
* deps.card_registry->RegisterCard(deps.session_id, {
|
|
* .card_id = "dungeon.room_selector",
|
|
* .display_name = "Room Selector",
|
|
* .icon = ICON_MD_LIST,
|
|
* .category = "Dungeon",
|
|
* .on_show = []() { }
|
|
* });
|
|
*
|
|
* // Programmatic control:
|
|
* deps.card_registry->ShowCard(deps.session_id, "dungeon.room_selector");
|
|
* ```
|
|
*/
|
|
class EditorCardRegistry {
|
|
public:
|
|
EditorCardRegistry() = default;
|
|
~EditorCardRegistry() = default;
|
|
|
|
// Non-copyable, non-movable (manages pointers and callbacks)
|
|
EditorCardRegistry(const EditorCardRegistry&) = delete;
|
|
EditorCardRegistry& operator=(const EditorCardRegistry&) = delete;
|
|
EditorCardRegistry(EditorCardRegistry&&) = delete;
|
|
EditorCardRegistry& operator=(EditorCardRegistry&&) = delete;
|
|
|
|
// ============================================================================
|
|
// Session Lifecycle Management
|
|
// ============================================================================
|
|
|
|
/**
|
|
* @brief Register a new session in the registry
|
|
* @param session_id Unique session identifier
|
|
*
|
|
* Creates internal tracking structures for the session.
|
|
* Must be called before registering cards for a session.
|
|
*/
|
|
void RegisterSession(size_t session_id);
|
|
|
|
/**
|
|
* @brief Unregister a session and all its cards
|
|
* @param session_id Session identifier to remove
|
|
*
|
|
* Automatically unregisters all cards associated with the session.
|
|
*/
|
|
void UnregisterSession(size_t session_id);
|
|
|
|
/**
|
|
* @brief Set the currently active session
|
|
* @param session_id Session to make active
|
|
*
|
|
* Used for determining whether to apply card ID prefixing.
|
|
*/
|
|
void SetActiveSession(size_t session_id);
|
|
|
|
// ============================================================================
|
|
// Card Registration
|
|
// ============================================================================
|
|
|
|
/**
|
|
* @brief Register a card for a specific session
|
|
* @param session_id Session this card belongs to
|
|
* @param base_info Card metadata (ID will be automatically prefixed if needed)
|
|
*
|
|
* The card_id in base_info should be the unprefixed ID. This method
|
|
* automatically applies session prefixing when multiple sessions exist.
|
|
*/
|
|
void RegisterCard(size_t session_id, const CardInfo& base_info);
|
|
|
|
/**
|
|
* @brief Register a card with inline parameters (convenience method)
|
|
*/
|
|
void RegisterCard(size_t session_id,
|
|
const std::string& card_id,
|
|
const std::string& display_name,
|
|
const std::string& icon,
|
|
const std::string& category,
|
|
const std::string& shortcut_hint = "",
|
|
int priority = 50,
|
|
std::function<void()> on_show = nullptr,
|
|
std::function<void()> on_hide = nullptr,
|
|
bool visible_by_default = false);
|
|
|
|
/**
|
|
* @brief Unregister a specific card
|
|
* @param session_id Session the card belongs to
|
|
* @param base_card_id Unprefixed card ID
|
|
*/
|
|
void UnregisterCard(size_t session_id, const std::string& base_card_id);
|
|
|
|
/**
|
|
* @brief Unregister all cards with a given prefix
|
|
* @param prefix Prefix to match (e.g., "s0" or "s1.dungeon")
|
|
*
|
|
* Useful for cleaning up session cards or category cards.
|
|
*/
|
|
void UnregisterCardsWithPrefix(const std::string& prefix);
|
|
|
|
/**
|
|
* @brief Remove all registered cards (use with caution)
|
|
*/
|
|
void ClearAllCards();
|
|
|
|
// ============================================================================
|
|
// Card Control (Programmatic, No GUI)
|
|
// ============================================================================
|
|
|
|
/**
|
|
* @brief Show a card programmatically
|
|
* @param session_id Session the card belongs to
|
|
* @param base_card_id Unprefixed card ID
|
|
* @return true if card was found and shown
|
|
*/
|
|
bool ShowCard(size_t session_id, const std::string& base_card_id);
|
|
|
|
/**
|
|
* @brief Hide a card programmatically
|
|
*/
|
|
bool HideCard(size_t session_id, const std::string& base_card_id);
|
|
|
|
/**
|
|
* @brief Toggle a card's visibility
|
|
*/
|
|
bool ToggleCard(size_t session_id, const std::string& base_card_id);
|
|
|
|
/**
|
|
* @brief Check if a card is currently visible
|
|
*/
|
|
bool IsCardVisible(size_t session_id, const std::string& base_card_id) const;
|
|
|
|
/**
|
|
* @brief Get visibility flag pointer for a card
|
|
* @return Pointer to bool controlling card visibility (for passing to EditorCard::Begin)
|
|
*/
|
|
bool* GetVisibilityFlag(size_t session_id, const std::string& base_card_id);
|
|
|
|
// ============================================================================
|
|
// Batch Operations
|
|
// ============================================================================
|
|
|
|
/**
|
|
* @brief Show all cards in a specific session
|
|
*/
|
|
void ShowAllCardsInSession(size_t session_id);
|
|
|
|
/**
|
|
* @brief Hide all cards in a specific session
|
|
*/
|
|
void HideAllCardsInSession(size_t session_id);
|
|
|
|
/**
|
|
* @brief Show all cards in a category for a session
|
|
*/
|
|
void ShowAllCardsInCategory(size_t session_id, const std::string& category);
|
|
|
|
/**
|
|
* @brief Hide all cards in a category for a session
|
|
*/
|
|
void HideAllCardsInCategory(size_t session_id, const std::string& category);
|
|
|
|
/**
|
|
* @brief Show only one card, hiding all others in its category
|
|
*/
|
|
void ShowOnlyCard(size_t session_id, const std::string& base_card_id);
|
|
|
|
// ============================================================================
|
|
// Query Methods
|
|
// ============================================================================
|
|
|
|
/**
|
|
* @brief Get all cards registered for a session
|
|
* @return Vector of prefixed card IDs
|
|
*/
|
|
std::vector<std::string> GetCardsInSession(size_t session_id) const;
|
|
|
|
/**
|
|
* @brief Get cards in a specific category for a session
|
|
*/
|
|
std::vector<CardInfo> GetCardsInCategory(size_t session_id, const std::string& category) const;
|
|
|
|
/**
|
|
* @brief Get all categories for a session
|
|
*/
|
|
std::vector<std::string> GetAllCategories(size_t session_id) const;
|
|
|
|
/**
|
|
* @brief Get card metadata
|
|
* @param session_id Session the card belongs to
|
|
* @param base_card_id Unprefixed card ID
|
|
*/
|
|
const CardInfo* GetCardInfo(size_t session_id, const std::string& base_card_id) const;
|
|
|
|
/**
|
|
* @brief Get all registered categories across all sessions
|
|
*/
|
|
std::vector<std::string> GetAllCategories() const;
|
|
|
|
// ============================================================================
|
|
// View Menu Integration
|
|
// ============================================================================
|
|
|
|
/**
|
|
* @brief Draw view menu section for a category
|
|
*/
|
|
void DrawViewMenuSection(size_t session_id, const std::string& category);
|
|
|
|
/**
|
|
* @brief Draw all categories as view menu submenus
|
|
*/
|
|
void DrawViewMenuAll(size_t session_id);
|
|
|
|
// ============================================================================
|
|
// VSCode-Style Sidebar
|
|
// ============================================================================
|
|
|
|
/**
|
|
* @brief Draw sidebar for a category with session filtering
|
|
*/
|
|
void DrawSidebar(size_t session_id,
|
|
const std::string& category,
|
|
const std::vector<std::string>& active_categories = {},
|
|
std::function<void(const std::string&)> on_category_switch = nullptr,
|
|
std::function<void()> on_collapse = nullptr);
|
|
|
|
static constexpr float GetSidebarWidth() { return 48.0f; }
|
|
|
|
// ============================================================================
|
|
// Compact Controls for Menu Bar
|
|
// ============================================================================
|
|
|
|
/**
|
|
* @brief Draw compact card control for active editor's cards
|
|
*/
|
|
void DrawCompactCardControl(size_t session_id, const std::string& category);
|
|
|
|
/**
|
|
* @brief Draw minimal inline card toggles
|
|
*/
|
|
void DrawInlineCardToggles(size_t session_id, const std::string& category);
|
|
|
|
// ============================================================================
|
|
// Card Browser UI
|
|
// ============================================================================
|
|
|
|
/**
|
|
* @brief Draw visual card browser/toggler
|
|
*/
|
|
void DrawCardBrowser(size_t session_id, bool* p_open);
|
|
|
|
// ============================================================================
|
|
// Workspace Presets
|
|
// ============================================================================
|
|
|
|
struct WorkspacePreset {
|
|
std::string name;
|
|
std::vector<std::string> visible_cards; // Card IDs
|
|
std::string description;
|
|
};
|
|
|
|
void SavePreset(const std::string& name, const std::string& description = "");
|
|
bool LoadPreset(const std::string& name);
|
|
void DeletePreset(const std::string& name);
|
|
std::vector<WorkspacePreset> GetPresets() const;
|
|
|
|
// ============================================================================
|
|
// Quick Actions
|
|
// ============================================================================
|
|
|
|
void ShowAll(size_t session_id);
|
|
void HideAll(size_t session_id);
|
|
void ResetToDefaults(size_t session_id);
|
|
|
|
// ============================================================================
|
|
// Statistics
|
|
// ============================================================================
|
|
|
|
size_t GetCardCount() const { return cards_.size(); }
|
|
size_t GetVisibleCardCount(size_t session_id) const;
|
|
size_t GetSessionCount() const { return session_count_; }
|
|
|
|
// ============================================================================
|
|
// Session Prefixing Utilities
|
|
// ============================================================================
|
|
|
|
/**
|
|
* @brief Generate session-aware card ID
|
|
* @param session_id Session identifier
|
|
* @param base_id Unprefixed card ID
|
|
* @return Prefixed ID if multiple sessions, otherwise base ID
|
|
*
|
|
* Examples:
|
|
* - Single session: "dungeon.room_selector" → "dungeon.room_selector"
|
|
* - Multi-session: "dungeon.room_selector" → "s0.dungeon.room_selector"
|
|
*/
|
|
std::string MakeCardId(size_t session_id, const std::string& base_id) const;
|
|
|
|
/**
|
|
* @brief Check if card IDs should be prefixed
|
|
* @return true if session_count > 1
|
|
*/
|
|
bool ShouldPrefixCards() const { return session_count_ > 1; }
|
|
|
|
// ============================================================================
|
|
// Convenience Methods (for EditorManager direct usage without session_id)
|
|
// ============================================================================
|
|
|
|
/**
|
|
* @brief Register card for active session (convenience)
|
|
*/
|
|
void RegisterCard(const CardInfo& base_info) {
|
|
RegisterCard(active_session_, base_info);
|
|
}
|
|
|
|
/**
|
|
* @brief Show card in active session (convenience)
|
|
*/
|
|
bool ShowCard(const std::string& base_card_id) {
|
|
return ShowCard(active_session_, base_card_id);
|
|
}
|
|
|
|
/**
|
|
* @brief Hide card in active session (convenience)
|
|
*/
|
|
bool HideCard(const std::string& base_card_id) {
|
|
return HideCard(active_session_, base_card_id);
|
|
}
|
|
|
|
/**
|
|
* @brief Check if card is visible in active session (convenience)
|
|
*/
|
|
bool IsCardVisible(const std::string& base_card_id) const {
|
|
return IsCardVisible(active_session_, base_card_id);
|
|
}
|
|
|
|
/**
|
|
* @brief Hide all cards in category for active session (convenience)
|
|
*/
|
|
void HideAllCardsInCategory(const std::string& category) {
|
|
HideAllCardsInCategory(active_session_, category);
|
|
}
|
|
|
|
/**
|
|
* @brief Draw card browser for active session (convenience)
|
|
*/
|
|
void DrawCardBrowser(bool* p_open) {
|
|
DrawCardBrowser(active_session_, p_open);
|
|
}
|
|
|
|
/**
|
|
* @brief Get active category (for sidebar)
|
|
*/
|
|
std::string GetActiveCategory() const { return active_category_; }
|
|
|
|
/**
|
|
* @brief Set active category (for sidebar)
|
|
*/
|
|
void SetActiveCategory(const std::string& category) { active_category_ = category; }
|
|
|
|
/**
|
|
* @brief Show all cards in category for active session (convenience)
|
|
*/
|
|
void ShowAllCardsInCategory(const std::string& category) {
|
|
ShowAllCardsInCategory(active_session_, category);
|
|
}
|
|
|
|
/**
|
|
* @brief Get visibility flag for active session (convenience)
|
|
*/
|
|
bool* GetVisibilityFlag(const std::string& base_card_id) {
|
|
return GetVisibilityFlag(active_session_, base_card_id);
|
|
}
|
|
|
|
/**
|
|
* @brief Show all cards for active session (convenience)
|
|
*/
|
|
void ShowAll() {
|
|
ShowAll(active_session_);
|
|
}
|
|
|
|
/**
|
|
* @brief Hide all cards for active session (convenience)
|
|
*/
|
|
void HideAll() {
|
|
HideAll(active_session_);
|
|
}
|
|
|
|
/**
|
|
* @brief Draw sidebar for active session (convenience)
|
|
*/
|
|
void DrawSidebar(const std::string& category,
|
|
const std::vector<std::string>& active_categories = {},
|
|
std::function<void(const std::string&)> on_category_switch = nullptr,
|
|
std::function<void()> on_collapse = nullptr) {
|
|
DrawSidebar(active_session_, category, active_categories, on_category_switch, on_collapse);
|
|
}
|
|
|
|
private:
|
|
// Core card storage (prefixed IDs → CardInfo)
|
|
std::unordered_map<std::string, CardInfo> cards_;
|
|
|
|
// Centralized visibility flags for cards without external flags
|
|
std::unordered_map<std::string, bool> centralized_visibility_;
|
|
|
|
// Session tracking
|
|
size_t session_count_ = 0;
|
|
size_t active_session_ = 0;
|
|
|
|
// Maps session_id → vector of prefixed card IDs registered for that session
|
|
std::unordered_map<size_t, std::vector<std::string>> session_cards_;
|
|
|
|
// Maps session_id → (base_card_id → prefixed_card_id)
|
|
std::unordered_map<size_t, std::unordered_map<std::string, std::string>> session_card_mapping_;
|
|
|
|
// Workspace presets
|
|
std::unordered_map<std::string, WorkspacePreset> presets_;
|
|
|
|
// Active category tracking
|
|
std::string active_category_;
|
|
std::vector<std::string> recent_categories_;
|
|
static constexpr size_t kMaxRecentCategories = 5;
|
|
|
|
// Helper methods
|
|
void UpdateSessionCount();
|
|
std::string GetPrefixedCardId(size_t session_id, const std::string& base_id) const;
|
|
void UnregisterSessionCards(size_t session_id);
|
|
void SavePresetsToFile();
|
|
void LoadPresetsFromFile();
|
|
|
|
// UI drawing helpers (internal)
|
|
void DrawCardMenuItem(const CardInfo& info);
|
|
void DrawCardInSidebar(const CardInfo& info, bool is_active);
|
|
};
|
|
|
|
} // namespace editor
|
|
} // namespace yaze
|
|
|
|
#endif // YAZE_APP_EDITOR_SYSTEM_EDITOR_CARD_REGISTRY_H_
|
|
|