Enhance EditorManager with session management and workspace preset improvements
- Introduced session renaming functionality, allowing users to customize session names for better organization. - Implemented duplicate session detection to prevent loading the same ROM in multiple sessions. - Enhanced workspace preset management with improved error handling and validation during loading and saving. - Updated UI elements to support lazy loading of workspace presets, ensuring they are available when needed. - Refactored session display logic to provide clearer naming and improved user experience in session management.
This commit is contained in:
@@ -78,16 +78,39 @@ void EditorManager::SaveUserSettings() {
|
||||
}
|
||||
|
||||
void EditorManager::RefreshWorkspacePresets() {
|
||||
workspace_presets_.clear();
|
||||
// Try to read a simple index file of presets
|
||||
// Safe clearing with error handling
|
||||
try {
|
||||
auto data = core::LoadConfigFile("workspace_presets.txt");
|
||||
std::istringstream ss(data);
|
||||
std::string name;
|
||||
while (std::getline(ss, name)) {
|
||||
if (!name.empty()) workspace_presets_.push_back(name);
|
||||
// Create a new vector instead of clearing to avoid corruption
|
||||
std::vector<std::string> new_presets;
|
||||
|
||||
// Try to read a simple index file of presets
|
||||
try {
|
||||
auto data = core::LoadConfigFile("workspace_presets.txt");
|
||||
if (!data.empty()) {
|
||||
std::istringstream ss(data);
|
||||
std::string name;
|
||||
while (std::getline(ss, name)) {
|
||||
// Trim whitespace and validate
|
||||
name.erase(0, name.find_first_not_of(" \t\r\n"));
|
||||
name.erase(name.find_last_not_of(" \t\r\n") + 1);
|
||||
if (!name.empty() && name.length() < 256) { // Reasonable length limit
|
||||
new_presets.emplace_back(std::move(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
util::logf("Warning: Failed to load workspace presets: %s", e.what());
|
||||
}
|
||||
} catch (...) {
|
||||
|
||||
// Safely replace the vector
|
||||
workspace_presets_ = std::move(new_presets);
|
||||
workspace_presets_loaded_ = true;
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
util::logf("Error in RefreshWorkspacePresets: %s", e.what());
|
||||
// Ensure we have a valid empty vector
|
||||
workspace_presets_ = std::vector<std::string>();
|
||||
workspace_presets_loaded_ = true; // Mark as loaded even if empty to avoid retry
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,13 +118,22 @@ void EditorManager::SaveWorkspacePreset(const std::string &name) {
|
||||
if (name.empty()) return;
|
||||
std::string ini_name = absl::StrCat("yaze_workspace_", name, ".ini");
|
||||
ImGui::SaveIniSettingsToDisk(ini_name.c_str());
|
||||
|
||||
// Ensure presets are loaded before updating
|
||||
if (!workspace_presets_loaded_) {
|
||||
RefreshWorkspacePresets();
|
||||
}
|
||||
|
||||
// Update index
|
||||
RefreshWorkspacePresets();
|
||||
if (std::find(workspace_presets_.begin(), workspace_presets_.end(), name) == workspace_presets_.end()) {
|
||||
workspace_presets_.push_back(name);
|
||||
std::ostringstream ss;
|
||||
for (auto &n : workspace_presets_) ss << n << "\n";
|
||||
core::SaveFile("workspace_presets.txt", ss.str());
|
||||
workspace_presets_.emplace_back(name);
|
||||
try {
|
||||
std::ostringstream ss;
|
||||
for (const auto &n : workspace_presets_) ss << n << "\n";
|
||||
core::SaveFile("workspace_presets.txt", ss.str());
|
||||
} catch (const std::exception& e) {
|
||||
util::logf("Warning: Failed to save workspace presets: %s", e.what());
|
||||
}
|
||||
}
|
||||
last_workspace_preset_ = name;
|
||||
}
|
||||
@@ -158,11 +190,13 @@ void EditorManager::Initialize(const std::string &filename) {
|
||||
// Set the popup manager in the context
|
||||
context_.popup_manager = popup_manager_.get();
|
||||
|
||||
// Load user settings and workspace presets
|
||||
// Load critical user settings first
|
||||
LoadUserSettings();
|
||||
RefreshWorkspacePresets();
|
||||
|
||||
// Initialize testing system
|
||||
// Defer workspace presets loading to avoid initialization crashes
|
||||
// This will be called lazily when workspace features are accessed
|
||||
|
||||
// Initialize testing system (lightweight)
|
||||
InitializeTestSuites();
|
||||
|
||||
// TestManager will be updated when ROMs are loaded via SetCurrentRom calls
|
||||
@@ -720,8 +754,9 @@ absl::Status EditorManager::Update() {
|
||||
}
|
||||
}
|
||||
|
||||
// Clean window titles without session clutter
|
||||
std::string window_title = GetEditorName(editor->type());
|
||||
// Generate unique window titles for multi-session support
|
||||
size_t session_index = GetCurrentSessionIndex();
|
||||
std::string window_title = GenerateUniqueEditorTitle(editor->type(), session_index);
|
||||
|
||||
if (ImGui::Begin(window_title.c_str(), editor->active())) {
|
||||
current_editor_ = editor;
|
||||
@@ -919,7 +954,7 @@ void EditorManager::DrawMenuBar() {
|
||||
End();
|
||||
}
|
||||
|
||||
if (show_imgui_demo_) ShowDemoWindow();
|
||||
if (show_imgui_demo_) ShowDemoWindow(&show_imgui_demo_);
|
||||
if (show_imgui_metrics_) ShowMetricsWindow(&show_imgui_metrics_);
|
||||
if (show_memory_editor_ && current_editor_set_) {
|
||||
current_editor_set_->memory_editor_.Update(show_memory_editor_);
|
||||
@@ -932,7 +967,7 @@ void EditorManager::DrawMenuBar() {
|
||||
if (show_test_dashboard_) {
|
||||
auto& test_manager = test::TestManager::Get();
|
||||
test_manager.UpdateResourceStats(); // Update monitoring data
|
||||
test_manager.DrawTestDashboard();
|
||||
test_manager.DrawTestDashboard(&show_test_dashboard_);
|
||||
}
|
||||
|
||||
if (show_emulator_) {
|
||||
@@ -1087,6 +1122,12 @@ void EditorManager::DrawMenuBar() {
|
||||
|
||||
if (show_load_workspace_preset_) {
|
||||
Begin("Load Workspace Preset", &show_load_workspace_preset_, ImGuiWindowFlags_AlwaysAutoResize);
|
||||
|
||||
// Lazy load workspace presets when UI is accessed
|
||||
if (!workspace_presets_loaded_) {
|
||||
RefreshWorkspacePresets();
|
||||
}
|
||||
|
||||
for (const auto &name : workspace_presets_) {
|
||||
if (Selectable(name.c_str())) {
|
||||
LoadWorkspacePreset(name);
|
||||
@@ -1102,6 +1143,7 @@ void EditorManager::DrawMenuBar() {
|
||||
DrawSessionSwitcher();
|
||||
DrawSessionManager();
|
||||
DrawLayoutPresets();
|
||||
DrawSessionRenameDialog();
|
||||
}
|
||||
|
||||
absl::Status EditorManager::LoadRom() {
|
||||
@@ -1109,11 +1151,20 @@ absl::Status EditorManager::LoadRom() {
|
||||
if (file_name.empty()) {
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
// Check for duplicate sessions
|
||||
if (HasDuplicateSession(file_name)) {
|
||||
toast_manager_.Show("ROM already open in another session", editor::ToastType::kWarning);
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
Rom temp_rom;
|
||||
RETURN_IF_ERROR(temp_rom.LoadFromFile(file_name));
|
||||
|
||||
sessions_.emplace_back(std::move(temp_rom));
|
||||
RomSession &session = sessions_.back();
|
||||
session.filepath = file_name; // Store filepath for duplicate detection
|
||||
|
||||
// Wire editor contexts
|
||||
for (auto *editor : session.editors.active_editors_) {
|
||||
editor->set_context(&context_);
|
||||
@@ -1121,11 +1172,6 @@ absl::Status EditorManager::LoadRom() {
|
||||
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_);
|
||||
|
||||
// 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");
|
||||
@@ -1353,11 +1399,8 @@ void EditorManager::SwitchToSession(size_t index) {
|
||||
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_);
|
||||
test::TestManager::Get().SetCurrentRom(current_rom_);
|
||||
|
||||
std::string session_name = current_rom_->title().empty() ?
|
||||
absl::StrFormat("Session %zu", index + 1) :
|
||||
current_rom_->title();
|
||||
std::string session_name = session.GetDisplayName();
|
||||
toast_manager_.Show(absl::StrFormat("Switched to %s", session_name),
|
||||
editor::ToastType::kInfo);
|
||||
}
|
||||
@@ -1504,9 +1547,7 @@ void EditorManager::DrawSessionSwitcher() {
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.2f, 0.7f, 0.2f, 1.0f));
|
||||
}
|
||||
|
||||
std::string session_name = session.rom.title().empty() ?
|
||||
absl::StrFormat("Session %zu", i + 1) :
|
||||
session.rom.title();
|
||||
std::string session_name = session.GetDisplayName();
|
||||
|
||||
if (ImGui::Button(absl::StrFormat("%s %s %s",
|
||||
ICON_MD_STORAGE,
|
||||
@@ -1583,8 +1624,12 @@ void EditorManager::DrawSessionManager() {
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
std::string rom_title = session.rom.title().empty() ? "No ROM" : session.rom.title();
|
||||
ImGui::Text("%s", rom_title.c_str());
|
||||
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 {
|
||||
ImGui::Text("%s", display_name.c_str());
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
if (session.rom.is_loaded()) {
|
||||
@@ -1604,6 +1649,13 @@ void EditorManager::DrawSessionManager() {
|
||||
SwitchToSession(i);
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button(absl::StrCat(ICON_MD_EDIT, " Rename").c_str())) {
|
||||
session_to_rename_ = i;
|
||||
strncpy(session_rename_buffer_, session.GetDisplayName().c_str(), sizeof(session_rename_buffer_) - 1);
|
||||
show_session_rename_dialog_ = true;
|
||||
}
|
||||
|
||||
if (is_current) {
|
||||
ImGui::BeginDisabled();
|
||||
}
|
||||
@@ -1683,5 +1735,75 @@ void EditorManager::DrawLayoutPresets() {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
std::string EditorManager::GenerateUniqueEditorTitle(EditorType type, size_t session_index) {
|
||||
std::string base_name = GetEditorName(type);
|
||||
|
||||
if (sessions_.size() <= 1) {
|
||||
return base_name; // No need for session identifier with single session
|
||||
}
|
||||
|
||||
// Add session identifier
|
||||
const auto& session = sessions_[session_index];
|
||||
std::string session_name = session.GetDisplayName();
|
||||
|
||||
// Truncate long session names
|
||||
if (session_name.length() > 15) {
|
||||
session_name = session_name.substr(0, 12) + "...";
|
||||
}
|
||||
|
||||
return absl::StrFormat("%s (%s)", base_name.c_str(), session_name.c_str());
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
} // namespace editor
|
||||
} // namespace yaze
|
||||
|
||||
@@ -137,6 +137,9 @@ class EditorManager {
|
||||
bool show_homepage_ = true;
|
||||
bool show_command_palette_ = false;
|
||||
bool show_global_search_ = false;
|
||||
bool show_session_rename_dialog_ = false;
|
||||
size_t session_to_rename_ = 0;
|
||||
char session_rename_buffer_[256] = {};
|
||||
|
||||
// Testing interface
|
||||
bool show_test_dashboard_ = false;
|
||||
@@ -147,6 +150,7 @@ class EditorManager {
|
||||
std::vector<std::string> workspace_presets_;
|
||||
std::string last_workspace_preset_ = "";
|
||||
std::string status_message_ = "";
|
||||
bool workspace_presets_loaded_ = false;
|
||||
|
||||
absl::Status status_;
|
||||
emu::Emulator emulator_;
|
||||
@@ -154,10 +158,22 @@ class EditorManager {
|
||||
struct RomSession {
|
||||
Rom rom;
|
||||
EditorSet editors;
|
||||
std::string custom_name; // User-defined session name
|
||||
std::string filepath; // ROM filepath for duplicate detection
|
||||
|
||||
RomSession() = default;
|
||||
explicit RomSession(Rom&& r)
|
||||
: rom(std::move(r)), editors(&rom) {}
|
||||
: rom(std::move(r)), editors(&rom) {
|
||||
filepath = rom.filename();
|
||||
}
|
||||
|
||||
// Get display name (custom name or ROM title)
|
||||
std::string GetDisplayName() const {
|
||||
if (!custom_name.empty()) {
|
||||
return custom_name;
|
||||
}
|
||||
return rom.title().empty() ? "Untitled Session" : rom.title();
|
||||
}
|
||||
};
|
||||
|
||||
std::deque<RomSession> sessions_;
|
||||
@@ -196,10 +212,16 @@ class EditorManager {
|
||||
void LoadDesignerLayout();
|
||||
void LoadModderLayout();
|
||||
|
||||
// Session management helpers
|
||||
bool HasDuplicateSession(const std::string& filepath);
|
||||
void RenameSession(size_t index, const std::string& new_name);
|
||||
std::string GenerateUniqueEditorTitle(EditorType type, size_t session_index);
|
||||
|
||||
// UI drawing helpers
|
||||
void DrawSessionSwitcher();
|
||||
void DrawSessionManager();
|
||||
void DrawLayoutPresets();
|
||||
void DrawSessionRenameDialog();
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
|
||||
Reference in New Issue
Block a user