feat: Display pattern descriptions in file chooser and pattern popup

This commit is contained in:
WerWolv 2024-08-03 22:00:47 +02:00
parent e9f7908afb
commit 5dfd8c89a3
3 changed files with 60 additions and 23 deletions

View file

@ -18,8 +18,6 @@ namespace hex::plugin::builtin {
struct Workspace {
Workspace() = default;
std::unique_ptr<ImNodesContext, void(*)(ImNodesContext*)> context = { []{
ImNodesContext *ctx = ImNodes::CreateContext();
ctx->Style = ImNodes::GetStyle();

View file

@ -261,6 +261,8 @@ namespace hex::plugin::builtin {
bool m_parentHighlightingEnabled = true;
bool m_replaceMode = false;
std::map<std::fs::path, std::string> m_patternNames;
static inline std::array<std::string,256> m_findHistory;
static inline u32 m_findHistorySize = 0;
@ -281,7 +283,7 @@ namespace hex::plugin::builtin {
void drawFindReplaceDialog(std::string &findWord, bool &requestFocus, u64 &position, u64 &count, bool &updateCount);
void historyInsert(std::array<std::string,256> &history,u32 &size, u32 &index, const std::string &value);
void historyInsert(std::array<std::string, 256> &history, u32 &size, u32 &index, const std::string &value);
void loadPatternFile(const std::fs::path &path, prv::Provider *provider);
@ -306,12 +308,34 @@ namespace hex::plugin::builtin {
paths.push_back(entry.path());
}
}
ui::PopupFileChooser::open(
basePaths, paths, std::vector<hex::fs::ItemFilter>{ { "Pattern File", "hexpat" } }, false,
[this, provider](const std::fs::path &path) {
this->loadPatternFile(path, provider);
AchievementManager::unlockAchievement("hex.builtin.achievement.patterns", "hex.builtin.achievement.patterns.load_existing.name");
ui::PopupNamedFileChooser::open(
basePaths, paths, std::vector<hex::fs::ItemFilter>{ { "Pattern File", "hexpat" } }, false,
[this, provider](const std::fs::path &path, const std::fs::path &adjustedPath) mutable -> std::string {
auto it = m_patternNames.find(path);
if (it != m_patternNames.end()) {
return it->second;
}
const auto fileName = wolv::util::toUTF8String(adjustedPath.filename());
m_patternNames[path] = fileName;
pl::PatternLanguage runtime;
ContentRegistry::PatternLanguage::configureRuntime(runtime, provider);
runtime.addPragma("description", [&](pl::PatternLanguage &, const std::string &value) -> bool {
m_patternNames[path] = hex::format("{} ({})", value, fileName);
return true;
});
wolv::io::File file(path, wolv::io::File::Mode::Read);
hex::unused(runtime.preprocessString(file.readString(), pl::api::Source::DefaultSource));
return m_patternNames[path];
},
[this, provider](const std::fs::path &path) {
this->loadPatternFile(path, provider);
AchievementManager::unlockAchievement("hex.builtin.achievement.patterns", "hex.builtin.achievement.patterns.load_existing.name");
}
);
};

View file

@ -17,10 +17,10 @@ namespace hex::ui {
template<typename T>
class PopupNamedFileChooserBase : public Popup<T> {
public:
PopupNamedFileChooserBase(const std::vector<std::fs::path> &basePaths, const std::vector<std::fs::path> &files, const std::vector<hex::fs::ItemFilter> &validExtensions, bool multiple, const std::function<std::string(const std::fs::path &)> &nameCallback, const std::function<void(std::fs::path)> &callback)
PopupNamedFileChooserBase(const std::vector<std::fs::path> &basePaths, const std::vector<std::fs::path> &files, const std::vector<hex::fs::ItemFilter> &validExtensions, bool multiple, const std::function<void(std::fs::path)> &callback)
: hex::Popup<T>("hex.ui.common.choose_file"),
m_files(files),
m_selectedFiles({ }),
m_nameCallback(nameCallback),
m_openCallback(callback),
m_validExtensions(validExtensions),
m_multiple(multiple) {
@ -37,11 +37,11 @@ namespace hex::ui {
if (adjustedPath.empty())
adjustedPath = path.filename();
m_files.push_back({ path, adjustedPath });
m_adjustedPaths[path] = adjustedPath;
}
std::sort(m_files.begin(), m_files.end(), [](const auto &a, const auto &b) {
return a.first < b.first;
return a < b;
});
}
@ -59,9 +59,9 @@ namespace hex::ui {
if (ImGui::BeginListBox("##files", scaled(ImVec2(500, 400)))) {
for (auto fileIt = m_files.begin(); fileIt != m_files.end(); ++fileIt) {
const auto &[path, pathName] = *fileIt;
const auto &path = *fileIt;
const auto &pathNameString = m_nameCallback(pathName);
const auto &pathNameString = getEntryName(path);
if (!m_filter.empty() && !pathNameString.contains(m_filter))
continue;
@ -94,7 +94,7 @@ namespace hex::ui {
if (ImGui::Button("hex.ui.common.open"_lang) || doubleClicked) {
for (const auto &it : m_selectedFiles)
m_openCallback(it->first);
m_openCallback(*it);
Popup<T>::close();
}
@ -115,6 +115,14 @@ namespace hex::ui {
return ImGuiWindowFlags_AlwaysAutoResize;
}
protected:
const std::fs::path& getAdjustedPath(const std::fs::path &path) const {
return m_adjustedPaths.at(path);
}
virtual std::string getEntryName(const std::fs::path &path) = 0;
private:
static bool isSubpath(const std::fs::path &basePath, const std::fs::path &path) {
auto relativePath = std::fs::relative(path, basePath);
@ -124,9 +132,9 @@ namespace hex::ui {
private:
std::string m_filter;
std::vector<std::pair<std::fs::path, std::fs::path>> m_files;
std::set<std::vector<std::pair<std::fs::path, std::fs::path>>::const_iterator> m_selectedFiles;
std::function<std::string(const std::fs::path &)> m_nameCallback;
std::vector<std::fs::path> m_files;
std::map<std::fs::path, std::fs::path> m_adjustedPaths;
std::set<std::vector<std::fs::path>::const_iterator> m_selectedFiles;
std::function<void(std::fs::path)> m_openCallback;
std::vector<hex::fs::ItemFilter> m_validExtensions;
bool m_multiple = false;
@ -135,17 +143,24 @@ namespace hex::ui {
class PopupNamedFileChooser : public PopupNamedFileChooserBase<PopupNamedFileChooser> {
public:
PopupNamedFileChooser(const std::vector<std::fs::path> &basePaths, const std::vector<std::fs::path> &files, const std::vector<hex::fs::ItemFilter> &validExtensions, bool multiple, const std::function<std::string(const std::fs::path &)> &nameCallback, const std::function<void(std::fs::path)> &callback)
: PopupNamedFileChooserBase(basePaths, files, validExtensions, multiple, nameCallback, callback) { }
PopupNamedFileChooser(const std::vector<std::fs::path> &basePaths, const std::vector<std::fs::path> &files, const std::vector<hex::fs::ItemFilter> &validExtensions, bool multiple, const std::function<std::string(std::fs::path, std::fs::path)> &nameCallback, const std::function<void(std::fs::path)> &callback)
: PopupNamedFileChooserBase(basePaths, files, validExtensions, multiple, callback), m_nameCallback(nameCallback) { }
std::string getEntryName(const std::fs::path &path) override {
return m_nameCallback(path, getAdjustedPath(path));
}
private:
std::function<std::string(std::fs::path, std::fs::path)> m_nameCallback;
};
class PopupFileChooser : public PopupNamedFileChooserBase<PopupFileChooser> {
public:
PopupFileChooser(const std::vector<std::fs::path> &basePaths, const std::vector<std::fs::path> &files, const std::vector<hex::fs::ItemFilter> &validExtensions, bool multiple, const std::function<void(std::fs::path)> &callback)
: PopupNamedFileChooserBase(basePaths, files, validExtensions, multiple, nameCallback, callback) { }
: PopupNamedFileChooserBase(basePaths, files, validExtensions, multiple, callback) { }
static std::string nameCallback(const std::fs::path &path) {
return wolv::util::toUTF8String(path);
std::string getEntryName(const std::fs::path &path) override {
return wolv::util::toUTF8String(getAdjustedPath(path));
}
};