editor manager refactor

This commit is contained in:
scawful
2025-10-15 12:37:59 -04:00
parent f09e8c0a58
commit 16f2bfe15e
15 changed files with 1073 additions and 894 deletions

View File

@@ -9,9 +9,6 @@
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_format.h"
#include "app/editor/system/command_manager.h"
#include "app/editor/system/extension_manager.h"
#include "app/editor/system/history_manager.h"
#include "app/editor/system/popup_manager.h"
#include "app/editor/system/shortcut_manager.h"
@@ -65,36 +62,11 @@ class UserSettings;
* ```
*/
struct EditorDependencies {
Rom* rom = nullptr;
EditorCardRegistry* card_registry = nullptr;
ToastManager* toast_manager = nullptr;
PopupManager* popup_manager = nullptr;
ShortcutManager* shortcut_manager = nullptr;
UserSettings* user_settings = nullptr;
size_t session_id = 0;
gfx::IRenderer* renderer = nullptr;
void* custom_data = nullptr;
};
struct EditorContext {
CommandManager command_manager;
ExtensionManager extension_manager;
HistoryManager history_manager;
PopupManager* popup_manager = nullptr;
ShortcutManager shortcut_manager;
// Session identification for multi-session support
// Used by child panels to create unique ImGui IDs
size_t session_id = 0;
// Cross-session shared clipboard for editor data transfers
struct SharedClipboard {
// Overworld tile16 selection payload
bool has_overworld_tile16 = false;
std::vector<int> overworld_tile16_ids;
int overworld_width = 0; // in tile16 units
int overworld_height = 0; // in tile16 units
int overworld_width = 0;
int overworld_height = 0;
void Clear() {
has_overworld_tile16 = false;
@@ -102,7 +74,20 @@ struct EditorContext {
overworld_width = 0;
overworld_height = 0;
}
} shared_clipboard;
};
Rom* rom = nullptr;
EditorCardRegistry* card_registry = nullptr;
ToastManager* toast_manager = nullptr;
PopupManager* popup_manager = nullptr;
ShortcutManager* shortcut_manager = nullptr;
SharedClipboard* shared_clipboard = nullptr;
UserSettings* user_settings = nullptr;
size_t session_id = 0;
gfx::IRenderer* renderer = nullptr;
void* custom_data = nullptr;
};
enum class EditorType {
@@ -139,6 +124,8 @@ class Editor {
Editor() = default;
virtual ~Editor() = default;
void SetDependencies(const EditorDependencies& deps) { dependencies_ = deps; }
// Initialization of the editor, no ROM assets.
virtual void Initialize() = 0;
@@ -164,8 +151,6 @@ class Editor {
EditorType type() const { return type_; }
void set_context(EditorContext* context) { context_ = context; }
bool* active() { return &active_; }
void set_active(bool active) { active_ = active; }
void toggle_active() { active_ = !active_; }
@@ -177,20 +162,20 @@ class Editor {
protected:
bool active_ = false;
EditorType type_;
EditorContext* context_ = nullptr;
EditorDependencies dependencies_;
// Helper method to create session-aware card titles for multi-session support
std::string MakeCardTitle(const std::string& base_title) const {
if (context_ && context_->session_id > 0) {
return absl::StrFormat("%s [S%zu]", base_title, context_->session_id);
if (dependencies_.session_id > 0) {
return absl::StrFormat("%s [S%zu]", base_title, dependencies_.session_id);
}
return base_title;
}
// Helper method to create session-aware card IDs for multi-session support
std::string MakeCardId(const std::string& base_id) const {
if (context_ && context_->session_id > 0) {
return absl::StrFormat("s%zu.%s", context_->session_id, base_id);
if (dependencies_.session_id > 0) {
return absl::StrFormat("s%zu.%s", dependencies_.session_id, base_id);
}
return base_id;
}

View File

@@ -46,6 +46,7 @@ set(
app/editor/system/session_coordinator.cc
app/editor/system/user_settings.cc
app/editor/system/window_delegate.cc
app/editor/system/shortcut_configurator.cc
app/editor/ui/editor_selection_dialog.cc
app/editor/ui/menu_builder.cc
app/editor/ui/ui_coordinator.cc

File diff suppressed because it is too large Load Diff

View File

@@ -3,54 +3,55 @@
#define IMGUI_DEFINE_MATH_OPERATORS
#include "app/editor/editor.h"
#include "app/editor/system/user_settings.h"
#include "app/editor/ui/workspace_manager.h"
#include "imgui/imgui.h"
#include <cstddef>
#include <deque>
#include <vector>
#include "absl/status/status.h"
#include "app/core/features.h"
#include "app/core/project.h"
#include "app/editor/agent/agent_chat_history_popup.h"
#include "app/editor/code/assembly_editor.h"
#include "app/editor/code/memory_editor.h"
#include "app/editor/ui/menu_builder.h"
#include "app/editor/code/project_file_editor.h"
#include "app/editor/dungeon/dungeon_editor_v2.h"
#include "app/editor/graphics/graphics_editor.h"
#include "app/editor/palette/palette_editor.h"
#include "app/editor/graphics/screen_editor.h"
#include "app/editor/message/message_editor.h"
#include "app/editor/music/music_editor.h"
#include "app/editor/overworld/overworld_editor.h"
#include "app/editor/palette/palette_editor.h"
#include "app/editor/sprite/sprite_editor.h"
#include "app/editor/system/popup_manager.h"
#include "app/editor/system/proposal_drawer.h"
#include "app/editor/agent/agent_chat_history_popup.h"
#ifdef YAZE_WITH_GRPC
#include "app/editor/agent/agent_editor.h"
#include "app/editor/agent/automation_bridge.h"
#endif
#include "app/editor/system/settings_editor.h"
#include "app/editor/system/toast_manager.h"
#include "app/rom.h"
#include "app/editor/system/editor_card_registry.h"
#include "app/editor/system/editor_registry.h"
#include "app/editor/system/menu_orchestrator.h"
#include "app/editor/system/popup_manager.h"
#include "app/editor/system/project_manager.h"
#include "app/editor/system/proposal_drawer.h"
#include "app/editor/system/rom_file_manager.h"
#include "app/editor/system/editor_card_registry.h"
#include "app/editor/system/session_coordinator.h"
#include "app/editor/system/settings_editor.h"
#include "app/editor/system/toast_manager.h"
#include "app/editor/system/window_delegate.h"
#include "app/editor/ui/editor_selection_dialog.h"
#include "app/editor/ui/menu_builder.h"
#include "app/editor/ui/ui_coordinator.h"
#include "app/editor/ui/welcome_screen.h"
#include "app/emu/emulator.h"
#include "app/gfx/debug/performance/performance_dashboard.h"
#include "zelda3/overworld/overworld.h"
#include "app/rom.h"
#include "yaze_config.h"
#ifdef YAZE_WITH_GRPC
#include "app/editor/agent/agent_editor.h"
#include "app/editor/agent/automation_bridge.h"
// Forward declarations for gRPC-dependent types
namespace yaze::agent {
class AgentControlServer;
@@ -66,7 +67,8 @@ namespace editor {
*/
class EditorSet {
public:
explicit EditorSet(Rom* rom = nullptr, UserSettings* user_settings = nullptr, size_t session_id = 0)
explicit EditorSet(Rom* rom = nullptr, UserSettings* user_settings = nullptr,
size_t session_id = 0)
: session_id_(session_id),
assembly_editor_(rom),
dungeon_editor_(rom),
@@ -84,11 +86,13 @@ class EditorSet {
&music_editor_, &screen_editor_, &settings_editor_,
&assembly_editor_};
}
void set_user_settings(UserSettings* settings) {
settings_editor_.set_user_settings(settings);
}
void ApplyDependencies(const EditorDependencies& dependencies);
size_t session_id() const { return session_id_; }
AssemblyEditor assembly_editor_;
@@ -104,7 +108,7 @@ class EditorSet {
MemoryEditorWithDiffChecker memory_editor_;
std::vector<Editor*> active_editors_;
private:
size_t session_id_ = 0;
};
@@ -130,28 +134,29 @@ class EditorManager {
// Processes startup flags to open a specific editor and cards.
void OpenEditorAndCardsFromFlags(const std::string& editor_name,
const std::string& cards_str);
const std::string& cards_str);
absl::Status Update();
void DrawMenuBar();
auto emulator() -> emu::Emulator& { return emulator_; }
auto quit() const { return quit_; }
auto version() const { return version_; }
void DrawMenuBarExtras();
MenuBuilder& menu_builder() { return menu_builder_; }
void ShowSessionSwitcher();
void ShowEditorSelection();
void ShowDisplaySettings();
absl::Status SetCurrentRom(Rom* rom);
auto GetCurrentRom() -> Rom* { return current_rom_; }
auto GetCurrentEditorSet() -> EditorSet* { return current_editor_set_; }
auto GetCurrentEditor() -> Editor* { return current_editor_; }
auto overworld() -> yaze::zelda3::Overworld* { return &current_editor_set_->overworld_editor_.overworld(); }
size_t GetCurrentSessionId() const { return current_session_id_; }
UICoordinator* ui_coordinator() { return ui_coordinator_.get(); }
auto overworld() -> yaze::zelda3::Overworld* {
return &current_editor_set_->overworld_editor_.overworld();
}
// Session management helpers
size_t GetCurrentSessionIndex() const;
// Get current session's feature flags (falls back to global if no session)
core::FeatureFlags::Flags* GetCurrentFeatureFlags() {
size_t current_index = GetCurrentSessionIndex();
@@ -164,41 +169,41 @@ class EditorManager {
void SetFontGlobalScale(float scale) {
user_settings_.prefs().font_global_scale = scale;
ImGui::GetIO().FontGlobalScale = scale;
SaveUserSettings();
auto status = user_settings_.Save();
if (!status.ok()) {
LOG_WARN("EditorManager", "Failed to save user settings: %s",
status.ToString().c_str());
}
}
void BuildModernMenu();
// User settings helpers
void LoadUserSettings();
void SaveUserSettings();
// Workspace management (delegates to WorkspaceManager)
void RefreshWorkspacePresets() { workspace_manager_.RefreshPresets(); }
void SaveWorkspacePreset(const std::string& name) { workspace_manager_.SaveWorkspacePreset(name); }
void LoadWorkspacePreset(const std::string& name) { workspace_manager_.LoadWorkspacePreset(name); }
void SaveWorkspacePreset(const std::string& name) {
workspace_manager_.SaveWorkspacePreset(name);
}
void LoadWorkspacePreset(const std::string& name) {
workspace_manager_.LoadWorkspacePreset(name);
}
// Jump-to functionality for cross-editor navigation
void JumpToDungeonRoom(int room_id);
void JumpToOverworldMap(int map_id);
void SwitchToEditor(EditorType editor_type);
// Card-based editor registry
static bool IsCardBasedEditor(EditorType type);
static std::string GetEditorCategory(EditorType type);
static EditorType GetEditorTypeFromCategory(const std::string& category);
bool IsSidebarVisible() const {
return ui_coordinator_ ? ui_coordinator_->IsCardSidebarVisible() : false;
bool IsSidebarVisible() const {
return ui_coordinator_ ? ui_coordinator_->IsCardSidebarVisible() : false;
}
void SetSidebarVisible(bool visible) {
void SetSidebarVisible(bool visible) {
if (ui_coordinator_) {
ui_coordinator_->SetCardSidebarVisible(visible);
}
}
// Clean up cards when switching editors
void HideCurrentEditorCards();
// Session management
void CreateNewSession();
void DuplicateCurrentSession();
@@ -206,44 +211,72 @@ class EditorManager {
void RemoveSession(size_t index);
void SwitchToSession(size_t index);
size_t GetActiveSessionCount() const;
// Workspace layout management
// Window management - inline delegation (reduces EditorManager bloat)
void SaveWorkspaceLayout() { window_delegate_.SaveWorkspaceLayout(); }
void LoadWorkspaceLayout() { window_delegate_.LoadWorkspaceLayout(); }
void ResetWorkspaceLayout() { window_delegate_.ResetWorkspaceLayout(); }
void ShowAllWindows() { if (ui_coordinator_) ui_coordinator_->ShowAllWindows(); }
void HideAllWindows() { if (ui_coordinator_) ui_coordinator_->HideAllWindows(); }
void ShowAllWindows() {
if (ui_coordinator_)
ui_coordinator_->ShowAllWindows();
}
void HideAllWindows() {
if (ui_coordinator_)
ui_coordinator_->HideAllWindows();
}
// Layout presets (inline delegation)
void LoadDeveloperLayout() { window_delegate_.LoadDeveloperLayout(); }
void LoadDesignerLayout() { window_delegate_.LoadDesignerLayout(); }
void LoadModderLayout() { window_delegate_.LoadModderLayout(); }
// Helper methods
std::string GenerateUniqueEditorTitle(EditorType type, size_t session_index) const;
std::string GenerateUniqueEditorTitle(EditorType type,
size_t session_index) const;
bool HasDuplicateSession(const std::string& filepath);
void RenameSession(size_t index, const std::string& new_name);
void Quit() { quit_ = true; }
// UI visibility controls (public for MenuOrchestrator)
// UI visibility controls - inline for performance (single-line wrappers delegating to UICoordinator)
void ShowGlobalSearch() { if (ui_coordinator_) ui_coordinator_->ShowGlobalSearch(); }
void ShowCommandPalette() { if (ui_coordinator_) ui_coordinator_->ShowCommandPalette(); }
void ShowPerformanceDashboard() { if (ui_coordinator_) ui_coordinator_->SetPerformanceDashboardVisible(true); }
void ShowImGuiDemo() { if (ui_coordinator_) ui_coordinator_->SetImGuiDemoVisible(true); }
void ShowImGuiMetrics() { if (ui_coordinator_) ui_coordinator_->SetImGuiMetricsVisible(true); }
void ShowGlobalSearch() {
if (ui_coordinator_)
ui_coordinator_->ShowGlobalSearch();
}
void ShowCommandPalette() {
if (ui_coordinator_)
ui_coordinator_->ShowCommandPalette();
}
void ShowPerformanceDashboard() {
if (ui_coordinator_)
ui_coordinator_->SetPerformanceDashboardVisible(true);
}
void ShowImGuiDemo() {
if (ui_coordinator_)
ui_coordinator_->SetImGuiDemoVisible(true);
}
void ShowImGuiMetrics() {
if (ui_coordinator_)
ui_coordinator_->SetImGuiMetricsVisible(true);
}
void ShowHexEditor();
void ShowEmulator() { show_emulator_ = true; }
void ShowMemoryEditor() { show_memory_editor_ = true; }
void ShowResourceLabelManager() { show_resource_label_manager = true; }
void ShowCardBrowser() { if (ui_coordinator_) ui_coordinator_->ShowCardBrowser(); }
void ShowWelcomeScreen() { if (ui_coordinator_) ui_coordinator_->SetWelcomeScreenVisible(true); }
void ShowCardBrowser() {
if (ui_coordinator_)
ui_coordinator_->ShowCardBrowser();
}
void ShowWelcomeScreen() {
if (ui_coordinator_)
ui_coordinator_->SetWelcomeScreenVisible(true);
}
#ifdef YAZE_ENABLE_TESTING
void ShowTestDashboard() { show_test_dashboard_ = true; }
#endif
#ifdef YAZE_WITH_GRPC
void ShowAIAgent();
void ShowChatHistory();
@@ -255,23 +288,18 @@ class EditorManager {
absl::Status SaveRom();
absl::Status SaveRomAs(const std::string& filename);
absl::Status OpenRomOrProject(const std::string& filename);
absl::Status CreateNewProject(const std::string& template_name = "Basic ROM Hack");
absl::Status CreateNewProject(
const std::string& template_name = "Basic ROM Hack");
absl::Status OpenProject();
absl::Status SaveProject();
absl::Status SaveProjectAs();
absl::Status ImportProject(const std::string& project_path);
absl::Status RepairCurrentProject();
void ShowProjectHelp();
private:
void DrawWelcomeScreen();
absl::Status DrawRomSelector();
void DrawContextSensitiveCardControl(); // Card control for current editor
void DrawSessionSwitcher();
void DrawSessionManager();
void DrawLayoutPresets();
void DrawSessionRenameDialog();
absl::Status LoadAssets();
// Testing system
@@ -311,7 +339,7 @@ class EditorManager {
// Project file editor
ProjectFileEditor project_file_editor_;
// Note: Editor selection dialog and welcome screen are now managed by UICoordinator
// Kept here for backward compatibility during transition
EditorSelectionDialog editor_selection_dialog_;
@@ -336,7 +364,8 @@ class EditorManager {
core::FeatureFlags::Flags feature_flags; // Per-session feature flags
RomSession() = default;
explicit RomSession(Rom&& r, UserSettings* user_settings = nullptr, size_t session_id = 0)
explicit RomSession(Rom&& r, UserSettings* user_settings = nullptr,
size_t session_id = 0)
: rom(std::move(r)), editors(&rom, user_settings, session_id) {
filepath = rom.filename();
// Initialize with default feature flags
@@ -353,23 +382,26 @@ class EditorManager {
};
private:
std::deque<RomSession> sessions_;
Rom* current_rom_ = nullptr;
EditorSet* current_editor_set_ = nullptr;
Editor* current_editor_ = nullptr;
EditorSet blank_editor_set_{};
// Tracks which session is currently active so delegators (menus, popups,
// shortcuts) stay in sync without relying on per-editor context.
size_t current_session_id_ = 0;
gfx::IRenderer* renderer_ = nullptr;
core::YazeProject current_project_;
EditorContext context_;
EditorDependencies::SharedClipboard shared_clipboard_;
std::unique_ptr<PopupManager> popup_manager_;
ToastManager toast_manager_;
MenuBuilder menu_builder_;
ShortcutManager shortcut_manager_;
UserSettings user_settings_;
WorkspaceManager workspace_manager_{&toast_manager_};
// New delegated components (dependency injection architecture)
EditorCardRegistry card_registry_; // Card management with session awareness
EditorRegistry editor_registry_;
@@ -379,21 +411,24 @@ class EditorManager {
std::unique_ptr<UICoordinator> ui_coordinator_;
WindowDelegate window_delegate_;
std::unique_ptr<SessionCoordinator> session_coordinator_;
float autosave_timer_ = 0.0f;
// RAII helper for clean session context switching
class SessionScope {
public:
SessionScope(EditorManager* manager, size_t session_id);
~SessionScope();
private:
EditorManager* manager_;
Rom* prev_rom_;
EditorSet* prev_editor_set_;
size_t prev_session_id_;
};
void ConfigureEditorDependencies(EditorSet* editor_set, Rom* rom,
size_t session_id);
};
} // namespace editor

View File

@@ -315,7 +315,9 @@ void MessageEditor::DrawExpandedMessageSettings() {
expanded_messages_,
message_preview_.all_dictionaries_)
.ok()) {
context_->popup_manager->Show("Error");
if (auto* popup_manager = dependencies_.popup_manager) {
popup_manager->Show("Error");
}
}
}
}

View File

@@ -35,6 +35,11 @@ class MessageEditor : public Editor {
type_ = EditorType::kMessage;
}
explicit MessageEditor(Rom* rom, const EditorDependencies& deps)
: MessageEditor(rom) {
dependencies_ = deps;
}
void Initialize() override;
absl::Status Load() override;
absl::Status Update() override;

View File

@@ -1032,8 +1032,9 @@ void OverworldEditor::CheckForSelectRectangle() {
}
absl::Status OverworldEditor::Copy() {
if (!context_)
return absl::FailedPreconditionError("No editor context");
if (!dependencies_.shared_clipboard) {
return absl::FailedPreconditionError("Clipboard unavailable");
}
// If a rectangle selection exists, copy its tile16 IDs into shared clipboard
if (ow_map_canvas_.select_rect_active() &&
!ow_map_canvas_.selected_points().empty()) {
@@ -1059,27 +1060,28 @@ absl::Status OverworldEditor::Copy() {
}
}
context_->shared_clipboard.overworld_tile16_ids = std::move(ids);
context_->shared_clipboard.overworld_width = width;
context_->shared_clipboard.overworld_height = height;
context_->shared_clipboard.has_overworld_tile16 = true;
dependencies_.shared_clipboard->overworld_tile16_ids = std::move(ids);
dependencies_.shared_clipboard->overworld_width = width;
dependencies_.shared_clipboard->overworld_height = height;
dependencies_.shared_clipboard->has_overworld_tile16 = true;
return absl::OkStatus();
}
// Single tile copy fallback
if (current_tile16_ >= 0) {
context_->shared_clipboard.overworld_tile16_ids = {current_tile16_};
context_->shared_clipboard.overworld_width = 1;
context_->shared_clipboard.overworld_height = 1;
context_->shared_clipboard.has_overworld_tile16 = true;
dependencies_.shared_clipboard->overworld_tile16_ids = {current_tile16_};
dependencies_.shared_clipboard->overworld_width = 1;
dependencies_.shared_clipboard->overworld_height = 1;
dependencies_.shared_clipboard->has_overworld_tile16 = true;
return absl::OkStatus();
}
return absl::FailedPreconditionError("Nothing selected to copy");
}
absl::Status OverworldEditor::Paste() {
if (!context_)
return absl::FailedPreconditionError("No editor context");
if (!context_->shared_clipboard.has_overworld_tile16) {
if (!dependencies_.shared_clipboard) {
return absl::FailedPreconditionError("Clipboard unavailable");
}
if (!dependencies_.shared_clipboard->has_overworld_tile16) {
return absl::FailedPreconditionError("Clipboard empty");
}
if (ow_map_canvas_.points().empty() &&
@@ -1105,9 +1107,9 @@ absl::Status OverworldEditor::Paste() {
const int superX = current_map_ % 8;
const int tiles_per_local_map = 512 / kTile16Size;
const int width = context_->shared_clipboard.overworld_width;
const int height = context_->shared_clipboard.overworld_height;
const auto& ids = context_->shared_clipboard.overworld_tile16_ids;
const int width = dependencies_.shared_clipboard->overworld_width;
const int height = dependencies_.shared_clipboard->overworld_height;
const auto& ids = dependencies_.shared_clipboard->overworld_tile16_ids;
// Guard
if (width * height != static_cast<int>(ids.size())) {

View File

@@ -69,6 +69,11 @@ class OverworldEditor : public Editor, public gfx::GfxContext {
// MapPropertiesSystem will be initialized after maps_bmp_ and canvas are ready
}
explicit OverworldEditor(Rom* rom, const EditorDependencies& deps)
: OverworldEditor(rom) {
dependencies_ = deps;
}
void Initialize(gfx::IRenderer* renderer, Rom* rom);
void Initialize() override;
absl::Status Load() override;
@@ -104,6 +109,8 @@ class OverworldEditor : public Editor, public gfx::GfxContext {
return absl::StrFormat("ROM loaded: %s", rom_->title());
}
Rom* rom() const { return rom_; }
// Jump-to functionality
void set_current_map(int map_id) {
if (map_id >= 0 && map_id < zelda3::kNumOverworldMaps) {

View File

@@ -96,23 +96,24 @@ absl::Status OverworldEditor::DrawScratchSpace() {
scratch_spaces_[current_scratch_slot_].tile_data[tile_x][tile_y]);
}
}
if (!scratch_tile_ids.empty() && context_) {
if (!scratch_tile_ids.empty() && dependencies_.shared_clipboard) {
const auto& points = scratch_canvas_.selected_points();
int width =
std::abs(static_cast<int>((points[1].x - points[0].x) / 32)) + 1;
int height =
std::abs(static_cast<int>((points[1].y - points[0].y) / 32)) + 1;
context_->shared_clipboard.overworld_tile16_ids =
dependencies_.shared_clipboard->overworld_tile16_ids =
std::move(scratch_tile_ids);
context_->shared_clipboard.overworld_width = width;
context_->shared_clipboard.overworld_height = height;
context_->shared_clipboard.has_overworld_tile16 = true;
dependencies_.shared_clipboard->overworld_width = width;
dependencies_.shared_clipboard->overworld_height = height;
dependencies_.shared_clipboard->has_overworld_tile16 = true;
}
}
}
HOVER_HINT("Copy scratch selection to clipboard for pasting in overworld");
if (context_ && context_->shared_clipboard.has_overworld_tile16) {
if (dependencies_.shared_clipboard &&
dependencies_.shared_clipboard->has_overworld_tile16) {
Text(ICON_MD_CONTENT_PASTE
" Pattern ready! Use Shift+Click to stamp, or paste in overworld");
}
@@ -223,13 +224,15 @@ void OverworldEditor::DrawScratchSpacePattern() {
int start_tile_y = static_cast<int>(mouse_position.y) / 32;
// Get the selected tiles from overworld via clipboard
if (!context_ || !context_->shared_clipboard.has_overworld_tile16) {
if (!dependencies_.shared_clipboard ||
!dependencies_.shared_clipboard->has_overworld_tile16) {
return;
}
const auto& tile_ids = context_->shared_clipboard.overworld_tile16_ids;
int pattern_width = context_->shared_clipboard.overworld_width;
int pattern_height = context_->shared_clipboard.overworld_height;
const auto& tile_ids =
dependencies_.shared_clipboard->overworld_tile16_ids;
int pattern_width = dependencies_.shared_clipboard->overworld_width;
int pattern_height = dependencies_.shared_clipboard->overworld_height;
if (tile_ids.empty())
return;

View File

@@ -549,15 +549,21 @@ void MenuOrchestrator::OnSwitchToEditor(EditorType editor_type) {
void MenuOrchestrator::OnShowEditorSelection() {
// Delegate to EditorManager
// TODO: Draw editor selection via UICoordinator
if (editor_manager_) {
editor_manager_->ShowEditorSelection();
if (auto* ui = editor_manager_->ui_coordinator()) {
ui->ShowEditorSelection();
}
}
}
void MenuOrchestrator::OnShowDisplaySettings() {
// Delegate to EditorManager
// TODO: Draw display settings via UICoordinator
if (editor_manager_) {
editor_manager_->ShowDisplaySettings();
if (auto* ui = editor_manager_->ui_coordinator()) {
ui->ShowDisplaySettings();
}
}
}
@@ -624,8 +630,11 @@ void MenuOrchestrator::OnSwitchToSession(size_t session_index) {
}
void MenuOrchestrator::OnShowSessionSwitcher() {
// TODO: Draw session switcher via UICoordinator
if (editor_manager_) {
editor_manager_->ShowSessionSwitcher();
if (auto* ui = editor_manager_->ui_coordinator()) {
ui->ShowSessionSwitcher();
}
}
}
@@ -879,7 +888,8 @@ void MenuOrchestrator::OnQuit() {
// Menu item validation helpers
bool MenuOrchestrator::CanSaveRom() const {
return rom_manager_.IsRomLoaded();
auto* rom = editor_manager_->GetCurrentRom();
return rom ? rom_manager_.IsRomLoaded(rom) : false;
}
bool MenuOrchestrator::CanSaveProject() const {
@@ -887,7 +897,8 @@ bool MenuOrchestrator::CanSaveProject() const {
}
bool MenuOrchestrator::HasActiveRom() const {
return rom_manager_.IsRomLoaded();
auto* rom = editor_manager_->GetCurrentRom();
return rom ? rom_manager_.IsRomLoaded(rom) : false;
}
bool MenuOrchestrator::HasActiveProject() const {
@@ -904,7 +915,8 @@ bool MenuOrchestrator::HasMultipleSessions() const {
// Menu item text generation
std::string MenuOrchestrator::GetRomFilename() const {
return rom_manager_.GetRomFilename();
auto* rom = editor_manager_->GetCurrentRom();
return rom ? rom_manager_.GetRomFilename(rom) : "";
}
std::string MenuOrchestrator::GetProjectName() const {

View File

@@ -2,37 +2,162 @@
#include <filesystem>
#include <fstream>
#include <chrono>
#include "absl/strings/str_format.h"
#include "app/editor/system/toast_manager.h"
#include "app/rom.h"
#include "util/file_util.h"
namespace yaze {
namespace editor {
namespace yaze::editor {
RomFileManager::RomFileManager(ToastManager* toast_manager)
: toast_manager_(toast_manager) {
}
: toast_manager_(toast_manager) {}
absl::Status RomFileManager::LoadRom(const std::string& filename) {
absl::Status RomFileManager::LoadRom(Rom* rom, const std::string& filename) {
if (!rom) {
return absl::InvalidArgumentError("ROM pointer cannot be null");
}
if (filename.empty()) {
// TODO: Show file dialog
return absl::InvalidArgumentError("No filename provided");
}
return LoadRomFromFile(filename);
return LoadRomFromFile(rom, filename);
}
absl::Status RomFileManager::LoadRomFromFile(const std::string& filename) {
absl::Status RomFileManager::SaveRom(Rom* rom) {
if (!IsRomLoaded(rom)) {
return absl::FailedPreconditionError("No ROM loaded to save");
}
Rom::SaveSettings settings;
settings.backup = true;
settings.save_new = false;
settings.z3_save = true;
auto status = rom->SaveToFile(settings);
if (!status.ok() && toast_manager_) {
toast_manager_->Show(
absl::StrFormat("Failed to save ROM: %s", status.message()),
ToastType::kError);
} else if (toast_manager_) {
toast_manager_->Show("ROM saved successfully", ToastType::kSuccess);
}
return status;
}
absl::Status RomFileManager::SaveRomAs(Rom* rom, const std::string& filename) {
if (!IsRomLoaded(rom)) {
return absl::FailedPreconditionError("No ROM loaded to save");
}
if (filename.empty()) {
return absl::InvalidArgumentError(
"No filename provided for save as");
}
Rom::SaveSettings settings;
settings.backup = false;
settings.save_new = true;
settings.filename = filename;
settings.z3_save = true;
auto status = rom->SaveToFile(settings);
if (!status.ok() && toast_manager_) {
toast_manager_->Show(
absl::StrFormat("Failed to save ROM as: %s", status.message()),
ToastType::kError);
} else if (toast_manager_) {
toast_manager_->Show(
absl::StrFormat("ROM saved as: %s", filename),
ToastType::kSuccess);
}
return status;
}
absl::Status RomFileManager::OpenRomOrProject(Rom* rom,
const std::string& filename) {
if (!rom) {
return absl::InvalidArgumentError("ROM pointer cannot be null");
}
if (filename.empty()) {
return absl::InvalidArgumentError("No filename provided");
}
std::string extension =
std::filesystem::path(filename).extension().string();
if (extension == ".yaze" || extension == ".json") {
return absl::UnimplementedError(
"Project file loading not yet implemented");
}
return LoadRom(rom, filename);
}
absl::Status RomFileManager::CreateBackup(Rom* rom) {
if (!IsRomLoaded(rom)) {
return absl::FailedPreconditionError("No ROM loaded to backup");
}
std::string backup_filename = GenerateBackupFilename(rom->filename());
Rom::SaveSettings settings;
settings.backup = true;
settings.filename = backup_filename;
settings.z3_save = true;
auto status = rom->SaveToFile(settings);
if (!status.ok() && toast_manager_) {
toast_manager_->Show(
absl::StrFormat("Failed to create backup: %s", status.message()),
ToastType::kError);
} else if (toast_manager_) {
toast_manager_->Show(
absl::StrFormat("Backup created: %s", backup_filename),
ToastType::kSuccess);
}
return status;
}
absl::Status RomFileManager::ValidateRom(Rom* rom) {
if (!IsRomLoaded(rom)) {
return absl::FailedPreconditionError("No valid ROM to validate");
}
if (rom->size() < 512 * 1024 || rom->size() > 8 * 1024 * 1024) {
return absl::InvalidArgumentError("ROM size is outside expected range");
}
if (rom->title().empty()) {
return absl::InvalidArgumentError("ROM title is empty or invalid");
}
if (toast_manager_) {
toast_manager_->Show("ROM validation passed", ToastType::kSuccess);
}
return absl::OkStatus();
}
bool RomFileManager::IsRomLoaded(Rom* rom) const {
return rom && rom->is_loaded();
}
std::string RomFileManager::GetRomFilename(Rom* rom) const {
if (!IsRomLoaded(rom)) {
return "";
}
return rom->filename();
}
absl::Status RomFileManager::LoadRomFromFile(
Rom* rom, const std::string& filename) {
if (!rom) {
return absl::InvalidArgumentError("ROM pointer cannot be null");
}
if (!IsValidRomFile(filename)) {
return absl::InvalidArgumentError(
absl::StrFormat("Invalid ROM file: %s", filename));
}
// Create new ROM instance
Rom new_rom;
auto status = new_rom.LoadFromFile(filename);
auto status = rom->LoadFromFile(filename);
if (!status.ok()) {
if (toast_manager_) {
toast_manager_->Show(
@@ -41,204 +166,23 @@ absl::Status RomFileManager::LoadRomFromFile(const std::string& filename) {
}
return status;
}
// Set as current ROM
current_rom_ = &new_rom;
if (toast_manager_) {
toast_manager_->Show(
absl::StrFormat("ROM loaded: %s", new_rom.title()),
ToastType::kSuccess);
toast_manager_->Show(absl::StrFormat("ROM loaded: %s", rom->title()),
ToastType::kSuccess);
}
return absl::OkStatus();
}
absl::Status RomFileManager::SaveRom() {
if (!IsRomLoaded()) {
return absl::FailedPreconditionError("No ROM loaded to save");
}
Rom::SaveSettings settings;
settings.backup = true;
settings.save_new = false;
settings.z3_save = true;
auto status = current_rom_->SaveToFile(settings);
if (!status.ok()) {
if (toast_manager_) {
toast_manager_->Show(
absl::StrFormat("Failed to save ROM: %s", status.message()),
ToastType::kError);
}
return status;
}
if (toast_manager_) {
toast_manager_->Show("ROM saved successfully", ToastType::kSuccess);
}
return absl::OkStatus();
}
absl::Status RomFileManager::SaveRomAs(const std::string& filename) {
if (!IsRomLoaded()) {
return absl::FailedPreconditionError("No ROM loaded to save");
}
if (filename.empty()) {
return absl::InvalidArgumentError("No filename provided for save as");
}
Rom::SaveSettings settings;
settings.backup = false;
settings.save_new = true;
settings.filename = filename;
settings.z3_save = true;
auto status = current_rom_->SaveToFile(settings);
if (!status.ok()) {
if (toast_manager_) {
toast_manager_->Show(
absl::StrFormat("Failed to save ROM as: %s", status.message()),
ToastType::kError);
}
return status;
}
if (toast_manager_) {
toast_manager_->Show(
absl::StrFormat("ROM saved as: %s", filename),
ToastType::kSuccess);
}
return absl::OkStatus();
}
absl::Status RomFileManager::OpenRomOrProject(const std::string& filename) {
if (filename.empty()) {
return absl::InvalidArgumentError("No filename provided");
}
// Check if it's a project file or ROM file
std::string extension = std::filesystem::path(filename).extension().string();
if (extension == ".yaze" || extension == ".json") {
// TODO: Handle project files
return absl::UnimplementedError("Project file loading not yet implemented");
} else {
// Assume it's a ROM file
return LoadRom(filename);
}
}
absl::Status RomFileManager::LoadAssets() {
if (!IsRomLoaded()) {
return absl::FailedPreconditionError("No ROM loaded to load assets from");
}
// TODO: Implement asset loading logic
// This would typically load graphics, music, etc. from the ROM
if (toast_manager_) {
toast_manager_->Show("Assets loaded", ToastType::kInfo);
}
return absl::OkStatus();
}
absl::Status RomFileManager::SetCurrentRom(Rom* rom) {
if (!rom) {
return absl::InvalidArgumentError("ROM pointer cannot be null");
}
current_rom_ = rom;
return absl::OkStatus();
}
std::string RomFileManager::GetRomFilename() const {
if (!IsRomLoaded()) {
return "";
}
return current_rom_->filename();
}
std::string RomFileManager::GetRomTitle() const {
if (!IsRomLoaded()) {
return "";
}
return current_rom_->title();
}
absl::Status RomFileManager::ValidateRom() {
return ValidateRom(current_rom_);
}
absl::Status RomFileManager::ValidateRom(Rom* rom) {
if (!rom || !rom->is_loaded()) {
return absl::FailedPreconditionError("No valid ROM to validate");
}
// TODO: Implement ROM validation logic
// This would check ROM integrity, checksums, expected data structures, etc.
// Basic validation: check if ROM size is reasonable
if (rom->size() < 512 * 1024 || rom->size() > 8 * 1024 * 1024) {
return absl::InvalidArgumentError("ROM size is outside expected range");
}
// Check if ROM title is readable
if (rom->title().empty()) {
return absl::InvalidArgumentError("ROM title is empty or invalid");
}
if (toast_manager_) {
toast_manager_->Show("ROM validation passed", ToastType::kSuccess);
}
return absl::OkStatus();
}
absl::Status RomFileManager::CreateBackup() {
if (!IsRomLoaded()) {
return absl::FailedPreconditionError("No ROM loaded to backup");
}
std::string backup_filename = GenerateBackupFilename(GetRomFilename());
Rom::SaveSettings settings;
settings.backup = true;
settings.filename = backup_filename;
settings.z3_save = true;
auto status = current_rom_->SaveToFile(settings);
if (!status.ok()) {
if (toast_manager_) {
toast_manager_->Show(
absl::StrFormat("Failed to create backup: %s", status.message()),
ToastType::kError);
}
return status;
}
if (toast_manager_) {
toast_manager_->Show(
absl::StrFormat("Backup created: %s", backup_filename),
ToastType::kSuccess);
}
return absl::OkStatus();
}
std::string RomFileManager::GenerateBackupFilename(const std::string& original_filename) const {
std::string RomFileManager::GenerateBackupFilename(
const std::string& original_filename) const {
std::filesystem::path path(original_filename);
std::string stem = path.stem().string();
std::string extension = path.extension().string();
// Add timestamp to make it unique
auto now = std::chrono::system_clock::now();
auto time_t = std::chrono::system_clock::to_time_t(now);
return absl::StrFormat("%s_backup_%ld%s", stem, time_t, extension);
}
@@ -246,21 +190,17 @@ bool RomFileManager::IsValidRomFile(const std::string& filename) const {
if (filename.empty()) {
return false;
}
if (!std::filesystem::exists(filename)) {
return false;
}
// Check file size (SNES ROMs are typically 2MB, 3MB, 4MB, 6MB, etc.)
auto file_size = std::filesystem::file_size(filename);
if (file_size < 1024 * 1024 || file_size > 8 * 1024 * 1024) {
return false;
}
// TODO: Add more ROM validation (header checks, etc.)
return true;
}
} // namespace editor
} // namespace yaze
} // namespace yaze::editor

View File

@@ -27,34 +27,21 @@ class RomFileManager {
~RomFileManager() = default;
// ROM file operations
absl::Status LoadRom(const std::string& filename = "");
absl::Status SaveRom();
absl::Status SaveRomAs(const std::string& filename);
absl::Status OpenRomOrProject(const std::string& filename);
// Asset operations
absl::Status LoadAssets();
// ROM state management
absl::Status SetCurrentRom(Rom* rom);
Rom* GetCurrentRom() const { return current_rom_; }
// ROM information
bool IsRomLoaded() const { return current_rom_ && current_rom_->is_loaded(); }
std::string GetRomFilename() const;
std::string GetRomTitle() const;
// Validation and backup
absl::Status ValidateRom();
absl::Status ValidateRom(Rom* rom); // Validate a specific ROM
absl::Status CreateBackup();
absl::Status LoadRom(Rom* rom, const std::string& filename);
absl::Status SaveRom(Rom* rom);
absl::Status SaveRomAs(Rom* rom, const std::string& filename);
absl::Status OpenRomOrProject(Rom* rom, const std::string& filename);
absl::Status CreateBackup(Rom* rom);
absl::Status ValidateRom(Rom* rom);
// Utility helpers
bool IsRomLoaded(Rom* rom) const;
std::string GetRomFilename(Rom* rom) const;
private:
Rom* current_rom_ = nullptr;
ToastManager* toast_manager_ = nullptr;
// Helper methods
absl::Status LoadRomFromFile(const std::string& filename);
absl::Status LoadRomFromFile(Rom* rom, const std::string& filename);
std::string GenerateBackupFilename(const std::string& original_filename) const;
bool IsValidRomFile(const std::string& filename) const;
};

View File

@@ -0,0 +1,350 @@
#include "app/editor/system/shortcut_configurator.h"
#include "absl/functional/bind_front.h"
#include "absl/strings/str_format.h"
#include "app/editor/editor_manager.h"
#include "app/editor/system/editor_card_registry.h"
#include "app/editor/system/menu_orchestrator.h"
#include "app/editor/system/proposal_drawer.h"
#include "app/editor/system/rom_file_manager.h"
#include "app/editor/system/session_coordinator.h"
#include "app/editor/system/toast_manager.h"
#include "app/editor/ui/ui_coordinator.h"
#include "app/editor/ui/workspace_manager.h"
#include "app/editor/system/popup_manager.h"
#include "app/core/project.h"
namespace yaze::editor {
namespace {
void RegisterIfValid(ShortcutManager* shortcut_manager,
const std::string& name,
const std::vector<ImGuiKey>& keys,
std::function<void()> callback) {
if (!shortcut_manager || !callback) {
return;
}
shortcut_manager->RegisterShortcut(name, keys, std::move(callback));
}
void RegisterIfValid(ShortcutManager* shortcut_manager,
const std::string& name,
ImGuiKey key,
std::function<void()> callback) {
if (!shortcut_manager || !callback) {
return;
}
shortcut_manager->RegisterShortcut(name, key, std::move(callback));
}
} // namespace
void ConfigureEditorShortcuts(const ShortcutDependencies& deps,
ShortcutManager* shortcut_manager) {
if (!shortcut_manager) {
return;
}
auto* editor_manager = deps.editor_manager;
auto* ui_coordinator = deps.ui_coordinator;
auto* popup_manager = deps.popup_manager;
auto* card_registry = deps.card_registry;
RegisterIfValid(
shortcut_manager, "global.toggle_sidebar",
{ImGuiKey_LeftCtrl, ImGuiKey_B},
[ui_coordinator]() {
if (ui_coordinator) {
ui_coordinator->ToggleCardSidebar();
}
});
RegisterIfValid(shortcut_manager, "Open", {ImGuiMod_Ctrl, ImGuiKey_O},
[editor_manager]() {
if (editor_manager) {
editor_manager->LoadRom();
}
});
RegisterIfValid(shortcut_manager, "Save", {ImGuiMod_Ctrl, ImGuiKey_S},
[editor_manager]() {
if (editor_manager) {
editor_manager->SaveRom();
}
});
RegisterIfValid(shortcut_manager, "Save As",
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_S},
[editor_manager]() {
if (editor_manager) {
// Use project-aware default filename when possible
std::string filename = editor_manager->GetCurrentRom()
? editor_manager->GetCurrentRom()->filename()
: "";
editor_manager->SaveRomAs(filename);
}
});
RegisterIfValid(shortcut_manager, "Close ROM", {ImGuiMod_Ctrl, ImGuiKey_W},
[editor_manager]() {
if (editor_manager && editor_manager->GetCurrentRom()) {
editor_manager->GetCurrentRom()->Close();
}
});
RegisterIfValid(shortcut_manager, "Quit", {ImGuiMod_Ctrl, ImGuiKey_Q},
[editor_manager]() {
if (editor_manager) {
editor_manager->Quit();
}
});
RegisterIfValid(shortcut_manager, "Undo", {ImGuiMod_Ctrl, ImGuiKey_Z},
[editor_manager]() {
if (editor_manager && editor_manager->GetCurrentEditor()) {
editor_manager->GetCurrentEditor()->Undo();
}
});
RegisterIfValid(shortcut_manager, "Redo",
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_Z},
[editor_manager]() {
if (editor_manager && editor_manager->GetCurrentEditor()) {
editor_manager->GetCurrentEditor()->Redo();
}
});
RegisterIfValid(shortcut_manager, "Cut", {ImGuiMod_Ctrl, ImGuiKey_X},
[editor_manager]() {
if (editor_manager && editor_manager->GetCurrentEditor()) {
editor_manager->GetCurrentEditor()->Cut();
}
});
RegisterIfValid(shortcut_manager, "Copy", {ImGuiMod_Ctrl, ImGuiKey_C},
[editor_manager]() {
if (editor_manager && editor_manager->GetCurrentEditor()) {
editor_manager->GetCurrentEditor()->Copy();
}
});
RegisterIfValid(shortcut_manager, "Paste", {ImGuiMod_Ctrl, ImGuiKey_V},
[editor_manager]() {
if (editor_manager && editor_manager->GetCurrentEditor()) {
editor_manager->GetCurrentEditor()->Paste();
}
});
RegisterIfValid(shortcut_manager, "Find", {ImGuiMod_Ctrl, ImGuiKey_F},
[editor_manager]() {
if (editor_manager && editor_manager->GetCurrentEditor()) {
editor_manager->GetCurrentEditor()->Find();
}
});
RegisterIfValid(
shortcut_manager, "Command Palette",
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_P},
[ui_coordinator]() {
if (ui_coordinator) {
ui_coordinator->ShowCommandPalette();
}
});
RegisterIfValid(
shortcut_manager, "Global Search",
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_K},
[ui_coordinator]() {
if (ui_coordinator) {
ui_coordinator->ShowGlobalSearch();
}
});
RegisterIfValid(shortcut_manager, "Load Last ROM",
{ImGuiMod_Ctrl, ImGuiKey_R},
[editor_manager]() {
auto& recent = core::RecentFilesManager::GetInstance();
if (!recent.GetRecentFiles().empty() && editor_manager) {
editor_manager->OpenRomOrProject(
recent.GetRecentFiles().front());
}
});
RegisterIfValid(shortcut_manager, "Show About", ImGuiKey_F1,
[popup_manager]() {
if (popup_manager) {
popup_manager->Show("About");
}
});
auto register_editor_shortcut = [&](EditorType type, ImGuiKey key) {
RegisterIfValid(shortcut_manager,
absl::StrFormat("switch.%d", static_cast<int>(type)),
{ImGuiMod_Ctrl, key},
[editor_manager, type]() {
if (editor_manager) {
editor_manager->SwitchToEditor(type);
}
});
};
register_editor_shortcut(EditorType::kOverworld, ImGuiKey_1);
register_editor_shortcut(EditorType::kDungeon, ImGuiKey_2);
register_editor_shortcut(EditorType::kGraphics, ImGuiKey_3);
register_editor_shortcut(EditorType::kSprite, ImGuiKey_4);
register_editor_shortcut(EditorType::kMessage, ImGuiKey_5);
register_editor_shortcut(EditorType::kMusic, ImGuiKey_6);
register_editor_shortcut(EditorType::kPalette, ImGuiKey_7);
register_editor_shortcut(EditorType::kScreen, ImGuiKey_8);
register_editor_shortcut(EditorType::kAssembly, ImGuiKey_9);
register_editor_shortcut(EditorType::kSettings, ImGuiKey_0);
RegisterIfValid(shortcut_manager, "Editor Selection",
{ImGuiMod_Ctrl, ImGuiKey_E},
[ui_coordinator]() {
if (ui_coordinator) {
ui_coordinator->ShowEditorSelection();
}
});
RegisterIfValid(
shortcut_manager, "Card Browser",
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_B},
[ui_coordinator]() {
if (ui_coordinator) {
ui_coordinator->ShowCardBrowser();
}
});
if (card_registry) {
RegisterIfValid(shortcut_manager, "Show Dungeon Cards",
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_D},
[card_registry]() {
card_registry->ShowAllCardsInCategory("Dungeon");
});
RegisterIfValid(shortcut_manager, "Show Graphics Cards",
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_G},
[card_registry]() {
card_registry->ShowAllCardsInCategory("Graphics");
});
RegisterIfValid(shortcut_manager, "Show Screen Cards",
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_S},
[card_registry]() {
card_registry->ShowAllCardsInCategory("Screen");
});
}
#ifdef YAZE_WITH_GRPC
RegisterIfValid(shortcut_manager, "Agent Editor",
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_A},
[editor_manager]() {
if (editor_manager) {
editor_manager->ShowAIAgent();
}
});
RegisterIfValid(shortcut_manager, "Agent Chat History",
{ImGuiMod_Ctrl, ImGuiKey_H},
[editor_manager]() {
if (editor_manager) {
editor_manager->ShowChatHistory();
}
});
RegisterIfValid(shortcut_manager, "Proposal Drawer",
{ImGuiMod_Ctrl, ImGuiKey_P},
[editor_manager]() {
if (editor_manager) {
editor_manager->ShowProposalDrawer();
}
});
#endif
}
void ConfigureMenuShortcuts(const ShortcutDependencies& deps,
ShortcutManager* shortcut_manager) {
if (!shortcut_manager) {
return;
}
auto* menu_orchestrator = deps.menu_orchestrator;
auto* session_coordinator = deps.session_coordinator;
auto* workspace_manager = deps.workspace_manager;
RegisterIfValid(shortcut_manager, "New Session",
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_N},
[session_coordinator]() {
if (session_coordinator) {
session_coordinator->CreateNewSession();
}
});
RegisterIfValid(shortcut_manager, "Duplicate Session",
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_D},
[session_coordinator]() {
if (session_coordinator) {
session_coordinator->DuplicateCurrentSession();
}
});
RegisterIfValid(shortcut_manager, "Close Session",
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_W},
[session_coordinator]() {
if (session_coordinator) {
session_coordinator->CloseCurrentSession();
}
});
RegisterIfValid(shortcut_manager, "Session Switcher",
{ImGuiMod_Ctrl, ImGuiKey_Tab},
[session_coordinator]() {
if (session_coordinator) {
session_coordinator->ShowSessionSwitcher();
}
});
RegisterIfValid(shortcut_manager, "Save Layout",
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_L},
[workspace_manager]() {
if (workspace_manager) {
workspace_manager->SaveWorkspaceLayout();
}
});
RegisterIfValid(shortcut_manager, "Load Layout",
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_O},
[workspace_manager]() {
if (workspace_manager) {
workspace_manager->LoadWorkspaceLayout();
}
});
RegisterIfValid(shortcut_manager, "Reset Layout",
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_R},
[workspace_manager]() {
if (workspace_manager) {
workspace_manager->ResetWorkspaceLayout();
}
});
RegisterIfValid(shortcut_manager, "Maximize Window", ImGuiKey_F11,
[workspace_manager]() {
if (workspace_manager) {
workspace_manager->MaximizeCurrentWindow();
}
});
#ifdef YAZE_ENABLE_TESTING
RegisterIfValid(shortcut_manager, "Test Dashboard",
{ImGuiMod_Ctrl, ImGuiKey_T},
[menu_orchestrator]() {
if (menu_orchestrator) {
menu_orchestrator->OnShowTestDashboard();
}
});
#endif
}
} // namespace yaze::editor

View File

@@ -0,0 +1,48 @@
#ifndef YAZE_APP_EDITOR_SYSTEM_SHORTCUT_CONFIGURATOR_H_
#define YAZE_APP_EDITOR_SYSTEM_SHORTCUT_CONFIGURATOR_H_
#include <functional>
#include "app/editor/editor.h"
#include "app/editor/system/shortcut_manager.h"
namespace yaze {
namespace editor {
class EditorManager;
class EditorRegistry;
class MenuOrchestrator;
class RomFileManager;
class ProjectManager;
class SessionCoordinator;
class UICoordinator;
class WorkspaceManager;
class PopupManager;
class ToastManager;
class EditorCardRegistry;
struct ShortcutDependencies {
EditorManager* editor_manager = nullptr;
EditorRegistry* editor_registry = nullptr;
MenuOrchestrator* menu_orchestrator = nullptr;
RomFileManager* rom_file_manager = nullptr;
ProjectManager* project_manager = nullptr;
SessionCoordinator* session_coordinator = nullptr;
UICoordinator* ui_coordinator = nullptr;
WorkspaceManager* workspace_manager = nullptr;
PopupManager* popup_manager = nullptr;
ToastManager* toast_manager = nullptr;
EditorCardRegistry* card_registry = nullptr;
};
void ConfigureEditorShortcuts(const ShortcutDependencies& deps,
ShortcutManager* shortcut_manager);
void ConfigureMenuShortcuts(const ShortcutDependencies& deps,
ShortcutManager* shortcut_manager);
} // namespace editor
} // namespace yaze
#endif // YAZE_APP_EDITOR_SYSTEM_SHORTCUT_CONFIGURATOR_H_

View File

@@ -111,7 +111,8 @@ void UICoordinator::DrawAllUI() {
}
void UICoordinator::DrawMenuBarExtras() {
auto* current_rom = rom_manager_.GetCurrentRom();
// Get current ROM from EditorManager (RomFileManager doesn't track "current")
auto* current_rom = editor_manager_->GetCurrentRom();
std::string version_text = absl::StrFormat("v%s", editor_manager_->version().c_str());
float version_width = ImGui::CalcTextSize(version_text.c_str()).x;
float session_rom_area_width = 280.0f;