Preserve saved editor dock layouts

This commit is contained in:
2026-04-01 16:43:46 +08:00
parent 3f18530396
commit 6e2711f9e8
3 changed files with 67 additions and 4 deletions

View File

@@ -194,7 +194,7 @@ bool Application::SwitchProject(const std::string& projectPath) {
return false;
}
m_imguiSession.SetProjectPath(projectPath);
const bool hasSavedDockLayout = m_imguiSession.SetProjectPath(projectPath);
m_editorContext->SetProjectPath(projectPath);
auto& logger = Debug::Logger::Get();
@@ -208,6 +208,11 @@ bool Application::SwitchProject(const std::string& projectPath) {
m_lastWindowTitle.clear();
UpdateWindowTitle();
if (!hasSavedDockLayout) {
m_editorContext->GetEventBus().Publish(DockLayoutResetRequestedEvent{});
}
return true;
}

View File

@@ -6,6 +6,7 @@
#include "UI/DockHostStyle.h"
#include "UI/DockTabBarChrome.h"
#include <fstream>
#include <imgui.h>
#include <imgui_internal.h>
@@ -24,6 +25,8 @@ public:
[this](const DockLayoutResetRequestedEvent&) {
RequestReset();
});
m_layoutDirty = true;
m_forceRebuild = false;
}
void Detach() {
@@ -34,10 +37,12 @@ public:
m_context = nullptr;
m_resetLayoutHandlerId = 0;
m_layoutDirty = true;
m_forceRebuild = false;
}
void RequestReset() {
m_layoutDirty = true;
m_forceRebuild = true;
}
void RenderDockspace() {
@@ -65,8 +70,11 @@ public:
}
if (m_layoutDirty) {
BuildDefaultLayout(dockspaceId, viewport->Size);
if (m_forceRebuild || !HasSavedDockLayout()) {
BuildDefaultLayout(dockspaceId, viewport->Size);
}
m_layoutDirty = false;
m_forceRebuild = false;
}
UI::ConfigureDockTabBarChrome(dockspaceId);
@@ -74,6 +82,31 @@ public:
}
private:
static bool HasSavedDockLayout() {
if (ImGui::GetCurrentContext() == nullptr) {
return false;
}
const char* iniFilename = ImGui::GetIO().IniFilename;
if (iniFilename == nullptr || iniFilename[0] == '\0') {
return false;
}
std::ifstream input(iniFilename, std::ios::in);
if (!input.is_open()) {
return false;
}
std::string line;
while (std::getline(input, line)) {
if (line == "[Docking][Data]") {
return true;
}
}
return false;
}
void BuildDefaultLayout(ImGuiID dockspaceId, const ImVec2& dockspaceSize) {
ImGui::DockBuilderRemoveNode(dockspaceId);
ImGui::DockBuilderAddNode(dockspaceId, m_dockspaceFlags | ImGuiDockNodeFlags_DockSpace);
@@ -97,6 +130,7 @@ private:
IEditorContext* m_context = nullptr;
uint64_t m_resetLayoutHandlerId = 0;
bool m_layoutDirty = true;
bool m_forceRebuild = false;
ImGuiDockNodeFlags m_dockspaceFlags = ImGuiDockNodeFlags_NoWindowMenuButton;
};

View File

@@ -5,6 +5,7 @@
#include <imgui.h>
#include <filesystem>
#include <fstream>
#include <string>
namespace XCEngine {
@@ -48,15 +49,17 @@ public:
return m_iniPath;
}
void SetProjectPath(const std::string& projectPath) {
bool SetProjectPath(const std::string& projectPath) {
if (ImGui::GetCurrentContext() == nullptr) {
return;
return false;
}
SaveSettings();
ImGuiIO& io = ImGui::GetIO();
ConfigureIniFile(projectPath, io);
const bool hasSavedLayout = HasSavedDockLayoutOnDisk(m_iniPath);
ImGui::LoadIniSettingsFromDisk(m_iniPath.c_str());
return hasSavedLayout;
}
private:
@@ -64,6 +67,27 @@ private:
static constexpr const char* kPrimaryUiFontPath = "C:/Windows/Fonts/segoeui.ttf";
static constexpr const char* kChineseFallbackFontPath = "C:/Windows/Fonts/msyh.ttc";
static bool HasSavedDockLayoutOnDisk(const std::filesystem::path& iniPath) {
std::error_code ec;
if (!std::filesystem::is_regular_file(iniPath, ec) || ec) {
return false;
}
std::ifstream input(iniPath, std::ios::in);
if (!input.is_open()) {
return false;
}
std::string line;
while (std::getline(input, line)) {
if (line == "[Docking][Data]") {
return true;
}
}
return false;
}
void ConfigureIniFile(const std::string& projectPath, ImGuiIO& io) {
const std::filesystem::path configDir = std::filesystem::path(projectPath) / ".xceditor";
std::error_code ec;