2023-05-11 18:44:50 +02:00
|
|
|
#include <hex/api/layout_manager.hpp>
|
|
|
|
|
|
|
|
#include <hex/helpers/fs.hpp>
|
2023-12-06 13:49:58 +01:00
|
|
|
#include <hex/helpers/logger.hpp>
|
2024-01-30 15:50:00 +01:00
|
|
|
#include <hex/helpers/auto_reset.hpp>
|
2023-05-11 18:44:50 +02:00
|
|
|
#include <wolv/utils/string.hpp>
|
|
|
|
|
|
|
|
#include <imgui.h>
|
2023-12-06 13:49:58 +01:00
|
|
|
#include <hex/api/content_registry.hpp>
|
2023-12-24 14:51:47 +01:00
|
|
|
#include <hex/ui/view.hpp>
|
2023-05-11 23:21:52 +02:00
|
|
|
|
2023-05-11 18:44:50 +02:00
|
|
|
namespace hex {
|
|
|
|
|
2023-07-26 13:50:51 +02:00
|
|
|
namespace {
|
|
|
|
|
2024-01-30 11:21:34 +01:00
|
|
|
AutoReset<std::optional<std::fs::path>> s_layoutPathToLoad;
|
|
|
|
AutoReset<std::optional<std::string>> s_layoutStringToLoad;
|
|
|
|
AutoReset<std::vector<LayoutManager::Layout>> s_layouts;
|
2023-07-26 13:50:51 +02:00
|
|
|
|
2024-02-10 23:31:05 +01:00
|
|
|
AutoReset<std::vector<LayoutManager::LoadCallback>> s_loadCallbacks;
|
|
|
|
AutoReset<std::vector<LayoutManager::StoreCallback>> s_storeCallbacks;
|
|
|
|
|
2023-12-06 13:49:58 +01:00
|
|
|
bool s_layoutLocked = false;
|
|
|
|
|
2023-07-26 13:50:51 +02:00
|
|
|
}
|
|
|
|
|
2023-05-11 18:44:50 +02:00
|
|
|
|
|
|
|
void LayoutManager::load(const std::fs::path &path) {
|
|
|
|
s_layoutPathToLoad = path;
|
|
|
|
}
|
|
|
|
|
2023-12-11 15:54:22 +01:00
|
|
|
void LayoutManager::loadFromString(const std::string &content) {
|
2023-05-11 18:44:50 +02:00
|
|
|
s_layoutStringToLoad = content;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LayoutManager::save(const std::string &name) {
|
|
|
|
auto fileName = name;
|
|
|
|
fileName = wolv::util::replaceStrings(fileName, " ", "_");
|
2024-01-30 11:21:34 +01:00
|
|
|
std::ranges::transform(fileName, fileName.begin(), tolower);
|
2023-05-11 18:44:50 +02:00
|
|
|
fileName += ".hexlyt";
|
|
|
|
|
2023-12-06 13:49:58 +01:00
|
|
|
std::fs::path layoutPath;
|
|
|
|
for (const auto &path : hex::fs::getDefaultPaths(fs::ImHexPath::Layouts)) {
|
|
|
|
if (!hex::fs::isPathWritable(layoutPath))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
layoutPath = path / fileName;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (layoutPath.empty()) {
|
|
|
|
log::error("Failed to save layout '{}'. No writable path found", name);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto pathString = wolv::util::toUTF8String(layoutPath);
|
|
|
|
ImGui::SaveIniSettingsToDisk(pathString.c_str());
|
|
|
|
log::info("Layout '{}' saved to {}", name, pathString);
|
2023-05-11 18:44:50 +02:00
|
|
|
|
|
|
|
LayoutManager::reload();
|
|
|
|
}
|
|
|
|
|
2023-12-11 15:54:22 +01:00
|
|
|
std::string LayoutManager::saveToString() {
|
|
|
|
return ImGui::SaveIniSettingsToMemory();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-02-28 22:10:48 +01:00
|
|
|
const std::vector<LayoutManager::Layout>& LayoutManager::getLayouts() {
|
2023-05-11 18:44:50 +02:00
|
|
|
return s_layouts;
|
|
|
|
}
|
|
|
|
|
2024-02-28 22:10:48 +01:00
|
|
|
void LayoutManager::removeLayout(const std::string& name) {
|
|
|
|
for (const auto &layout : *s_layouts) {
|
|
|
|
if (layout.name == name) {
|
|
|
|
if (wolv::io::File(layout.path, wolv::io::File::Mode::Write).remove()) {
|
|
|
|
log::info("Removed layout '{}'", name);
|
|
|
|
LayoutManager::reload();
|
|
|
|
} else {
|
|
|
|
log::error("Failed to remove layout '{}'", name);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-12-24 14:51:47 +01:00
|
|
|
void LayoutManager::closeAllViews() {
|
|
|
|
for (const auto &[name, view] : ContentRegistry::Views::impl::getEntries())
|
|
|
|
view->getWindowOpenState() = false;
|
|
|
|
}
|
|
|
|
|
2023-05-11 18:44:50 +02:00
|
|
|
void LayoutManager::process() {
|
2024-01-30 11:21:34 +01:00
|
|
|
if (s_layoutPathToLoad->has_value()) {
|
|
|
|
const auto pathString = wolv::util::toUTF8String(**s_layoutPathToLoad);
|
2023-12-24 14:51:47 +01:00
|
|
|
|
|
|
|
LayoutManager::closeAllViews();
|
2023-12-06 13:49:58 +01:00
|
|
|
ImGui::LoadIniSettingsFromDisk(pathString.c_str());
|
2023-12-24 14:51:47 +01:00
|
|
|
|
2023-05-11 18:44:50 +02:00
|
|
|
s_layoutPathToLoad = std::nullopt;
|
2023-12-06 13:49:58 +01:00
|
|
|
log::info("Loaded layout from {}", pathString);
|
2023-05-11 18:44:50 +02:00
|
|
|
}
|
|
|
|
|
2024-01-30 11:21:34 +01:00
|
|
|
if (s_layoutStringToLoad->has_value()) {
|
2023-12-24 14:51:47 +01:00
|
|
|
LayoutManager::closeAllViews();
|
2024-01-30 11:21:34 +01:00
|
|
|
ImGui::LoadIniSettingsFromMemory((*s_layoutStringToLoad)->c_str());
|
2023-12-24 14:51:47 +01:00
|
|
|
|
2023-05-11 18:44:50 +02:00
|
|
|
s_layoutStringToLoad = std::nullopt;
|
2023-12-06 13:49:58 +01:00
|
|
|
log::info("Loaded layout from string");
|
2023-05-11 18:44:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void LayoutManager::reload() {
|
2024-01-30 11:21:34 +01:00
|
|
|
s_layouts->clear();
|
2023-05-11 18:44:50 +02:00
|
|
|
|
|
|
|
for (const auto &directory : hex::fs::getDefaultPaths(fs::ImHexPath::Layouts)) {
|
|
|
|
for (const auto &entry : std::fs::directory_iterator(directory)) {
|
|
|
|
const auto &path = entry.path();
|
|
|
|
|
|
|
|
if (path.extension() != ".hexlyt")
|
|
|
|
continue;
|
|
|
|
|
|
|
|
auto name = path.stem().string();
|
|
|
|
name = wolv::util::replaceStrings(name, "_", " ");
|
|
|
|
for (size_t i = 0; i < name.size(); i++) {
|
|
|
|
if (i == 0 || name[i - 1] == '_')
|
|
|
|
name[i] = char(std::toupper(name[i]));
|
|
|
|
}
|
|
|
|
|
2024-01-30 11:21:34 +01:00
|
|
|
s_layouts->push_back({
|
2023-05-11 18:44:50 +02:00
|
|
|
name,
|
|
|
|
path
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-11 23:21:52 +02:00
|
|
|
void LayoutManager::reset() {
|
|
|
|
s_layoutPathToLoad.reset();
|
|
|
|
s_layoutStringToLoad.reset();
|
2024-01-30 11:21:34 +01:00
|
|
|
s_layouts->clear();
|
2023-05-11 23:21:52 +02:00
|
|
|
}
|
|
|
|
|
2023-12-06 13:49:58 +01:00
|
|
|
bool LayoutManager::isLayoutLocked() {
|
|
|
|
return s_layoutLocked;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LayoutManager::lockLayout(bool locked) {
|
|
|
|
log::info("Layout {}", locked ? "locked" : "unlocked");
|
|
|
|
s_layoutLocked = locked;
|
|
|
|
}
|
|
|
|
|
2024-02-10 23:31:05 +01:00
|
|
|
void LayoutManager::registerLoadCallback(const LoadCallback &callback) {
|
|
|
|
s_loadCallbacks->push_back(callback);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LayoutManager::registerStoreCallback(const StoreCallback &callback) {
|
|
|
|
s_storeCallbacks->push_back(callback);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LayoutManager::onLoad(std::string_view line) {
|
|
|
|
for (const auto &callback : *s_loadCallbacks)
|
|
|
|
callback(line);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LayoutManager::onStore(ImGuiTextBuffer *buffer) {
|
|
|
|
for (const auto &callback : *s_storeCallbacks)
|
|
|
|
callback(buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-12-06 13:49:58 +01:00
|
|
|
}
|