backend-infra-engineer: Release v0.3.2 snapshot
This commit is contained in:
500
src/app/editor/system/editor_card_registry.h
Normal file
500
src/app/editor/system/editor_card_registry.h
Normal file
@@ -0,0 +1,500 @@
|
||||
#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_
|
||||
|
||||
Reference in New Issue
Block a user