From 83593397ec8766a4af53f7c0253699cdb367d255 Mon Sep 17 00:00:00 2001 From: paxcut Date: Mon, 6 Jan 2025 08:48:48 -0700 Subject: [PATCH] fix: Bookmark comment shortcuts (issue #2055) Added the registrations for the editor shortcuts and reorganized the registration calls into events and handlers. Needed a way to select which of the possibly multiple editors sees the effects of the keyboard so a pointer to the current text editor in use was added to the view bookmarks class. The pointer may be empty so the shortcuts need to check it before using it. To detect which of the editors needs to see the effects of the shortcuts a function ws added to text editor that tells if window has focus. To avoid errors when editors become read only, asserts were exchanged with do-nothing early returns on the text editor. To avoid using the default language coloring (HLSL), the colorize enabling variable was set to false. A suggestion by cppcheck simplified the logic of a conditional on view bookmarks. On view pattern editor some icons were added to console menu entries. --- .../ColorTextEditor/include/TextEditor.h | 2 + .../ColorTextEditor/source/TextEditor.cpp | 40 +- .../include/content/views/view_bookmarks.hpp | 3 + .../source/content/views/view_bookmarks.cpp | 526 ++++++++++++------ .../content/views/view_pattern_editor.cpp | 8 +- 5 files changed, 381 insertions(+), 198 deletions(-) diff --git a/lib/third_party/imgui/ColorTextEditor/include/TextEditor.h b/lib/third_party/imgui/ColorTextEditor/include/TextEditor.h index f9cdd08674639..c6e1b06cdef96 100644 --- a/lib/third_party/imgui/ColorTextEditor/include/TextEditor.h +++ b/lib/third_party/imgui/ColorTextEditor/include/TextEditor.h @@ -342,6 +342,7 @@ class TextEditor mFocusAtCoords = coords; mUpdateFocus = true; } + bool GetWindowFocused() { return mWindowFocused; } void SetOverwrite(bool aValue) { mOverwrite = aValue; } std::string ReplaceStrings(std::string string, const std::string &search, const std::string &replace); @@ -641,6 +642,7 @@ class TextEditor bool mRaiseContextMenu = false; Coordinates mFocusAtCoords = {}; bool mUpdateFocus = false; + bool mWindowFocused = false; std::vector mClickableText; diff --git a/lib/third_party/imgui/ColorTextEditor/source/TextEditor.cpp b/lib/third_party/imgui/ColorTextEditor/source/TextEditor.cpp index c86d435baab2f..270246299820c 100644 --- a/lib/third_party/imgui/ColorTextEditor/source/TextEditor.cpp +++ b/lib/third_party/imgui/ColorTextEditor/source/TextEditor.cpp @@ -203,14 +203,11 @@ void TextEditor::Advance(Coordinates &aCoordinates) const { } void TextEditor::DeleteRange(const Coordinates &aStart, const Coordinates &aEnd) { - IM_ASSERT(aEnd >= aStart); - IM_ASSERT(!mReadOnly); + if (mReadOnly || aEnd <= aStart) + return; // printf("D(%d.%d)-(%d.%d)\n", aStart.mLine, aStart.mColumn, aEnd.mLine, aEnd.mColumn); - if (aEnd == aStart) - return; - auto start = GetCharacterIndex(aStart); auto end = GetCharacterIndex(aEnd); if (start == -1 || end == -1) @@ -293,7 +290,8 @@ int TextEditor::InsertTextAt(Coordinates & /* inout */ aWhere, const char *aValu } void TextEditor::AddUndo(UndoRecord &aValue) { - IM_ASSERT(!mReadOnly); + if (mReadOnly) + return; // printf("AddUndo: (@%d.%d) +\'%s' [%d.%d .. %d.%d], -\'%s', [%d.%d .. %d.%d] (@%d.%d)\n", // aValue.mBefore.mCursorPosition.mLine, aValue.mBefore.mCursorPosition.mColumn, // aValue.mAdded.c_str(), aValue.mAddedStart.mLine, aValue.mAddedStart.mColumn, aValue.mAddedEnd.mLine, aValue.mAddedEnd.mColumn, @@ -587,8 +585,8 @@ bool TextEditor::IsOnWordBoundary(const Coordinates &aAt) const { } void TextEditor::RemoveLine(int aStart, int aEnd) { - IM_ASSERT(!mReadOnly); - IM_ASSERT(aEnd >= aStart); + if (mReadOnly || aEnd < aStart) + return; ErrorMarkers etmp; for (auto &i : mErrorMarkers) { @@ -620,8 +618,8 @@ void TextEditor::RemoveLine(int aStart, int aEnd) { } void TextEditor::RemoveLine(int aIndex) { - IM_ASSERT(!mReadOnly); - IM_ASSERT(mLines.size() > 1); + if (mReadOnly || mLines.size() <= 1) + return; ErrorMarkers etmp; for (auto &i : mErrorMarkers) { @@ -948,7 +946,7 @@ void TextEditor::RenderText(const char *aTitle, const ImVec2 &lineNumbersStartPo } ImVec2 lineNoStartScreenPos = ImVec2(position.x, mTopMargin + cursorScreenPos.y + std::floor(lineNo) * mCharAdvance.y); auto start = ImVec2(lineNoStartScreenPos.x + mLineNumberFieldWidth, lineStartScreenPos.y); - bool focused = ImGui::IsWindowFocused(); + mWindowFocused = ImGui::IsWindowFocused(); if (!mIgnoreImGuiChild) ImGui::EndChild(); // Draw line number (right aligned) @@ -980,7 +978,7 @@ void TextEditor::RenderText(const char *aTitle, const ImVec2 &lineNumbersStartPo // Highlight the current line (where the cursor is) if (!HasSelection()) { auto end = ImVec2(lineNoStartScreenPos.x + contentSize.x + mLineNumberFieldWidth, lineStartScreenPos.y + mCharAdvance.y); - drawList->AddRectFilled(ImVec2(lineNumbersStartPos.x, lineStartScreenPos.y), end, mPalette[(int)(focused ? PaletteIndex::CurrentLineFill : PaletteIndex::CurrentLineFillInactive)]); + drawList->AddRectFilled(ImVec2(lineNumbersStartPos.x, lineStartScreenPos.y), end, mPalette[(int)(mWindowFocused ? PaletteIndex::CurrentLineFill : PaletteIndex::CurrentLineFillInactive)]); drawList->AddRect(ImVec2(lineNumbersStartPos.x, lineStartScreenPos.y), end, mPalette[(int)PaletteIndex::CurrentLineEdge], 1.0f); } } @@ -991,7 +989,7 @@ void TextEditor::RenderText(const char *aTitle, const ImVec2 &lineNumbersStartPo ImGui::BeginChild(aTitle); if (mState.mCursorPosition.mLine == lineNo && mShowCursor) { // Render the cursor - if (focused) { + if (mWindowFocused) { auto timeEnd = ImGui::GetTime() * 1000; auto elapsed = timeEnd - mStartTime; if (elapsed > sCursorBlinkOnTime) { @@ -1330,7 +1328,8 @@ void TextEditor::SetTextLines(const std::vector &aLines) { } void TextEditor::EnterCharacter(ImWchar aChar, bool aShift) { - IM_ASSERT(!mReadOnly); + if (mReadOnly) + return; UndoRecord u; @@ -1900,12 +1899,10 @@ void TextEditor::MoveEnd(bool aSelect) { } void TextEditor::Delete() { - ResetCursorBlinkTime(); - IM_ASSERT(!mReadOnly); - - if (isEmpty()) + if (mReadOnly || isEmpty()) return; + ResetCursorBlinkTime(); UndoRecord u; u.mBefore = mState; @@ -1957,12 +1954,11 @@ void TextEditor::Delete() { } void TextEditor::Backspace() { - ResetCursorBlinkTime(); - IM_ASSERT(!mReadOnly); - - if (isEmpty()) + if (mReadOnly || isEmpty()) return; + ResetCursorBlinkTime(); + UndoRecord u; u.mBefore = mState; diff --git a/plugins/builtin/include/content/views/view_bookmarks.hpp b/plugins/builtin/include/content/views/view_bookmarks.hpp index 9626eb252b9d3..d8299ba54995b 100644 --- a/plugins/builtin/include/content/views/view_bookmarks.hpp +++ b/plugins/builtin/include/content/views/view_bookmarks.hpp @@ -28,13 +28,16 @@ namespace hex::plugin::builtin { bool importBookmarks(hex::prv::Provider *provider, const nlohmann::json &json); bool exportBookmarks(hex::prv::Provider *provider, nlohmann::json &json); + void registerEvents(); void registerMenuItems(); + void registerHandlers(); private: std::string m_currFilter; PerProvider> m_bookmarks; PerProvider m_currBookmarkId; + TextEditor *m_currTextEditor; }; } \ No newline at end of file diff --git a/plugins/builtin/source/content/views/view_bookmarks.cpp b/plugins/builtin/source/content/views/view_bookmarks.cpp index b00ec5114b2f8..e362f3b1e98f2 100644 --- a/plugins/builtin/source/content/views/view_bookmarks.cpp +++ b/plugins/builtin/source/content/views/view_bookmarks.cpp @@ -21,180 +21,11 @@ namespace hex::plugin::builtin { ViewBookmarks::ViewBookmarks() : View::Window("hex.builtin.view.bookmarks.name", ICON_VS_BOOKMARK) { - // Handle bookmark add requests sent by the API - RequestAddBookmark::subscribe(this, [this](Region region, std::string name, std::string comment, color_t color, u64 *id) { - if (name.empty()) { - name = hex::format("hex.builtin.view.bookmarks.default_title"_lang, region.address, region.address + region.size - 1); - } - - if (color == 0x00) - color = ImGui::GetColorU32(ImGuiCol_Header); - - m_currBookmarkId += 1; - u64 bookmarkId = m_currBookmarkId; - if (id != nullptr) - *id = bookmarkId; - - auto bookmark = ImHexApi::Bookmarks::Entry { - region, - name, - std::move(comment), - color, - true, - bookmarkId - }; - - m_bookmarks->emplace_back(std::move(bookmark), TextEditor(), true); - - ImHexApi::Provider::markDirty(); - - EventBookmarkCreated::post(m_bookmarks->back().entry); - EventHighlightingChanged::post(); - }); - - RequestRemoveBookmark::subscribe([this](u64 id) { - std::erase_if(m_bookmarks.get(), [id](const auto &bookmark) { - return bookmark.entry.id == id; - }); - }); - - // Draw hex editor background highlights for bookmarks - ImHexApi::HexEditor::addBackgroundHighlightingProvider([this](u64 address, const u8* data, size_t size, bool) -> std::optional { - std::ignore = data; - - // Check all bookmarks for potential overlaps with the current address - std::optional color; - for (const auto &bookmark : *m_bookmarks) { - if (!bookmark.highlightVisible) - continue; - - if (Region { address, size }.isWithin(bookmark.entry.region)) { - color = blendColors(color, bookmark.entry.color); - } - } - - return color; - }); - - // Draw hex editor tooltips for bookmarks - ImHexApi::HexEditor::addTooltipProvider([this](u64 address, const u8 *data, size_t size) { - std::ignore = data; - - // Loop over all bookmarks - for (const auto &[bookmark, editor, highlightVisible] : *m_bookmarks) { - if (!highlightVisible) - continue; - - // Make sure the bookmark overlaps the currently hovered address - if (!Region { address, size }.isWithin(bookmark.region)) - continue; - - // Draw tooltip - ImGui::BeginTooltip(); - - ImGui::PushID(&bookmark); - if (ImGui::BeginTable("##tooltips", 1, ImGuiTableFlags_RowBg | ImGuiTableFlags_NoClip)) { - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - - { - // Draw bookmark header - ImGui::ColorButton("##color", ImColor(bookmark.color)); - ImGui::SameLine(0, 10); - ImGuiExt::TextFormatted("{} ", bookmark.name); - - // Draw extra information table when holding down shift - if (ImGui::GetIO().KeyShift) { - ImGui::Indent(); - if (ImGui::BeginTable("##extra_info", 2, ImGuiTableFlags_RowBg | ImGuiTableFlags_NoClip)) { - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - - // Draw region - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGuiExt::TextFormatted("{}: ", "hex.ui.common.region"_lang.get()); - ImGui::TableNextColumn(); - ImGuiExt::TextFormatted("[ 0x{:08X} - 0x{:08X} ] ", bookmark.region.getStartAddress(), bookmark.region.getEndAddress()); - - // Draw comment if it's not empty - if (!bookmark.comment.empty() && bookmark.comment[0] != '\x00') { - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGuiExt::TextFormatted("{}: ", "hex.builtin.view.bookmarks.header.comment"_lang.get()); - ImGui::TableNextColumn(); - ImGui::PushTextWrapPos(ImGui::CalcTextSize("X").x * 40); - ImGuiExt::TextFormattedWrapped("{}", bookmark.comment); - ImGui::PopTextWrapPos(); - } - - ImGui::EndTable(); - } - ImGui::Unindent(); - } - } - - - ImGui::PushStyleColor(ImGuiCol_TableRowBg, bookmark.color); - ImGui::PushStyleColor(ImGuiCol_TableRowBgAlt, bookmark.color); - ImGui::EndTable(); - ImGui::PopStyleColor(2); - } - ImGui::PopID(); - - ImGui::EndTooltip(); - } - }); - // Handle saving / restoring of bookmarks in projects - ProjectFile::registerPerProviderHandler({ - .basePath = "bookmarks.json", - .required = false, - .load = [this](prv::Provider *provider, const std::fs::path &basePath, const Tar &tar) -> bool { - auto fileContent = tar.readString(basePath); - if (fileContent.empty()) - return true; - - auto data = nlohmann::json::parse(fileContent.begin(), fileContent.end()); - m_bookmarks.get(provider).clear(); - return this->importBookmarks(provider, data); - }, - .store = [this](prv::Provider *provider, const std::fs::path &basePath, const Tar &tar) -> bool { - nlohmann::json data; - - bool result = this->exportBookmarks(provider, data); - tar.writeString(basePath, data.dump(4)); - - return result; - } - }); - - ContentRegistry::Reports::addReportProvider([this](prv::Provider *provider) -> std::string { - std::string result; - - const auto &bookmarks = m_bookmarks.get(provider); - if (bookmarks.empty()) - return ""; - - result += "## Bookmarks\n\n"; - - for (const auto &[bookmark, editor, highlightVisible] : bookmarks) { - result += hex::format("### {} [0x{:04X} - 0x{:04X}]\n\n", hex::changeEndianness(bookmark.color, std::endian::big) >> 8, bookmark.name, bookmark.region.getStartAddress(), bookmark.region.getEndAddress()); - - for (const auto &line : hex::splitString(bookmark.comment, "\n")) - result += hex::format("> {}\n", line); - result += "\n"; - - result += "```\n"; - result += hex::generateHexView(bookmark.region.getStartAddress(), bookmark.region.getSize(), provider); - result += "\n```\n\n"; - } - - return result; - }); + this->registerEvents(); this->registerMenuItems(); + this->registerHandlers(); } ViewBookmarks::~ViewBookmarks() { @@ -510,10 +341,15 @@ namespace hex::plugin::builtin { editor.SetShowLineNumbers(!locked); editor.SetShowCursor(!locked); editor.SetShowWhitespaces(false); + editor.SetColorizerEnable(false); - if (!locked || (locked && !comment.empty())) { + if (!locked || !comment.empty()) { if (ImGuiExt::BeginSubWindow("hex.builtin.view.bookmarks.header.comment"_lang)) { editor.Render("##comment", ImVec2(ImGui::GetContentRegionAvail().x, 150_scaled), false); + if (editor.GetWindowFocused()) + m_currTextEditor = &editor; + else if (m_currTextEditor == &editor) + m_currTextEditor = nullptr; } ImGuiExt::EndSubWindow(); @@ -597,6 +433,46 @@ namespace hex::plugin::builtin { return true; } + void ViewBookmarks::registerEvents() { + // Handle bookmark add requests sent by the API + RequestAddBookmark::subscribe(this, [this](Region region, std::string name, std::string comment, color_t color, u64 *id) { + if (name.empty()) { + name = hex::format("hex.builtin.view.bookmarks.default_title"_lang, region.address, region.address + region.size - 1); + } + + if (color == 0x00) + color = ImGui::GetColorU32(ImGuiCol_Header); + + m_currBookmarkId += 1; + u64 bookmarkId = m_currBookmarkId; + if (id != nullptr) + *id = bookmarkId; + + auto bookmark = ImHexApi::Bookmarks::Entry { + region, + name, + std::move(comment), + color, + true, + bookmarkId + }; + + m_bookmarks->emplace_back(std::move(bookmark), TextEditor(), true); + + ImHexApi::Provider::markDirty(); + + EventBookmarkCreated::post(m_bookmarks->back().entry); + EventHighlightingChanged::post(); + }); + + RequestRemoveBookmark::subscribe([this](u64 id) { + std::erase_if(m_bookmarks.get(), [id](const auto &bookmark) { + return bookmark.entry.id == id; + }); + }); + + } + void ViewBookmarks::registerMenuItems() { /* Create bookmark */ ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.menu.edit.bookmark.create" }, ICON_VS_BOOKMARK, 1900, CTRLCMD + Keys::B, [&] { @@ -635,4 +511,310 @@ namespace hex::plugin::builtin { }); } + void ViewBookmarks::registerHandlers() { + // Draw hex editor background highlights for bookmarks + ImHexApi::HexEditor::addBackgroundHighlightingProvider([this](u64 address, const u8* data, size_t size, bool) -> std::optional { + std::ignore = data; + + // Check all bookmarks for potential overlaps with the current address + std::optional color; + for (const auto &bookmark : *m_bookmarks) { + if (!bookmark.highlightVisible) + continue; + + if (Region { address, size }.isWithin(bookmark.entry.region)) { + color = blendColors(color, bookmark.entry.color); + } + } + + return color; + }); + + // Draw hex editor tooltips for bookmarks + ImHexApi::HexEditor::addTooltipProvider([this](u64 address, const u8 *data, size_t size) { + std::ignore = data; + + // Loop over all bookmarks + for (const auto &[bookmark, editor, highlightVisible] : *m_bookmarks) { + if (!highlightVisible) + continue; + + // Make sure the bookmark overlaps the currently hovered address + if (!Region { address, size }.isWithin(bookmark.region)) + continue; + + // Draw tooltip + ImGui::BeginTooltip(); + + ImGui::PushID(&bookmark); + if (ImGui::BeginTable("##tooltips", 1, ImGuiTableFlags_RowBg | ImGuiTableFlags_NoClip)) { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + + { + // Draw bookmark header + ImGui::ColorButton("##color", ImColor(bookmark.color)); + ImGui::SameLine(0, 10); + ImGuiExt::TextFormatted("{} ", bookmark.name); + + // Draw extra information table when holding down shift + if (ImGui::GetIO().KeyShift) { + ImGui::Indent(); + if (ImGui::BeginTable("##extra_info", 2, ImGuiTableFlags_RowBg | ImGuiTableFlags_NoClip)) { + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + + // Draw region + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGuiExt::TextFormatted("{}: ", "hex.ui.common.region"_lang.get()); + ImGui::TableNextColumn(); + ImGuiExt::TextFormatted("[ 0x{:08X} - 0x{:08X} ] ", bookmark.region.getStartAddress(), bookmark.region.getEndAddress()); + + // Draw comment if it's not empty + if (!bookmark.comment.empty() && bookmark.comment[0] != '\x00') { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGuiExt::TextFormatted("{}: ", "hex.builtin.view.bookmarks.header.comment"_lang.get()); + ImGui::TableNextColumn(); + ImGui::PushTextWrapPos(ImGui::CalcTextSize("X").x * 40); + ImGuiExt::TextFormattedWrapped("{}", bookmark.comment); + ImGui::PopTextWrapPos(); + } + + ImGui::EndTable(); + } + ImGui::Unindent(); + } + } + + + ImGui::PushStyleColor(ImGuiCol_TableRowBg, bookmark.color); + ImGui::PushStyleColor(ImGuiCol_TableRowBgAlt, bookmark.color); + ImGui::EndTable(); + ImGui::PopStyleColor(2); + } + ImGui::PopID(); + + ImGui::EndTooltip(); + } + }); + + // Handle saving / restoring of bookmarks in projects + ProjectFile::registerPerProviderHandler({ + .basePath = "bookmarks.json", + .required = false, + .load = [this](prv::Provider *provider, const std::fs::path &basePath, const Tar &tar) -> bool { + auto fileContent = tar.readString(basePath); + if (fileContent.empty()) + return true; + + auto data = nlohmann::json::parse(fileContent.begin(), fileContent.end()); + m_bookmarks.get(provider).clear(); + return this->importBookmarks(provider, data); + }, + .store = [this](prv::Provider *provider, const std::fs::path &basePath, const Tar &tar) -> bool { + nlohmann::json data; + + bool result = this->exportBookmarks(provider, data); + tar.writeString(basePath, data.dump(4)); + + return result; + } + }); + + ContentRegistry::Reports::addReportProvider([this](prv::Provider *provider) -> std::string { + std::string result; + + const auto &bookmarks = m_bookmarks.get(provider); + if (bookmarks.empty()) + return ""; + + result += "## Bookmarks\n\n"; + + for (const auto &[bookmark, editor, highlightVisible] : bookmarks) { + result += hex::format("### {} [0x{:04X} - 0x{:04X}]\n\n", hex::changeEndianness(bookmark.color, std::endian::big) >> 8, bookmark.name, bookmark.region.getStartAddress(), bookmark.region.getEndAddress()); + + for (const auto &line : hex::splitString(bookmark.comment, "\n")) + result += hex::format("> {}\n", line); + result += "\n"; + + result += "```\n"; + result += hex::generateHexView(bookmark.region.getStartAddress(), bookmark.region.getSize(), provider); + result += "\n```\n\n"; + } + + return result; + }); + + + + // ShortcutManager::addShortcut(this, CTRLCMD + Keys::Insert + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.copy", [this] { + // editor.Copy(); + // }); + + ShortcutManager::addShortcut(this, CTRLCMD + Keys::C + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.copy", [this] { + if (m_currTextEditor) m_currTextEditor->Copy(); + }); + + // ShortcutManager::addShortcut(this, SHIFT + Keys::Insert + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.paste", [this] { + // if (m_currTextEditor) editor.Paste(); + // }); + + ShortcutManager::addShortcut(this, CTRLCMD + Keys::V + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.paste", [this] { + if (m_currTextEditor) m_currTextEditor->Paste(); + }); + + ShortcutManager::addShortcut(this, CTRLCMD + Keys::X + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.cut", [this] { + if (m_currTextEditor) m_currTextEditor->Cut(); + }); + + // ShortcutManager::addShortcut(this, SHIFT + Keys::Delete + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.cut", [this] { + //if (m_currTextEditor) m_currTextEditor.Cut(); + // }); + + ShortcutManager::addShortcut(this, CTRLCMD + Keys::Z + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.undo", [this] { + if (m_currTextEditor) m_currTextEditor->Undo(); + }); + + // ShortcutManager::addShortcut(this, ALT + Keys::Backspace + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.undo", [this] { + // if (m_currTextEditor) m_currTextEditor.Undo(); + // }); + + ShortcutManager::addShortcut(this, Keys::Delete + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.delete", [this] { + if (m_currTextEditor) m_currTextEditor->Delete(); + }); + + ShortcutManager::addShortcut(this, CTRLCMD + Keys::Y + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.redo", [this] { + if (m_currTextEditor) m_currTextEditor->Redo(); + }); + + ShortcutManager::addShortcut(this, CTRLCMD + Keys::A + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.select_all", [this] { + if (m_currTextEditor) m_currTextEditor->SelectAll(); + }); + + ShortcutManager::addShortcut(this, SHIFT + Keys::Right + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.select_right", [this] { + if (m_currTextEditor) m_currTextEditor->MoveRight(1, true, false); + }); + + ShortcutManager::addShortcut(this, CTRLCMD + SHIFT + Keys::Right + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.select_word_right", [this] { + if (m_currTextEditor) m_currTextEditor->MoveRight(1, true, true); + }); + + ShortcutManager::addShortcut(this, SHIFT + Keys::Left + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.select_left", [this] { + if (m_currTextEditor) m_currTextEditor->MoveLeft(1, true, false); + }); + + ShortcutManager::addShortcut(this, CTRLCMD + SHIFT + Keys::Left + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.select_word_left", [this] { + if (m_currTextEditor) m_currTextEditor->MoveLeft(1, true, true); + }); + + ShortcutManager::addShortcut(this, SHIFT + Keys::Up + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.select_up", [this] { + if (m_currTextEditor) m_currTextEditor->MoveUp(1, true); + }); + + ShortcutManager::addShortcut(this, SHIFT +Keys::PageUp + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.select_page_up", [this] { + if (m_currTextEditor) m_currTextEditor->MoveUp(m_currTextEditor->GetPageSize()-4, true); + }); + + ShortcutManager::addShortcut(this, SHIFT + Keys::Down + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.select_down", [this] { + if (m_currTextEditor) m_currTextEditor->MoveDown(1, true); + }); + + ShortcutManager::addShortcut(this, SHIFT +Keys::PageDown + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.select_page_down", [this] { + if (m_currTextEditor) m_currTextEditor->MoveDown(m_currTextEditor->GetPageSize()-4, true); + }); + + ShortcutManager::addShortcut(this, CTRLCMD + SHIFT + Keys::Home + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.select_top", [this] { + if (m_currTextEditor) m_currTextEditor->MoveTop(true); + }); + + ShortcutManager::addShortcut(this, CTRLCMD + SHIFT + Keys::End + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.select_bottom", [this] { + if (m_currTextEditor) m_currTextEditor->MoveBottom(true); + }); + + ShortcutManager::addShortcut(this, SHIFT + Keys::Home + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.select_home", [this] { + if (m_currTextEditor) m_currTextEditor->MoveHome(true); + }); + + ShortcutManager::addShortcut(this, SHIFT + Keys::End + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.select_end", [this] { + if (m_currTextEditor) m_currTextEditor->MoveEnd(true); + }); + + ShortcutManager::addShortcut(this, CTRLCMD + Keys::Delete + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.delete_word_right", [this] { + if (m_currTextEditor) m_currTextEditor->DeleteWordRight(); + }); + + ShortcutManager::addShortcut(this, CTRLCMD + Keys::Backspace + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.delete_word_left", [this] { + if (m_currTextEditor) m_currTextEditor->DeleteWordLeft(); + }); + + ShortcutManager::addShortcut(this, Keys::Backspace + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.backspace", [this] { + if (m_currTextEditor) m_currTextEditor->Backspace(); + }); + + ShortcutManager::addShortcut(this, Keys::Insert + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.toggle_insert", [this] { + if (m_currTextEditor) m_currTextEditor->SetOverwrite(!m_currTextEditor->IsOverwrite()); + }); + + ShortcutManager::addShortcut(this, CTRLCMD + Keys::Right + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_word_right", [this] { + if (m_currTextEditor) m_currTextEditor->MoveRight(1, false, true); + }); + + ShortcutManager::addShortcut(this, Keys::Right + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_right", [this] { + if (m_currTextEditor) m_currTextEditor->MoveRight(1, false, false); + }); + + ShortcutManager::addShortcut(this, CTRLCMD + Keys::Left + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_word_left", [this] { + if (m_currTextEditor) m_currTextEditor->MoveLeft(1, false, true); + }); + + ShortcutManager::addShortcut(this, Keys::Left + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_left", [this] { + if (m_currTextEditor) m_currTextEditor->MoveLeft(1, false, false); + }); + + ShortcutManager::addShortcut(this, Keys::Up + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_up", [this] { + if (m_currTextEditor) m_currTextEditor->MoveUp(1, false); + }); + + ShortcutManager::addShortcut(this, ALT + Keys::Up + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_pixel_up", [this] { + if (m_currTextEditor) m_currTextEditor->MoveUp(-1, false); + }); + + ShortcutManager::addShortcut(this, Keys::PageUp + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_page_up", [this] { + if (m_currTextEditor) m_currTextEditor->MoveUp(m_currTextEditor->GetPageSize()-4, false); + }); + + ShortcutManager::addShortcut(this, Keys::Down + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_down", [this] { + if (m_currTextEditor) m_currTextEditor->MoveDown(1, false); + }); + + ShortcutManager::addShortcut(this, ALT+ Keys::Down + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_pixel_down", [this] { + if (m_currTextEditor) m_currTextEditor->MoveDown(-1, false); + }); + + ShortcutManager::addShortcut(this, Keys::PageDown + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_page_down", [this] { + if (m_currTextEditor) m_currTextEditor->MoveDown(m_currTextEditor->GetPageSize()-4, false); + }); + + ShortcutManager::addShortcut(this, CTRLCMD + Keys::Home + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_top", [this] { + if (m_currTextEditor) m_currTextEditor->MoveTop(false); + }); + + ShortcutManager::addShortcut(this, CTRLCMD + Keys::End + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_bottom", [this] { + if (m_currTextEditor) m_currTextEditor->MoveBottom(false); + }); + + ShortcutManager::addShortcut(this, Keys::Home + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_home", [this] { + if (m_currTextEditor) m_currTextEditor->MoveHome(false); + }); + + ShortcutManager::addShortcut(this, Keys::End + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_end", [this] { + if (m_currTextEditor) m_currTextEditor->MoveEnd(false); + }); + + + } + } \ No newline at end of file diff --git a/plugins/builtin/source/content/views/view_pattern_editor.cpp b/plugins/builtin/source/content/views/view_pattern_editor.cpp index c9e5d597b42e8..a191f665b4c22 100644 --- a/plugins/builtin/source/content/views/view_pattern_editor.cpp +++ b/plugins/builtin/source/content/views/view_pattern_editor.cpp @@ -1036,15 +1036,15 @@ namespace hex::plugin::builtin { const bool hasSelection = m_consoleEditor.HasSelection(); if (ImGui::BeginPopup("##console_context_menu")) { - if (ImGui::MenuItem("hex.builtin.view.hex_editor.menu.edit.copy"_lang, Shortcut(CTRLCMD + Keys::C).toString().c_str(), false, hasSelection)) { + if (ImGui::MenuItemEx("hex.builtin.view.hex_editor.menu.edit.copy"_lang, ICON_VS_COPY, Shortcut(CTRLCMD + Keys::C).toString().c_str(), false, hasSelection)) { m_consoleEditor.Copy(); } - if (ImGui::MenuItem("hex.builtin.view.hex_editor.menu.edit.select_all"_lang, Shortcut(CTRLCMD + Keys::A).toString().c_str())) { + if (ImGui::MenuItemEx("hex.builtin.view.hex_editor.menu.edit.select_all"_lang, ICON_VS_LIST_SELECTION, Shortcut(CTRLCMD + Keys::A).toString().c_str())) { m_consoleEditor.SelectAll(); } ImGui::Separator(); // Search and replace entries - if (ImGui::MenuItem("hex.builtin.view.pattern_editor.menu.find"_lang, Shortcut(CTRLCMD + Keys::F).toString().c_str())) { + if (ImGui::MenuItemEx("hex.builtin.view.pattern_editor.menu.find"_lang, ICON_VS_SEARCH, Shortcut(CTRLCMD + Keys::F).toString().c_str())) { m_openFindReplacePopUp = true; m_replaceMode = false; } @@ -1057,7 +1057,7 @@ namespace hex::plugin::builtin { ImGui::Separator(); - if (ImGui::MenuItem("hex.builtin.view.pattern_editor.menu.goto_line"_lang, Shortcut(ALT + Keys::G).toString().c_str())) + if (ImGui::MenuItemEx("hex.builtin.view.pattern_editor.menu.goto_line"_lang, ICON_VS_DEBUG_STEP_INTO, Shortcut(ALT + Keys::G).toString().c_str())) m_openGotoLinePopUp = true;