1
0
mirror of synced 2025-02-17 10:58:34 +01:00

impr: Moved pattern editor shortcuts to the Shortcut manager (#1892)

### Problem description
There are some recent issues about Mac keys not configured properly for
the pattern editor. This PR moves all the shortcuts to the shortcut
manager, so they can be edited at will. Even if the key is not
identified correctly it should be possible to use preferred keys for any
action.

---------

Co-authored-by: Nik <werwolv98@gmail.com>
This commit is contained in:
paxcut 2024-09-15 06:18:50 -07:00 committed by GitHub
parent 187d90e8f2
commit 4b3bbb4a97
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 553 additions and 248 deletions

View File

@ -215,6 +215,7 @@ public:
FindReplaceHandler *GetFindReplaceHandler() { return &mFindReplaceHandler; }
int GetTotalLines() const { return (int)mLines.size(); }
bool IsOverwrite() const { return mOverwrite; }
void SetOverwrite(bool aValue) { mOverwrite = aValue; }
void SetReadOnly(bool aValue);
bool IsReadOnly() const { return mReadOnly; }
@ -268,6 +269,7 @@ public:
void Cut();
void Paste();
void Delete();
int32_t GetPageSize() const;
ImVec2 &GetCharAdvance() { return mCharAdvance; }
@ -276,6 +278,10 @@ public:
void Undo(int aSteps = 1);
void Redo(int aSteps = 1);
void DeleteWordLeft();
void DeleteWordRight();
void Backspace();
static const Palette& GetDarkPalette();
static const Palette& GetLightPalette();
static const Palette& GetRetroBluePalette();
@ -400,7 +406,6 @@ private:
void ColorizeInternal();
float TextDistanceToLineStart(const Coordinates& aFrom) const;
void EnsureCursorVisible();
int GetPageSize() const;
std::string GetText(const Coordinates& aStart, const Coordinates& aEnd) const;
Coordinates GetActualCursorCoordinates() const;
Coordinates SanitizeCoordinates(const Coordinates& aValue) const;
@ -425,7 +430,6 @@ private:
void RemoveLine(int aIndex);
Line& InsertLine(int aIndex);
void EnterCharacter(ImWchar aChar, bool aShift);
void Backspace();
void DeleteSelection();
std::string GetWordUnderCursor() const;
std::string GetWordAt(const Coordinates& aCoords) const;

View File

@ -304,6 +304,22 @@ TextEditor::Coordinates TextEditor::ScreenPosToCoordinates(const ImVec2 &aPositi
return SanitizeCoordinates(Coordinates(lineNo, columnCoord));
}
void TextEditor::DeleteWordLeft() {
const auto wordEnd = GetCursorPosition();
MoveLeft();
const auto wordStart = FindWordStart(GetCursorPosition());
SetSelection(wordStart, wordEnd);
Backspace();
}
void TextEditor::DeleteWordRight() {
const auto wordStart = GetCursorPosition();
MoveRight();
const auto wordEnd = FindWordEnd(GetCursorPosition());
SetSelection(wordStart, wordEnd);
Backspace();
}
bool isWordChar(char c) {
auto asUChar = static_cast<unsigned char>(c);
return std::isalnum(asUChar) || c == '_' || asUChar > 0x7F;
@ -640,21 +656,21 @@ void TextEditor::HandleKeyboardInputs() {
// command => Ctrl
// control => Super
// option => Alt
auto ctrl = io.KeyCtrl;
auto alt = io.KeyAlt;
auto shift = io.KeyShift;
auto left = ImGui::IsKeyPressed(ImGuiKey_LeftArrow);
/* auto left = ImGui::IsKeyPressed(ImGuiKey_LeftArrow);
auto right = ImGui::IsKeyPressed(ImGuiKey_RightArrow);
auto up = ImGui::IsKeyPressed(ImGuiKey_UpArrow);
auto down = ImGui::IsKeyPressed(ImGuiKey_DownArrow);
auto ctrl = io.KeyCtrl;
auto alt = io.KeyAlt;
auto home = io.ConfigMacOSXBehaviors ? io.KeySuper && left : ImGui::IsKeyPressed(ImGuiKey_Home);
auto end = io.ConfigMacOSXBehaviors ? io.KeySuper && right : ImGui::IsKeyPressed(ImGuiKey_End);
auto top = io.ConfigMacOSXBehaviors ? io.KeySuper && up : ctrl && ImGui::IsKeyPressed(ImGuiKey_Home);
auto bottom = io.ConfigMacOSXBehaviors ? io.KeySuper && down : ctrl && ImGui::IsKeyPressed(ImGuiKey_End);
auto pageUp = io.ConfigMacOSXBehaviors ? ctrl && up : ImGui::IsKeyPressed(ImGuiKey_PageUp);
auto pageDown = io.ConfigMacOSXBehaviors ? ctrl && down : ImGui::IsKeyPressed(ImGuiKey_PageDown);
*/
if (ImGui::IsWindowFocused()) {
if (ImGui::IsWindowHovered())
ImGui::SetMouseCursor(ImGuiMouseCursor_TextInput);
@ -663,87 +679,10 @@ void TextEditor::HandleKeyboardInputs() {
io.WantCaptureKeyboard = true;
io.WantTextInput = true;
bool handledKeyEvent = true;
if (!IsReadOnly() && ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_Z))
Undo();
else if (!IsReadOnly() && !ctrl && !shift && alt && ImGui::IsKeyPressed(ImGuiKey_Backspace))
Undo();
else if (!IsReadOnly() && ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_Y))
Redo();
else if (!ctrl && !alt && up)
MoveUp(1, shift);
else if (!ctrl && !alt && down)
MoveDown(1, shift);
else if (!alt && left)
MoveLeft(1, shift, ctrl);
else if (!alt && right)
MoveRight(1, shift, ctrl);
else if (!alt && pageUp)
MoveUp(GetPageSize() - 4, shift);
else if (!alt && pageDown)
MoveDown(GetPageSize() - 4, shift);
else if (!alt && top)
MoveTop(shift);
else if (!alt && bottom)
MoveBottom(shift);
else if (!ctrl && !alt && home)
MoveHome(shift);
else if (!ctrl && !alt && end)
MoveEnd(shift);
else if (!IsReadOnly() && !ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_Delete))
Delete();
else if (!IsReadOnly() && ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_Delete)) {
auto wordStart = GetCursorPosition();
MoveRight();
auto wordEnd = FindWordEnd(GetCursorPosition());
SetSelection(wordStart, wordEnd);
Backspace();
}
else if (!IsReadOnly() && !ctrl && !alt && ImGui::IsKeyPressed(ImGuiKey_Backspace))
Backspace();
else if (!IsReadOnly() && ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_Backspace)) {
auto wordEnd = GetCursorPosition();
MoveLeft();
auto wordStart = FindWordStart(GetCursorPosition());
SetSelection(wordStart, wordEnd);
Backspace();
}
else if (!ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_Insert))
mOverwrite = !mOverwrite;
else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_Insert))
Copy();
else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_C))
Copy();
else if (!IsReadOnly() && !ctrl && shift && !alt && ImGui::IsKeyPressed(ImGuiKey_Insert))
Paste();
else if (!IsReadOnly() && ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_V))
Paste();
else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_X))
Cut();
else if (!ctrl && shift && !alt && ImGui::IsKeyPressed(ImGuiKey_Delete))
Cut();
else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_A))
SelectAll();
else if (!IsReadOnly() && !ctrl && !shift && !alt && (ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_KeypadEnter)))
if (!IsReadOnly() && !ctrl && !shift && !alt && (ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_KeypadEnter)))
EnterCharacter('\n', false);
else if (!IsReadOnly() && !ctrl && !alt && ImGui::IsKeyPressed(ImGuiKey_Tab))
EnterCharacter('\t', shift);
else if (!ctrl && !alt && !shift && ImGui::IsKeyPressed(ImGuiKey_F3))
mFindReplaceHandler.FindMatch(this, true);
else if (!ctrl && !alt && shift && ImGui::IsKeyPressed(ImGuiKey_F3))
mFindReplaceHandler.FindMatch(this, false);
else if (!ctrl && alt && !shift && ImGui::IsKeyPressed(ImGuiKey_C))
mFindReplaceHandler.SetMatchCase(this,!mFindReplaceHandler.GetMatchCase());
else if (!ctrl && alt && !shift && ImGui::IsKeyPressed(ImGuiKey_R))
mFindReplaceHandler.SetFindRegEx(this,!mFindReplaceHandler.GetFindRegEx());
else if (!ctrl && alt && !shift && ImGui::IsKeyPressed(ImGuiKey_W))
mFindReplaceHandler.SetWholeWord(this,!mFindReplaceHandler.GetWholeWord());
else
handledKeyEvent = false;
if (handledKeyEvent)
ResetCursorBlinkTime();
if (!IsReadOnly() && !io.InputQueueCharacters.empty()) {
for (int i = 0; i < io.InputQueueCharacters.Size; i++) {

View File

@ -635,12 +635,12 @@ namespace hex {
EventViewOpened::post(view.get());
}
ImGui::End();
}
// Pass on currently pressed keys to the shortcut handler
for (const auto &key : m_pressedKeys) {
ShortcutManager::process(view.get(), io.KeyCtrl, io.KeyAlt, io.KeyShift, io.KeySuper, focused, key);
}
// Pass on currently pressed keys to the shortcut handler
for (const auto &key : m_pressedKeys) {
ShortcutManager::process(view.get(), io.KeyCtrl, io.KeyAlt, io.KeyShift, io.KeySuper, focused, key);
ImGui::End();
}
}
}

View File

@ -22,6 +22,15 @@ namespace pl::ptrn { class Pattern; }
namespace hex::plugin::builtin {
constexpr static auto textEditorView = "/Pattern editor_";
constexpr static auto consoleView = "/##console_";
constexpr static auto variablesView = "/##env_vars_";
constexpr static auto settingsView = "/##settings_";
constexpr static auto sectionsView = "/##sections_table_";
constexpr static auto virtualFilesView = "/Virtual File Tree_";
constexpr static auto debuggerView = "/##debugger_";
class PatternSourceCode {
public:
const std::string& get(prv::Provider *provider) {
@ -260,9 +269,13 @@ namespace hex::plugin::builtin {
u32 m_accessHistoryIndex = 0;
bool m_parentHighlightingEnabled = true;
bool m_replaceMode = false;
bool m_openFindReplacePopUp = false;
std::map<std::fs::path, std::string> m_patternNames;
ImRect m_textEditorHoverBox;
ImRect m_consoleHoverBox;
std::string m_focusedSubWindowName;
static inline std::array<std::string,256> m_findHistory;
static inline u32 m_findHistorySize = 0;
@ -281,7 +294,7 @@ namespace hex::plugin::builtin {
void drawPatternTooltip(pl::ptrn::Pattern *pattern);
void drawFindReplaceDialog(std::string &findWord, bool &requestFocus, u64 &position, u64 &count, bool &updateCount);
void drawFindReplaceDialog(TextEditor *textEditor, std::string &findWord, bool &requestFocus, u64 &position, u64 &count, bool &updateCount, bool canReplace);
void historyInsert(std::array<std::string, 256> &history, u32 &size, u32 &index, const std::string &value);
@ -290,6 +303,9 @@ namespace hex::plugin::builtin {
void parsePattern(const std::string &code, prv::Provider *provider);
void evaluatePattern(const std::string &code, prv::Provider *provider);
TextEditor *getEditorFromFocusedWindow();
void setupFindReplace(TextEditor *editor);
void registerEvents();
void registerMenuItems();
void registerHandlers();

View File

@ -920,6 +920,7 @@
"hex.builtin.view.pattern_editor.auto": "Auto evaluate",
"hex.builtin.view.pattern_editor.breakpoint_hit": "Halted at line {0}",
"hex.builtin.view.pattern_editor.console": "Console",
"hex.builtin.view.pattern_editor.console.shortcut.copy": "Copy",
"hex.builtin.view.pattern_editor.dangerous_function.desc": "This pattern tried to call a dangerous function.\nAre you sure you want to trust this pattern?",
"hex.builtin.view.pattern_editor.dangerous_function.name": "Allow dangerous function?",
"hex.builtin.view.pattern_editor.debugger": "Debugger",
@ -958,6 +959,51 @@
"hex.builtin.view.pattern_editor.sections.view": "View content",
"hex.builtin.view.pattern_editor.sections.export": "Export content",
"hex.builtin.view.pattern_editor.settings": "Settings",
"hex.builtin.view.pattern_editor.shortcut.find": "Search ...",
"hex.builtin.view.pattern_editor.shortcut.replace": "Replace ...",
"hex.builtin.view.pattern_editor.shortcut.find_next": "Find Next",
"hex.builtin.view.pattern_editor.shortcut.find_previous": "Find Previous",
"hex.builtin.view.pattern_editor.shortcut.match_case_toggle": "Toggle Case Sensitive Search",
"hex.builtin.view.pattern_editor.shortcut.regex_toggle": "Toggle Regular Expression Search/Replace",
"hex.builtin.view.pattern_editor.shortcut.whole_word_toggle": "Toggle Whole Word Search",
"hex.builtin.view.pattern_editor.shortcut.save_project": "Save Project",
"hex.builtin.view.pattern_editor.shortcut.open_project": "Open Project ...",
"hex.builtin.view.pattern_editor.shortcut.save_project_as": "Save Project As ...",
"hex.builtin.view.pattern_editor.shortcut.copy": "Copy Selection to the Clipboard",
"hex.builtin.view.pattern_editor.shortcut.cut": "Copy Selection to the Clipboard and Delete it",
"hex.builtin.view.pattern_editor.shortcut.paste": "Paste Clipboard Contents at the Cursor Position",
"hex.builtin.view.pattern_editor.shortcut.undo": "Undo",
"hex.builtin.view.pattern_editor.shortcut.redo": "Redo",
"hex.builtin.view.pattern_editor.shortcut.toggle_insert": "Toggle Write Over",
"hex.builtin.view.pattern_editor.shortcut.delete": "Delete One Character at the Cursor Position",
"hex.builtin.view.pattern_editor.shortcut.backspace": "Delete One Character to the Left of Cursor",
"hex.builtin.view.pattern_editor.shortcut.select_all": "Select Entire File",
"hex.builtin.view.pattern_editor.shortcut.select_left": "Extend Selection One Character to the Left of the Cursor",
"hex.builtin.view.pattern_editor.shortcut.select_right": "Extend Selection One Character to the Right of the Cursor",
"hex.builtin.view.pattern_editor.shortcut.select_word_left": "Extend Selection One Word to the Left of the Cursor",
"hex.builtin.view.pattern_editor.shortcut.select_word_right": "Extend Selection One Word to the Right of the Cursor",
"hex.builtin.view.pattern_editor.shortcut.select_up": "Extend Selection One Line Up from the Cursor",
"hex.builtin.view.pattern_editor.shortcut.select_down": "Extend Selection One Line Down from the Cursor",
"hex.builtin.view.pattern_editor.shortcut.select_page_up": "Extend Selection One Page Up from the Cursor",
"hex.builtin.view.pattern_editor.shortcut.select_page_down": "Extend Selection One Page Down from the Cursor",
"hex.builtin.view.pattern_editor.shortcut.select_home": "Extend Selection to the Start of the Line",
"hex.builtin.view.pattern_editor.shortcut.select_end": "Extend Selection to the End of the Line",
"hex.builtin.view.pattern_editor.shortcut.select_top": "Extend Selection to the Start of the File",
"hex.builtin.view.pattern_editor.shortcut.select_bottom": "Extend Selection to the End of the File",
"hex.builtin.view.pattern_editor.shortcut.move_left": "Move Cursor One Character to the Left",
"hex.builtin.view.pattern_editor.shortcut.move_right": "Move Cursor One Character to the Right",
"hex.builtin.view.pattern_editor.shortcut.move_word_left": "Move Cursor One Word to the Left",
"hex.builtin.view.pattern_editor.shortcut.move_word_right": "Move Cursor One Word to the Right",
"hex.builtin.view.pattern_editor.shortcut.move_up": "Move Cursor One Line Up",
"hex.builtin.view.pattern_editor.shortcut.move_down": "Move Cursor One Line Down",
"hex.builtin.view.pattern_editor.shortcut.move_page_up": "Move Cursor One Page Up",
"hex.builtin.view.pattern_editor.shortcut.move_page_down": "Move Cursor One Page Down",
"hex.builtin.view.pattern_editor.shortcut.move_home": "Move Cursor to the Start of the Line",
"hex.builtin.view.pattern_editor.shortcut.move_end": "Move Cursor to the End of the Line",
"hex.builtin.view.pattern_editor.shortcut.move_top": "Move Cursor to the Start of the File",
"hex.builtin.view.pattern_editor.shortcut.move_bottom": "Move Cursor to the End of the File",
"hex.builtin.view.pattern_editor.shortcut.delete_word_left": "Delete One Word to the Left of the Cursor",
"hex.builtin.view.pattern_editor.shortcut.delete_word_right": "Delete One Word to the Right of the Cursor",
"hex.builtin.view.pattern_editor.shortcut.run_pattern": "Run Pattern",
"hex.builtin.view.pattern_editor.shortcut.step_debugger": "Step Debugger",
"hex.builtin.view.pattern_editor.shortcut.continue_debugger": "Continue Debugger",

View File

@ -134,6 +134,12 @@ namespace hex::plugin::builtin {
return langDef;
}
int levelId;
static void loadPatternAsMemoryProvider(const ViewPatternEditor::VirtualFile *file) {
ImHexApi::Provider::add<prv::MemoryProvider>(file->data, wolv::util::toUTF8String(file->path.filename()));
}
static void drawVirtualFileTree(const std::vector<const ViewPatternEditor::VirtualFile*> &virtualFiles, u32 level = 0) {
ImGui::PushID(level + 1);
ON_SCOPE_EXIT { ImGui::PopID(); };
@ -148,13 +154,24 @@ namespace hex::plugin::builtin {
ImGui::TableNextColumn();
ImGui::TextUnformatted(ICON_VS_FILE);
ImGui::PushID(levelId);
ImGui::SameLine();
ImGui::TreeNodeEx(currSegment.c_str(), ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen);
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) && ImGui::IsItemHovered()) {
ImHexApi::Provider::add<prv::MemoryProvider>(file->data, wolv::util::toUTF8String(file->path.filename()));
if (ImGui::IsMouseDown(ImGuiMouseButton_Right) && ImGui::IsItemHovered() && !ImGui::IsMouseDragging(ImGuiMouseButton_Right)) {
ImGui::OpenPopup("##virtual_files_context_menu");
}
if (ImGui::BeginPopup("##virtual_files_context_menu")) {
if (ImGui::MenuItem("hex.builtin.view.hex_editor.menu.edit.open_in_new_provider"_lang, nullptr, false)) {
loadPatternAsMemoryProvider(file);
}
ImGui::EndPopup();
}
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) && ImGui::IsItemHovered()) {
loadPatternAsMemoryProvider(file);
}
ImGui::PopID();
levelId +=1;
continue;
}
@ -213,6 +230,101 @@ namespace hex::plugin::builtin {
RequestAddVirtualFile::unsubscribe(this);
}
void ViewPatternEditor::setupFindReplace(TextEditor *editor) {
// Context menu entries that open the find/replace popup
ImGui::PushID(editor);
static std::string findWord;
static bool requestFocus = false;
static u64 position = 0;
static u64 count = 0;
static bool updateCount = false;
TextEditor::FindReplaceHandler *findReplaceHandler = editor->GetFindReplaceHandler();
static bool canReplace = true;
if (m_openFindReplacePopUp) {
m_openFindReplacePopUp = false;
// Place the popup at the top right of the window
auto windowSize = ImGui::GetWindowSize();
auto style = ImGui::GetStyle();
// Set the scrollbar size only if it is visible
float scrollbarSize = 0;
// Calculate the number of lines to display in the text editor
auto totalTextHeight = editor->GetTotalLines() * editor->GetCharAdvance().y;
// Compare it to the window height
if (totalTextHeight > windowSize.y)
scrollbarSize = style.ScrollbarSize;
auto labelSize = ImGui::CalcTextSize(ICON_VS_WHOLE_WORD);
// Six icon buttons
auto popupSize = ImVec2({(labelSize.x + style.FramePadding.x * 2.0F) * 6.0F,
labelSize.y + style.FramePadding.y * 2.0F + style.WindowPadding.y + 3 });
// 2 * 11 spacings in between elements
popupSize.x += style.FramePadding.x * 22.0F;
// Text input fields are set to 12 characters wide
popupSize.x += ImGui::GetFontSize() * 12.0F;
// IndexOfCount text
popupSize.x += ImGui::CalcTextSize("2000 of 2000").x + 2.0F;
popupSize.x += scrollbarSize;
// Position of popup relative to parent window
ImVec2 windowPosForPopup = ImGui::GetWindowPos();
// Not the window height but the content height
windowPosForPopup.y += popupSize.y;
// Add remaining window height
popupSize.y += style.WindowPadding.y + 1;
// Move to the right so as not to overlap the scrollbar
windowPosForPopup.x += windowSize.x - popupSize.x;
findReplaceHandler->SetFindWindowPos(windowPosForPopup);
if (m_replaceMode) {
// Remove one window padding
popupSize.y -= style.WindowPadding.y;
// Add the replace window height
popupSize.y *= 2;
}
if (m_focusedSubWindowName.contains(consoleView)) {
windowPosForPopup.y = m_consoleHoverBox.Min.y;
canReplace = false;
} else if (m_focusedSubWindowName.contains(textEditorView))
canReplace = true;
ImGui::SetNextWindowPos(windowPosForPopup);
ImGui::SetNextWindowSize(popupSize);
ImGui::OpenPopup("##pattern_editor_find_replace");
findReplaceHandler->resetMatches();
// Use selection as find word if there is one, otherwise use the word under the cursor
if (!editor->HasSelection())
editor->SelectWordUnderCursor();
findWord = editor->GetSelectedText();
// Find all matches to findWord
findReplaceHandler->FindAllMatches(editor,findWord);
position = findReplaceHandler->FindPosition(editor,editor->GetCursorPosition(), true);
count = findReplaceHandler->GetMatches().size();
findReplaceHandler->SetFindWord(editor,findWord);
requestFocus = true;
updateCount = true;
}
drawFindReplaceDialog(editor, findWord, requestFocus, position, count, updateCount, canReplace);
ImGui::PopID();
}
void ViewPatternEditor::drawContent() {
auto provider = ImHexApi::Provider::get();
@ -221,6 +333,7 @@ namespace hex::plugin::builtin {
static bool dragging = false;
const auto availableSize = ImGui::GetContentRegionAvail();
const auto windowPosition = ImGui::GetCursorScreenPos();
auto textEditorSize = availableSize;
textEditorSize.y *= 3.5 / 5.0;
textEditorSize.y -= ImGui::GetTextLineHeightWithSpacing();
@ -228,15 +341,20 @@ namespace hex::plugin::builtin {
if (availableSize.y > 1)
textEditorSize.y = std::clamp(textEditorSize.y, 1.0F, std::max(1.0F, availableSize.y - ImGui::GetTextLineHeightWithSpacing() * 3));
const ImGuiContext& g = *GImGui;
if (g.NavWindow != nullptr) {
std::string name = g.NavWindow->Name;
if (name.contains(textEditorView) || name.contains(consoleView))
m_focusedSubWindowName = name;
}
m_textEditor.Render("hex.builtin.view.pattern_editor.name"_lang, textEditorSize, true);
m_textEditorHoverBox = ImRect(windowPosition,windowPosition+textEditorSize);
m_consoleHoverBox = ImRect(ImVec2(windowPosition.x,windowPosition.y+textEditorSize.y),windowPosition+availableSize);
TextEditor::FindReplaceHandler *findReplaceHandler = m_textEditor.GetFindReplaceHandler();
if (ImGui::IsMouseDown(ImGuiMouseButton_Right) && ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows) && !ImGui::IsMouseDragging(ImGuiMouseButton_Right)) {
if (ImGui::IsMouseDown(ImGuiMouseButton_Right) && ImGui::IsMouseHoveringRect(m_textEditorHoverBox.Min,m_textEditorHoverBox.Max) && !ImGui::IsMouseDragging(ImGuiMouseButton_Right)) {
ImGui::OpenPopup("##pattern_editor_context_menu");
}
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))
@ -268,8 +386,11 @@ namespace hex::plugin::builtin {
ImGui::Separator();
// Search and replace entries
if (ImGui::MenuItem("hex.builtin.view.pattern_editor.menu.find"_lang, Shortcut(CTRLCMD + Keys::F).toString().c_str(),false,this->m_textEditor.HasSelection()))
clickedMenuFind = true;
if (ImGui::MenuItem("hex.builtin.view.pattern_editor.menu.find"_lang, Shortcut(CTRLCMD + Keys::F).toString().c_str(),false, m_textEditor.HasSelection())){
m_replaceMode = false;
m_openFindReplacePopUp = true;
}
if (ImGui::MenuItem("hex.builtin.view.pattern_editor.menu.find_next"_lang, Shortcut(Keys::F3).toString().c_str(),false,!findReplaceHandler->GetFindWord().empty()))
findReplaceHandler->FindMatch(&m_textEditor,true);
@ -277,8 +398,10 @@ namespace hex::plugin::builtin {
if (ImGui::MenuItem("hex.builtin.view.pattern_editor.menu.find_previous"_lang, Shortcut(SHIFT + Keys::F3).toString().c_str(),false,!findReplaceHandler->GetFindWord().empty()))
findReplaceHandler->FindMatch(&m_textEditor,false);
if (ImGui::MenuItem("hex.builtin.view.pattern_editor.menu.replace"_lang, Shortcut(CTRLCMD + Keys::H).toString().c_str(),false,!findReplaceHandler->GetReplaceWord().empty()))
clickedMenuReplace = true;
if (ImGui::MenuItem("hex.builtin.view.pattern_editor.menu.replace"_lang, Shortcut(CTRLCMD + Keys::H).toString().c_str(),false,!findReplaceHandler->GetReplaceWord().empty())) {
m_replaceMode = true;
m_openFindReplacePopUp = true;
}
if (ImGui::MenuItem("hex.builtin.view.pattern_editor.menu.replace_next"_lang,"",false,!findReplaceHandler->GetReplaceWord().empty()))
findReplaceHandler->Replace(&m_textEditor,true);
@ -292,119 +415,8 @@ namespace hex::plugin::builtin {
ImGui::EndPopup();
}
// Context menu entries that open the find/replace popup
bool openFindPopup = false;
ImGui::PushID(&this->m_textEditor);
if (clickedMenuFind) {
m_replaceMode = false;
openFindPopup = true;
}
if (clickedMenuReplace) {
m_replaceMode = true;
openFindPopup = true;
}
// shortcuts to open the find/replace popup
if (ImGui::IsItemHovered()) {
if (ImGui::IsKeyPressed(ImGuiKey_F, false) && ImGui::GetIO().KeyCtrl) {
m_replaceMode = false;
openFindPopup = true;
}
if (ImGui::IsKeyPressed(ImGuiKey_H, false) && ImGui::GetIO().KeyCtrl) {
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;
static bool requestFocus = false;
static u64 position = 0;
static u64 count = 0;
static bool updateCount = false;
if (openFindPopup) {
// Place the popup at the top right of the window
auto windowSize = ImGui::GetWindowSize();
auto style = ImGui::GetStyle();
// Set the scrollbar size only if it is visible
float scrollbarSize = 0;
// Calculate the number of lines to display in the text editor
auto totalTextHeight = m_textEditor.GetTotalLines() * m_textEditor.GetCharAdvance().y;
// Compare it to the window height
if (totalTextHeight > windowSize.y)
scrollbarSize = style.ScrollbarSize;
auto labelSize = ImGui::CalcTextSize(ICON_VS_WHOLE_WORD);
// Six icon buttons
auto popupSize = ImVec2({(labelSize.x + style.FramePadding.x * 2.0F) * 6.0F,
labelSize.y + style.FramePadding.y * 2.0F + style.WindowPadding.y + 3 });
// 2 * 11 spacings in between elements
popupSize.x += style.FramePadding.x * 22.0F;
// Text input fields are set to 12 characters wide
popupSize.x += ImGui::GetFontSize() * 12.0F;
// IndexOfCount text
popupSize.x += ImGui::CalcTextSize("2000 of 2000").x + 2.0F;
popupSize.x += scrollbarSize;
// Position of popup relative to parent window
ImVec2 windowPosForPopup = ImGui::GetWindowPos();
// Not the window height but the content height
windowPosForPopup.y += popupSize.y;
// Add remaining window height
popupSize.y += style.WindowPadding.y + 1;
// Move to the right so as not to overlap the scrollbar
windowPosForPopup.x += windowSize.x - popupSize.x;
findReplaceHandler->SetFindWindowPos(windowPosForPopup);
if (m_replaceMode) {
// Remove one window padding
popupSize.y -= style.WindowPadding.y;
// Add the replace window height
popupSize.y *= 2;
}
ImGui::SetNextWindowPos(windowPosForPopup);
ImGui::SetNextWindowSize(popupSize);
ImGui::OpenPopup("##pattern_editor_find_replace");
findReplaceHandler->resetMatches();
// Use selection as find word if there is one, otherwise use the word under the cursor
if (!this->m_textEditor.HasSelection())
this->m_textEditor.SelectWordUnderCursor();
findWord = this->m_textEditor.GetSelectedText();
// Find all matches to findWord
findReplaceHandler->FindAllMatches(&m_textEditor,findWord);
position = findReplaceHandler->FindPosition(&m_textEditor,m_textEditor.GetCursorPosition(), true);
count = findReplaceHandler->GetMatches().size();
findReplaceHandler->SetFindWord(&m_textEditor,findWord);
requestFocus = true;
updateCount = true;
}
drawFindReplaceDialog(findWord, requestFocus, position, count, updateCount);
ImGui::PopID();
setupFindReplace(getEditorFromFocusedWindow());
ImGui::Button("##settings_drag_bar", ImVec2(ImGui::GetContentRegionAvail().x, 2_scaled));
if (ImGui::IsMouseDragging(ImGuiMouseButton_Left, 0)) {
@ -605,18 +617,9 @@ namespace hex::plugin::builtin {
}
}
void ViewPatternEditor::drawFindReplaceDialog(std::string &findWord, bool &requestFocus, u64 &position, u64 &count, bool &updateCount) {
static std::string replaceWord;
void ViewPatternEditor::drawFindReplaceDialog(TextEditor *textEditor, std::string &findWord, bool &requestFocus, u64 &position, u64 &count, bool &updateCount, bool canReplace) {
TextEditor::FindReplaceHandler *findReplaceHandler = m_textEditor.GetFindReplaceHandler();
static bool requestFocusReplace = false;
static bool requestFocusFind = false;
static bool downArrowFind = false;
static bool upArrowFind = false;
static bool downArrowReplace = false;
static bool upArrowReplace = false;
static bool enterPressedFind = false;
TextEditor::FindReplaceHandler *findReplaceHandler = textEditor->GetFindReplaceHandler();
bool enter = ImGui::IsKeyPressed(ImGuiKey_Enter, false) || ImGui::IsKeyPressed(ImGuiKey_KeypadEnter, false);
bool upArrow = ImGui::IsKeyPressed(ImGuiKey_UpArrow, false) || ImGui::IsKeyPressed(ImGuiKey_Keypad8, false);
@ -630,9 +633,14 @@ namespace hex::plugin::builtin {
ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_BordersInnerH)) {
ImGui::TableNextRow();
ImGui::TableNextColumn();
static bool requestFocusFind = false;
static bool requestFocusReplace = false;
bool oldReplace = m_replaceMode;
ImGuiExt::DimmedIconToggle(ICON_VS_TRIANGLE_DOWN, ICON_VS_TRIANGLE_RIGHT, &m_replaceMode);
if (canReplace)
ImGuiExt::DimmedIconToggle(ICON_VS_TRIANGLE_DOWN, ICON_VS_TRIANGLE_RIGHT, &m_replaceMode);
else
m_replaceMode = false;
if (oldReplace != m_replaceMode) {
if (m_replaceMode)
requestFocusReplace = true;
@ -659,16 +667,15 @@ namespace hex::plugin::builtin {
hint += ICON_BI_DATA_TRANSFER_BOTH;
hint += "hex.builtin.view.pattern_editor.find_hint_history"_lang.operator std::string();
}
static bool enterPressedFind = false;
ImGui::PushItemWidth(ImGui::GetFontSize() * 12);
if (ImGui::InputTextWithHint("###findInputTextWidget", hint.c_str(), findWord, findFlags) || enter ) {
if (enter) {
if (enter)
enterPressedFind = true;
enter = false;
}
updateCount = true;
requestFocusFind = true;
findReplaceHandler->SetFindWord(&m_textEditor,findWord);
findReplaceHandler->SetFindWord(textEditor,findWord);
}
if ((!m_replaceMode && requestFocus) || requestFocusFind) {
@ -686,8 +693,8 @@ namespace hex::plugin::builtin {
m_findHistoryIndex = (m_findHistoryIndex + 1) % m_findHistorySize;
findWord = m_findHistory[m_findHistoryIndex];
findReplaceHandler->SetFindWord(&m_textEditor,findWord);
position = findReplaceHandler->FindPosition(&m_textEditor,m_textEditor.GetCursorPosition(), true);
findReplaceHandler->SetFindWord(textEditor,findWord);
position = findReplaceHandler->FindPosition(textEditor,textEditor->GetCursorPosition(), true);
count = findReplaceHandler->GetMatches().size();
updateCount = true;
requestFocusFind = true;
@ -703,8 +710,8 @@ namespace hex::plugin::builtin {
if (altCPressed || ImGuiExt::DimmedIconToggle(ICON_VS_CASE_SENSITIVE, &matchCase)) {
if (altCPressed)
matchCase = !matchCase;
findReplaceHandler->SetMatchCase(&m_textEditor,matchCase);
position = findReplaceHandler->FindPosition(&m_textEditor,m_textEditor.GetCursorPosition(), true);
findReplaceHandler->SetMatchCase(textEditor,matchCase);
position = findReplaceHandler->FindPosition(textEditor,textEditor->GetCursorPosition(), true);
count = findReplaceHandler->GetMatches().size();
updateCount = true;
requestFocusFind = true;
@ -719,8 +726,8 @@ namespace hex::plugin::builtin {
if (altWPressed || ImGuiExt::DimmedIconToggle(ICON_VS_WHOLE_WORD, &matchWholeWord)) {
if (altWPressed)
matchWholeWord = !matchWholeWord;
findReplaceHandler->SetWholeWord(&m_textEditor,matchWholeWord);
position = findReplaceHandler->FindPosition(&m_textEditor,m_textEditor.GetCursorPosition(), true);
findReplaceHandler->SetWholeWord(textEditor,matchWholeWord);
position = findReplaceHandler->FindPosition(textEditor,textEditor->GetCursorPosition(), true);
count = findReplaceHandler->GetMatches().size();
updateCount = true;
requestFocusFind = true;
@ -735,8 +742,8 @@ namespace hex::plugin::builtin {
if (altRPressed || ImGuiExt::DimmedIconToggle(ICON_VS_REGEX, &useRegex)) {
if (altRPressed)
useRegex = !useRegex;
findReplaceHandler->SetFindRegEx(&m_textEditor,useRegex);
position = findReplaceHandler->FindPosition(&m_textEditor,m_textEditor.GetCursorPosition(), true);
findReplaceHandler->SetFindRegEx(textEditor,useRegex);
position = findReplaceHandler->FindPosition(textEditor,textEditor->GetCursorPosition(), true);
count = findReplaceHandler->GetMatches().size();
updateCount = true;
requestFocusFind = true;
@ -777,10 +784,12 @@ namespace hex::plugin::builtin {
ImGui::InvisibleButton("##find_result_padding", buttonSize);
ImGui::SameLine();
static bool downArrowFind = false;
if (ImGuiExt::IconButton(ICON_VS_ARROW_DOWN, ImVec4(1, 1, 1, 1)))
downArrowFind = true;
ImGui::SameLine();
static bool upArrowFind = false;
if (ImGuiExt::IconButton(ICON_VS_ARROW_UP, ImVec4(1, 1, 1, 1)))
upArrowFind = true;
@ -803,11 +812,14 @@ namespace hex::plugin::builtin {
}
ImGui::PushItemWidth(ImGui::GetFontSize() * 12);
static std::string replaceWord;
static bool downArrowReplace = false;
static bool upArrowReplace = false;
if (ImGui::InputTextWithHint("##replaceInputTextWidget", hint.c_str(), replaceWord, replaceFlags) || downArrowReplace || upArrowReplace) {
findReplaceHandler->SetReplaceWord(replaceWord);
historyInsert(m_replaceHistory, m_replaceHistorySize, m_replaceHistoryIndex, replaceWord);
bool textReplaced = findReplaceHandler->Replace(&m_textEditor,!shift && !upArrowReplace);
bool textReplaced = findReplaceHandler->Replace(textEditor,!shift && !upArrowReplace);
if (textReplaced) {
if (count > 0) {
if (position == count)
@ -863,7 +875,7 @@ namespace hex::plugin::builtin {
if (ImGuiExt::IconButton(ICON_VS_REPLACE_ALL, ImVec4(1, 1, 1, 1))) {
findReplaceHandler->SetReplaceWord(replaceWord);
historyInsert(m_replaceHistory,m_replaceHistorySize, m_replaceHistoryIndex, replaceWord);
findReplaceHandler->ReplaceAll(&m_textEditor);
findReplaceHandler->ReplaceAll(textEditor);
count = 0;
position = 0;
requestFocusFind = true;
@ -875,7 +887,7 @@ namespace hex::plugin::builtin {
if ((ImGui::IsKeyPressed(ImGuiKey_F3, false)) || downArrowFind || upArrowFind || enterPressedFind) {
historyInsert(m_findHistory, m_findHistorySize, m_findHistoryIndex, findWord);
position = findReplaceHandler->FindMatch(&m_textEditor,!shift && !upArrowFind);
position = findReplaceHandler->FindMatch(textEditor,!shift && !upArrowFind);
count = findReplaceHandler->GetMatches().size();
updateCount = true;
downArrowFind = false;
@ -895,6 +907,32 @@ namespace hex::plugin::builtin {
}
void ViewPatternEditor::drawConsole(ImVec2 size) {
auto findReplaceHandler = m_consoleEditor.GetFindReplaceHandler();
if (ImGui::IsMouseDown(ImGuiMouseButton_Right) && ImGui::IsMouseHoveringRect(m_consoleHoverBox.Min,m_consoleHoverBox.Max) && !ImGui::IsMouseDragging(ImGuiMouseButton_Right)) {
ImGui::OpenPopup("##console_context_menu");
}
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)) {
m_consoleEditor.Copy();
}
if (ImGui::MenuItem("hex.builtin.view.hex_editor.menu.edit.select_all"_lang, 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(),false, hasSelection)) {
m_openFindReplacePopUp = true;
m_replaceMode = false;
}
if (ImGui::MenuItem("hex.builtin.view.pattern_editor.menu.find_next"_lang, Shortcut(Keys::F3).toString().c_str(),false,!findReplaceHandler->GetFindWord().empty()))
findReplaceHandler->FindMatch(&m_consoleEditor,true);
if (ImGui::MenuItem("hex.builtin.view.pattern_editor.menu.find_previous"_lang, Shortcut(SHIFT + Keys::F3).toString().c_str(),false,!findReplaceHandler->GetFindWord().empty()))
findReplaceHandler->FindMatch(&m_consoleEditor,false);
ImGui::EndPopup();
}
if (m_consoleNeedsUpdate) {
std::scoped_lock lock(m_logMutex);
@ -1175,7 +1213,7 @@ namespace hex::plugin::builtin {
file.writeVector(runtime.getSection(id));
});
}
ImGui::SetItemTooltip("%s", (const char*)"hex.builtin.view.pattern_editor.sections.export"_lang.get());
ImGui::SetItemTooltip("%s", "hex.builtin.view.pattern_editor.sections.export"_lang.get());
ImGui::PopID();
}
@ -1193,7 +1231,7 @@ namespace hex::plugin::builtin {
if (ImGui::BeginTable("Virtual File Tree", 1, ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersInnerH | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY, size)) {
ImGui::TableSetupColumn("##path", ImGuiTableColumnFlags_WidthStretch);
levelId = 1;
drawVirtualFileTree(virtualFilePointers);
ImGui::EndTable();
@ -1203,9 +1241,10 @@ namespace hex::plugin::builtin {
void ViewPatternEditor::drawDebugger(ImVec2 size) {
const auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
auto &evaluator = runtime.getInternals().evaluator;
if (ImGui::BeginChild("##debugger", size, true)) {
auto &evaluator = runtime.getInternals().evaluator;
const auto &breakpoints = evaluator->getBreakpoints();
const auto line = m_textEditor.GetCursorPosition().mLine + 1;
@ -1372,8 +1411,8 @@ namespace hex::plugin::builtin {
const auto end = value.find(']');
if (end == std::string::npos)
return std::nullopt;
value = value.substr(0, end);
value.resize(end);
//value = value.substr(0, end);
value = wolv::util::trim(value);
return BinaryPattern(value);
@ -1851,6 +1890,16 @@ namespace hex::plugin::builtin {
appendEditorText(hex::format("{0} {0}_array_at_0x{1:02X}[0x{2:02X}] @ 0x{1:02X};", type, selection->getStartAddress(), (selection->getSize() + (size - 1)) / size));
}
TextEditor *ViewPatternEditor::getEditorFromFocusedWindow() {
if (m_focusedSubWindowName.contains(consoleView)) {
return &m_consoleEditor;
}
if (m_focusedSubWindowName.contains(textEditorView)) {
return &m_textEditor;
}
return nullptr;
}
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,
@ -2037,6 +2086,257 @@ namespace hex::plugin::builtin {
}
});
ShortcutManager::addShortcut(this, CTRL + Keys::F + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.find", [this] {
m_openFindReplacePopUp = true;
m_replaceMode = false;
});
ShortcutManager::addShortcut(this, CTRL + Keys::H + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.replace", [this] {
if (m_focusedSubWindowName.contains(textEditorView)) {
m_openFindReplacePopUp = true;
m_replaceMode = true;
}
});
ShortcutManager::addShortcut(this, Keys::F3 + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.find_next", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr) {
TextEditor::FindReplaceHandler *findReplaceHandler = editor->GetFindReplaceHandler();
findReplaceHandler->FindMatch(editor, true);
}
});
ShortcutManager::addShortcut(this, SHIFT + Keys::F3 + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.find_previous", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr) {
TextEditor::FindReplaceHandler *findReplaceHandler = editor->GetFindReplaceHandler();
findReplaceHandler->FindMatch(editor, false);
}
});
ShortcutManager::addShortcut(this, ALT + Keys::C + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.match_case_toggle", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr) {
TextEditor::FindReplaceHandler *findReplaceHandler = editor->GetFindReplaceHandler();
findReplaceHandler->SetMatchCase(editor, !findReplaceHandler->GetMatchCase());
}
});
ShortcutManager::addShortcut(this, ALT + Keys::R + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.regex_toggle", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr) {
TextEditor::FindReplaceHandler *findReplaceHandler = editor->GetFindReplaceHandler();
findReplaceHandler->SetFindRegEx(editor, !findReplaceHandler->GetFindRegEx());
}
});
ShortcutManager::addShortcut(this, ALT + Keys::W + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.whole_word_toggle", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr) {
TextEditor::FindReplaceHandler *findReplaceHandler = editor->GetFindReplaceHandler();
findReplaceHandler->SetWholeWord(editor, !findReplaceHandler->GetWholeWord());
}
});
ShortcutManager::addShortcut(this, ALT + Keys::S + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.save_project", [] {
hex::plugin::builtin::saveProject();
});
ShortcutManager::addShortcut(this, ALT + Keys::O + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.open_project", [] {
hex::plugin::builtin::openProject();
});
ShortcutManager::addShortcut(this, ALT + SHIFT + Keys::S + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.save_project_as", [] {
hex::plugin::builtin::saveProjectAs();
});
// ShortcutManager::addShortcut(this, CTRL + Keys::Insert + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.copy", [this] {
// m_textEditor.Copy();
// });
ShortcutManager::addShortcut(this, CTRL + Keys::C + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.copy", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
editor->Copy();
});
// ShortcutManager::addShortcut(this, SHIFT + Keys::Insert + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.paste", [this] {
// m_textEditor.Paste();
// });
ShortcutManager::addShortcut(this, CTRL + Keys::V + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.paste", [this] {
if (m_focusedSubWindowName.contains(textEditorView))
m_textEditor.Paste();
});
ShortcutManager::addShortcut(this, CTRL + Keys::X + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.cut", [this] {
if (m_focusedSubWindowName.contains(textEditorView))
m_textEditor.Cut();
});
// ShortcutManager::addShortcut(this, SHIFT + Keys::Delete + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.cut", [this] {
// m_textEditor.Cut();
// });
ShortcutManager::addShortcut(this, CTRL + Keys::Z + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.undo", [this] {
if (m_focusedSubWindowName.contains(textEditorView))
m_textEditor.Undo();
});
// ShortcutManager::addShortcut(this, ALT + Keys::Backspace + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.undo", [this] {
// m_textEditor.Undo();
// });
ShortcutManager::addShortcut(this, Keys::Delete + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.delete", [this] {
if (m_focusedSubWindowName.contains(textEditorView))
m_textEditor.Delete();
});
ShortcutManager::addShortcut(this, CTRL + Keys::Y + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.redo", [this] {
if (m_focusedSubWindowName.contains(textEditorView))
m_textEditor.Redo();
});
ShortcutManager::addShortcut(this, CTRL + Keys::A + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.select_all", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
editor->SelectAll();
});
ShortcutManager::addShortcut(this, SHIFT + Keys::Right + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.select_right", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
editor->MoveRight(1, true, false);
});
ShortcutManager::addShortcut(this, CTRL + SHIFT + Keys::Right + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.select_word_right", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
editor->MoveRight(1, true, true);
});
ShortcutManager::addShortcut(this, SHIFT + Keys::Left + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.select_left", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
editor->MoveLeft(1, true, false);
});
ShortcutManager::addShortcut(this, CTRL + SHIFT + Keys::Left + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.select_word_left", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
editor->MoveLeft(1, true, true);
});
ShortcutManager::addShortcut(this, SHIFT + Keys::Up + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.select_up", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
editor->MoveUp(1, true);
});
ShortcutManager::addShortcut(this, SHIFT +Keys::PageUp + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.select_page_up", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
editor->MoveUp(editor->GetPageSize()-4, true);
});
ShortcutManager::addShortcut(this, SHIFT + Keys::Down + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.select_down", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
editor->MoveDown(1, true);
});
ShortcutManager::addShortcut(this, SHIFT +Keys::PageDown + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.select_page_down", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
editor->MoveDown(editor->GetPageSize()-4, true);
});
ShortcutManager::addShortcut(this, CTRL + SHIFT + Keys::Home + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.select_top", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
editor->MoveTop(true);
});
ShortcutManager::addShortcut(this, CTRL + SHIFT + Keys::End + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.select_bottom", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
editor->MoveBottom(true);
});
ShortcutManager::addShortcut(this, SHIFT + Keys::Home + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.select_home", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
editor->MoveHome(true);
});
ShortcutManager::addShortcut(this, SHIFT + Keys::End + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.select_end", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
editor->MoveEnd(true);
});
ShortcutManager::addShortcut(this, CTRL + Keys::Delete + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.delete_word_right", [this] {
if (m_focusedSubWindowName.contains(textEditorView))
m_textEditor.DeleteWordRight();
});
ShortcutManager::addShortcut(this, CTRL + Keys::Backspace + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.delete_word_left", [this] {
if (m_focusedSubWindowName.contains(textEditorView))
m_textEditor.DeleteWordLeft();
});
ShortcutManager::addShortcut(this, Keys::Backspace + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.backspace", [this] {
if (m_focusedSubWindowName.contains(textEditorView))
m_textEditor.Backspace();
});
ShortcutManager::addShortcut(this, Keys::Insert + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.toggle_insert", [this] {
if (m_focusedSubWindowName.contains(textEditorView))
m_textEditor.SetOverwrite(!m_textEditor.IsOverwrite());
});
ShortcutManager::addShortcut(this, CTRL + Keys::Right + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_word_right", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
editor->MoveRight(1, false, true);
});
ShortcutManager::addShortcut(this, Keys::Right + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_right", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
editor->MoveRight(1, false, false);
});
ShortcutManager::addShortcut(this, CTRL + Keys::Left + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_word_left", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
editor->MoveLeft(1, false, true);
});
ShortcutManager::addShortcut(this, Keys::Left + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_left", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
editor->MoveLeft(1, false, false);
});
ShortcutManager::addShortcut(this, Keys::Up + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_up", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
editor->MoveUp(1, false);
});
ShortcutManager::addShortcut(this, Keys::PageUp + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_page_up", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
editor->MoveUp(editor->GetPageSize()-4, false);
});
ShortcutManager::addShortcut(this, Keys::Down + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_down", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
editor->MoveDown(1, false);
});
ShortcutManager::addShortcut(this, Keys::PageDown + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_page_down", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
editor->MoveDown(editor->GetPageSize()-4, false);
});
ShortcutManager::addShortcut(this, CTRL + Keys::Home + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_top", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
editor->MoveTop(false);
});
ShortcutManager::addShortcut(this, CTRL + Keys::End + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_bottom", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
editor->MoveBottom(false);
});
ShortcutManager::addShortcut(this, Keys::Home + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_home", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
editor->MoveHome(false);
});
ShortcutManager::addShortcut(this, Keys::End + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.move_end", [this] {
if (auto editor = getEditorFromFocusedWindow(); editor != nullptr)
editor->MoveEnd(false);
});
ShortcutManager::addShortcut(this, Keys::F8 + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.add_breakpoint", [this] {
const auto line = m_textEditor.GetCursorPosition().mLine + 1;
const auto &runtime = ContentRegistry::PatternLanguage::getRuntime();