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:
scawful
2025-09-25 17:22:48 -04:00
parent aaa7af9f07
commit 015a5600c5
4 changed files with 186 additions and 39 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -281,13 +281,16 @@ void TestManager::TrimResourceHistory() {
}
}
void TestManager::DrawTestDashboard() {
show_dashboard_ = true; // Enable dashboard visibility
void TestManager::DrawTestDashboard(bool* show_dashboard) {
bool* dashboard_flag = show_dashboard ? show_dashboard : &show_dashboard_;
// Set a larger default window size
ImGui::SetNextWindowSize(ImVec2(900, 700), ImGuiCond_FirstUseEver);
ImGui::Begin("Test Dashboard", &show_dashboard_, ImGuiWindowFlags_MenuBar);
if (!ImGui::Begin("Test Dashboard", dashboard_flag, ImGuiWindowFlags_MenuBar)) {
ImGui::End();
return;
}
// ROM status indicator with detailed information
bool has_rom = current_rom_ && current_rom_->is_loaded();

View File

@@ -164,7 +164,7 @@ class TestManager {
float GetProgress() const { return progress_; }
// UI Interface
void DrawTestDashboard();
void DrawTestDashboard(bool* show_dashboard = nullptr);
// ROM-dependent testing
void SetCurrentRom(Rom* rom) {