refactor(editor): integrate EditorCardRegistry for improved card management

- Updated EditorManager and various editor components to utilize EditorCardRegistry for card registration and visibility management, enhancing dependency injection and modularity.
- Refactored card registration logic across multiple editors, ensuring a consistent approach to managing editor cards.
- Improved UI coordination by delegating visibility checks and card management to the new registry, streamlining the user experience.

Benefits:
- Simplifies card management, leading to a more organized and efficient user experience.
- Enhances maintainability by clearly defining roles for card handling and editor operations, aligning with the overall architecture improvements.
This commit is contained in:
scawful
2025-10-15 14:04:01 -04:00
parent 651be0fdca
commit f5a54b8f01
20 changed files with 243 additions and 134 deletions

View File

@@ -1,4 +1,5 @@
#include "assembly_editor.h"
#include "app/editor/system/editor_card_registry.h"
#include <fstream>
#include <string>
@@ -176,11 +177,12 @@ void AssemblyEditor::Initialize() {
text_editor_.SetLanguageDefinition(GetAssemblyLanguageDef());
// Register cards with EditorCardManager
auto& card_manager = gui::EditorCardManager::Get();
card_manager.RegisterCard({.card_id = "assembly.editor", .display_name = "Assembly Editor",
if (!dependencies_.card_registry) return;
auto* card_registry = dependencies_.card_registry;
card_registry->RegisterCard({.card_id = "assembly.editor", .display_name = "Assembly Editor",
.icon = ICON_MD_CODE, .category = "Assembly",
.shortcut_hint = "", .priority = 10});
card_manager.RegisterCard({.card_id = "assembly.file_browser", .display_name = "File Browser",
card_registry->RegisterCard({.card_id = "assembly.file_browser", .display_name = "File Browser",
.icon = ICON_MD_FOLDER_OPEN, .category = "Assembly",
.shortcut_hint = "", .priority = 20});
@@ -188,9 +190,10 @@ void AssemblyEditor::Initialize() {
}
absl::Status AssemblyEditor::Load() {
// Register cards with EditorCardManager
// Register cards with EditorCardRegistry (dependency injection)
// Note: Assembly editor uses dynamic file tabs, so we register the main editor window
auto& card_manager = gui::EditorCardManager::Get();
if (!dependencies_.card_registry) return absl::OkStatus();
auto* card_registry = dependencies_.card_registry;
return absl::OkStatus();
}

View File

@@ -1,4 +1,5 @@
#include "dungeon_editor_v2.h"
#include "app/editor/system/editor_card_registry.h"
#include <algorithm>
#include <cstdio>
@@ -27,10 +28,11 @@ void DungeonEditorV2::Initialize(gfx::IRenderer* renderer, Rom* rom) {
room_window_class_.DockingAllowUnclassed = true; // Room windows can dock with anything
room_window_class_.DockingAlwaysTabBar = true; // Always show tabs when multiple rooms
// Register all cards with the card manager (done once during initialization)
auto& card_manager = gui::EditorCardManager::Get();
// Register all cards with EditorCardRegistry (dependency injection)
if (!dependencies_.card_registry) return;
auto* card_registry = dependencies_.card_registry;
card_manager.RegisterCard({
card_registry->RegisterCard({
.card_id = MakeCardId("dungeon.control_panel"),
.display_name = "Dungeon Controls",
.icon = ICON_MD_CASTLE,
@@ -40,7 +42,7 @@ void DungeonEditorV2::Initialize(gfx::IRenderer* renderer, Rom* rom) {
.priority = 10
});
card_manager.RegisterCard({
card_registry->RegisterCard({
.card_id = MakeCardId("dungeon.room_selector"),
.display_name = "Room Selector",
.icon = ICON_MD_LIST,
@@ -50,7 +52,7 @@ void DungeonEditorV2::Initialize(gfx::IRenderer* renderer, Rom* rom) {
.priority = 20
});
card_manager.RegisterCard({
card_registry->RegisterCard({
.card_id = MakeCardId("dungeon.room_matrix"),
.display_name = "Room Matrix",
.icon = ICON_MD_GRID_VIEW,
@@ -60,7 +62,7 @@ void DungeonEditorV2::Initialize(gfx::IRenderer* renderer, Rom* rom) {
.priority = 30
});
card_manager.RegisterCard({
card_registry->RegisterCard({
.card_id = MakeCardId("dungeon.entrances"),
.display_name = "Entrances",
.icon = ICON_MD_DOOR_FRONT,
@@ -70,7 +72,7 @@ void DungeonEditorV2::Initialize(gfx::IRenderer* renderer, Rom* rom) {
.priority = 40
});
card_manager.RegisterCard({
card_registry->RegisterCard({
.card_id = MakeCardId("dungeon.room_graphics"),
.display_name = "Room Graphics",
.icon = ICON_MD_IMAGE,
@@ -80,7 +82,7 @@ void DungeonEditorV2::Initialize(gfx::IRenderer* renderer, Rom* rom) {
.priority = 50
});
card_manager.RegisterCard({
card_registry->RegisterCard({
.card_id = MakeCardId("dungeon.object_editor"),
.display_name = "Object Editor",
.icon = ICON_MD_CONSTRUCTION,
@@ -90,7 +92,7 @@ void DungeonEditorV2::Initialize(gfx::IRenderer* renderer, Rom* rom) {
.priority = 60
});
card_manager.RegisterCard({
card_registry->RegisterCard({
.card_id = MakeCardId("dungeon.palette_editor"),
.display_name = "Palette Editor",
.icon = ICON_MD_PALETTE,
@@ -100,7 +102,7 @@ void DungeonEditorV2::Initialize(gfx::IRenderer* renderer, Rom* rom) {
.priority = 70
});
card_manager.RegisterCard({
card_registry->RegisterCard({
.card_id = MakeCardId("dungeon.debug_controls"),
.display_name = "Debug Controls",
.icon = ICON_MD_BUG_REPORT,

View File

@@ -176,9 +176,9 @@ EditorManager::EditorManager()
this, menu_builder_, rom_file_manager_, project_manager_,
editor_registry_, *session_coordinator_, toast_manager_, *popup_manager_);
// STEP 4: Initialize UICoordinator (depends on popup_manager_, session_coordinator_)
// STEP 4: Initialize UICoordinator (depends on popup_manager_, session_coordinator_, card_registry_)
ui_coordinator_ = std::make_unique<UICoordinator>(
this, rom_file_manager_, project_manager_, editor_registry_,
this, rom_file_manager_, project_manager_, editor_registry_, card_registry_,
*session_coordinator_, window_delegate_, toast_manager_, *popup_manager_,
shortcut_manager_);
@@ -235,8 +235,9 @@ void EditorManager::Initialize(gfx::IRenderer* renderer,
const std::string& filename) {
renderer_ = renderer;
// NOTE: Emulator will be initialized later when a ROM is loaded
// We just store the renderer for now
// Inject card_registry into emulator and workspace_manager
emulator_.set_card_registry(&card_registry_);
workspace_manager_.set_card_registry(&card_registry_);
// Point to a blank editor set when no ROM is loaded
current_editor_set_ = &blank_editor_set_;
@@ -987,14 +988,26 @@ void EditorManager::DrawMenuBar() {
if (show_display_settings) {
// Use the popup manager instead of a separate window
popup_manager_->Show("Display Settings");
popup_manager_->Show(PopupID::kDisplaySettings);
show_display_settings = false; // Close the old-style window
}
if (show_imgui_demo_)
ImGui::ShowDemoWindow(&show_imgui_demo_);
if (show_imgui_metrics_)
ImGui::ShowMetricsWindow(&show_imgui_metrics_);
// ImGui debug windows (delegated to UICoordinator for visibility state)
if (ui_coordinator_ && ui_coordinator_->IsImGuiDemoVisible()) {
bool visible = true;
ImGui::ShowDemoWindow(&visible);
if (!visible) {
ui_coordinator_->SetImGuiDemoVisible(false);
}
}
if (ui_coordinator_ && ui_coordinator_->IsImGuiMetricsVisible()) {
bool visible = true;
ImGui::ShowMetricsWindow(&visible);
if (!visible) {
ui_coordinator_->SetImGuiMetricsVisible(false);
}
}
// Using EditorCardRegistry directly
if (current_editor_set_) {
@@ -1045,7 +1058,7 @@ void EditorManager::DrawMenuBar() {
ui_coordinator_->DrawWelcomeScreen();
}
// Emulator is now card-based - it creates its own windows
// TODO: Fix emulator not appearing
if (show_emulator_) {
emulator_.Run(current_rom_);
}

View File

@@ -310,10 +310,9 @@ class EditorManager {
bool show_emulator_ = false;
bool show_memory_editor_ = false;
bool show_asm_editor_ = false;
bool show_imgui_metrics_ = false;
bool show_imgui_demo_ = false;
bool show_palette_editor_ = false;
bool show_resource_label_manager = false;
// Note: show_imgui_demo_ and show_imgui_metrics_ moved to UICoordinator
// Workspace dialog flags (managed by EditorManager, not UI)
bool show_workspace_layout = false;
bool show_save_workspace_preset_ = false;

View File

@@ -1,4 +1,5 @@
#include "graphics_editor.h"
#include "app/editor/system/editor_card_registry.h"
#include <filesystem>
@@ -43,23 +44,24 @@ constexpr ImGuiTableFlags kGfxEditTableFlags =
ImGuiTableFlags_SizingFixedFit;
void GraphicsEditor::Initialize() {
auto& card_manager = gui::EditorCardManager::Get();
if (!dependencies_.card_registry) return;
auto* card_registry = dependencies_.card_registry;
card_manager.RegisterCard({.card_id = "graphics.sheet_editor", .display_name = "Sheet Editor",
card_registry->RegisterCard({.card_id = "graphics.sheet_editor", .display_name = "Sheet Editor",
.icon = ICON_MD_EDIT, .category = "Graphics",
.shortcut_hint = "Ctrl+Shift+1", .priority = 10});
card_manager.RegisterCard({.card_id = "graphics.sheet_browser", .display_name = "Sheet Browser",
card_registry->RegisterCard({.card_id = "graphics.sheet_browser", .display_name = "Sheet Browser",
.icon = ICON_MD_VIEW_LIST, .category = "Graphics",
.shortcut_hint = "Ctrl+Shift+2", .priority = 20});
card_manager.RegisterCard({.card_id = "graphics.player_animations", .display_name = "Player Animations",
card_registry->RegisterCard({.card_id = "graphics.player_animations", .display_name = "Player Animations",
.icon = ICON_MD_PERSON, .category = "Graphics",
.shortcut_hint = "Ctrl+Shift+3", .priority = 30});
card_manager.RegisterCard({.card_id = "graphics.prototype_viewer", .display_name = "Prototype Viewer",
card_registry->RegisterCard({.card_id = "graphics.prototype_viewer", .display_name = "Prototype Viewer",
.icon = ICON_MD_CONSTRUCTION, .category = "Graphics",
.shortcut_hint = "Ctrl+Shift+4", .priority = 40});
// Show sheet editor by default when Graphics Editor is activated
card_manager.ShowCard("graphics.sheet_editor");
card_registry->ShowCard("graphics.sheet_editor");
}
absl::Status GraphicsEditor::Load() {
@@ -99,7 +101,8 @@ absl::Status GraphicsEditor::Load() {
}
absl::Status GraphicsEditor::Update() {
auto& card_manager = gui::EditorCardManager::Get();
if (!dependencies_.card_registry) return absl::OkStatus();
auto* card_registry = dependencies_.card_registry;
static gui::EditorCard sheet_editor_card("Sheet Editor", ICON_MD_EDIT);
static gui::EditorCard sheet_browser_card("Sheet Browser", ICON_MD_VIEW_LIST);
@@ -113,12 +116,12 @@ absl::Status GraphicsEditor::Update() {
// Get visibility flags from card manager and pass to Begin()
// Always call End() after Begin() - End() handles ImGui state safely
if (sheet_editor_card.Begin(card_manager.GetVisibilityFlag("graphics.sheet_editor"))) {
if (sheet_editor_card.Begin(card_registry->GetVisibilityFlag("graphics.sheet_editor"))) {
status_ = UpdateGfxEdit();
}
sheet_editor_card.End();
if (sheet_browser_card.Begin(card_manager.GetVisibilityFlag("graphics.sheet_browser"))) {
if (sheet_browser_card.Begin(card_registry->GetVisibilityFlag("graphics.sheet_browser"))) {
if (asset_browser_.Initialized == false) {
asset_browser_.Initialize(gfx::Arena::Get().gfx_sheets());
}
@@ -126,12 +129,12 @@ absl::Status GraphicsEditor::Update() {
}
sheet_browser_card.End();
if (player_anims_card.Begin(card_manager.GetVisibilityFlag("graphics.player_animations"))) {
if (player_anims_card.Begin(card_registry->GetVisibilityFlag("graphics.player_animations"))) {
status_ = UpdateLinkGfxView();
}
player_anims_card.End();
if (prototype_card.Begin(card_manager.GetVisibilityFlag("graphics.prototype_viewer"))) {
if (prototype_card.Begin(card_registry->GetVisibilityFlag("graphics.prototype_viewer"))) {
status_ = UpdateScadView();
}
prototype_card.End();

View File

@@ -1,4 +1,5 @@
#include "screen_editor.h"
#include "app/editor/system/editor_card_registry.h"
#include <fstream>
#include <iostream>
@@ -25,26 +26,27 @@ namespace editor {
constexpr uint32_t kRedPen = 0xFF0000FF;
void ScreenEditor::Initialize() {
auto& card_manager = gui::EditorCardManager::Get();
if (!dependencies_.card_registry) return;
auto* card_registry = dependencies_.card_registry;
card_manager.RegisterCard({.card_id = "screen.dungeon_maps", .display_name = "Dungeon Maps",
card_registry->RegisterCard({.card_id = "screen.dungeon_maps", .display_name = "Dungeon Maps",
.icon = ICON_MD_MAP, .category = "Screen",
.shortcut_hint = "Alt+1", .priority = 10});
card_manager.RegisterCard({.card_id = "screen.inventory_menu", .display_name = "Inventory Menu",
card_registry->RegisterCard({.card_id = "screen.inventory_menu", .display_name = "Inventory Menu",
.icon = ICON_MD_INVENTORY, .category = "Screen",
.shortcut_hint = "Alt+2", .priority = 20});
card_manager.RegisterCard({.card_id = "screen.overworld_map", .display_name = "Overworld Map",
card_registry->RegisterCard({.card_id = "screen.overworld_map", .display_name = "Overworld Map",
.icon = ICON_MD_PUBLIC, .category = "Screen",
.shortcut_hint = "Alt+3", .priority = 30});
card_manager.RegisterCard({.card_id = "screen.title_screen", .display_name = "Title Screen",
card_registry->RegisterCard({.card_id = "screen.title_screen", .display_name = "Title Screen",
.icon = ICON_MD_TITLE, .category = "Screen",
.shortcut_hint = "Alt+4", .priority = 40});
card_manager.RegisterCard({.card_id = "screen.naming_screen", .display_name = "Naming Screen",
card_registry->RegisterCard({.card_id = "screen.naming_screen", .display_name = "Naming Screen",
.icon = ICON_MD_EDIT, .category = "Screen",
.shortcut_hint = "Alt+5", .priority = 50});
// Show title screen by default
card_manager.ShowCard("screen.title_screen");
card_registry->ShowCard("screen.title_screen");
}
absl::Status ScreenEditor::Load() {
@@ -105,7 +107,8 @@ absl::Status ScreenEditor::Load() {
}
absl::Status ScreenEditor::Update() {
auto& card_manager = gui::EditorCardManager::Get();
if (!dependencies_.card_registry) return absl::OkStatus();
auto* card_registry = dependencies_.card_registry;
static gui::EditorCard dungeon_maps_card("Dungeon Maps", ICON_MD_MAP);
static gui::EditorCard inventory_menu_card("Inventory Menu", ICON_MD_INVENTORY);
@@ -121,27 +124,27 @@ absl::Status ScreenEditor::Update() {
// Get visibility flags from card manager and pass to Begin()
// Always call End() after Begin() - End() handles ImGui state safely
if (dungeon_maps_card.Begin(card_manager.GetVisibilityFlag("screen.dungeon_maps"))) {
if (dungeon_maps_card.Begin(card_registry->GetVisibilityFlag("screen.dungeon_maps"))) {
DrawDungeonMapsEditor();
}
dungeon_maps_card.End();
if (inventory_menu_card.Begin(card_manager.GetVisibilityFlag("screen.inventory_menu"))) {
if (inventory_menu_card.Begin(card_registry->GetVisibilityFlag("screen.inventory_menu"))) {
DrawInventoryMenuEditor();
}
inventory_menu_card.End();
if (overworld_map_card.Begin(card_manager.GetVisibilityFlag("screen.overworld_map"))) {
if (overworld_map_card.Begin(card_registry->GetVisibilityFlag("screen.overworld_map"))) {
DrawOverworldMapEditor();
}
overworld_map_card.End();
if (title_screen_card.Begin(card_manager.GetVisibilityFlag("screen.title_screen"))) {
if (title_screen_card.Begin(card_registry->GetVisibilityFlag("screen.title_screen"))) {
DrawTitleScreenEditor();
}
title_screen_card.End();
if (naming_screen_card.Begin(card_manager.GetVisibilityFlag("screen.naming_screen"))) {
if (naming_screen_card.Begin(card_registry->GetVisibilityFlag("screen.naming_screen"))) {
DrawNamingScreenEditor();
}
naming_screen_card.End();

View File

@@ -1,4 +1,5 @@
#include "message_editor.h"
#include "app/editor/system/editor_card_registry.h"
#include <string>
#include <vector>
@@ -62,35 +63,37 @@ constexpr ImGuiTableFlags kMessageTableFlags = ImGuiTableFlags_Hideable |
ImGuiTableFlags_Resizable;
void MessageEditor::Initialize() {
// Register cards with EditorCardManager (using centralized visibility)
auto& card_manager = gui::EditorCardManager::Get();
// Register cards with EditorCardRegistry (dependency injection)
if (!dependencies_.card_registry) return;
card_manager.RegisterCard({
.card_id = "message.message_list",
auto* card_registry = dependencies_.card_registry;
card_registry->RegisterCard({
.card_id = MakeCardId("message.message_list"),
.display_name = "Message List",
.icon = ICON_MD_LIST,
.category = "Message",
.priority = 10
});
card_manager.RegisterCard({
.card_id = "message.message_editor",
card_registry->RegisterCard({
.card_id = MakeCardId("message.message_editor"),
.display_name = "Message Editor",
.icon = ICON_MD_EDIT,
.category = "Message",
.priority = 20
});
card_manager.RegisterCard({
.card_id = "message.font_atlas",
card_registry->RegisterCard({
.card_id = MakeCardId("message.font_atlas"),
.display_name = "Font Atlas",
.icon = ICON_MD_FONT_DOWNLOAD,
.category = "Message",
.priority = 30
});
card_manager.RegisterCard({
.card_id = "message.dictionary",
card_registry->RegisterCard({
.card_id = MakeCardId("message.dictionary"),
.display_name = "Dictionary",
.icon = ICON_MD_BOOK,
.category = "Message",
@@ -98,7 +101,7 @@ void MessageEditor::Initialize() {
});
// Show message list by default
card_manager.ShowCard("message.message_list");
card_registry->ShowCard(MakeCardId("message.message_list"));
for (int i = 0; i < kWidthArraySize; i++) {
message_preview_.width_array[i] = rom()->data()[kCharactersWidth + i];
@@ -143,10 +146,12 @@ absl::Status MessageEditor::Load() {
}
absl::Status MessageEditor::Update() {
auto& card_manager = gui::EditorCardManager::Get();
if (!dependencies_.card_registry) return absl::OkStatus();
auto* card_registry = dependencies_.card_registry;
// Message List Card
if (card_manager.IsCardVisible("message.message_list")) {
if (card_registry->IsCardVisible(MakeCardId("message.message_list"))) {
static gui::EditorCard list_card("Message List", ICON_MD_LIST);
list_card.SetDefaultSize(400, 600);
if (list_card.Begin()) {
@@ -156,7 +161,7 @@ absl::Status MessageEditor::Update() {
}
// Message Editor Card
if (card_manager.IsCardVisible("message.message_editor")) {
if (card_registry->IsCardVisible(MakeCardId("message.message_editor"))) {
static gui::EditorCard editor_card("Message Editor", ICON_MD_EDIT);
editor_card.SetDefaultSize(500, 600);
if (editor_card.Begin()) {
@@ -166,7 +171,7 @@ absl::Status MessageEditor::Update() {
}
// Font Atlas Card
if (card_manager.IsCardVisible("message.font_atlas")) {
if (card_registry->IsCardVisible(MakeCardId("message.font_atlas"))) {
static gui::EditorCard font_card("Font Atlas", ICON_MD_FONT_DOWNLOAD);
font_card.SetDefaultSize(400, 500);
if (font_card.Begin()) {
@@ -177,7 +182,7 @@ absl::Status MessageEditor::Update() {
}
// Dictionary Card
if (card_manager.IsCardVisible("message.dictionary")) {
if (card_registry->IsCardVisible(MakeCardId("message.dictionary"))) {
static gui::EditorCard dict_card("Dictionary", ICON_MD_BOOK);
dict_card.SetDefaultSize(400, 500);
if (dict_card.Begin()) {

View File

@@ -1,4 +1,5 @@
#include "music_editor.h"
#include "app/editor/system/editor_card_registry.h"
#include "absl/strings/str_format.h"
#include "app/gfx/debug/performance/performance_profiler.h"
@@ -13,20 +14,21 @@ namespace yaze {
namespace editor {
void MusicEditor::Initialize() {
auto& card_manager = gui::EditorCardManager::Get();
if (!dependencies_.card_registry) return;
auto* card_registry = dependencies_.card_registry;
card_manager.RegisterCard({.card_id = "music.tracker", .display_name = "Music Tracker",
card_registry->RegisterCard({.card_id = "music.tracker", .display_name = "Music Tracker",
.icon = ICON_MD_MUSIC_NOTE, .category = "Music",
.shortcut_hint = "Ctrl+Shift+M", .priority = 10});
card_manager.RegisterCard({.card_id = "music.instrument_editor", .display_name = "Instrument Editor",
card_registry->RegisterCard({.card_id = "music.instrument_editor", .display_name = "Instrument Editor",
.icon = ICON_MD_PIANO, .category = "Music",
.shortcut_hint = "Ctrl+Shift+I", .priority = 20});
card_manager.RegisterCard({.card_id = "music.assembly", .display_name = "Assembly View",
card_registry->RegisterCard({.card_id = "music.assembly", .display_name = "Assembly View",
.icon = ICON_MD_CODE, .category = "Music",
.shortcut_hint = "Ctrl+Shift+A", .priority = 30});
// Show tracker by default
card_manager.ShowCard("music.tracker");
card_registry->ShowCard("music.tracker");
}
absl::Status MusicEditor::Load() {
@@ -35,7 +37,8 @@ absl::Status MusicEditor::Load() {
}
absl::Status MusicEditor::Update() {
auto& card_manager = gui::EditorCardManager::Get();
if (!dependencies_.card_registry) return absl::OkStatus();
auto* card_registry = dependencies_.card_registry;
static gui::EditorCard tracker_card("Music Tracker", ICON_MD_MUSIC_NOTE);
static gui::EditorCard instrument_card("Instrument Editor", ICON_MD_PIANO);
@@ -46,19 +49,19 @@ absl::Status MusicEditor::Update() {
assembly_card.SetDefaultSize(700, 600);
// Music Tracker Card
if (tracker_card.Begin(card_manager.GetVisibilityFlag("music.tracker"))) {
if (tracker_card.Begin(card_registry->GetVisibilityFlag("music.tracker"))) {
DrawTrackerView();
}
tracker_card.End();
// Instrument Editor Card
if (instrument_card.Begin(card_manager.GetVisibilityFlag("music.instrument_editor"))) {
if (instrument_card.Begin(card_registry->GetVisibilityFlag("music.instrument_editor"))) {
DrawInstrumentEditor();
}
instrument_card.End();
// Assembly View Card
if (assembly_card.Begin(card_manager.GetVisibilityFlag("music.assembly"))) {
if (assembly_card.Begin(card_registry->GetVisibilityFlag("music.assembly"))) {
assembly_editor_.InlineUpdate();
}
assembly_card.End();

View File

@@ -1,4 +1,5 @@
#include "overworld_editor.h"
#include "app/editor/system/editor_card_registry.h"
#ifndef IM_PI
#define IM_PI 3.14159265358979323846f
@@ -48,11 +49,12 @@ using namespace ImGui;
constexpr float kInputFieldSize = 30.f;
void OverworldEditor::Initialize() {
// Register cards with EditorCardManager
auto& card_manager = gui::EditorCardManager::Get();
// Register cards with EditorCardRegistry (dependency injection)
if (!dependencies_.card_registry) return;
auto* card_registry = dependencies_.card_registry;
// Register Overworld Canvas (main canvas card with toolset)
card_manager.RegisterCard({
card_registry->RegisterCard({
.card_id = MakeCardId("overworld.canvas"),
.display_name = "Overworld Canvas",
.icon = ICON_MD_MAP,
@@ -62,7 +64,7 @@ void OverworldEditor::Initialize() {
.priority = 5 // Show first, most important
});
card_manager.RegisterCard({
card_registry->RegisterCard({
.card_id = MakeCardId("overworld.tile16_selector"),
.display_name = "Tile16 Selector",
.icon = ICON_MD_GRID_ON,
@@ -72,7 +74,7 @@ void OverworldEditor::Initialize() {
.priority = 10
});
card_manager.RegisterCard({
card_registry->RegisterCard({
.card_id = MakeCardId("overworld.tile8_selector"),
.display_name = "Tile8 Selector",
.icon = ICON_MD_GRID_3X3,
@@ -82,7 +84,7 @@ void OverworldEditor::Initialize() {
.priority = 20
});
card_manager.RegisterCard({
card_registry->RegisterCard({
.card_id = MakeCardId("overworld.area_graphics"),
.display_name = "Area Graphics",
.icon = ICON_MD_IMAGE,
@@ -92,7 +94,7 @@ void OverworldEditor::Initialize() {
.priority = 30
});
card_manager.RegisterCard({
card_registry->RegisterCard({
.card_id = MakeCardId("overworld.scratch"),
.display_name = "Scratch Workspace",
.icon = ICON_MD_DRAW,
@@ -102,7 +104,7 @@ void OverworldEditor::Initialize() {
.priority = 40
});
card_manager.RegisterCard({
card_registry->RegisterCard({
.card_id = MakeCardId("overworld.gfx_groups"),
.display_name = "GFX Groups",
.icon = ICON_MD_FOLDER,
@@ -112,7 +114,7 @@ void OverworldEditor::Initialize() {
.priority = 50
});
card_manager.RegisterCard({
card_registry->RegisterCard({
.card_id = MakeCardId("overworld.usage_stats"),
.display_name = "Usage Statistics",
.icon = ICON_MD_ANALYTICS,
@@ -122,7 +124,7 @@ void OverworldEditor::Initialize() {
.priority = 60
});
card_manager.RegisterCard({
card_registry->RegisterCard({
.card_id = MakeCardId("overworld.v3_settings"),
.display_name = "v3 Settings",
.icon = ICON_MD_SETTINGS,

View File

@@ -1,4 +1,5 @@
#include "palette_editor.h"
#include "app/editor/system/editor_card_registry.h"
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
@@ -185,9 +186,10 @@ absl::Status DisplayPalette(gfx::SnesPalette& palette, bool loaded) {
void PaletteEditor::Initialize() {
// Register all cards with EditorCardManager (done once during initialization)
auto& card_manager = gui::EditorCardManager::Get();
if (!dependencies_.card_registry) return;
auto* card_registry = dependencies_.card_registry;
card_manager.RegisterCard({
card_registry->RegisterCard({
.card_id = "palette.control_panel",
.display_name = "Palette Controls",
.icon = ICON_MD_PALETTE,
@@ -197,7 +199,7 @@ void PaletteEditor::Initialize() {
.priority = 10
});
card_manager.RegisterCard({
card_registry->RegisterCard({
.card_id = "palette.ow_main",
.display_name = "Overworld Main",
.icon = ICON_MD_LANDSCAPE,
@@ -207,7 +209,7 @@ void PaletteEditor::Initialize() {
.priority = 20
});
card_manager.RegisterCard({
card_registry->RegisterCard({
.card_id = "palette.ow_animated",
.display_name = "Overworld Animated",
.icon = ICON_MD_WATER,
@@ -217,7 +219,7 @@ void PaletteEditor::Initialize() {
.priority = 30
});
card_manager.RegisterCard({
card_registry->RegisterCard({
.card_id = "palette.dungeon_main",
.display_name = "Dungeon Main",
.icon = ICON_MD_CASTLE,
@@ -227,7 +229,7 @@ void PaletteEditor::Initialize() {
.priority = 40
});
card_manager.RegisterCard({
card_registry->RegisterCard({
.card_id = "palette.sprites",
.display_name = "Global Sprite Palettes",
.icon = ICON_MD_PETS,
@@ -237,7 +239,7 @@ void PaletteEditor::Initialize() {
.priority = 50
});
card_manager.RegisterCard({
card_registry->RegisterCard({
.card_id = "palette.sprites_aux1",
.display_name = "Sprites Aux 1",
.icon = ICON_MD_FILTER_1,
@@ -247,7 +249,7 @@ void PaletteEditor::Initialize() {
.priority = 51
});
card_manager.RegisterCard({
card_registry->RegisterCard({
.card_id = "palette.sprites_aux2",
.display_name = "Sprites Aux 2",
.icon = ICON_MD_FILTER_2,
@@ -257,7 +259,7 @@ void PaletteEditor::Initialize() {
.priority = 52
});
card_manager.RegisterCard({
card_registry->RegisterCard({
.card_id = "palette.sprites_aux3",
.display_name = "Sprites Aux 3",
.icon = ICON_MD_FILTER_3,
@@ -267,7 +269,7 @@ void PaletteEditor::Initialize() {
.priority = 53
});
card_manager.RegisterCard({
card_registry->RegisterCard({
.card_id = "palette.equipment",
.display_name = "Equipment Palettes",
.icon = ICON_MD_SHIELD,
@@ -277,7 +279,7 @@ void PaletteEditor::Initialize() {
.priority = 60
});
card_manager.RegisterCard({
card_registry->RegisterCard({
.card_id = "palette.quick_access",
.display_name = "Quick Access",
.icon = ICON_MD_COLOR_LENS,
@@ -287,7 +289,7 @@ void PaletteEditor::Initialize() {
.priority = 70
});
card_manager.RegisterCard({
card_registry->RegisterCard({
.card_id = "palette.custom",
.display_name = "Custom Palette",
.icon = ICON_MD_BRUSH,
@@ -935,8 +937,9 @@ void PaletteEditor::DrawControlPanel() {
ImGui::Separator();
// Use EditorCardManager to draw the menu
auto& card_manager = gui::EditorCardManager::Get();
card_manager.DrawViewMenuSection("Palette");
if (!dependencies_.card_registry) return;
auto* card_registry = dependencies_.card_registry;
// View menu section now handled by EditorCardRegistry in EditorManager
ImGui::EndPopup();
}

View File

@@ -1,4 +1,5 @@
#include "sprite_editor.h"
#include "app/editor/system/editor_card_registry.h"
#include "app/gfx/debug/performance/performance_profiler.h"
#include "app/gui/core/ui_helpers.h"
@@ -25,17 +26,18 @@ using ImGui::TableSetupColumn;
using ImGui::Text;
void SpriteEditor::Initialize() {
auto& card_manager = gui::EditorCardManager::Get();
if (!dependencies_.card_registry) return;
auto* card_registry = dependencies_.card_registry;
card_manager.RegisterCard({.card_id = "sprite.vanilla_editor", .display_name = "Vanilla Sprites",
card_registry->RegisterCard({.card_id = "sprite.vanilla_editor", .display_name = "Vanilla Sprites",
.icon = ICON_MD_SMART_TOY, .category = "Sprite",
.shortcut_hint = "Alt+Shift+1", .priority = 10});
card_manager.RegisterCard({.card_id = "sprite.custom_editor", .display_name = "Custom Sprites",
card_registry->RegisterCard({.card_id = "sprite.custom_editor", .display_name = "Custom Sprites",
.icon = ICON_MD_ADD_CIRCLE, .category = "Sprite",
.shortcut_hint = "Alt+Shift+2", .priority = 20});
// Show vanilla editor by default
card_manager.ShowCard("sprite.vanilla_editor");
card_registry->ShowCard("sprite.vanilla_editor");
}
absl::Status SpriteEditor::Load() {
@@ -48,7 +50,8 @@ absl::Status SpriteEditor::Update() {
sheets_loaded_ = true;
}
auto& card_manager = gui::EditorCardManager::Get();
if (!dependencies_.card_registry) return absl::OkStatus();
auto* card_registry = dependencies_.card_registry;
static gui::EditorCard vanilla_card("Vanilla Sprites", ICON_MD_SMART_TOY);
static gui::EditorCard custom_card("Custom Sprites", ICON_MD_ADD_CIRCLE);
@@ -58,12 +61,12 @@ absl::Status SpriteEditor::Update() {
// Get visibility flags from card manager and pass to Begin()
// Always call End() after Begin() - End() handles ImGui state safely
if (vanilla_card.Begin(card_manager.GetVisibilityFlag("sprite.vanilla_editor"))) {
if (vanilla_card.Begin(card_registry->GetVisibilityFlag("sprite.vanilla_editor"))) {
DrawVanillaSpriteEditor();
}
vanilla_card.End();
if (custom_card.Begin(card_manager.GetVisibilityFlag("sprite.custom_editor"))) {
if (custom_card.Begin(card_registry->GetVisibilityFlag("sprite.custom_editor"))) {
DrawCustomSprites();
}
custom_card.End();

View File

@@ -387,6 +387,13 @@ class EditorCardRegistry {
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)
*/
@@ -425,6 +432,20 @@ class EditorCardRegistry {
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)
*/
@@ -434,7 +455,7 @@ class EditorCardRegistry {
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_;

View File

@@ -191,7 +191,7 @@ void MenuOrchestrator::AddViewMenuItems() {
.Item("Chat History", ICON_MD_CHAT,
[this]() { OnShowChatHistory(); }, "Ctrl+H")
.Item("Proposal Drawer", ICON_MD_PREVIEW,
[this]() { OnShowProposalDrawer(); }, "Ctrl+P");
[this]() { OnShowProposalDrawer(); }, "Ctrl+Shift+R");
#endif
menu_builder_

View File

@@ -253,7 +253,7 @@ void ConfigureEditorShortcuts(const ShortcutDependencies& deps,
});
RegisterIfValid(shortcut_manager, "Proposal Drawer",
{ImGuiMod_Ctrl, ImGuiKey_P},
{ImGuiMod_Ctrl | ImGuiMod_Shift, ImGuiKey_R}, // Changed from Ctrl+P to Ctrl+Shift+R
[editor_manager]() {
if (editor_manager) {
editor_manager->ShowProposalDrawer();

View File

@@ -33,6 +33,7 @@ UICoordinator::UICoordinator(
RomFileManager& rom_manager,
ProjectManager& project_manager,
EditorRegistry& editor_registry,
EditorCardRegistry& card_registry,
SessionCoordinator& session_coordinator,
WindowDelegate& window_delegate,
ToastManager& toast_manager,
@@ -42,6 +43,7 @@ UICoordinator::UICoordinator(
rom_manager_(rom_manager),
project_manager_(project_manager),
editor_registry_(editor_registry),
card_registry_(card_registry),
session_coordinator_(session_coordinator),
window_delegate_(window_delegate),
toast_manager_(toast_manager),
@@ -191,14 +193,38 @@ void UICoordinator::DrawContextSensitiveCardControl() {
if (!active_editor) return;
std::string category = editor_registry_.GetEditorCategory(active_editor->type());
size_t session_id = editor_manager_->GetCurrentSessionId();
// Draw compact card control with session awareness
auto& card_manager = gui::EditorCardManager::Get();
if (session_coordinator_.HasMultipleSessions()) {
std::string session_prefix = absl::StrFormat("s%zu", session_coordinator_.GetActiveSessionIndex());
card_manager.DrawCompactCardControlWithSession(category, session_prefix);
} else {
card_manager.DrawCompactCardControl(category);
// Draw compact card control in menu bar (mini dropdown for cards)
ImGui::SameLine();
ImGui::PushStyleColor(ImGuiCol_Button, gui::GetSurfaceContainerHighVec4());
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, gui::GetSurfaceContainerHighestVec4());
if (ImGui::SmallButton(absl::StrFormat("%s %s", ICON_MD_LAYERS, category.c_str()).c_str())) {
ImGui::OpenPopup("##CardQuickAccess");
}
ImGui::PopStyleColor(2);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Quick access to %s cards", category.c_str());
}
// Quick access popup for toggling cards
if (ImGui::BeginPopup("##CardQuickAccess")) {
auto cards = card_registry_.GetCardsInCategory(session_id, category);
for (const auto& card : cards) {
bool visible = card.visibility_flag ? *card.visibility_flag : false;
if (ImGui::MenuItem(card.display_name.c_str(), nullptr, visible)) {
if (visible) {
card_registry_.HideCard(session_id, card.card_id);
} else {
card_registry_.ShowCard(session_id, card.card_id);
}
}
}
ImGui::EndPopup();
}
}

View File

@@ -45,6 +45,7 @@ class UICoordinator {
RomFileManager& rom_manager,
ProjectManager& project_manager,
EditorRegistry& editor_registry,
EditorCardRegistry& card_registry,
SessionCoordinator& session_coordinator,
WindowDelegate& window_delegate,
ToastManager& toast_manager,
@@ -108,6 +109,8 @@ class UICoordinator {
bool IsCardBrowserVisible() const { return show_card_browser_; }
bool IsCommandPaletteVisible() const { return show_command_palette_; }
bool IsCardSidebarVisible() const { return show_card_sidebar_; }
bool IsImGuiDemoVisible() const { return show_imgui_demo_; }
bool IsImGuiMetricsVisible() const { return show_imgui_metrics_; }
// UI state setters (for programmatic control)
void SetEditorSelectionVisible(bool visible) { show_editor_selection_ = visible; }
@@ -131,6 +134,7 @@ class UICoordinator {
RomFileManager& rom_manager_;
ProjectManager& project_manager_;
EditorRegistry& editor_registry_;
EditorCardRegistry& card_registry_;
SessionCoordinator& session_coordinator_;
WindowDelegate& window_delegate_;
ToastManager& toast_manager_;
@@ -155,7 +159,7 @@ class UICoordinator {
bool show_asm_editor_ = false;
bool show_palette_editor_ = false;
bool show_resource_label_manager_ = false;
bool show_card_sidebar_ = false;
bool show_card_sidebar_ = true; // Show sidebar by default
// Command Palette state
char command_palette_query_[256] = {};

View File

@@ -1,6 +1,8 @@
#define IMGUI_DEFINE_MATH_OPERATORS
#include "app/editor/ui/workspace_manager.h"
#include "app/editor/system/editor_card_registry.h"
#include "app/editor/system/toast_manager.h"
#include "app/gui/app/editor_card_manager.h"
#include "app/rom.h"
#include "absl/strings/str_format.h"
#include "util/file_util.h"
@@ -125,14 +127,18 @@ void WorkspaceManager::LoadModderLayout() {
}
void WorkspaceManager::ShowAllWindows() {
gui::EditorCardManager::Get().ShowAll();
if (card_registry_) {
card_registry_->ShowAll();
}
if (toast_manager_) {
toast_manager_->Show("All windows shown", ToastType::kInfo);
}
}
void WorkspaceManager::HideAllWindows() {
gui::EditorCardManager::Get().HideAll();
if (card_registry_) {
card_registry_->HideAll();
}
if (toast_manager_) {
toast_manager_->Show("All windows hidden", ToastType::kInfo);
}

View File

@@ -12,6 +12,7 @@ namespace editor {
class EditorSet;
class ToastManager;
class EditorCardRegistry;
/**
* @brief Manages workspace layouts, sessions, and presets
@@ -28,6 +29,9 @@ class WorkspaceManager {
explicit WorkspaceManager(ToastManager* toast_manager)
: toast_manager_(toast_manager) {}
// Set card registry for window visibility management
void set_card_registry(EditorCardRegistry* registry) { card_registry_ = registry; }
// Layout management
absl::Status SaveWorkspaceLayout(const std::string& name = "");
absl::Status LoadWorkspaceLayout(const std::string& name = "");
@@ -69,6 +73,7 @@ class WorkspaceManager {
private:
ToastManager* toast_manager_;
EditorCardRegistry* card_registry_ = nullptr;
std::deque<SessionInfo>* sessions_ = nullptr;
std::string last_workspace_preset_;
std::vector<std::string> workspace_presets_;