diff --git a/src/app/editor/editor_library.cmake b/src/app/editor/editor_library.cmake index 09493c4f..facc2e70 100644 --- a/src/app/editor/editor_library.cmake +++ b/src/app/editor/editor_library.cmake @@ -43,11 +43,12 @@ set( app/editor/system/session_card_registry.cc app/editor/system/settings_editor.cc app/editor/system/shortcut_manager.cc + app/editor/system/session_coordinator.cc app/editor/system/user_settings.cc app/editor/system/window_delegate.cc app/editor/ui/editor_selection_dialog.cc app/editor/ui/menu_builder.cc - app/editor/ui/session_coordinator.cc + app/editor/ui/ui_coordinator.cc app/editor/ui/welcome_screen.cc app/editor/ui/workspace_manager.cc ) diff --git a/src/app/editor/editor_manager.cc b/src/app/editor/editor_manager.cc index ab8ecab0..0fc21aca 100644 --- a/src/app/editor/editor_manager.cc +++ b/src/app/editor/editor_manager.cc @@ -7,6 +7,7 @@ #include #include #include +#include "zelda3/screen/dungeon_map.h" #define IMGUI_DEFINE_MATH_OPERATORS @@ -138,6 +139,11 @@ EditorManager::EditorManager() menu_orchestrator_ = std::make_unique( menu_builder_, rom_file_manager_, project_manager_, editor_registry_, *session_coordinator_, toast_manager_); + + // Initialize UICoordinator after all other components are created + ui_coordinator_ = std::make_unique( + this, rom_file_manager_, project_manager_, editor_registry_, + *session_coordinator_, window_delegate_, toast_manager_, *popup_manager_); } EditorManager::~EditorManager() = default; @@ -1041,60 +1047,10 @@ absl::Status EditorManager::DrawRomSelector() { } void EditorManager::DrawContextSensitiveCardControl() { - if (!current_editor_set_ || !current_editor_) { - return; + // Delegate to UICoordinator for clean separation of concerns + if (ui_coordinator_) { + ui_coordinator_->DrawContextSensitiveCardControl(); } - - // Determine which category to show based on active editor - std::string category; - - switch (current_editor_->type()) { - case EditorType::kDungeon: - category = "Dungeon"; - break; - case EditorType::kGraphics: - category = "Graphics"; - break; - case EditorType::kScreen: - category = "Screen"; - break; - case EditorType::kSprite: - category = "Sprite"; - break; - case EditorType::kOverworld: - category = "Overworld"; - break; - case EditorType::kMessage: - category = "Message"; - break; - case EditorType::kPalette: - category = "Palette"; - break; - case EditorType::kAssembly: - // Assembly editor uses dynamic file tabs - return; - case EditorType::kEmulator: - category = "Emulator"; - break; - case EditorType::kMusic: - // Music editor doesn't use cards yet - return; - default: - return; // No cards for this editor type - } - - // Draw compact card control for the active editor's cards with session awareness - auto& card_manager = gui::EditorCardManager::Get(); - if (session_coordinator_ && session_coordinator_->HasMultipleSessions()) { - std::string session_prefix = absl::StrFormat("s%zu", context_.session_id); - card_manager.DrawCompactCardControlWithSession(category, session_prefix); - } else { - card_manager.DrawCompactCardControl(category); - } - - // Show visible/total count - SameLine(); - card_manager.DrawInlineCardToggles(category); } void EditorManager::BuildModernMenu() { @@ -1105,63 +1061,10 @@ void EditorManager::BuildModernMenu() { } void EditorManager::DrawMenuBarExtras() { - auto* current_rom = GetCurrentRom(); - std::string version_text = absl::StrFormat("v%s", version_.c_str()); - float version_width = ImGui::CalcTextSize(version_text.c_str()).x; - float session_rom_area_width = 280.0f; - - SameLine(ImGui::GetWindowWidth() - version_width - 10 - - session_rom_area_width); - - if (session_coordinator_ && session_coordinator_->HasMultipleSessions()) { - if (ImGui::SmallButton( - absl::StrFormat("%s%zu", ICON_MD_TAB, session_coordinator_->GetActiveSessionCount()) - .c_str())) { - session_coordinator_->ToggleSessionSwitcher(); - } - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Sessions: %zu active\nClick to switch", - session_coordinator_->GetActiveSessionCount()); - } - ImGui::SameLine(); + // Delegate to UICoordinator for clean separation of concerns + if (ui_coordinator_) { + ui_coordinator_->DrawMenuBarExtras(); } - - if (current_rom && current_rom->is_loaded()) { - if (ImGui::SmallButton(ICON_MD_APPS)) { - ShowEditorSelection(); - } - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip(ICON_MD_DASHBOARD " Editor Selection (Ctrl+E)"); - } - ImGui::SameLine(); - if (ImGui::SmallButton(ICON_MD_DISPLAY_SETTINGS)) { - ShowDisplaySettings(); - } - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip(ICON_MD_TUNE " Display Settings"); - } - ImGui::SameLine(); - ImGui::Separator(); - ImGui::SameLine(); - } - - if (current_rom && current_rom->is_loaded()) { - std::string rom_display = current_rom->title(); - if (rom_display.length() > 22) { - rom_display = rom_display.substr(0, 19) + "..."; - } - if (ImGui::SmallButton(absl::StrFormat("%s%s", rom_display.c_str(), - current_rom->dirty() ? "*" : "") - .c_str())) { - ImGui::OpenPopup("ROM Details"); - } - } else { - ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "No ROM"); - ImGui::SameLine(); - } - - SameLine(ImGui::GetWindowWidth() - version_width - 10); - ImGui::Text("%s", version_text.c_str()); } void EditorManager::ShowSessionSwitcher() { @@ -1170,13 +1073,25 @@ void EditorManager::ShowSessionSwitcher() { } } +void EditorManager::DrawSessionSwitcher() { + // Delegate to UICoordinator for clean separation of concerns + if (ui_coordinator_) { + ui_coordinator_->DrawSessionSwitcher(); + } +} + void EditorManager::ShowEditorSelection() { - show_editor_selection_ = true; + // Delegate to UICoordinator for clean separation of concerns + if (ui_coordinator_) { + ui_coordinator_->ShowEditorSelection(); + } } void EditorManager::ShowDisplaySettings() { - if (popup_manager_) - popup_manager_->Show("Display Settings"); + // Delegate to UICoordinator for clean separation of concerns + if (ui_coordinator_) { + ui_coordinator_->ShowDisplaySettings(); + } } void EditorManager::DrawMenuBar() { @@ -2030,8 +1945,8 @@ absl::Status EditorManager::CreateNewProject(const std::string& template_name) { auto status = project_manager_.CreateNewProject(template_name); if (status.ok()) { current_project_ = project_manager_.GetCurrentProject(); - // Show project creation dialog - popup_manager_->Show("Create New Project"); + // Show project creation dialog + popup_manager_->Show("Create New Project"); } return status; } @@ -2255,10 +2170,10 @@ void EditorManager::CreateNewSession() { // Wire editor contexts for new session if (!sessions_.empty()) { - RomSession& session = sessions_.back(); - session.editors.set_user_settings(&user_settings_); - for (auto* editor : session.editors.active_editors_) { - editor->set_context(&context_); + RomSession& session = sessions_.back(); + session.editors.set_user_settings(&user_settings_); + for (auto* editor : session.editors.active_editors_) { + editor->set_context(&context_); } } } @@ -2289,9 +2204,9 @@ void EditorManager::DuplicateCurrentSession() { // Wire editor contexts for duplicated session if (!sessions_.empty()) { RomSession& session = sessions_.back(); - for (auto* editor : session.editors.active_editors_) { - editor->set_context(&context_); - } + for (auto* editor : session.editors.active_editors_) { + editor->set_context(&context_); + } } } } @@ -2334,15 +2249,15 @@ void EditorManager::SwitchToSession(size_t index) { // Update current pointers after session switch if (index < sessions_.size()) { - auto& session = sessions_[index]; - current_rom_ = &session.rom; - current_editor_set_ = &session.editors; - - // Update test manager with current ROM for ROM-dependent tests - util::logf("EditorManager: Setting ROM in TestManager - %p ('%s')", - (void*)current_rom_, - current_rom_ ? current_rom_->title().c_str() : "null"); - test::TestManager::Get().SetCurrentRom(current_rom_); + auto& session = sessions_[index]; + current_rom_ = &session.rom; + current_editor_set_ = &session.editors; + + // Update test manager with current ROM for ROM-dependent tests + util::logf("EditorManager: Setting ROM in TestManager - %p ('%s')", + (void*)current_rom_, + current_rom_ ? current_rom_->title().c_str() : "null"); + test::TestManager::Get().SetCurrentRom(current_rom_); } } } @@ -2407,45 +2322,17 @@ void EditorManager::LoadWorkspaceLayout() { } void EditorManager::ShowAllWindows() { - if (!current_editor_set_) - return; - - // Delegate to WindowDelegate for registered windows - window_delegate_.ShowAllWindows(); - - // Also show editor windows - for (auto* editor : current_editor_set_->active_editors_) { - editor->set_active(true); + // Delegate to UICoordinator for clean separation of concerns + if (ui_coordinator_) { + ui_coordinator_->ShowAllWindows(); } - show_imgui_demo_ = true; - show_imgui_metrics_ = true; - show_performance_dashboard_ = true; -#ifdef YAZE_ENABLE_TESTING - show_test_dashboard_ = true; -#endif - - toast_manager_.Show("All windows shown", editor::ToastType::kInfo); } void EditorManager::HideAllWindows() { - if (!current_editor_set_) - return; - - // Delegate to WindowDelegate for registered windows - window_delegate_.HideAllWindows(); - - // Also hide editor windows - for (auto* editor : current_editor_set_->active_editors_) { - editor->set_active(false); + // Delegate to UICoordinator for clean separation of concerns + if (ui_coordinator_) { + ui_coordinator_->HideAllWindows(); } - show_imgui_demo_ = false; - show_imgui_metrics_ = false; - show_performance_dashboard_ = false; -#ifdef YAZE_ENABLE_TESTING - show_test_dashboard_ = false; -#endif - - toast_manager_.Show("All windows hidden", editor::ToastType::kInfo); } void EditorManager::MaximizeCurrentWindow() { @@ -2523,519 +2410,35 @@ void EditorManager::LoadModderLayout() { toast_manager_.Show("Modder layout loaded", editor::ToastType::kSuccess); } -void EditorManager::DrawSessionSwitcher() { - if (!show_session_switcher_) - return; - - ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), - ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); - ImGui::SetNextWindowSize(ImVec2(700, 450), ImGuiCond_Appearing); - - if (ImGui::Begin( - absl::StrFormat("%s Session Switcher", ICON_MD_SWITCH_ACCOUNT) - .c_str(), - &show_session_switcher_, ImGuiWindowFlags_NoCollapse)) { - - // Header with enhanced info - ImGui::Text("%s %zu Sessions Available", ICON_MD_TAB, sessions_.size()); - ImGui::SameLine(ImGui::GetWindowWidth() - 120); - if (ImGui::Button(absl::StrFormat("%s New", ICON_MD_ADD).c_str(), - ImVec2(50, 0))) { - CreateNewSession(); - } - ImGui::SameLine(); - if (ImGui::Button(absl::StrFormat("%s Manager", ICON_MD_SETTINGS).c_str(), - ImVec2(60, 0))) { - show_session_manager_ = true; - } - - ImGui::Separator(); - - // Enhanced session list using table for better layout - const float TABLE_HEIGHT = ImGui::GetContentRegionAvail().y - - 50; // Reserve space for close button - - if (ImGui::BeginTable("SessionSwitcherTable", 4, - ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | - ImGuiTableFlags_SizingStretchProp | - ImGuiTableFlags_ScrollY | - ImGuiTableFlags_Resizable, - ImVec2(0, TABLE_HEIGHT))) { - - // Setup columns with proper sizing weights - ImGui::TableSetupColumn("Session", ImGuiTableColumnFlags_WidthStretch, - 0.3f); - ImGui::TableSetupColumn("ROM Info", ImGuiTableColumnFlags_WidthStretch, - 0.4f); - ImGui::TableSetupColumn("Status", ImGuiTableColumnFlags_WidthFixed, - 90.0f); - ImGui::TableSetupColumn("Actions", ImGuiTableColumnFlags_WidthFixed, - 140.0f); - ImGui::TableHeadersRow(); - - for (size_t i = 0; i < sessions_.size(); ++i) { - auto& session = sessions_[i]; - - // Skip closed sessions - if (session.custom_name == "[CLOSED SESSION]") { - continue; - } - - bool is_current = (&session.rom == current_rom_); - - ImGui::PushID(static_cast(i)); - ImGui::TableNextRow(ImGuiTableRowFlags_None, - 55.0f); // Consistent row height - - // Session name column with better styling - ImGui::TableNextColumn(); - ImGui::AlignTextToFramePadding(); - - if (is_current) { - ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.2f, 0.8f, 0.2f, 1.0f)); - ImGui::Text("%s %s", ICON_MD_STAR, session.GetDisplayName().c_str()); - ImGui::PopStyleColor(); - } else { - ImGui::Text("%s %s", ICON_MD_TAB, session.GetDisplayName().c_str()); - } - - // ROM info column with better information layout - ImGui::TableNextColumn(); - ImGui::AlignTextToFramePadding(); - - if (session.rom.is_loaded()) { - ImGui::Text("%s %s", ICON_MD_VIDEOGAME_ASSET, - session.rom.title().c_str()); - ImGui::Text("%.1f MB | %s", session.rom.size() / 1048576.0f, - session.rom.dirty() ? "Modified" : "Clean"); - } else { - ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), "%s No ROM loaded", - ICON_MD_WARNING); - } - - // Status column with better visual indicators - ImGui::TableNextColumn(); - ImGui::AlignTextToFramePadding(); - - if (session.rom.is_loaded()) { - if (session.rom.dirty()) { - ImGui::TextColored(ImVec4(1.0f, 0.5f, 0.0f, 1.0f), "%s", - ICON_MD_EDIT); - } else { - ImGui::TextColored(ImVec4(0.2f, 0.8f, 0.2f, 1.0f), "%s", - ICON_MD_CHECK_CIRCLE); - } - } else { - ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), "%s", - ICON_MD_RADIO_BUTTON_UNCHECKED); - } - - // Actions column with improved button layout - ImGui::TableNextColumn(); - - // Create button group for better alignment - ImGui::BeginGroup(); - - if (!is_current) { - if (ImGui::Button("Switch")) { - SwitchToSession(i); - show_session_switcher_ = false; - } - } else { - ImGui::BeginDisabled(); - ImGui::Button("Current"); - ImGui::EndDisabled(); - } - - ImGui::SameLine(); - if (ImGui::Button("Rename")) { - session_to_rename_ = i; - // Safe string copy with bounds checking - const std::string& name = session.GetDisplayName(); - size_t copy_len = - std::min(name.length(), sizeof(session_rename_buffer_) - 1); - std::memcpy(session_rename_buffer_, name.c_str(), copy_len); - session_rename_buffer_[copy_len] = '\0'; - show_session_rename_dialog_ = true; - } - - ImGui::SameLine(); - - // Close button logic - bool can_close = GetActiveSessionCount() > 1; - if (!can_close) { - ImGui::BeginDisabled(); - } - - if (ImGui::Button("Close")) { - if (is_current) { - CloseCurrentSession(); - } else { - // Remove non-current session directly - RemoveSession(i); - show_session_switcher_ = - false; // Close switcher since indices changed - } - } - - if (!can_close) { - ImGui::EndDisabled(); - } - - ImGui::EndGroup(); - - ImGui::PopID(); - } - - ImGui::EndTable(); - } - - ImGui::Separator(); - if (ImGui::Button( - absl::StrFormat("%s Close Switcher", ICON_MD_CLOSE).c_str(), - ImVec2(-1, 0))) { - show_session_switcher_ = false; - } +void EditorManager::DrawWelcomeScreen() { + // Delegate to UICoordinator for clean separation of concerns + if (ui_coordinator_) { + ui_coordinator_->DrawWelcomeScreen(); } - ImGui::End(); } void EditorManager::DrawSessionManager() { - if (!show_session_manager_) - return; - - if (ImGui::Begin(absl::StrCat(ICON_MD_VIEW_LIST, " Session Manager").c_str(), - &show_session_manager_)) { - - ImGui::Text("%s Session Management", ICON_MD_MANAGE_ACCOUNTS); - - if (ImGui::Button(absl::StrCat(ICON_MD_ADD, " New Session").c_str())) { - CreateNewSession(); - } - ImGui::SameLine(); - if (ImGui::Button( - absl::StrCat(ICON_MD_CONTENT_COPY, " Duplicate Current").c_str()) && - current_rom_) { - DuplicateCurrentSession(); - } - - ImGui::Separator(); - ImGui::Text("%s Active Sessions (%zu)", ICON_MD_TAB, - GetActiveSessionCount()); - - // Enhanced session management table with proper sizing - const float AVAILABLE_HEIGHT = ImGui::GetContentRegionAvail().y; - - if (ImGui::BeginTable("SessionTable", 6, - ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | - ImGuiTableFlags_Resizable | - ImGuiTableFlags_ScrollY | - ImGuiTableFlags_SizingStretchProp | - ImGuiTableFlags_ContextMenuInBody, - ImVec2(0, AVAILABLE_HEIGHT))) { - - // Setup columns with explicit sizing for better control - ImGui::TableSetupColumn("Session", ImGuiTableColumnFlags_WidthStretch, - 0.15f); - ImGui::TableSetupColumn("ROM Title", ImGuiTableColumnFlags_WidthStretch, - 0.3f); - ImGui::TableSetupColumn("Size", ImGuiTableColumnFlags_WidthFixed, 70.0f); - ImGui::TableSetupColumn("Status", ImGuiTableColumnFlags_WidthFixed, - 80.0f); - ImGui::TableSetupColumn("Custom OW", ImGuiTableColumnFlags_WidthFixed, - 80.0f); - ImGui::TableSetupColumn("Actions", ImGuiTableColumnFlags_WidthStretch, - 0.25f); - ImGui::TableHeadersRow(); - - for (size_t i = 0; i < sessions_.size(); ++i) { - auto& session = sessions_[i]; - - // Skip closed sessions in session manager too - if (session.custom_name == "[CLOSED SESSION]") { - continue; - } - - bool is_current = (&session.rom == current_rom_); - - ImGui::TableNextRow(ImGuiTableRowFlags_None, - 50.0f); // Consistent row height - ImGui::PushID(static_cast(i)); - - // Session name column - ImGui::TableNextColumn(); - ImGui::AlignTextToFramePadding(); - if (is_current) { - ImGui::TextColored(ImVec4(0.2f, 0.8f, 0.2f, 1.0f), "%s Session %zu", - ICON_MD_STAR, i + 1); - } else { - ImGui::Text("%s Session %zu", ICON_MD_TAB, i + 1); - } - - // ROM title column - ImGui::TableNextColumn(); - ImGui::AlignTextToFramePadding(); - std::string display_name = session.GetDisplayName(); - if (!session.custom_name.empty()) { - ImGui::TextColored(ImVec4(0.7f, 0.9f, 1.0f, 1.0f), "%s %s", - ICON_MD_EDIT, display_name.c_str()); - } else { - // Use TextWrapped for long ROM titles - ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + - ImGui::GetColumnWidth()); - ImGui::Text("%s", display_name.c_str()); - ImGui::PopTextWrapPos(); - } - - // File size column - ImGui::TableNextColumn(); - ImGui::AlignTextToFramePadding(); - if (session.rom.is_loaded()) { - ImGui::Text("%.1f MB", session.rom.size() / 1048576.0f); - } else { - ImGui::TextDisabled("N/A"); - } - - // Status column - ImGui::TableNextColumn(); - ImGui::AlignTextToFramePadding(); - if (session.rom.is_loaded()) { - if (session.rom.dirty()) { - ImGui::TextColored(ImVec4(1.0f, 0.5f, 0.0f, 1.0f), "%s", - ICON_MD_EDIT); - } else { - ImGui::TextColored(ImVec4(0.2f, 0.8f, 0.2f, 1.0f), "%s", - ICON_MD_CHECK_CIRCLE); - } - } else { - ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), "%s", - ICON_MD_RADIO_BUTTON_UNCHECKED); - } - - // Custom Overworld checkbox column - ImGui::TableNextColumn(); - - // Center the checkbox vertically - float checkbox_offset = - (ImGui::GetFrameHeight() - ImGui::GetTextLineHeight()) * 0.5f; - ImGui::SetCursorPosY(ImGui::GetCursorPosY() + checkbox_offset); - - ImGui::PushID( - static_cast(i + 100)); // Different ID to avoid conflicts - bool custom_ow_enabled = - session.feature_flags.overworld.kLoadCustomOverworld; - if (ImGui::Checkbox("##CustomOW", &custom_ow_enabled)) { - session.feature_flags.overworld.kLoadCustomOverworld = - custom_ow_enabled; - if (is_current) { - core::FeatureFlags::get().overworld.kLoadCustomOverworld = - custom_ow_enabled; - } - toast_manager_.Show( - absl::StrFormat("Session %zu: Custom Overworld %s", i + 1, - custom_ow_enabled ? "Enabled" : "Disabled"), - editor::ToastType::kInfo); - } - ImGui::PopID(); - - // Actions column with better button layout - ImGui::TableNextColumn(); - - // Create button group for better alignment - ImGui::BeginGroup(); - - if (!is_current) { - if (ImGui::Button("Switch")) { - SwitchToSession(i); - } - } else { - ImGui::BeginDisabled(); - ImGui::Button("Current"); - ImGui::EndDisabled(); - } - - ImGui::SameLine(); - if (ImGui::Button("Rename")) { - session_to_rename_ = i; - // Safe string copy with bounds checking - const std::string& name = session.GetDisplayName(); - size_t copy_len = - std::min(name.length(), sizeof(session_rename_buffer_) - 1); - std::memcpy(session_rename_buffer_, name.c_str(), copy_len); - session_rename_buffer_[copy_len] = '\0'; - show_session_rename_dialog_ = true; - } - - ImGui::SameLine(); - - // Close button logic - bool can_close = GetActiveSessionCount() > 1; - if (!can_close || is_current) { - ImGui::BeginDisabled(); - } - - if (ImGui::Button("Close")) { - if (is_current) { - CloseCurrentSession(); - break; // Exit loop since current session was closed - } else { - // Remove non-current session directly - RemoveSession(i); - break; // Exit loop since session indices changed - } - } - - if (!can_close || is_current) { - ImGui::EndDisabled(); - } - - ImGui::EndGroup(); - - ImGui::PopID(); - } - - ImGui::EndTable(); - } - } - ImGui::End(); -} - -void EditorManager::DrawLayoutPresets() { - if (!show_layout_presets_) - return; - - if (ImGui::Begin(absl::StrCat(ICON_MD_BOOKMARK, " Layout Presets").c_str(), - &show_layout_presets_)) { - - ImGui::Text("%s Predefined Layouts", ICON_MD_DASHBOARD); - - // Predefined layouts - if (ImGui::Button( - absl::StrCat(ICON_MD_DEVELOPER_MODE, " Developer Layout").c_str(), - ImVec2(-1, 40))) { - LoadDeveloperLayout(); - } - ImGui::SameLine(); - ImGui::Text("Code editing, debugging, testing"); - - if (ImGui::Button( - absl::StrCat(ICON_MD_DESIGN_SERVICES, " Designer Layout").c_str(), - ImVec2(-1, 40))) { - LoadDesignerLayout(); - } - ImGui::SameLine(); - ImGui::Text("Graphics, palettes, sprites"); - - if (ImGui::Button(absl::StrCat(ICON_MD_GAMEPAD, " Modder Layout").c_str(), - ImVec2(-1, 40))) { - LoadModderLayout(); - } - ImGui::SameLine(); - ImGui::Text("All gameplay editors"); - - ImGui::Separator(); - ImGui::Text("%s Custom Presets", ICON_MD_BOOKMARK); - - // Lazy load workspace presets when UI is accessed - if (!workspace_manager_.workspace_presets_loaded()) { - RefreshWorkspacePresets(); - } - - for (const auto& preset : workspace_manager_.workspace_presets()) { - if (ImGui::Button( - absl::StrFormat("%s %s", ICON_MD_BOOKMARK, preset.c_str()) - .c_str(), - ImVec2(-1, 0))) { - LoadWorkspacePreset(preset); - toast_manager_.Show( - absl::StrFormat("Loaded preset: %s", preset.c_str()), - editor::ToastType::kSuccess); - } - } - - if (workspace_manager_.workspace_presets().empty()) { - ImGui::TextColored(ImVec4(0.6f, 0.6f, 0.6f, 1.0f), - "No custom presets saved"); - } - - ImGui::Separator(); - if (ImGui::Button( - absl::StrCat(ICON_MD_ADD, " Save Current Layout").c_str())) { - show_save_workspace_preset_ = true; - } - } - ImGui::End(); -} - -bool EditorManager::HasDuplicateSession(const std::string& filepath) { - for (const auto& session : sessions_) { - if (session.filepath == filepath) { - return true; - } - } - return false; -} - -void EditorManager::RenameSession(size_t index, const std::string& new_name) { - if (index < sessions_.size()) { - sessions_[index].custom_name = new_name; - toast_manager_.Show( - absl::StrFormat("Session renamed to: %s", new_name.c_str()), - editor::ToastType::kSuccess); + // Delegate to UICoordinator for clean separation of concerns + if (ui_coordinator_) { + ui_coordinator_->DrawSessionManager(); } } void EditorManager::DrawSessionRenameDialog() { - if (!show_session_rename_dialog_) - return; - - ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), - ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); - ImGui::SetNextWindowSize(ImVec2(400, 150), ImGuiCond_Appearing); - - if (ImGui::Begin("Rename Session", &show_session_rename_dialog_, - ImGuiWindowFlags_NoResize)) { - if (session_to_rename_ < sessions_.size()) { - const auto& session = sessions_[session_to_rename_]; - - ImGui::Text("Rename Session:"); - ImGui::Text("Current: %s", session.GetDisplayName().c_str()); - ImGui::Separator(); - - ImGui::InputText("New Name", session_rename_buffer_, - sizeof(session_rename_buffer_)); - - ImGui::Separator(); - if (ImGui::Button("Rename", ImVec2(120, 0))) { - std::string new_name(session_rename_buffer_); - if (!new_name.empty()) { - RenameSession(session_to_rename_, new_name); - } - show_session_rename_dialog_ = false; - } - - ImGui::SameLine(); - if (ImGui::Button("Cancel", ImVec2(120, 0))) { - show_session_rename_dialog_ = false; - } - } - } - ImGui::End(); -} - -void EditorManager::DrawWelcomeScreen() { - // Use the new WelcomeScreen class for a modern, feature-rich experience - welcome_screen_.RefreshRecentProjects(); - bool was_open = show_welcome_screen_; - bool action_taken = welcome_screen_.Show(&show_welcome_screen_); - - // Check if the welcome screen was manually closed via the close button - if (was_open && !show_welcome_screen_) { - welcome_screen_manually_closed_ = true; - welcome_screen_.MarkManuallyClosed(); + // Delegate to UICoordinator for clean separation of concerns + if (ui_coordinator_) { + ui_coordinator_->DrawSessionRenameDialog(); } } +void EditorManager::DrawLayoutPresets() { + // Delegate to UICoordinator for clean separation of concerns + if (ui_coordinator_) { + ui_coordinator_->DrawLayoutPresets(); + } +} + + // ============================================================================ // Jump-to Functionality for Cross-Editor Navigation // ============================================================================ @@ -3148,5 +2551,14 @@ EditorManager::SessionScope::~SessionScope() { manager_->context_.session_id = prev_session_id_; } +bool EditorManager::HasDuplicateSession(const std::string& filepath) { + for (const auto& session : sessions_) { + if (session.filepath == filepath) { + return true; + } + } + return false; +} + } // namespace editor } // namespace yaze diff --git a/src/app/editor/editor_manager.h b/src/app/editor/editor_manager.h index 5c407839..20f9835b 100644 --- a/src/app/editor/editor_manager.h +++ b/src/app/editor/editor_manager.h @@ -41,9 +41,10 @@ #include "app/editor/system/project_manager.h" #include "app/editor/system/rom_file_manager.h" #include "app/editor/system/session_card_registry.h" +#include "app/editor/system/session_coordinator.h" #include "app/editor/system/window_delegate.h" -#include "app/editor/ui/session_coordinator.h" #include "app/editor/ui/editor_selection_dialog.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" @@ -359,6 +360,7 @@ class EditorManager { ProjectManager project_manager_; RomFileManager rom_file_manager_; SessionCardRegistry card_registry_; + std::unique_ptr ui_coordinator_; WindowDelegate window_delegate_; std::unique_ptr session_coordinator_; diff --git a/src/app/editor/system/menu_orchestrator.cc b/src/app/editor/system/menu_orchestrator.cc index 5beea66a..85842abc 100644 --- a/src/app/editor/system/menu_orchestrator.cc +++ b/src/app/editor/system/menu_orchestrator.cc @@ -7,7 +7,7 @@ #include "app/editor/system/rom_file_manager.h" #include "app/editor/system/toast_manager.h" #include "app/editor/ui/menu_builder.h" -#include "app/editor/ui/session_coordinator.h" +#include "app/editor/system/session_coordinator.h" #include "app/gui/core/icons.h" namespace yaze { diff --git a/src/app/editor/system/menu_orchestrator.h b/src/app/editor/system/menu_orchestrator.h index 85878d2d..80f0c5e9 100644 --- a/src/app/editor/system/menu_orchestrator.h +++ b/src/app/editor/system/menu_orchestrator.h @@ -6,6 +6,7 @@ #include "absl/status/status.h" #include "app/editor/editor.h" +#include "app/editor/system/session_coordinator.h" #include "app/editor/ui/menu_builder.h" namespace yaze { diff --git a/src/app/editor/ui/session_coordinator.cc b/src/app/editor/system/session_coordinator.cc similarity index 100% rename from src/app/editor/ui/session_coordinator.cc rename to src/app/editor/system/session_coordinator.cc diff --git a/src/app/editor/ui/session_coordinator.h b/src/app/editor/system/session_coordinator.h similarity index 96% rename from src/app/editor/ui/session_coordinator.h rename to src/app/editor/system/session_coordinator.h index 2298407e..b69929d6 100644 --- a/src/app/editor/ui/session_coordinator.h +++ b/src/app/editor/system/session_coordinator.h @@ -1,5 +1,5 @@ -#ifndef YAZE_APP_EDITOR_UI_SESSION_COORDINATOR_H_ -#define YAZE_APP_EDITOR_UI_SESSION_COORDINATOR_H_ +#ifndef YAZE_APP_EDITOR_SYSTEM_SESSION_COORDINATOR_H_ +#define YAZE_APP_EDITOR_SYSTEM_SESSION_COORDINATOR_H_ #include #include @@ -161,4 +161,4 @@ class SessionCoordinator { } // namespace editor } // namespace yaze -#endif // YAZE_APP_EDITOR_UI_SESSION_COORDINATOR_H_ +#endif // YAZE_APP_EDITOR_SYSTEM_SESSION_COORDINATOR_H_ diff --git a/src/app/editor/system/ui_coordinator.cc b/src/app/editor/system/ui_coordinator.cc new file mode 100644 index 00000000..fc5f0f87 --- /dev/null +++ b/src/app/editor/system/ui_coordinator.cc @@ -0,0 +1,492 @@ +#include "ui_coordinator.h" + +#include +#include +#include + +#include "absl/strings/str_format.h" +#include "app/editor/editor.h" +#include "app/editor/editor_manager.h" +#include "app/editor/system/editor_registry.h" +#include "app/editor/system/popup_manager.h" +#include "app/editor/system/project_manager.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/system/window_delegate.h" +#include "app/editor/ui/welcome_screen.h" +#include "app/gui/core/icons.h" +#include "app/gui/core/style.h" +#include "app/gui/core/theme_manager.h" +#include "imgui/imgui.h" + +namespace yaze { +namespace editor { + +UICoordinator::UICoordinator( + EditorManager* editor_manager, + RomFileManager& rom_manager, + ProjectManager& project_manager, + EditorRegistry& editor_registry, + SessionCoordinator& session_coordinator, + WindowDelegate& window_delegate, + ToastManager& toast_manager, + PopupManager& popup_manager) + : editor_manager_(editor_manager), + rom_manager_(rom_manager), + project_manager_(project_manager), + editor_registry_(editor_registry), + session_coordinator_(session_coordinator), + window_delegate_(window_delegate), + toast_manager_(toast_manager), + popup_manager_(popup_manager) { + + // Initialize welcome screen + welcome_screen_ = std::make_unique(); +} + +void UICoordinator::DrawAllUI() { + // Apply Material Design styling + ApplyMaterialDesignStyling(); + + // Draw all UI components in order + DrawMenuBarExtras(); + DrawContextSensitiveCardControl(); + DrawSessionSwitcher(); + DrawSessionManager(); + DrawSessionRenameDialog(); + DrawLayoutPresets(); + DrawWelcomeScreen(); + DrawProjectHelp(); + DrawWindowManagementUI(); + + // Draw all popups + DrawAllPopups(); +} + +void UICoordinator::DrawMenuBarExtras() { + auto* current_rom = rom_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; + + ImGui::SameLine(ImGui::GetWindowWidth() - version_width - 10 - session_rom_area_width); + + // Session indicator with Material Design styling + if (session_coordinator_.HasMultipleSessions()) { + std::string session_button_text = absl::StrFormat("%s%zu", ICON_MD_TAB, + session_coordinator_.GetActiveSessionCount()); + + // Material Design button styling + ImGui::PushStyleColor(ImGuiCol_Button, gui::GetPrimaryVec4()); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, gui::GetPrimaryHoverVec4()); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, gui::GetPrimaryActiveVec4()); + + if (ImGui::SmallButton(session_button_text.c_str())) { + session_coordinator_.ToggleSessionSwitcher(); + } + + ImGui::PopStyleColor(3); + + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Sessions: %zu active\nClick to switch", + session_coordinator_.GetActiveSessionCount()); + } + ImGui::SameLine(); + } + + // ROM information display with Material Design card styling + if (current_rom && current_rom->is_loaded()) { + ImGui::PushStyleColor(ImGuiCol_Text, gui::GetTextSecondaryVec4()); + ImGui::Text("%s %s", ICON_MD_INSERT_DRIVE_FILE, current_rom->title().c_str()); + ImGui::PopStyleColor(); + ImGui::SameLine(); + } + + // Version info with subtle styling + ImGui::PushStyleColor(ImGuiCol_Text, gui::GetTextDisabledVec4()); + ImGui::Text("%s", version_text.c_str()); + ImGui::PopStyleColor(); +} + +void UICoordinator::DrawContextSensitiveCardControl() { + // Get current editor and determine category + auto* current_editor = editor_manager_->GetCurrentEditorSet(); + if (!current_editor) return; + + // Find active card-based editor + Editor* active_editor = nullptr; + for (auto* editor : current_editor->active_editors_) { + if (*editor->active() && editor_registry_.IsCardBasedEditor(editor->type())) { + active_editor = editor; + break; + } + } + + if (!active_editor) return; + + std::string category = editor_registry_.GetEditorCategory(active_editor->type()); + + // 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); + } +} + +void UICoordinator::DrawSessionSwitcher() { + if (!show_session_switcher_) return; + + // Material Design dialog styling + ImGui::SetNextWindowSize(ImVec2(400, 300), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(16, 16)); + ImGui::PushStyleColor(ImGuiCol_WindowBg, gui::GetSurfaceVec4()); + ImGui::PushStyleColor(ImGuiCol_Border, gui::GetOutlineVec4()); + + if (ImGui::Begin("Session Switcher", &show_session_switcher_, + ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse)) { + + // Header with Material Design typography + ImGui::PushStyleColor(ImGuiCol_Text, gui::GetOnSurfaceVec4()); + ImGui::Text("%s Session Switcher", ICON_MD_TAB); + ImGui::PopStyleColor(); + ImGui::Separator(); + + // Session list with Material Design list styling + for (size_t i = 0; i < session_coordinator_.GetActiveSessionCount(); ++i) { + std::string session_name = session_coordinator_.GetSessionDisplayName(i); + bool is_active = (i == session_coordinator_.GetActiveSessionIndex()); + + // Active session highlighting + if (is_active) { + ImGui::PushStyleColor(ImGuiCol_Button, gui::GetPrimaryVec4()); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, gui::GetPrimaryHoverVec4()); + ImGui::PushStyleColor(ImGuiCol_Text, gui::GetOnPrimaryVec4()); + } + + std::string button_text = absl::StrFormat("%s %s", + is_active ? ICON_MD_RADIO_BUTTON_CHECKED : ICON_MD_RADIO_BUTTON_UNCHECKED, + session_name.c_str()); + + if (ImGui::Button(button_text.c_str(), ImVec2(-1, 0))) { + session_coordinator_.SwitchToSession(i); + show_session_switcher_ = false; + } + + if (is_active) { + ImGui::PopStyleColor(3); + } + } + + ImGui::Separator(); + + // Action buttons with Material Design styling + if (ImGui::Button(absl::StrFormat("%s New Session", ICON_MD_ADD).c_str(), ImVec2(-1, 0))) { + session_coordinator_.CreateNewSession(); + show_session_switcher_ = false; + } + + if (ImGui::Button(absl::StrFormat("%s Close", ICON_MD_CLOSE).c_str(), ImVec2(-1, 0))) { + show_session_switcher_ = false; + } + } + + ImGui::End(); + ImGui::PopStyleColor(2); + ImGui::PopStyleVar(); +} + +void UICoordinator::DrawSessionManager() { + // TODO: Implement session manager dialog + // This would be a more comprehensive session management interface +} + +void UICoordinator::DrawSessionRenameDialog() { + // TODO: Implement session rename dialog + // This would allow users to rename sessions for better organization +} + +void UICoordinator::DrawLayoutPresets() { + // TODO: Implement layout presets UI + // This would show available layout presets (Developer, Designer, Modder) +} + +void UICoordinator::DrawWelcomeScreen() { + if (!show_welcome_screen_) return; + + if (welcome_screen_) { + welcome_screen_->Show(&show_welcome_screen_); + } +} + +void UICoordinator::DrawProjectHelp() { + // TODO: Implement project help UI + // This would show project-specific help and documentation +} + +void UICoordinator::DrawWindowManagementUI() { + // TODO: Implement window management UI + // This would provide controls for window visibility, docking, etc. +} + +void UICoordinator::DrawAllPopups() { + // Draw all registered popups + popup_manager_.DrawPopups(); +} + +void UICoordinator::ShowPopup(const std::string& popup_name) { + popup_manager_.Show(popup_name.c_str()); +} + +void UICoordinator::HidePopup(const std::string& popup_name) { + popup_manager_.Hide(popup_name.c_str()); +} + +void UICoordinator::ShowEditorSelection() { + show_editor_selection_ = true; +} + +void UICoordinator::ShowDisplaySettings() { + show_display_settings_ = true; + ShowPopup("Display Settings"); +} + +void UICoordinator::ShowSessionSwitcher() { + show_session_switcher_ = true; +} + +void UICoordinator::HideCurrentEditorCards() { + // TODO: Implement card hiding logic + // This would hide cards for the current editor +} + +void UICoordinator::ShowAllWindows() { + window_delegate_.ShowAllWindows(); +} + +void UICoordinator::HideAllWindows() { + window_delegate_.HideAllWindows(); +} + +void UICoordinator::ApplyMaterialDesignStyling() { + // Apply Material Design 3 color scheme + ImGuiStyle& style = ImGui::GetStyle(); + + // Set Material Design colors + style.Colors[ImGuiCol_WindowBg] = gui::GetSurfaceVec4(); + style.Colors[ImGuiCol_ChildBg] = gui::GetSurfaceVariantVec4(); + style.Colors[ImGuiCol_PopupBg] = gui::GetSurfaceContainerVec4(); + style.Colors[ImGuiCol_Border] = gui::GetOutlineVec4(); + style.Colors[ImGuiCol_BorderShadow] = gui::GetShadowVec4(); + + // Text colors + style.Colors[ImGuiCol_Text] = gui::GetOnSurfaceVec4(); + style.Colors[ImGuiCol_TextDisabled] = gui::GetOnSurfaceVariantVec4(); + + // Button colors + style.Colors[ImGuiCol_Button] = gui::GetSurfaceContainerHighestVec4(); + style.Colors[ImGuiCol_ButtonHovered] = gui::GetSurfaceContainerHighVec4(); + style.Colors[ImGuiCol_ButtonActive] = gui::GetPrimaryVec4(); + + // Header colors + style.Colors[ImGuiCol_Header] = gui::GetSurfaceContainerHighVec4(); + style.Colors[ImGuiCol_HeaderHovered] = gui::GetSurfaceContainerHighestVec4(); + style.Colors[ImGuiCol_HeaderActive] = gui::GetPrimaryVec4(); + + // Frame colors + style.Colors[ImGuiCol_FrameBg] = gui::GetSurfaceContainerHighestVec4(); + style.Colors[ImGuiCol_FrameBgHovered] = gui::GetSurfaceContainerHighVec4(); + style.Colors[ImGuiCol_FrameBgActive] = gui::GetPrimaryVec4(); + + // Scrollbar colors + style.Colors[ImGuiCol_ScrollbarBg] = gui::GetSurfaceContainerVec4(); + style.Colors[ImGuiCol_ScrollbarGrab] = gui::GetOutlineVec4(); + style.Colors[ImGuiCol_ScrollbarGrabHovered] = gui::GetOnSurfaceVariantVec4(); + style.Colors[ImGuiCol_ScrollbarGrabActive] = gui::GetOnSurfaceVec4(); + + // Slider colors + style.Colors[ImGuiCol_SliderGrab] = gui::GetPrimaryVec4(); + style.Colors[ImGuiCol_SliderGrabActive] = gui::GetPrimaryActiveVec4(); + + // Tab colors + style.Colors[ImGuiCol_Tab] = gui::GetSurfaceContainerHighVec4(); + style.Colors[ImGuiCol_TabHovered] = gui::GetSurfaceContainerHighestVec4(); + style.Colors[ImGuiCol_TabActive] = gui::GetPrimaryVec4(); + style.Colors[ImGuiCol_TabUnfocused] = gui::GetSurfaceContainerVec4(); + style.Colors[ImGuiCol_TabUnfocusedActive] = gui::GetPrimaryActiveVec4(); + + // Title bar colors + style.Colors[ImGuiCol_TitleBg] = gui::GetSurfaceContainerVec4(); + style.Colors[ImGuiCol_TitleBgActive] = gui::GetSurfaceContainerHighVec4(); + style.Colors[ImGuiCol_TitleBgCollapsed] = gui::GetSurfaceContainerVec4(); + + // Menu bar colors + style.Colors[ImGuiCol_MenuBarBg] = gui::GetSurfaceContainerVec4(); + + // Modal dimming + style.Colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.0f, 0.0f, 0.0f, 0.6f); +} + +void UICoordinator::UpdateThemeElements() { + // Update theme-specific elements + ApplyMaterialDesignStyling(); +} + +void UICoordinator::DrawThemePreview() { + // TODO: Implement theme preview + // This would show a preview of the current theme +} + +// Helper methods for drawing operations +void UICoordinator::DrawSessionIndicator() { + // TODO: Implement session indicator +} + +void UICoordinator::DrawVersionInfo() { + // TODO: Implement version info display +} + +void UICoordinator::DrawSessionTabs() { + // TODO: Implement session tabs +} + +void UICoordinator::DrawSessionBadges() { + // TODO: Implement session badges +} + +// Material Design component helpers +void UICoordinator::DrawMaterialButton(const std::string& text, const std::string& icon, + std::function callback, bool enabled) { + if (!enabled) { + ImGui::PushStyleColor(ImGuiCol_Button, gui::GetSurfaceContainerHighestVec4()); + ImGui::PushStyleColor(ImGuiCol_Text, gui::GetOnSurfaceVariantVec4()); + } + + std::string button_text = absl::StrFormat("%s %s", icon.c_str(), text.c_str()); + if (ImGui::Button(button_text.c_str())) { + if (enabled && callback) { + callback(); + } + } + + if (!enabled) { + ImGui::PopStyleColor(2); + } +} + +void UICoordinator::DrawMaterialCard(const std::string& title, const std::string& content) { + // TODO: Implement Material Design card component +} + +void UICoordinator::DrawMaterialDialog(const std::string& title, std::function content) { + // TODO: Implement Material Design dialog component +} + +// Layout and positioning helpers +void UICoordinator::CenterWindow(const std::string& window_name) { + ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); +} + +void UICoordinator::PositionWindow(const std::string& window_name, float x, float y) { + ImGui::SetNextWindowPos(ImVec2(x, y), ImGuiCond_Appearing); +} + +void UICoordinator::SetWindowSize(const std::string& window_name, float width, float height) { + ImGui::SetNextWindowSize(ImVec2(width, height), ImGuiCond_FirstUseEver); +} + +// Icon and theming helpers +std::string UICoordinator::GetIconForEditor(EditorType type) const { + switch (type) { + case EditorType::kDungeon: return ICON_MD_CASTLE; + case EditorType::kOverworld: return ICON_MD_MAP; + case EditorType::kGraphics: return ICON_MD_IMAGE; + case EditorType::kPalette: return ICON_MD_PALETTE; + case EditorType::kSprite: return ICON_MD_TOYS; + case EditorType::kScreen: return ICON_MD_TV; + case EditorType::kMessage: return ICON_MD_CHAT_BUBBLE; + case EditorType::kMusic: return ICON_MD_MUSIC_NOTE; + case EditorType::kAssembly: return ICON_MD_CODE; + case EditorType::kHex: return ICON_MD_DATA_ARRAY; + case EditorType::kEmulator: return ICON_MD_PLAY_ARROW; + case EditorType::kSettings: return ICON_MD_SETTINGS; + default: return ICON_MD_HELP; + } +} + +std::string UICoordinator::GetColorForEditor(EditorType type) const { + // TODO: Implement editor-specific colors + return "primary"; // Placeholder for now +} + +void UICoordinator::ApplyEditorTheme(EditorType type) { + // TODO: Implement editor-specific theming +} + +// Session UI helpers +void UICoordinator::DrawSessionList() { + // TODO: Implement session list +} + +void UICoordinator::DrawSessionControls() { + // TODO: Implement session controls +} + +void UICoordinator::DrawSessionInfo() { + // TODO: Implement session info +} + +void UICoordinator::DrawSessionStatus() { + // TODO: Implement session status +} + +// Popup helpers +void UICoordinator::DrawHelpMenuPopups() { + // TODO: Implement help menu popups +} + +void UICoordinator::DrawSettingsPopups() { + // TODO: Implement settings popups +} + +void UICoordinator::DrawProjectPopups() { + // TODO: Implement project popups +} + +void UICoordinator::DrawSessionPopups() { + // TODO: Implement session popups +} + +// Window management helpers +void UICoordinator::DrawWindowControls() { + // TODO: Implement window controls +} + +void UICoordinator::DrawLayoutControls() { + // TODO: Implement layout controls +} + +void UICoordinator::DrawDockingControls() { + // TODO: Implement docking controls +} + +// Performance and debug UI +void UICoordinator::DrawPerformanceUI() { + // TODO: Implement performance UI +} + +void UICoordinator::DrawDebugUI() { + // TODO: Implement debug UI +} + +void UICoordinator::DrawTestingUI() { + // TODO: Implement testing UI +} + +} // namespace editor +} // namespace yaze diff --git a/src/app/editor/system/ui_coordinator.h b/src/app/editor/system/ui_coordinator.h new file mode 100644 index 00000000..6665e4f6 --- /dev/null +++ b/src/app/editor/system/ui_coordinator.h @@ -0,0 +1,181 @@ +#ifndef YAZE_APP_EDITOR_SYSTEM_UI_COORDINATOR_H_ +#define YAZE_APP_EDITOR_SYSTEM_UI_COORDINATOR_H_ + +#include +#include + +#include "absl/status/status.h" +#include "app/editor/editor.h" +#include "app/editor/system/popup_manager.h" +#include "app/editor/system/session_coordinator.h" +#include "app/editor/ui/welcome_screen.h" +#include "app/gui/core/icons.h" + +namespace yaze { +namespace editor { + +// Forward declarations to avoid circular dependencies +class EditorManager; +class RomFileManager; +class ProjectManager; +class EditorRegistry; +class SessionCoordinator; +class ToastManager; +class WindowDelegate; + +/** + * @class UICoordinator + * @brief Handles all UI drawing operations and state management + * + * Extracted from EditorManager to provide focused UI coordination: + * - Drawing operations (menus, dialogs, screens) + * - UI state management (visibility, focus, layout) + * - Popup and dialog coordination + * - Welcome screen and session UI + * - Material Design theming and icons + * + * This class follows the Single Responsibility Principle by focusing solely + * on UI presentation and user interaction, delegating business logic to + * specialized managers. + */ +class UICoordinator { + public: + // Constructor takes references to the managers it coordinates with + UICoordinator(EditorManager* editor_manager, + RomFileManager& rom_manager, + ProjectManager& project_manager, + EditorRegistry& editor_registry, + SessionCoordinator& session_coordinator, + WindowDelegate& window_delegate, + ToastManager& toast_manager, + PopupManager& popup_manager); + ~UICoordinator() = default; + + // Non-copyable due to reference members + UICoordinator(const UICoordinator&) = delete; + UICoordinator& operator=(const UICoordinator&) = delete; + + // Main UI drawing interface + void DrawAllUI(); + void DrawMenuBarExtras(); + void DrawContextSensitiveCardControl(); + + // Session UI components + void DrawSessionSwitcher(); + void DrawSessionManager(); + void DrawSessionRenameDialog(); + void DrawLayoutPresets(); + + // Welcome screen and project UI + void DrawWelcomeScreen(); + void DrawProjectHelp(); + + // Window management UI + void DrawWindowManagementUI(); + + // Popup and dialog management + void DrawAllPopups(); + void ShowPopup(const std::string& popup_name); + void HidePopup(const std::string& popup_name); + + // UI state management + void ShowEditorSelection(); + void ShowDisplaySettings(); + void ShowSessionSwitcher(); + void HideCurrentEditorCards(); + + // Window visibility management + void ShowAllWindows(); + void HideAllWindows(); + + // UI state queries + bool IsEditorSelectionVisible() const { return show_editor_selection_; } + bool IsDisplaySettingsVisible() const { return show_display_settings_; } + bool IsSessionSwitcherVisible() const { return show_session_switcher_; } + bool IsWelcomeScreenVisible() const { return show_welcome_screen_; } + + // UI state setters + void SetEditorSelectionVisible(bool visible) { show_editor_selection_ = visible; } + void SetDisplaySettingsVisible(bool visible) { show_display_settings_ = visible; } + void SetSessionSwitcherVisible(bool visible) { show_session_switcher_ = visible; } + void SetWelcomeScreenVisible(bool visible) { show_welcome_screen_ = visible; } + + // Theme and styling helpers + void ApplyMaterialDesignStyling(); + void UpdateThemeElements(); + void DrawThemePreview(); + + private: + // References to coordinated managers + EditorManager* editor_manager_; + RomFileManager& rom_manager_; + ProjectManager& project_manager_; + EditorRegistry& editor_registry_; + SessionCoordinator& session_coordinator_; + WindowDelegate& window_delegate_; + ToastManager& toast_manager_; + PopupManager& popup_manager_; + + // UI state flags + bool show_editor_selection_ = false; + bool show_display_settings_ = false; + bool show_session_switcher_ = false; + bool show_welcome_screen_ = true; + bool show_global_search_ = false; + bool show_performance_dashboard_ = false; + bool show_imgui_demo_ = false; + bool show_imgui_metrics_ = false; + bool show_test_dashboard_ = false; + + // Welcome screen component + std::unique_ptr welcome_screen_; + + // Helper methods for drawing operations + void DrawSessionIndicator(); + void DrawVersionInfo(); + void DrawSessionTabs(); + void DrawSessionBadges(); + + // Material Design component helpers + void DrawMaterialButton(const std::string& text, const std::string& icon, + std::function callback, bool enabled = true); + void DrawMaterialCard(const std::string& title, const std::string& content); + void DrawMaterialDialog(const std::string& title, std::function content); + + // Layout and positioning helpers + void CenterWindow(const std::string& window_name); + void PositionWindow(const std::string& window_name, float x, float y); + void SetWindowSize(const std::string& window_name, float width, float height); + + // Icon and theming helpers + std::string GetIconForEditor(EditorType type) const; + std::string GetColorForEditor(EditorType type) const; + void ApplyEditorTheme(EditorType type); + + // Session UI helpers + void DrawSessionList(); + void DrawSessionControls(); + void DrawSessionInfo(); + void DrawSessionStatus(); + + // Popup helpers + void DrawHelpMenuPopups(); + void DrawSettingsPopups(); + void DrawProjectPopups(); + void DrawSessionPopups(); + + // Window management helpers + void DrawWindowControls(); + void DrawLayoutControls(); + void DrawDockingControls(); + + // Performance and debug UI + void DrawPerformanceUI(); + void DrawDebugUI(); + void DrawTestingUI(); +}; + +} // namespace editor +} // namespace yaze + +#endif // YAZE_APP_EDITOR_SYSTEM_UI_COORDINATOR_H_ diff --git a/src/app/editor/ui/ui_coordinator.cc b/src/app/editor/ui/ui_coordinator.cc new file mode 100644 index 00000000..cbf24585 --- /dev/null +++ b/src/app/editor/ui/ui_coordinator.cc @@ -0,0 +1,492 @@ +#include "app/editor/ui/ui_coordinator.h" + +#include +#include +#include + +#include "absl/strings/str_format.h" +#include "app/editor/editor.h" +#include "app/editor/editor_manager.h" +#include "app/editor/system/editor_registry.h" +#include "app/editor/system/popup_manager.h" +#include "app/editor/system/project_manager.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/system/window_delegate.h" +#include "app/editor/ui/welcome_screen.h" +#include "app/gui/core/icons.h" +#include "app/gui/core/style.h" +#include "app/gui/core/theme_manager.h" +#include "imgui/imgui.h" + +namespace yaze { +namespace editor { + +UICoordinator::UICoordinator( + EditorManager* editor_manager, + RomFileManager& rom_manager, + ProjectManager& project_manager, + EditorRegistry& editor_registry, + SessionCoordinator& session_coordinator, + WindowDelegate& window_delegate, + ToastManager& toast_manager, + PopupManager& popup_manager) + : editor_manager_(editor_manager), + rom_manager_(rom_manager), + project_manager_(project_manager), + editor_registry_(editor_registry), + session_coordinator_(session_coordinator), + window_delegate_(window_delegate), + toast_manager_(toast_manager), + popup_manager_(popup_manager) { + + // Initialize welcome screen + welcome_screen_ = std::make_unique(); +} + +void UICoordinator::DrawAllUI() { + // Apply Material Design styling + ApplyMaterialDesignStyling(); + + // Draw all UI components in order + DrawMenuBarExtras(); + DrawContextSensitiveCardControl(); + DrawSessionSwitcher(); + DrawSessionManager(); + DrawSessionRenameDialog(); + DrawLayoutPresets(); + DrawWelcomeScreen(); + DrawProjectHelp(); + DrawWindowManagementUI(); + + // Draw all popups + DrawAllPopups(); +} + +void UICoordinator::DrawMenuBarExtras() { + auto* current_rom = rom_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; + + ImGui::SameLine(ImGui::GetWindowWidth() - version_width - 10 - session_rom_area_width); + + // Session indicator with Material Design styling + if (session_coordinator_.HasMultipleSessions()) { + std::string session_button_text = absl::StrFormat("%s%zu", ICON_MD_TAB, + session_coordinator_.GetActiveSessionCount()); + + // Material Design button styling + ImGui::PushStyleColor(ImGuiCol_Button, gui::GetPrimaryVec4()); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, gui::GetPrimaryHoverVec4()); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, gui::GetPrimaryActiveVec4()); + + if (ImGui::SmallButton(session_button_text.c_str())) { + session_coordinator_.ToggleSessionSwitcher(); + } + + ImGui::PopStyleColor(3); + + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Sessions: %zu active\nClick to switch", + session_coordinator_.GetActiveSessionCount()); + } + ImGui::SameLine(); + } + + // ROM information display with Material Design card styling + if (current_rom && current_rom->is_loaded()) { + ImGui::PushStyleColor(ImGuiCol_Text, gui::GetTextSecondaryVec4()); + ImGui::Text("%s %s", ICON_MD_INSERT_DRIVE_FILE, current_rom->title().c_str()); + ImGui::PopStyleColor(); + ImGui::SameLine(); + } + + // Version info with subtle styling + ImGui::PushStyleColor(ImGuiCol_Text, gui::GetTextDisabledVec4()); + ImGui::Text("%s", version_text.c_str()); + ImGui::PopStyleColor(); +} + +void UICoordinator::DrawContextSensitiveCardControl() { + // Get current editor and determine category + auto* current_editor = editor_manager_->GetCurrentEditorSet(); + if (!current_editor) return; + + // Find active card-based editor + Editor* active_editor = nullptr; + for (auto* editor : current_editor->active_editors_) { + if (*editor->active() && editor_registry_.IsCardBasedEditor(editor->type())) { + active_editor = editor; + break; + } + } + + if (!active_editor) return; + + std::string category = editor_registry_.GetEditorCategory(active_editor->type()); + + // 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); + } +} + +void UICoordinator::DrawSessionSwitcher() { + if (!show_session_switcher_) return; + + // Material Design dialog styling + ImGui::SetNextWindowSize(ImVec2(400, 300), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); + + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(16, 16)); + ImGui::PushStyleColor(ImGuiCol_WindowBg, gui::GetSurfaceVec4()); + ImGui::PushStyleColor(ImGuiCol_Border, gui::GetOutlineVec4()); + + if (ImGui::Begin("Session Switcher", &show_session_switcher_, + ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse)) { + + // Header with Material Design typography + ImGui::PushStyleColor(ImGuiCol_Text, gui::GetOnSurfaceVec4()); + ImGui::Text("%s Session Switcher", ICON_MD_TAB); + ImGui::PopStyleColor(); + ImGui::Separator(); + + // Session list with Material Design list styling + for (size_t i = 0; i < session_coordinator_.GetActiveSessionCount(); ++i) { + std::string session_name = session_coordinator_.GetSessionDisplayName(i); + bool is_active = (i == session_coordinator_.GetActiveSessionIndex()); + + // Active session highlighting + if (is_active) { + ImGui::PushStyleColor(ImGuiCol_Button, gui::GetPrimaryVec4()); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, gui::GetPrimaryHoverVec4()); + ImGui::PushStyleColor(ImGuiCol_Text, gui::GetOnPrimaryVec4()); + } + + std::string button_text = absl::StrFormat("%s %s", + is_active ? ICON_MD_RADIO_BUTTON_CHECKED : ICON_MD_RADIO_BUTTON_UNCHECKED, + session_name.c_str()); + + if (ImGui::Button(button_text.c_str(), ImVec2(-1, 0))) { + session_coordinator_.SwitchToSession(i); + show_session_switcher_ = false; + } + + if (is_active) { + ImGui::PopStyleColor(3); + } + } + + ImGui::Separator(); + + // Action buttons with Material Design styling + if (ImGui::Button(absl::StrFormat("%s New Session", ICON_MD_ADD).c_str(), ImVec2(-1, 0))) { + session_coordinator_.CreateNewSession(); + show_session_switcher_ = false; + } + + if (ImGui::Button(absl::StrFormat("%s Close", ICON_MD_CLOSE).c_str(), ImVec2(-1, 0))) { + show_session_switcher_ = false; + } + } + + ImGui::End(); + ImGui::PopStyleColor(2); + ImGui::PopStyleVar(); +} + +void UICoordinator::DrawSessionManager() { + // TODO: Implement session manager dialog + // This would be a more comprehensive session management interface +} + +void UICoordinator::DrawSessionRenameDialog() { + // TODO: Implement session rename dialog + // This would allow users to rename sessions for better organization +} + +void UICoordinator::DrawLayoutPresets() { + // TODO: Implement layout presets UI + // This would show available layout presets (Developer, Designer, Modder) +} + +void UICoordinator::DrawWelcomeScreen() { + if (!show_welcome_screen_) return; + + if (welcome_screen_) { + welcome_screen_->Show(&show_welcome_screen_); + } +} + +void UICoordinator::DrawProjectHelp() { + // TODO: Implement project help UI + // This would show project-specific help and documentation +} + +void UICoordinator::DrawWindowManagementUI() { + // TODO: Implement window management UI + // This would provide controls for window visibility, docking, etc. +} + +void UICoordinator::DrawAllPopups() { + // Draw all registered popups + popup_manager_.DrawPopups(); +} + +void UICoordinator::ShowPopup(const std::string& popup_name) { + popup_manager_.Show(popup_name.c_str()); +} + +void UICoordinator::HidePopup(const std::string& popup_name) { + popup_manager_.Hide(popup_name.c_str()); +} + +void UICoordinator::ShowEditorSelection() { + show_editor_selection_ = true; +} + +void UICoordinator::ShowDisplaySettings() { + show_display_settings_ = true; + ShowPopup("Display Settings"); +} + +void UICoordinator::ShowSessionSwitcher() { + show_session_switcher_ = true; +} + +void UICoordinator::HideCurrentEditorCards() { + // TODO: Implement card hiding logic + // This would hide cards for the current editor +} + +void UICoordinator::ShowAllWindows() { + window_delegate_.ShowAllWindows(); +} + +void UICoordinator::HideAllWindows() { + window_delegate_.HideAllWindows(); +} + +void UICoordinator::ApplyMaterialDesignStyling() { + // Apply Material Design 3 color scheme + ImGuiStyle& style = ImGui::GetStyle(); + + // Set Material Design colors + style.Colors[ImGuiCol_WindowBg] = gui::GetSurfaceVec4(); + style.Colors[ImGuiCol_ChildBg] = gui::GetSurfaceVariantVec4(); + style.Colors[ImGuiCol_PopupBg] = gui::GetSurfaceContainerVec4(); + style.Colors[ImGuiCol_Border] = gui::GetOutlineVec4(); + style.Colors[ImGuiCol_BorderShadow] = gui::GetShadowVec4(); + + // Text colors + style.Colors[ImGuiCol_Text] = gui::GetOnSurfaceVec4(); + style.Colors[ImGuiCol_TextDisabled] = gui::GetOnSurfaceVariantVec4(); + + // Button colors + style.Colors[ImGuiCol_Button] = gui::GetSurfaceContainerHighestVec4(); + style.Colors[ImGuiCol_ButtonHovered] = gui::GetSurfaceContainerHighVec4(); + style.Colors[ImGuiCol_ButtonActive] = gui::GetPrimaryVec4(); + + // Header colors + style.Colors[ImGuiCol_Header] = gui::GetSurfaceContainerHighVec4(); + style.Colors[ImGuiCol_HeaderHovered] = gui::GetSurfaceContainerHighestVec4(); + style.Colors[ImGuiCol_HeaderActive] = gui::GetPrimaryVec4(); + + // Frame colors + style.Colors[ImGuiCol_FrameBg] = gui::GetSurfaceContainerHighestVec4(); + style.Colors[ImGuiCol_FrameBgHovered] = gui::GetSurfaceContainerHighVec4(); + style.Colors[ImGuiCol_FrameBgActive] = gui::GetPrimaryVec4(); + + // Scrollbar colors + style.Colors[ImGuiCol_ScrollbarBg] = gui::GetSurfaceContainerVec4(); + style.Colors[ImGuiCol_ScrollbarGrab] = gui::GetOutlineVec4(); + style.Colors[ImGuiCol_ScrollbarGrabHovered] = gui::GetOnSurfaceVariantVec4(); + style.Colors[ImGuiCol_ScrollbarGrabActive] = gui::GetOnSurfaceVec4(); + + // Slider colors + style.Colors[ImGuiCol_SliderGrab] = gui::GetPrimaryVec4(); + style.Colors[ImGuiCol_SliderGrabActive] = gui::GetPrimaryActiveVec4(); + + // Tab colors + style.Colors[ImGuiCol_Tab] = gui::GetSurfaceContainerHighVec4(); + style.Colors[ImGuiCol_TabHovered] = gui::GetSurfaceContainerHighestVec4(); + style.Colors[ImGuiCol_TabActive] = gui::GetPrimaryVec4(); + style.Colors[ImGuiCol_TabUnfocused] = gui::GetSurfaceContainerVec4(); + style.Colors[ImGuiCol_TabUnfocusedActive] = gui::GetPrimaryActiveVec4(); + + // Title bar colors + style.Colors[ImGuiCol_TitleBg] = gui::GetSurfaceContainerVec4(); + style.Colors[ImGuiCol_TitleBgActive] = gui::GetSurfaceContainerHighVec4(); + style.Colors[ImGuiCol_TitleBgCollapsed] = gui::GetSurfaceContainerVec4(); + + // Menu bar colors + style.Colors[ImGuiCol_MenuBarBg] = gui::GetSurfaceContainerVec4(); + + // Modal dimming + style.Colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.0f, 0.0f, 0.0f, 0.6f); +} + +void UICoordinator::UpdateThemeElements() { + // Update theme-specific elements + ApplyMaterialDesignStyling(); +} + +void UICoordinator::DrawThemePreview() { + // TODO: Implement theme preview + // This would show a preview of the current theme +} + +// Helper methods for drawing operations +void UICoordinator::DrawSessionIndicator() { + // TODO: Implement session indicator +} + +void UICoordinator::DrawVersionInfo() { + // TODO: Implement version info display +} + +void UICoordinator::DrawSessionTabs() { + // TODO: Implement session tabs +} + +void UICoordinator::DrawSessionBadges() { + // TODO: Implement session badges +} + +// Material Design component helpers +void UICoordinator::DrawMaterialButton(const std::string& text, const std::string& icon, + std::function callback, bool enabled) { + if (!enabled) { + ImGui::PushStyleColor(ImGuiCol_Button, gui::GetSurfaceContainerHighestVec4()); + ImGui::PushStyleColor(ImGuiCol_Text, gui::GetOnSurfaceVariantVec4()); + } + + std::string button_text = absl::StrFormat("%s %s", icon.c_str(), text.c_str()); + if (ImGui::Button(button_text.c_str())) { + if (enabled && callback) { + callback(); + } + } + + if (!enabled) { + ImGui::PopStyleColor(2); + } +} + +void UICoordinator::DrawMaterialCard(const std::string& title, const std::string& content) { + // TODO: Implement Material Design card component +} + +void UICoordinator::DrawMaterialDialog(const std::string& title, std::function content) { + // TODO: Implement Material Design dialog component +} + +// Layout and positioning helpers +void UICoordinator::CenterWindow(const std::string& window_name) { + ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); +} + +void UICoordinator::PositionWindow(const std::string& window_name, float x, float y) { + ImGui::SetNextWindowPos(ImVec2(x, y), ImGuiCond_Appearing); +} + +void UICoordinator::SetWindowSize(const std::string& window_name, float width, float height) { + ImGui::SetNextWindowSize(ImVec2(width, height), ImGuiCond_FirstUseEver); +} + +// Icon and theming helpers +std::string UICoordinator::GetIconForEditor(EditorType type) const { + switch (type) { + case EditorType::kDungeon: return ICON_MD_CASTLE; + case EditorType::kOverworld: return ICON_MD_MAP; + case EditorType::kGraphics: return ICON_MD_IMAGE; + case EditorType::kPalette: return ICON_MD_PALETTE; + case EditorType::kSprite: return ICON_MD_TOYS; + case EditorType::kScreen: return ICON_MD_TV; + case EditorType::kMessage: return ICON_MD_CHAT_BUBBLE; + case EditorType::kMusic: return ICON_MD_MUSIC_NOTE; + case EditorType::kAssembly: return ICON_MD_CODE; + case EditorType::kHex: return ICON_MD_DATA_ARRAY; + case EditorType::kEmulator: return ICON_MD_PLAY_ARROW; + case EditorType::kSettings: return ICON_MD_SETTINGS; + default: return ICON_MD_HELP; + } +} + +std::string UICoordinator::GetColorForEditor(EditorType type) const { + // TODO: Implement editor-specific colors + return "primary"; // Placeholder for now +} + +void UICoordinator::ApplyEditorTheme(EditorType type) { + // TODO: Implement editor-specific theming +} + +// Session UI helpers +void UICoordinator::DrawSessionList() { + // TODO: Implement session list +} + +void UICoordinator::DrawSessionControls() { + // TODO: Implement session controls +} + +void UICoordinator::DrawSessionInfo() { + // TODO: Implement session info +} + +void UICoordinator::DrawSessionStatus() { + // TODO: Implement session status +} + +// Popup helpers +void UICoordinator::DrawHelpMenuPopups() { + // TODO: Implement help menu popups +} + +void UICoordinator::DrawSettingsPopups() { + // TODO: Implement settings popups +} + +void UICoordinator::DrawProjectPopups() { + // TODO: Implement project popups +} + +void UICoordinator::DrawSessionPopups() { + // TODO: Implement session popups +} + +// Window management helpers +void UICoordinator::DrawWindowControls() { + // TODO: Implement window controls +} + +void UICoordinator::DrawLayoutControls() { + // TODO: Implement layout controls +} + +void UICoordinator::DrawDockingControls() { + // TODO: Implement docking controls +} + +// Performance and debug UI +void UICoordinator::DrawPerformanceUI() { + // TODO: Implement performance UI +} + +void UICoordinator::DrawDebugUI() { + // TODO: Implement debug UI +} + +void UICoordinator::DrawTestingUI() { + // TODO: Implement testing UI +} + +} // namespace editor +} // namespace yaze diff --git a/src/app/editor/ui/ui_coordinator.h b/src/app/editor/ui/ui_coordinator.h new file mode 100644 index 00000000..56b04859 --- /dev/null +++ b/src/app/editor/ui/ui_coordinator.h @@ -0,0 +1,180 @@ +#ifndef YAZE_APP_EDITOR_UI_UI_COORDINATOR_H_ +#define YAZE_APP_EDITOR_UI_UI_COORDINATOR_H_ + +#include +#include + +#include "absl/status/status.h" +#include "app/editor/editor.h" +#include "app/editor/system/popup_manager.h" +#include "app/editor/ui/welcome_screen.h" +#include "app/gui/core/icons.h" + +namespace yaze { +namespace editor { + +// Forward declarations to avoid circular dependencies +class EditorManager; +class RomFileManager; +class ProjectManager; +class EditorRegistry; +class SessionCoordinator; +class ToastManager; +class WindowDelegate; + +/** + * @class UICoordinator + * @brief Handles all UI drawing operations and state management + * + * Extracted from EditorManager to provide focused UI coordination: + * - Drawing operations (menus, dialogs, screens) + * - UI state management (visibility, focus, layout) + * - Popup and dialog coordination + * - Welcome screen and session UI + * - Material Design theming and icons + * + * This class follows the Single Responsibility Principle by focusing solely + * on UI presentation and user interaction, delegating business logic to + * specialized managers. + */ +class UICoordinator { + public: + // Constructor takes references to the managers it coordinates with + UICoordinator(EditorManager* editor_manager, + RomFileManager& rom_manager, + ProjectManager& project_manager, + EditorRegistry& editor_registry, + SessionCoordinator& session_coordinator, + WindowDelegate& window_delegate, + ToastManager& toast_manager, + PopupManager& popup_manager); + ~UICoordinator() = default; + + // Non-copyable due to reference members + UICoordinator(const UICoordinator&) = delete; + UICoordinator& operator=(const UICoordinator&) = delete; + + // Main UI drawing interface + void DrawAllUI(); + void DrawMenuBarExtras(); + void DrawContextSensitiveCardControl(); + + // Session UI components + void DrawSessionSwitcher(); + void DrawSessionManager(); + void DrawSessionRenameDialog(); + void DrawLayoutPresets(); + + // Welcome screen and project UI + void DrawWelcomeScreen(); + void DrawProjectHelp(); + + // Window management UI + void DrawWindowManagementUI(); + + // Popup and dialog management + void DrawAllPopups(); + void ShowPopup(const std::string& popup_name); + void HidePopup(const std::string& popup_name); + + // UI state management + void ShowEditorSelection(); + void ShowDisplaySettings(); + void ShowSessionSwitcher(); + void HideCurrentEditorCards(); + + // Window visibility management + void ShowAllWindows(); + void HideAllWindows(); + + // UI state queries + bool IsEditorSelectionVisible() const { return show_editor_selection_; } + bool IsDisplaySettingsVisible() const { return show_display_settings_; } + bool IsSessionSwitcherVisible() const { return show_session_switcher_; } + bool IsWelcomeScreenVisible() const { return show_welcome_screen_; } + + // UI state setters + void SetEditorSelectionVisible(bool visible) { show_editor_selection_ = visible; } + void SetDisplaySettingsVisible(bool visible) { show_display_settings_ = visible; } + void SetSessionSwitcherVisible(bool visible) { show_session_switcher_ = visible; } + void SetWelcomeScreenVisible(bool visible) { show_welcome_screen_ = visible; } + + // Theme and styling helpers + void ApplyMaterialDesignStyling(); + void UpdateThemeElements(); + void DrawThemePreview(); + + private: + // References to coordinated managers + EditorManager* editor_manager_; + RomFileManager& rom_manager_; + ProjectManager& project_manager_; + EditorRegistry& editor_registry_; + SessionCoordinator& session_coordinator_; + WindowDelegate& window_delegate_; + ToastManager& toast_manager_; + PopupManager& popup_manager_; + + // UI state flags + bool show_editor_selection_ = false; + bool show_display_settings_ = false; + bool show_session_switcher_ = false; + bool show_welcome_screen_ = true; + bool show_global_search_ = false; + bool show_performance_dashboard_ = false; + bool show_imgui_demo_ = false; + bool show_imgui_metrics_ = false; + bool show_test_dashboard_ = false; + + // Welcome screen component + std::unique_ptr welcome_screen_; + + // Helper methods for drawing operations + void DrawSessionIndicator(); + void DrawVersionInfo(); + void DrawSessionTabs(); + void DrawSessionBadges(); + + // Material Design component helpers + void DrawMaterialButton(const std::string& text, const std::string& icon, + std::function callback, bool enabled = true); + void DrawMaterialCard(const std::string& title, const std::string& content); + void DrawMaterialDialog(const std::string& title, std::function content); + + // Layout and positioning helpers + void CenterWindow(const std::string& window_name); + void PositionWindow(const std::string& window_name, float x, float y); + void SetWindowSize(const std::string& window_name, float width, float height); + + // Icon and theming helpers + std::string GetIconForEditor(EditorType type) const; + std::string GetColorForEditor(EditorType type) const; + void ApplyEditorTheme(EditorType type); + + // Session UI helpers + void DrawSessionList(); + void DrawSessionControls(); + void DrawSessionInfo(); + void DrawSessionStatus(); + + // Popup helpers + void DrawHelpMenuPopups(); + void DrawSettingsPopups(); + void DrawProjectPopups(); + void DrawSessionPopups(); + + // Window management helpers + void DrawWindowControls(); + void DrawLayoutControls(); + void DrawDockingControls(); + + // Performance and debug UI + void DrawPerformanceUI(); + void DrawDebugUI(); + void DrawTestingUI(); +}; + +} // namespace editor +} // namespace yaze + +#endif // YAZE_APP_EDITOR_UI_UI_COORDINATOR_H_ diff --git a/src/app/gui/core/theme_manager.h b/src/app/gui/core/theme_manager.h index 1b2d02e9..a50098a6 100644 --- a/src/app/gui/core/theme_manager.h +++ b/src/app/gui/core/theme_manager.h @@ -217,6 +217,28 @@ public: Color GetWelcomeScreenBorder() const; Color GetWelcomeScreenAccent() const; + // Convenient theme color access interface + Color GetThemeColor(const std::string& color_name) const; + ImVec4 GetThemeColorVec4(const std::string& color_name) const; + + // Material Design color accessors + Color GetPrimary() const { return current_theme_.primary; } + Color GetPrimaryHover() const { return current_theme_.button_hovered; } + Color GetPrimaryActive() const { return current_theme_.button_active; } + Color GetSecondary() const { return current_theme_.secondary; } + Color GetSurface() const { return current_theme_.surface; } + Color GetSurfaceVariant() const { return current_theme_.child_bg; } + Color GetSurfaceContainer() const { return current_theme_.popup_bg; } + Color GetSurfaceContainerHigh() const { return current_theme_.header; } + Color GetSurfaceContainerHighest() const { return current_theme_.header_hovered; } + Color GetOnSurface() const { return current_theme_.text_primary; } + Color GetOnSurfaceVariant() const { return current_theme_.text_secondary; } + Color GetOnPrimary() const { return current_theme_.text_primary; } + Color GetOutline() const { return current_theme_.border; } + Color GetTextSecondary() const { return current_theme_.text_secondary; } + Color GetTextDisabled() const { return current_theme_.text_disabled; } + Color GetShadow() const { return current_theme_.border_shadow; } + private: ThemeManager() { InitializeBuiltInThemes(); } @@ -235,7 +257,52 @@ private: std::string GetCurrentThemeFilePath() const; }; +// Global convenience functions for easy theme color access + // Material Design color accessors - global convenience functions + inline Color GetThemeColor(const std::string& color_name) { + return ThemeManager::Get().GetThemeColor(color_name); + } + + inline ImVec4 GetThemeColorVec4(const std::string& color_name) { + return ThemeManager::Get().GetThemeColorVec4(color_name); + } + + // Material Design color accessors + inline Color GetPrimary() { return ThemeManager::Get().GetPrimary(); } + inline Color GetPrimaryHover() { return ThemeManager::Get().GetPrimaryHover(); } + inline Color GetPrimaryActive() { return ThemeManager::Get().GetPrimaryActive(); } + inline Color GetSecondary() { return ThemeManager::Get().GetSecondary(); } + inline Color GetSurface() { return ThemeManager::Get().GetSurface(); } + inline Color GetSurfaceVariant() { return ThemeManager::Get().GetSurfaceVariant(); } + inline Color GetSurfaceContainer() { return ThemeManager::Get().GetSurfaceContainer(); } + inline Color GetSurfaceContainerHigh() { return ThemeManager::Get().GetSurfaceContainerHigh(); } + inline Color GetSurfaceContainerHighest() { return ThemeManager::Get().GetSurfaceContainerHighest(); } + inline Color GetOnSurface() { return ThemeManager::Get().GetOnSurface(); } + inline Color GetOnSurfaceVariant() { return ThemeManager::Get().GetOnSurfaceVariant(); } + inline Color GetOnPrimary() { return ThemeManager::Get().GetOnPrimary(); } + inline Color GetOutline() { return ThemeManager::Get().GetOutline(); } + inline Color GetTextSecondary() { return ThemeManager::Get().GetTextSecondary(); } + inline Color GetTextDisabled() { return ThemeManager::Get().GetTextDisabled(); } + inline Color GetShadow() { return ThemeManager::Get().GetShadow(); } + + // ImVec4 versions for direct ImGui usage + inline ImVec4 GetPrimaryVec4() { return ConvertColorToImVec4(GetPrimary()); } + inline ImVec4 GetPrimaryHoverVec4() { return ConvertColorToImVec4(GetPrimaryHover()); } + inline ImVec4 GetPrimaryActiveVec4() { return ConvertColorToImVec4(GetPrimaryActive()); } + inline ImVec4 GetSurfaceVec4() { return ConvertColorToImVec4(GetSurface()); } + inline ImVec4 GetSurfaceVariantVec4() { return ConvertColorToImVec4(GetSurfaceVariant()); } + inline ImVec4 GetSurfaceContainerVec4() { return ConvertColorToImVec4(GetSurfaceContainer()); } + inline ImVec4 GetSurfaceContainerHighVec4() { return ConvertColorToImVec4(GetSurfaceContainerHigh()); } + inline ImVec4 GetSurfaceContainerHighestVec4() { return ConvertColorToImVec4(GetSurfaceContainerHighest()); } + inline ImVec4 GetOnSurfaceVec4() { return ConvertColorToImVec4(GetOnSurface()); } + inline ImVec4 GetOnSurfaceVariantVec4() { return ConvertColorToImVec4(GetOnSurfaceVariant()); } + inline ImVec4 GetOnPrimaryVec4() { return ConvertColorToImVec4(GetOnPrimary()); } + inline ImVec4 GetOutlineVec4() { return ConvertColorToImVec4(GetOutline()); } + inline ImVec4 GetTextSecondaryVec4() { return ConvertColorToImVec4(GetTextSecondary()); } + inline ImVec4 GetTextDisabledVec4() { return ConvertColorToImVec4(GetTextDisabled()); } + inline ImVec4 GetShadowVec4() { return ConvertColorToImVec4(GetShadow()); } } // namespace gui + } // namespace yaze #endif // YAZE_APP_GUI_THEME_MANAGER_H