impr: Various fixes and an enhancement for the pattern editor (#1528)
Fixed console error messages using doc comment syntax highlights. Fixed results of find not updating when march case was toggled. Fixed syntax highlights of nested ifdefs. Fixed editor cursor blinks if OS focus goes to another window. Fixed Highlights of "\\\"" was incorrectly handled. --------- Co-authored-by: Nik <werwolv98@gmail.com>
This commit is contained in:
parent
f5987fde5a
commit
3b3701135f
@ -175,7 +175,7 @@ public:
|
||||
bool mCaseSensitive;
|
||||
|
||||
LanguageDefinition()
|
||||
: mGlobalDocComment("/*!"), mDocComment("/**"), mPreprocChar('#'), mAutoIndentation(true), mTokenize(nullptr), mCaseSensitive(true)
|
||||
: mPreprocChar('#'), mAutoIndentation(true), mTokenize(nullptr), mCaseSensitive(true)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -604,7 +604,7 @@ ImU32 TextEditor::GetGlyphColor(const Glyph &aGlyph) const {
|
||||
return mPalette[(int)PaletteIndex::Comment];
|
||||
if (aGlyph.mMultiLineComment)
|
||||
return mPalette[(int)PaletteIndex::MultiLineComment];
|
||||
if (aGlyph.mDeactivated && !aGlyph.mPreprocessor)
|
||||
if (aGlyph.mDeactivated)
|
||||
return mPalette[(int)PaletteIndex::PreprocessorDeactivated];
|
||||
auto const color = mPalette[(int)aGlyph.mColorIndex];
|
||||
if (aGlyph.mPreprocessor) {
|
||||
@ -621,8 +621,18 @@ ImU32 TextEditor::GetGlyphColor(const Glyph &aGlyph) const {
|
||||
void TextEditor::HandleKeyboardInputs() {
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
auto shift = io.KeyShift;
|
||||
auto ctrl = io.ConfigMacOSXBehaviors ? io.KeySuper : io.KeyCtrl;
|
||||
auto left = ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_LeftArrow));
|
||||
auto right = ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_RightArrow));
|
||||
auto up = ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_UpArrow));
|
||||
auto down = ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_DownArrow));
|
||||
auto ctrl = io.ConfigMacOSXBehaviors ? io.KeyAlt : io.KeyCtrl;
|
||||
auto alt = io.ConfigMacOSXBehaviors ? io.KeyCtrl : io.KeyAlt;
|
||||
auto home = io.ConfigMacOSXBehaviors ? io.KeySuper && left : ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Home));
|
||||
auto end = io.ConfigMacOSXBehaviors ? io.KeySuper && right : ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_End));
|
||||
auto top = io.ConfigMacOSXBehaviors ? io.KeySuper && up : ctrl && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Home));
|
||||
auto bottom = io.ConfigMacOSXBehaviors ? io.KeySuper && down : ctrl && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_End));
|
||||
auto pageUp = io.ConfigMacOSXBehaviors ? ctrl && up : ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_PageUp));
|
||||
auto pageDown = io.ConfigMacOSXBehaviors ? ctrl && down : ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_PageDown));
|
||||
|
||||
if (ImGui::IsWindowFocused()) {
|
||||
if (ImGui::IsWindowHovered())
|
||||
@ -638,25 +648,25 @@ void TextEditor::HandleKeyboardInputs() {
|
||||
Undo();
|
||||
else if (!IsReadOnly() && ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Y)))
|
||||
Redo();
|
||||
else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_UpArrow)))
|
||||
else if (!ctrl && !alt && up)
|
||||
MoveUp(1, shift);
|
||||
else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_DownArrow)))
|
||||
else if (!ctrl && !alt && down)
|
||||
MoveDown(1, shift);
|
||||
else if (!alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_LeftArrow)))
|
||||
else if (!alt && left)
|
||||
MoveLeft(1, shift, ctrl);
|
||||
else if (!alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_RightArrow)))
|
||||
else if (!alt && right)
|
||||
MoveRight(1, shift, ctrl);
|
||||
else if (!alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_PageUp)))
|
||||
else if (!alt && pageUp)
|
||||
MoveUp(GetPageSize() - 4, shift);
|
||||
else if (!alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_PageDown)))
|
||||
else if (!alt && pageDown)
|
||||
MoveDown(GetPageSize() - 4, shift);
|
||||
else if (!alt && ctrl && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Home)))
|
||||
else if (!alt && top)
|
||||
MoveTop(shift);
|
||||
else if (ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_End)))
|
||||
else if (!alt && bottom)
|
||||
MoveBottom(shift);
|
||||
else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Home)))
|
||||
else if (!ctrl && !alt && home)
|
||||
MoveHome(shift);
|
||||
else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_End)))
|
||||
else if (!ctrl && !alt && end)
|
||||
MoveEnd(shift);
|
||||
else if (!IsReadOnly() && !ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Delete)))
|
||||
Delete();
|
||||
@ -722,7 +732,7 @@ void TextEditor::HandleKeyboardInputs() {
|
||||
void TextEditor::HandleMouseInputs() {
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
auto shift = io.KeyShift;
|
||||
auto ctrl = io.ConfigMacOSXBehaviors ? io.KeySuper : io.KeyCtrl;
|
||||
auto ctrl = io.ConfigMacOSXBehaviors ? io.KeyAlt : io.KeyCtrl;
|
||||
auto alt = io.ConfigMacOSXBehaviors ? io.KeyCtrl : io.KeyAlt;
|
||||
|
||||
if (ImGui::IsWindowHovered()) {
|
||||
@ -905,7 +915,10 @@ void TextEditor::Render() {
|
||||
}
|
||||
|
||||
if (mState.mCursorPosition.mLine == lineNo && mShowCursor) {
|
||||
auto focused = ImGui::IsWindowFocused();
|
||||
bool focused = false;
|
||||
ImGuiViewport *viewport = ImGui::GetWindowViewport();
|
||||
if (viewport->PlatformUserData != NULL && ImGui::GetPlatformIO().Platform_GetWindowFocus(viewport))
|
||||
focused = ImGui::IsWindowFocused();
|
||||
|
||||
// Highlight the current line (where the cursor is)
|
||||
if (!HasSelection()) {
|
||||
@ -2505,6 +2518,7 @@ void TextEditor::ColorizeInternal() {
|
||||
auto firstChar = true; // there is no other non-whitespace characters in the line before
|
||||
auto currentLine = 0;
|
||||
auto currentIndex = 0;
|
||||
auto commentLength = 0;
|
||||
auto &startStr = mLanguageDefinition.mCommentStart;
|
||||
auto &singleStartStr = mLanguageDefinition.mSingleLineComment;
|
||||
auto &docStartStr = mLanguageDefinition.mDocComment;
|
||||
@ -2516,6 +2530,14 @@ void TextEditor::ColorizeInternal() {
|
||||
while (currentLine < endLine || currentIndex < endIndex) {
|
||||
auto &line = mLines[currentLine];
|
||||
|
||||
auto setGlyphFlags = [&](int index) {
|
||||
line[index].mMultiLineComment = withinComment;
|
||||
line[index].mComment = withinSingleLineComment;
|
||||
line[index].mDocComment = withinDocComment;
|
||||
line[index].mGlobalDocComment = withinGlobalDocComment;
|
||||
line[index].mDeactivated = withinNotDef;
|
||||
};
|
||||
|
||||
if (currentIndex == 0) {
|
||||
withinSingleLineComment = false;
|
||||
withinPreproc = false;
|
||||
@ -2532,24 +2554,12 @@ void TextEditor::ColorizeInternal() {
|
||||
bool inComment = (commentStartLine < currentLine || (commentStartLine == currentLine && commentStartIndex <= currentIndex));
|
||||
|
||||
if (withinString) {
|
||||
line[currentIndex].mMultiLineComment = withinComment;
|
||||
line[currentIndex].mComment = withinSingleLineComment;
|
||||
line[currentIndex].mDocComment = withinDocComment;
|
||||
line[currentIndex].mGlobalDocComment = withinGlobalDocComment;
|
||||
line[currentIndex].mDeactivated = withinNotDef;
|
||||
if (c == '\"') {
|
||||
if (currentIndex > 2 && line[currentIndex - 1].mChar == '\\' && line[currentIndex - 2].mChar != '\\') {
|
||||
currentIndex += 1;
|
||||
if (currentIndex < (int)line.size()) {
|
||||
line[currentIndex].mMultiLineComment = withinComment;
|
||||
line[currentIndex].mComment = withinSingleLineComment;
|
||||
line[currentIndex].mDocComment = withinDocComment;
|
||||
line[currentIndex].mGlobalDocComment = withinGlobalDocComment;
|
||||
line[currentIndex].mDeactivated = withinNotDef;
|
||||
}
|
||||
} else
|
||||
setGlyphFlags(currentIndex);
|
||||
if (c == '\\') {
|
||||
currentIndex++;
|
||||
setGlyphFlags(currentIndex);
|
||||
} else if (c == '\"')
|
||||
withinString = false;
|
||||
}
|
||||
} else {
|
||||
if (firstChar && c == mLanguageDefinition.mPreprocChar) {
|
||||
withinPreproc = true;
|
||||
@ -2594,7 +2604,6 @@ void TextEditor::ColorizeInternal() {
|
||||
}
|
||||
if (!withinNotDef) {
|
||||
bool isConditionMet = std::find(mDefines.begin(),mDefines.end(),identifier) != mDefines.end();
|
||||
withinNotDef = !isConditionMet;
|
||||
ifDefs.push_back(isConditionMet);
|
||||
} else
|
||||
ifDefs.push_back(false);
|
||||
@ -2608,7 +2617,6 @@ void TextEditor::ColorizeInternal() {
|
||||
}
|
||||
if (!withinNotDef) {
|
||||
bool isConditionMet = std::find(mDefines.begin(),mDefines.end(),identifier) == mDefines.end();
|
||||
withinNotDef = !isConditionMet;
|
||||
ifDefs.push_back(isConditionMet);
|
||||
} else
|
||||
ifDefs.push_back(false);
|
||||
@ -2616,20 +2624,17 @@ void TextEditor::ColorizeInternal() {
|
||||
}
|
||||
} else {
|
||||
if (directive == "endif") {
|
||||
if (ifDefs.size() > 1)
|
||||
if (ifDefs.size() > 1) {
|
||||
ifDefs.pop_back();
|
||||
withinNotDef = !ifDefs.back();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (c == '\"') {
|
||||
withinString = true;
|
||||
line[currentIndex].mMultiLineComment = withinComment;
|
||||
line[currentIndex].mComment = withinSingleLineComment;
|
||||
line[currentIndex].mDocComment = withinDocComment;
|
||||
line[currentIndex].mGlobalDocComment = withinGlobalDocComment;
|
||||
line[currentIndex].mDeactivated = withinNotDef;
|
||||
setGlyphFlags(currentIndex);
|
||||
} else {
|
||||
auto pred = [](const char &a, const Glyph &b) { return a == b.mChar; };
|
||||
|
||||
@ -2653,29 +2658,30 @@ void TextEditor::ColorizeInternal() {
|
||||
if (isGlobalDocComment || isDocComment || isComment) {
|
||||
commentStartLine = currentLine;
|
||||
commentStartIndex = currentIndex;
|
||||
if (isGlobalDocComment)
|
||||
if (isGlobalDocComment) {
|
||||
withinGlobalDocComment = true;
|
||||
else if (isDocComment)
|
||||
commentLength = 3;
|
||||
} else if (isDocComment) {
|
||||
withinDocComment = true;
|
||||
else
|
||||
commentLength = 3;
|
||||
} else {
|
||||
withinComment = true;
|
||||
commentLength = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
inComment = (commentStartLine < currentLine || (commentStartLine == currentLine && commentStartIndex <= currentIndex));
|
||||
}
|
||||
line[currentIndex].mGlobalDocComment = withinGlobalDocComment;
|
||||
line[currentIndex].mDocComment = withinDocComment;
|
||||
line[currentIndex].mMultiLineComment = withinComment;
|
||||
line[currentIndex].mComment = withinSingleLineComment;
|
||||
line[currentIndex].mDeactivated = withinNotDef;
|
||||
setGlyphFlags(currentIndex);
|
||||
|
||||
auto &endStr = mLanguageDefinition.mCommentEnd;
|
||||
if (compareBack(endStr, line)) {
|
||||
if (compareBack(endStr, line) && ((commentStartLine != currentLine) || (commentStartIndex + commentLength < currentIndex))) {
|
||||
withinComment = false;
|
||||
withinDocComment = false;
|
||||
withinGlobalDocComment = false;
|
||||
commentStartLine = endLine;
|
||||
commentStartIndex = endIndex;
|
||||
commentLength = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2684,6 +2690,7 @@ void TextEditor::ColorizeInternal() {
|
||||
|
||||
currentIndex += UTF8CharLength(c);
|
||||
if (currentIndex >= (int)line.size()) {
|
||||
withinNotDef = !ifDefs.back();
|
||||
currentIndex = 0;
|
||||
++currentLine;
|
||||
}
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include <functional>
|
||||
|
||||
#include <TextEditor.h>
|
||||
#include "popups/popup_file_chooser.hpp"
|
||||
#include "hex/api/achievement_manager.hpp"
|
||||
|
||||
namespace pl::ptrn { class Pattern; }
|
||||
|
||||
@ -255,6 +257,39 @@ namespace hex::plugin::builtin {
|
||||
void registerMenuItems();
|
||||
void registerHandlers();
|
||||
|
||||
std::function<void()> importPatternFile = [&] {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
const auto basePaths = fs::getDefaultPaths(fs::ImHexPath::Patterns);
|
||||
std::vector<std::fs::path> paths;
|
||||
|
||||
for (const auto &imhexPath : basePaths) {
|
||||
if (!wolv::io::fs::exists(imhexPath)) continue;
|
||||
|
||||
std::error_code error;
|
||||
for (auto &entry : std::fs::recursive_directory_iterator(imhexPath, error)) {
|
||||
if (entry.is_regular_file() && entry.path().extension() == ".hexpat")
|
||||
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");
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
std::function<void()> exportPatternFile = [&] {
|
||||
fs::openFileBrowser(
|
||||
fs::DialogMode::Save, { {"Pattern", "hexpat"} },
|
||||
[this](const auto &path) {
|
||||
wolv::io::File file(path, wolv::io::File::Mode::Create);
|
||||
file.writeString(wolv::util::trim(m_textEditor.GetText()));
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
void appendEditorText(const std::string &text);
|
||||
void appendVariable(const std::string &type);
|
||||
void appendArray(const std::string &type, size_t size);
|
||||
|
@ -135,6 +135,7 @@
|
||||
"hex.builtin.menu.file.export.ips32": "IPS32 Patch",
|
||||
"hex.builtin.menu.file.export.bookmark": "Bookmark",
|
||||
"hex.builtin.menu.file.export.pattern": "Pattern File",
|
||||
"hex.builtin.menu.file.export.pattern_file": "Export pattern File",
|
||||
"hex.builtin.menu.file.export.data_processor": "Data Processor Workspace",
|
||||
"hex.builtin.menu.file.export.popup.create": "Cannot export data. Failed to create file!",
|
||||
"hex.builtin.menu.file.export.report": "Report",
|
||||
@ -147,6 +148,7 @@
|
||||
"hex.builtin.menu.file.import.modified_file": "Modified File",
|
||||
"hex.builtin.menu.file.import.bookmark": "Bookmark",
|
||||
"hex.builtin.menu.file.import.pattern": "Pattern File",
|
||||
"hex.builtin.menu.file.import.pattern_file": "Import pattern File",
|
||||
"hex.builtin.menu.file.import.data_processor": "Data Processor Workspace",
|
||||
"hex.builtin.menu.file.import.custom_encoding": "Custom Encoding File",
|
||||
"hex.builtin.menu.file.import.modified_file.popup.invalid_size": "File selected do not have the same size as the current file. Both sizes must match",
|
||||
|
@ -3,13 +3,11 @@
|
||||
|
||||
#include <hex/api/content_registry.hpp>
|
||||
#include <hex/api/project_file_manager.hpp>
|
||||
#include <hex/api/achievement_manager.hpp>
|
||||
|
||||
#include <pl/patterns/pattern.hpp>
|
||||
#include <pl/core/preprocessor.hpp>
|
||||
#include <pl/core/parser.hpp>
|
||||
#include <pl/core/ast/ast_node_variable_decl.hpp>
|
||||
#include <pl/core/ast/ast_node_type_decl.hpp>
|
||||
#include <pl/core/ast/ast_node_builtin_type.hpp>
|
||||
|
||||
#include <hex/helpers/fs.hpp>
|
||||
@ -22,11 +20,9 @@
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
#include <fmt/chrono.h>
|
||||
|
||||
#include <popups/popup_file_chooser.hpp>
|
||||
#include <popups/popup_question.hpp>
|
||||
#include <toasts/toast_notification.hpp>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <chrono>
|
||||
|
||||
#include <wolv/io/file.hpp>
|
||||
@ -34,6 +30,8 @@
|
||||
#include <wolv/utils/guards.hpp>
|
||||
#include <wolv/utils/lock.hpp>
|
||||
|
||||
#include <content/global_actions.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
using namespace hex::literals;
|
||||
@ -88,6 +86,9 @@ namespace hex::plugin::builtin {
|
||||
langDef.mAutoIndentation = true;
|
||||
langDef.mPreprocChar = '#';
|
||||
|
||||
langDef.mGlobalDocComment = "/*!";
|
||||
langDef.mDocComment = "/**";
|
||||
|
||||
langDef.mName = "Pattern Language";
|
||||
|
||||
initialized = true;
|
||||
@ -236,6 +237,14 @@ namespace hex::plugin::builtin {
|
||||
bool clickedMenuFind = false;
|
||||
bool clickedMenuReplace = false;
|
||||
if (ImGui::BeginPopup("##pattern_editor_context_menu")) {
|
||||
// no shortcut for this
|
||||
if (ImGui::MenuItem("hex.builtin.menu.file.import.pattern_file"_lang, nullptr, false))
|
||||
importPatternFile();
|
||||
if (ImGui::MenuItem("hex.builtin.menu.file.export.pattern_file"_lang, nullptr, false))
|
||||
exportPatternFile();
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
const bool hasSelection = m_textEditor.HasSelection();
|
||||
if (ImGui::MenuItem("hex.builtin.view.hex_editor.menu.edit.cut"_lang, Shortcut(CTRLCMD + Keys::X).toString().c_str(), false, hasSelection)) {
|
||||
m_textEditor.Cut();
|
||||
@ -306,6 +315,12 @@ namespace hex::plugin::builtin {
|
||||
m_replaceMode = true;
|
||||
openFindPopup = true;
|
||||
}
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_S, false) && ImGui::GetIO().KeyAlt)
|
||||
hex::plugin::builtin::saveProject();
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_O, false) && ImGui::GetIO().KeyAlt)
|
||||
hex::plugin::builtin::openProject();
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_S, false) && ImGui::GetIO().KeyAlt && ImGui::GetIO().KeyShift)
|
||||
hex::plugin::builtin::saveProjectAs();
|
||||
}
|
||||
|
||||
static std::string findWord;
|
||||
@ -685,6 +700,8 @@ namespace hex::plugin::builtin {
|
||||
if (altCPressed)
|
||||
matchCase = !matchCase;
|
||||
findReplaceHandler->SetMatchCase(&m_textEditor,matchCase);
|
||||
position = findReplaceHandler->FindPosition(&m_textEditor,m_textEditor.GetCursorPosition(), true);
|
||||
count = findReplaceHandler->GetMatches().size();
|
||||
updateCount = true;
|
||||
requestFocusFind = true;
|
||||
}
|
||||
@ -1733,39 +1750,11 @@ namespace hex::plugin::builtin {
|
||||
void ViewPatternEditor::registerMenuItems() {
|
||||
/* Import Pattern */
|
||||
ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.file", "hex.builtin.menu.file.import", "hex.builtin.menu.file.import.pattern" }, ICON_VS_FILE_CODE, 4050, Shortcut::None,
|
||||
[this] {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
const auto basePaths = fs::getDefaultPaths(fs::ImHexPath::Patterns);
|
||||
std::vector<std::fs::path> paths;
|
||||
|
||||
for (const auto &imhexPath : basePaths) {
|
||||
if (!wolv::io::fs::exists(imhexPath)) continue;
|
||||
|
||||
std::error_code error;
|
||||
for (auto &entry : std::fs::recursive_directory_iterator(imhexPath, error)) {
|
||||
if (entry.is_regular_file() && entry.path().extension() == ".hexpat") {
|
||||
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");
|
||||
});
|
||||
}, ImHexApi::Provider::isValid);
|
||||
importPatternFile, ImHexApi::Provider::isValid);
|
||||
|
||||
/* Export Pattern */
|
||||
ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.file", "hex.builtin.menu.file.export", "hex.builtin.menu.file.export.pattern" }, ICON_VS_FILE_CODE, 7050, Shortcut::None,
|
||||
[this] {
|
||||
fs::openFileBrowser(fs::DialogMode::Save, { {"Pattern", "hexpat"} },
|
||||
[this](const auto &path) {
|
||||
wolv::io::File file(path, wolv::io::File::Mode::Create);
|
||||
|
||||
file.writeString(wolv::util::trim(m_textEditor.GetText()));
|
||||
});
|
||||
}, [this] {
|
||||
exportPatternFile, [this] {
|
||||
return !wolv::util::trim(m_textEditor.GetText()).empty() && ImHexApi::Provider::isValid();
|
||||
}
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user