Skip to content

Commit

Permalink
Remember dockSpaces ids from previous runs (added SplitIdsHelper + se…
Browse files Browse the repository at this point in the history
…rialization)
  • Loading branch information
pthom committed Sep 19, 2024
1 parent 9480a37 commit a54cc5f
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 20 deletions.
6 changes: 1 addition & 5 deletions src/hello_imgui/doc_params.md
Original file line number Diff line number Diff line change
Expand Up @@ -1310,11 +1310,7 @@ struct DockingParams
bool focusDockableWindow(const std::string& windowName);

// `optional<ImGuiID> dockSpaceIdFromName(const std::string& dockSpaceName)`:
// may return the ImGuiID corresponding to the dockspace with this name.
// **Warning**: this will work reliably only if
// layoutCondition = DockingLayoutCondition::ApplicationStart.
// In other cases, the ID may be cached by ImGui himself at the first run,
// and HelloImGui will *not* know it on subsequent runs!
// returns the ImGuiID corresponding to the dockspace with this name
std::optional<ImGuiID> dockSpaceIdFromName(const std::string& dockSpaceName);
};
```
Expand Down
6 changes: 1 addition & 5 deletions src/hello_imgui/docking_params.h
Original file line number Diff line number Diff line change
Expand Up @@ -364,11 +364,7 @@ struct DockingParams
bool focusDockableWindow(const std::string& windowName);

// `optional<ImGuiID> dockSpaceIdFromName(const std::string& dockSpaceName)`:
// may return the ImGuiID corresponding to the dockspace with this name.
// **Warning**: this will work reliably only if
// layoutCondition = DockingLayoutCondition::ApplicationStart.
// In other cases, the ID may be cached by ImGui himself at the first run,
// and HelloImGui will *not* know it on subsequent runs!
// returns the ImGuiID corresponding to the dockspace with this name
std::optional<ImGuiID> dockSpaceIdFromName(const std::string& dockSpaceName);
};
// @@md
Expand Down
75 changes: 65 additions & 10 deletions src/hello_imgui/internal/docking_details.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "hello_imgui/hello_imgui.h"
#include "hello_imgui/internal/functional_utils.h"
#include "imgui_internal.h"
#include "nlohmann/json.hpp"
#include <map>
#include <vector>
#include <cassert>
Expand All @@ -17,8 +18,60 @@ namespace HelloImGui
// From hello_imgui.cpp
bool ShouldRemoteDisplay();

namespace SplitIdsHelper
{
std::map<DockSpaceName, ImGuiID> gImGuiSplitIDs;

bool ContainsSplit(const DockSpaceName& dockSpaceName)
{
return gImGuiSplitIDs.find(dockSpaceName) != gImGuiSplitIDs.end();
}

ImGuiID GetSplitId(const DockSpaceName& dockSpaceName)
{
IM_ASSERT(ContainsSplit(dockSpaceName) && "GetSplitId: dockSpaceName not found in gImGuiSplitIDs");
return gImGuiSplitIDs.at(dockSpaceName);
}

std::map<DockSpaceName, ImGuiID> gImGuiSplitIDs;
void SetSplitId(const DockSpaceName& dockSpaceName, ImGuiID imguiId)
{
gImGuiSplitIDs[dockSpaceName] = imguiId;
}

std::string SaveSplitIds()
{
// Serialize gImGuiSplitIDs using json
nlohmann::json j;
j["gImGuiSplitIDs"] = gImGuiSplitIDs;
return j.dump();
}

void LoadSplitIds(const std::string& jsonStr)
{
// Deserialize gImGuiSplitIDs using json
try
{
nlohmann::json j = nlohmann::json::parse(jsonStr);
gImGuiSplitIDs = j.at("gImGuiSplitIDs").get<std::map<DockSpaceName, ImGuiID>>();
}
catch (const nlohmann::json::parse_error& e)
{
std::cerr << "LoadSplitIds: Failed to parse JSON: " << e.what() << std::endl;
}
catch (const nlohmann::json::type_error& e)
{
std::cerr << "LoadSplitIds: Type error during deserialization: " << e.what() << std::endl;
}
catch (const nlohmann::json::out_of_range& e)
{
std::cerr << "LoadSplitIds: Missing or incorrect key in JSON: " << e.what() << std::endl;
}
catch (const std::exception& e)
{
std::cerr << "LoadSplitIds: Unexpected error: " << e.what() << std::endl;
}
}
}


static bool gShowTweakWindow = false;
Expand Down Expand Up @@ -65,9 +118,9 @@ bool _makeImGuiWindowTabVisible(const std::string& windowName)

void DoSplit(const DockingSplit & dockingSplit)
{
IM_ASSERT(gImGuiSplitIDs.find(dockingSplit.initialDock) != gImGuiSplitIDs.end());
IM_ASSERT(SplitIdsHelper::ContainsSplit(dockingSplit.initialDock) && "DoSplit: initialDock not found in gImGuiSplitIDs");

ImGuiID initialDock_imguiId = gImGuiSplitIDs.at(dockingSplit.initialDock);
ImGuiID initialDock_imguiId = SplitIdsHelper::GetSplitId(dockingSplit.initialDock);
ImGuiID newDock_imguiId
= ImGui::DockBuilderSplitNode(
initialDock_imguiId,
Expand All @@ -76,8 +129,8 @@ void DoSplit(const DockingSplit & dockingSplit)
nullptr,
&initialDock_imguiId);

gImGuiSplitIDs[dockingSplit.initialDock] = initialDock_imguiId;
gImGuiSplitIDs[dockingSplit.newDock] = newDock_imguiId;
SplitIdsHelper::SetSplitId(dockingSplit.initialDock, initialDock_imguiId);
SplitIdsHelper::SetSplitId(dockingSplit.newDock, newDock_imguiId);

// apply flags
ImGuiDockNode* newDockNode = ImGui::DockBuilderGetNode(newDock_imguiId);
Expand All @@ -94,10 +147,12 @@ void ApplyWindowDockingLocations(
const std::vector<DockableWindow> & dockableWindows)
{
for (const auto & dockableWindow: dockableWindows)
{
ImGui::DockBuilderDockWindow(
dockableWindow.label.c_str(),
gImGuiSplitIDs[dockableWindow.dockSpaceName]
SplitIdsHelper::GetSplitId(dockableWindow.dockSpaceName)
);
}
}

std::vector<std::string> _GetStaticallyOrderedLayoutsList(const RunnerParams& runnerParams)
Expand Down Expand Up @@ -524,7 +579,7 @@ void ImplProvideFullScreenDockSpace(const RunnerParams& runnerParams)
DoCreateFullScreenImGuiWindow(runnerParams, true);
ImGuiID mainDockspaceId = ImGui::GetID("MainDockSpace");
ImGui::DockSpace(mainDockspaceId, ImVec2(0.0f, 0.0f), runnerParams.dockingParams.mainDockSpaceNodeFlags);
gImGuiSplitIDs["MainDockSpace"] = mainDockspaceId;
SplitIdsHelper::SetSplitId("MainDockSpace", mainDockspaceId);
}

void ConfigureImGuiDocking(const ImGuiWindowParams& imGuiWindowParams)
Expand Down Expand Up @@ -602,10 +657,10 @@ bool DockingParams::focusDockableWindow(const std::string& windowName)

std::optional<ImGuiID> DockingParams::dockSpaceIdFromName(const std::string& dockSpaceName)
{
if (gImGuiSplitIDs.find(dockSpaceName) == gImGuiSplitIDs.end())
return std::nullopt;
if (SplitIdsHelper::ContainsSplit(dockSpaceName))
return SplitIdsHelper::GetSplitId(dockSpaceName);
else
return gImGuiSplitIDs.at(dockSpaceName);
return std::nullopt;
}


Expand Down
27 changes: 27 additions & 0 deletions src/hello_imgui/internal/hello_imgui_ini_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@

namespace HelloImGui
{
// Encapsulated in docking_details.cpp
namespace SplitIdsHelper
{
std::string SaveSplitIds();
void LoadSplitIds(const std::string&);
}


std::string IntPairToString(std::array<int, 2> v);
std::array<int, 2> StringToIntPair(const std::string& s);

Expand Down Expand Up @@ -379,6 +387,21 @@ namespace HelloImGui
}
}

void LoadSplitIds(const std::string& iniPartsFilename)
{
const std::string iniPartName = "SplitIds";
std::string serialized = LoadUserPref(iniPartsFilename, iniPartName);
if (!serialized.empty())
SplitIdsHelper::LoadSplitIds(serialized);
}

void SaveSplitIds(const std::string& iniPartsFilename)
{
const std::string iniPartName = "SplitIds";
std::string serialized = SplitIdsHelper::SaveSplitIds();
SaveUserPref(iniPartsFilename, iniPartName, serialized);
}

void LoadHelloImGuiMiscSettings(const std::string& iniPartsFilename, RunnerParams* inOutRunnerParams)
{
std::string iniPartName = "HelloImGui_Misc";
Expand Down Expand Up @@ -432,6 +455,8 @@ namespace HelloImGui
ImGuiTheme::ApplyTheme(theme);
}
HelloImGui::SwitchLayout(layoutName);

LoadSplitIds(iniPartsFilename);
}

void SaveHelloImGuiMiscSettings(const std::string& iniPartsFilename, const RunnerParams& runnerParams)
Expand All @@ -455,6 +480,8 @@ namespace HelloImGui
IniParts iniParts = IniParts::LoadFromFile(iniPartsFilename);
iniParts.SetIniPart(iniPartName, iniFile.encode());
iniParts.WriteToFile(iniPartsFilename);

SaveSplitIds(iniPartsFilename);
}


Expand Down

0 comments on commit a54cc5f

Please sign in to comment.