diff --git a/lib/libimhex/include/hex/api/content_registry.hpp b/lib/libimhex/include/hex/api/content_registry.hpp index 6c7b1ed86..a562d89a7 100644 --- a/lib/libimhex/include/hex/api/content_registry.hpp +++ b/lib/libimhex/include/hex/api/content_registry.hpp @@ -900,12 +900,14 @@ EXPORT_MODULE namespace hex { * @param priority The priority of the entry. Lower values are displayed first * @param function The function to call when the entry is clicked * @param enabledCallback The function to call to determine if the entry is enabled + * @param view The view to use for the entry. If nullptr, the item will always be visible */ void addMenuItemSubMenu( std::vector unlocalizedMainMenuNames, u32 priority, const impl::MenuCallback &function, - const impl::EnabledCallback& enabledCallback = []{ return true; } + const impl::EnabledCallback& enabledCallback = []{ return true; }, + View *view = nullptr ); /** @@ -915,13 +917,15 @@ EXPORT_MODULE namespace hex { * @param priority The priority of the entry. Lower values are displayed first * @param function The function to call when the entry is clicked * @param enabledCallback The function to call to determine if the entry is enabled + * @param view The view to use for the entry. If nullptr, the item will always be visible */ void addMenuItemSubMenu( std::vector unlocalizedMainMenuNames, const char *icon, u32 priority, const impl::MenuCallback &function, - const impl::EnabledCallback& enabledCallback = []{ return true; } + const impl::EnabledCallback& enabledCallback = []{ return true; }, + View *view = nullptr ); @@ -929,8 +933,9 @@ EXPORT_MODULE namespace hex { * @brief Adds a new main menu separator * @param unlocalizedMainMenuNames The unlocalized names of the main menu entries * @param priority The priority of the entry. Lower values are displayed first + * @param view The view to use for the entry. If nullptr, the item will always be visible */ - void addMenuItemSeparator(std::vector unlocalizedMainMenuNames, u32 priority); + void addMenuItemSeparator(std::vector unlocalizedMainMenuNames, u32 priority, View *view = nullptr); /** diff --git a/lib/libimhex/include/hex/ui/view.hpp b/lib/libimhex/include/hex/ui/view.hpp index b52e4ac56..abbbf2d37 100644 --- a/lib/libimhex/include/hex/ui/view.hpp +++ b/lib/libimhex/include/hex/ui/view.hpp @@ -79,6 +79,12 @@ namespace hex { */ [[nodiscard]] virtual ImGuiWindowFlags getWindowFlags() const; + /** + * @brief Returns a view whose menu items should be additionally visible when this view is focused + * @return + */ + [[nodiscard]] virtual View* getMenuItemInheritView() const { return nullptr; } + [[nodiscard]] virtual bool shouldStoreWindowState() const { return true; } [[nodiscard]] const char *getIcon() const { return m_icon; } @@ -104,7 +110,9 @@ namespace hex { * @brief Used for focus handling. Don't use this directly * @param focused Whether this view is focused */ - void setFocused(bool focused) { m_focused = focused; } + void setFocused(bool focused); + + [[nodiscard]] static const View* getLastFocusedView(); public: class Window; diff --git a/lib/libimhex/source/api/content_registry.cpp b/lib/libimhex/source/api/content_registry.cpp index 16fa0a90c..29ae01390 100644 --- a/lib/libimhex/source/api/content_registry.cpp +++ b/lib/libimhex/source/api/content_registry.cpp @@ -969,23 +969,23 @@ namespace hex { } } - void addMenuItemSubMenu(std::vector unlocalizedMainMenuNames, u32 priority, const impl::MenuCallback &function, const impl::EnabledCallback& enabledCallback) { - addMenuItemSubMenu(std::move(unlocalizedMainMenuNames), "", priority, function, enabledCallback); + void addMenuItemSubMenu(std::vector unlocalizedMainMenuNames, u32 priority, const impl::MenuCallback &function, const impl::EnabledCallback& enabledCallback, View *view) { + addMenuItemSubMenu(std::move(unlocalizedMainMenuNames), "", priority, function, enabledCallback, view); } - void addMenuItemSubMenu(std::vector unlocalizedMainMenuNames, const char *icon, u32 priority, const impl::MenuCallback &function, const impl::EnabledCallback& enabledCallback) { + void addMenuItemSubMenu(std::vector unlocalizedMainMenuNames, const char *icon, u32 priority, const impl::MenuCallback &function, const impl::EnabledCallback& enabledCallback, View *view) { log::debug("Added new menu item sub menu to menu {} with priority {}", unlocalizedMainMenuNames[0].get(), priority); unlocalizedMainMenuNames.emplace_back(impl::SubMenuValue); impl::s_menuItems->insert({ - priority, impl::MenuItem { unlocalizedMainMenuNames, icon, Shortcut::None, nullptr, function, enabledCallback, []{ return false; }, -1 } + priority, impl::MenuItem { unlocalizedMainMenuNames, icon, Shortcut::None, view, function, enabledCallback, []{ return false; }, -1 } }); } - void addMenuItemSeparator(std::vector unlocalizedMainMenuNames, u32 priority) { + void addMenuItemSeparator(std::vector unlocalizedMainMenuNames, u32 priority, View *view) { unlocalizedMainMenuNames.emplace_back(impl::SeparatorValue); impl::s_menuItems->insert({ - priority, impl::MenuItem { unlocalizedMainMenuNames, "", Shortcut::None, nullptr, []{}, []{ return true; }, []{ return false; }, -1 } + priority, impl::MenuItem { unlocalizedMainMenuNames, "", Shortcut::None, view, []{}, []{ return true; }, []{ return false; }, -1 } }); } diff --git a/lib/libimhex/source/ui/view.cpp b/lib/libimhex/source/ui/view.cpp index add68ccff..81cde98d6 100644 --- a/lib/libimhex/source/ui/view.cpp +++ b/lib/libimhex/source/ui/view.cpp @@ -6,6 +6,8 @@ namespace hex { + static View* s_lastFocusedView = nullptr; + View::View(UnlocalizedString unlocalizedName, const char *icon) : m_unlocalizedViewName(std::move(unlocalizedName)), m_icon(icon) { } bool View::shouldDraw() const { @@ -74,4 +76,19 @@ namespace hex { return fmt::format("{}###{}", Lang(unlocalizedName), unlocalizedName.get()); } + void View::setFocused(bool focused) { + m_focused = focused; + if (focused) + s_lastFocusedView = this; + } + + + const View* View::getLastFocusedView() { + if (!ImHexApi::Provider::isValid()) + return nullptr; + + return s_lastFocusedView; + } + + } \ No newline at end of file diff --git a/lib/third_party/imgui/ColorTextEditor/source/TextEditor.cpp b/lib/third_party/imgui/ColorTextEditor/source/TextEditor.cpp index 7159bea67..dbb1d0588 100644 --- a/lib/third_party/imgui/ColorTextEditor/source/TextEditor.cpp +++ b/lib/third_party/imgui/ColorTextEditor/source/TextEditor.cpp @@ -726,6 +726,7 @@ void TextEditor::HandleMouseInputs() { } ResetCursorBlinkTime(); mRaiseContextMenu = true; + ImGui::SetWindowFocus(); } // Mouse left button dragging (=> update selection) else if (ImGui::IsMouseDragging(0) && ImGui::IsMouseDown(0)) { diff --git a/plugins/builtin/include/content/views/view_data_inspector.hpp b/plugins/builtin/include/content/views/view_data_inspector.hpp index 5fbc55e77..b5f01d243 100644 --- a/plugins/builtin/include/content/views/view_data_inspector.hpp +++ b/plugins/builtin/include/content/views/view_data_inspector.hpp @@ -18,6 +18,10 @@ namespace hex::plugin::builtin { void drawContent() override; + View* getMenuItemInheritView() const override { + return ContentRegistry::Views::getViewByName("hex.builtin.view.hex_editor.name"); + } + private: struct InspectorCacheEntry { UnlocalizedString unlocalizedName; diff --git a/plugins/builtin/include/content/views/view_find.hpp b/plugins/builtin/include/content/views/view_find.hpp index a276e7739..8335e9f9c 100644 --- a/plugins/builtin/include/content/views/view_find.hpp +++ b/plugins/builtin/include/content/views/view_find.hpp @@ -22,6 +22,10 @@ namespace hex::plugin::builtin { void drawContent() override; + View* getMenuItemInheritView() const override { + return ContentRegistry::Views::getViewByName("hex.builtin.view.hex_editor.name"); + } + private: using Occurrence = hex::ContentRegistry::DataFormatter::impl::FindOccurrence; diff --git a/plugins/builtin/include/content/views/view_pattern_data.hpp b/plugins/builtin/include/content/views/view_pattern_data.hpp index b8eb0cf7e..547fa5f09 100644 --- a/plugins/builtin/include/content/views/view_pattern_data.hpp +++ b/plugins/builtin/include/content/views/view_pattern_data.hpp @@ -13,6 +13,10 @@ namespace hex::plugin::builtin { void drawContent() override; + View* getMenuItemInheritView() const override { + return ContentRegistry::Views::getViewByName("hex.builtin.view.pattern_editor.name"); + } + private: bool m_rowColoring = false; u32 m_maxFilterItems = 128; diff --git a/plugins/builtin/romfs/lang/de_DE.json b/plugins/builtin/romfs/lang/de_DE.json index 760b33af4..05a94b569 100644 --- a/plugins/builtin/romfs/lang/de_DE.json +++ b/plugins/builtin/romfs/lang/de_DE.json @@ -820,7 +820,7 @@ "hex.builtin.view.highlight_rules.config": "Konfiguration", "hex.builtin.view.highlight_rules.expression": "Ausdruck", "hex.builtin.view.highlight_rules.help_text": "Gib einen Mathematischen ausdruck ein, welcher für jedes Byte evaluiert wird. Wenn der Ausdruck wahr ist, wird das Byte markiert.", - "hex.builtin.view.highlight_rules.menu.file.rules": "Highlighting Regeln...", + "hex.builtin.view.highlight_rules.menu.edit.rules": "Highlighting Regeln...", "hex.builtin.view.highlight_rules.name": "Highlight Regeln", "hex.builtin.view.highlight_rules.new_rule": "Neue Regel", "hex.builtin.view.highlight_rules.no_rule": "Erstelle eine neue Regel um sie zu bearbeiten.", diff --git a/plugins/builtin/romfs/lang/en_US.json b/plugins/builtin/romfs/lang/en_US.json index 5707420aa..6d7e8f1f9 100644 --- a/plugins/builtin/romfs/lang/en_US.json +++ b/plugins/builtin/romfs/lang/en_US.json @@ -901,7 +901,7 @@ "hex.builtin.view.highlight_rules.expression": "Expression", "hex.builtin.view.highlight_rules.help_text": "Enter a mathematical expression that will be evaluated for each byte in the file.\n\nThe expression can use the variables 'value' and 'offset'.\nIf the expression evaluates to true (result is greater than 0), the byte will be highlighted with the specified color.", "hex.builtin.view.highlight_rules.no_rule": "Create a rule to edit it", - "hex.builtin.view.highlight_rules.menu.file.rules": "Highlighting Rules", + "hex.builtin.view.highlight_rules.menu.edit.rules": "Highlighting Rules...", "hex.builtin.view.information.analyze": "Analyze page", "hex.builtin.view.information.analyzing": "Analyzing...", "hex.builtin.information_section.magic.apple_type": "Apple Creator / Type Code", diff --git a/plugins/builtin/romfs/lang/es_ES.json b/plugins/builtin/romfs/lang/es_ES.json index 0211c07f8..e9c83e6e4 100644 --- a/plugins/builtin/romfs/lang/es_ES.json +++ b/plugins/builtin/romfs/lang/es_ES.json @@ -816,7 +816,7 @@ "hex.builtin.view.highlight_rules.config": "", "hex.builtin.view.highlight_rules.expression": "", "hex.builtin.view.highlight_rules.help_text": "", - "hex.builtin.view.highlight_rules.menu.file.rules": "", + "hex.builtin.view.highlight_rules.menu.edit.rules": "", "hex.builtin.view.highlight_rules.name": "", "hex.builtin.view.highlight_rules.new_rule": "", "hex.builtin.view.highlight_rules.no_rule": "", diff --git a/plugins/builtin/romfs/lang/fr_FR.json b/plugins/builtin/romfs/lang/fr_FR.json index 7981d8245..a0cb29085 100644 --- a/plugins/builtin/romfs/lang/fr_FR.json +++ b/plugins/builtin/romfs/lang/fr_FR.json @@ -891,7 +891,7 @@ "hex.builtin.view.highlight_rules.expression": "Expression", "hex.builtin.view.highlight_rules.help_text": "Entrez une expression mathématique qui sera évaluée pour chaque octet du fichier.\n\nL'expression peut utiliser les variables 'value' et 'offset'.\nSi l'expression est vraie (résultat supérieur à 0), l'octet ssurligné avec la couleur spécifiée.", "hex.builtin.view.highlight_rules.no_rule": "Créez une règle pour l'éditer", - "hex.builtin.view.highlight_rules.menu.file.rules": "Règles de surbrillance", + "hex.builtin.view.highlight_rules.menu.edit.rules": "Règles de surbrillance", "hex.builtin.view.information.analyze": "Analyser la page", "hex.builtin.view.information.analyzing": "Analyse en cours...", "hex.builtin.information_section.magic.apple_type": "Code créateur/type Apple", diff --git a/plugins/builtin/romfs/lang/hu_HU.json b/plugins/builtin/romfs/lang/hu_HU.json index 9f01b4ccd..b3a99cad8 100644 --- a/plugins/builtin/romfs/lang/hu_HU.json +++ b/plugins/builtin/romfs/lang/hu_HU.json @@ -820,7 +820,7 @@ "hex.builtin.view.highlight_rules.expression": "Kifejezés", "hex.builtin.view.highlight_rules.help_text": "Adj meg egy matematikai kifejezést, ami a fájl minden egyes bájtjára kiértékelődik.\n\nA kifejezés használhatja a 'value' és 'offset' változókat. Ha a kifejezés igazra értékelődik (az eredmény nagyobb mint 0), a bájt a megadott színnel lesz kiemelve.", "hex.builtin.view.highlight_rules.no_rule": "Hozz létre egy szabályt a szerkesztéséhez", - "hex.builtin.view.highlight_rules.menu.file.rules": "Kiemelési szabályok módosítása...", + "hex.builtin.view.highlight_rules.menu.edit.rules": "Kiemelési szabályok módosítása...", "hex.builtin.view.information.analyze": "Lap elemzése", "hex.builtin.view.information.analyzing": "Elemzés...", "hex.builtin.information_section.magic.apple_type": "Apple Creator / Type Code", diff --git a/plugins/builtin/romfs/lang/it_IT.json b/plugins/builtin/romfs/lang/it_IT.json index 32a51d660..f61fff659 100644 --- a/plugins/builtin/romfs/lang/it_IT.json +++ b/plugins/builtin/romfs/lang/it_IT.json @@ -816,7 +816,7 @@ "hex.builtin.view.highlight_rules.config": "", "hex.builtin.view.highlight_rules.expression": "", "hex.builtin.view.highlight_rules.help_text": "", - "hex.builtin.view.highlight_rules.menu.file.rules": "", + "hex.builtin.view.highlight_rules.menu.edit.rules": "", "hex.builtin.view.highlight_rules.name": "", "hex.builtin.view.highlight_rules.new_rule": "", "hex.builtin.view.highlight_rules.no_rule": "", diff --git a/plugins/builtin/romfs/lang/ja_JP.json b/plugins/builtin/romfs/lang/ja_JP.json index 82e8adc0f..010964a50 100644 --- a/plugins/builtin/romfs/lang/ja_JP.json +++ b/plugins/builtin/romfs/lang/ja_JP.json @@ -816,7 +816,7 @@ "hex.builtin.view.highlight_rules.config": "", "hex.builtin.view.highlight_rules.expression": "", "hex.builtin.view.highlight_rules.help_text": "", - "hex.builtin.view.highlight_rules.menu.file.rules": "", + "hex.builtin.view.highlight_rules.menu.edit.rules": "", "hex.builtin.view.highlight_rules.name": "", "hex.builtin.view.highlight_rules.new_rule": "", "hex.builtin.view.highlight_rules.no_rule": "", diff --git a/plugins/builtin/romfs/lang/ko_KR.json b/plugins/builtin/romfs/lang/ko_KR.json index 0b033fd2e..eb0635856 100644 --- a/plugins/builtin/romfs/lang/ko_KR.json +++ b/plugins/builtin/romfs/lang/ko_KR.json @@ -816,7 +816,7 @@ "hex.builtin.view.highlight_rules.config": "구성", "hex.builtin.view.highlight_rules.expression": "표현식", "hex.builtin.view.highlight_rules.help_text": "파일의 각 바이트에 대해 판단할 수학 표현식을 입력합니다.\n\n표현식에는 '값' 및 '오프셋' 변수를 사용할 수 있습니다.\n표현식이 참으로 판단되면(결과가 0보다 크면) 해당 바이트가 지정 색상으로 강조 표시됩니다.", - "hex.builtin.view.highlight_rules.menu.file.rules": "강조 규칙 수정...", + "hex.builtin.view.highlight_rules.menu.edit.rules": "강조 규칙 수정...", "hex.builtin.view.highlight_rules.name": "강조 규칙", "hex.builtin.view.highlight_rules.new_rule": "새 규칙", "hex.builtin.view.highlight_rules.no_rule": "규칙을 만들어 편집하세요", diff --git a/plugins/builtin/romfs/lang/pl_PL.json b/plugins/builtin/romfs/lang/pl_PL.json index fb5182404..dd6473788 100644 --- a/plugins/builtin/romfs/lang/pl_PL.json +++ b/plugins/builtin/romfs/lang/pl_PL.json @@ -935,7 +935,7 @@ "hex.builtin.view.highlight_rules.config": "Konfiguracja", "hex.builtin.view.highlight_rules.expression": "Wyrażenie", "hex.builtin.view.highlight_rules.help_text": "Wprowadź wyrażenie matematyczne które zostanie ocenione dla każdego bajtu w pliku.\n\nWyrażenie może używać zmiennych 'value' i 'offset'.\nJeśli wyrażenie oceniane jest jako prawdziwe (wynik jest większy niż 0), bajt zostanie podświetlony określonym kolorem.", - "hex.builtin.view.highlight_rules.menu.file.rules": "Reguły podświetlania", + "hex.builtin.view.highlight_rules.menu.edit.rules": "Reguły podświetlania...", "hex.builtin.view.highlight_rules.name": "Reguły podświetlania", "hex.builtin.view.highlight_rules.new_rule": "Nowa reguła", "hex.builtin.view.highlight_rules.no_rule": "Utwórz regułę aby ją edytować", diff --git a/plugins/builtin/romfs/lang/pt_BR.json b/plugins/builtin/romfs/lang/pt_BR.json index 0ee90dce0..97a129adb 100644 --- a/plugins/builtin/romfs/lang/pt_BR.json +++ b/plugins/builtin/romfs/lang/pt_BR.json @@ -816,7 +816,7 @@ "hex.builtin.view.highlight_rules.config": "", "hex.builtin.view.highlight_rules.expression": "", "hex.builtin.view.highlight_rules.help_text": "", - "hex.builtin.view.highlight_rules.menu.file.rules": "", + "hex.builtin.view.highlight_rules.menu.edit.rules": "", "hex.builtin.view.highlight_rules.name": "", "hex.builtin.view.highlight_rules.new_rule": "", "hex.builtin.view.highlight_rules.no_rule": "", diff --git a/plugins/builtin/romfs/lang/ru_RU.json b/plugins/builtin/romfs/lang/ru_RU.json index 1a8867b1b..0c6ab82a5 100644 --- a/plugins/builtin/romfs/lang/ru_RU.json +++ b/plugins/builtin/romfs/lang/ru_RU.json @@ -868,7 +868,7 @@ "hex.builtin.view.highlight_rules.expression": "Выражение", "hex.builtin.view.highlight_rules.help_text": "Введите математическое выражение, которое будет применено к каждому байту в файле.\n\nМожно испорльзовать переменные 'value' и 'offset'.\nЕсли выражение становится истинным (результат больше 0), байт будет выделен указанным цветом.", "hex.builtin.view.highlight_rules.no_rule": "Создайте правило прежде чем редактировать его", - "hex.builtin.view.highlight_rules.menu.file.rules": "Правила подсветки", + "hex.builtin.view.highlight_rules.menu.edit.rules": "Правила подсветки...", "hex.builtin.view.information.analyze": "Проанализировать", "hex.builtin.view.information.analyzing": "Анализ...", "hex.builtin.information_section.magic.apple_type": "Apple Creator / Код типа", diff --git a/plugins/builtin/romfs/lang/zh_CN.json b/plugins/builtin/romfs/lang/zh_CN.json index 3721c4714..3cb16d9ac 100644 --- a/plugins/builtin/romfs/lang/zh_CN.json +++ b/plugins/builtin/romfs/lang/zh_CN.json @@ -894,7 +894,7 @@ "hex.builtin.view.highlight_rules.expression": "表达式", "hex.builtin.view.highlight_rules.help_text": "输入将针对文件中的每个字节求值的数学表达式。\n\n该表达式可以使用变量“value”和“offset”。\n如果表达式求值 为 true(结果大于 0),该字节将以指定的颜色突出显示。", "hex.builtin.view.highlight_rules.no_rule": "创建一个规则来编辑它", - "hex.builtin.view.highlight_rules.menu.file.rules": "修改突出显示规则……", + "hex.builtin.view.highlight_rules.menu.edit.rules": "修改突出显示规则……", "hex.builtin.view.information.analyze": "分析", "hex.builtin.view.information.analyzing": "分析中……", "hex.builtin.information_section.magic.apple_type": "Apple 创建者 / 类型代码", diff --git a/plugins/builtin/romfs/lang/zh_TW.json b/plugins/builtin/romfs/lang/zh_TW.json index f38554b4f..e00162f29 100644 --- a/plugins/builtin/romfs/lang/zh_TW.json +++ b/plugins/builtin/romfs/lang/zh_TW.json @@ -816,7 +816,7 @@ "hex.builtin.view.highlight_rules.config": "", "hex.builtin.view.highlight_rules.expression": "", "hex.builtin.view.highlight_rules.help_text": "", - "hex.builtin.view.highlight_rules.menu.file.rules": "", + "hex.builtin.view.highlight_rules.menu.edit.rules": "", "hex.builtin.view.highlight_rules.name": "", "hex.builtin.view.highlight_rules.new_rule": "", "hex.builtin.view.highlight_rules.no_rule": "", diff --git a/plugins/builtin/source/content/main_menu_items.cpp b/plugins/builtin/source/content/main_menu_items.cpp index de1c9c20c..4755d593b 100644 --- a/plugins/builtin/source/content/main_menu_items.cpp +++ b/plugins/builtin/source/content/main_menu_items.cpp @@ -500,19 +500,6 @@ namespace hex::plugin::builtin { static void createEditMenu() { ContentRegistry::Interface::registerMainMenuItem("hex.builtin.menu.edit", 2000); - - /* Undo */ - ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.menu.edit.undo" }, ICON_VS_DISCARD, 1000, CTRLCMD + Keys::Z, [] { - auto provider = ImHexApi::Provider::get(); - provider->undo(); - }, [&] { return ImHexApi::Provider::isValid() && ImHexApi::Provider::get()->canUndo(); }); - - /* Redo */ - ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.menu.edit.redo" }, ICON_VS_REDO, 1050, CTRLCMD + Keys::Y, [] { - auto provider = ImHexApi::Provider::get(); - provider->redo(); - }, [&] { return ImHexApi::Provider::isValid() && ImHexApi::Provider::get()->canRedo(); }); - } static void createViewMenu() { diff --git a/plugins/builtin/source/content/views/view_bookmarks.cpp b/plugins/builtin/source/content/views/view_bookmarks.cpp index ead13fdaa..670465721 100644 --- a/plugins/builtin/source/content/views/view_bookmarks.cpp +++ b/plugins/builtin/source/content/views/view_bookmarks.cpp @@ -602,7 +602,8 @@ namespace hex::plugin::builtin { auto selection = ImHexApi::HexEditor::getSelection(); ImHexApi::Bookmarks::add(selection->getStartAddress(), selection->getSize(), {}, {}); - }, []{ return ImHexApi::Provider::isValid() && ImHexApi::HexEditor::isSelectionValid(); }); + }, []{ return ImHexApi::Provider::isValid() && ImHexApi::HexEditor::isSelectionValid(); }, + ContentRegistry::Views::getViewByName("hex.builtin.view.hex_editor.name")); ContentRegistry::Interface::addMenuItemSeparator({ "hex.builtin.menu.file", "hex.builtin.menu.file.import" }, 3000); diff --git a/plugins/builtin/source/content/views/view_hex_editor.cpp b/plugins/builtin/source/content/views/view_hex_editor.cpp index 333c35f7f..fb296b403 100644 --- a/plugins/builtin/source/content/views/view_hex_editor.cpp +++ b/plugins/builtin/source/content/views/view_hex_editor.cpp @@ -722,8 +722,10 @@ namespace hex::plugin::builtin { ImGui::PopStyleVar(); // Right click menu - if (ImGui::IsMouseDown(ImGuiMouseButton_Right) && ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows) && !ImGui::IsAnyItemHovered() && !ImGui::IsMouseDragging(ImGuiMouseButton_Right)) + if (ImGui::IsMouseDown(ImGuiMouseButton_Right) && ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows) && !ImGui::IsAnyItemHovered() && !ImGui::IsMouseDragging(ImGuiMouseButton_Right)) { RequestOpenPopup::post("hex.builtin.menu.edit"); + ImGui::SetWindowFocus(); + } } void ViewHexEditor::drawContent() { @@ -1169,6 +1171,19 @@ namespace hex::plugin::builtin { } void ViewHexEditor::registerMenuItems() { + /* Undo */ + ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.menu.edit.undo" }, ICON_VS_DISCARD, 1000, CTRLCMD + Keys::Z, [] { + auto provider = ImHexApi::Provider::get(); + provider->undo(); + }, [&] { return ImHexApi::Provider::isValid() && ImHexApi::Provider::get()->canUndo(); }, + this); + + /* Redo */ + ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.menu.edit.redo" }, ICON_VS_REDO, 1050, CTRLCMD + Keys::Y, [] { + auto provider = ImHexApi::Provider::get(); + provider->redo(); + }, [&] { return ImHexApi::Provider::isValid() && ImHexApi::Provider::get()->canRedo(); }, + this); ContentRegistry::Interface::addMenuItemSeparator({ "hex.builtin.menu.file" }, 1300); @@ -1181,7 +1196,8 @@ namespace hex::plugin::builtin { bool providerValid = ImHexApi::Provider::isValid(); return providerValid && provider->isWritable() && provider->isSavable() && provider->isDirty(); - }); + }, + this); /* Save As */ ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.file", "hex.builtin.view.hex_editor.menu.file.save_as" }, ICON_VS_SAVE_AS, 1375, @@ -1192,7 +1208,8 @@ namespace hex::plugin::builtin { bool providerValid = ImHexApi::Provider::isValid(); return providerValid && provider->isDumpable(); - }); + }, + this); /* Load Encoding File */ ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.file", "hex.builtin.menu.file.import", "hex.builtin.menu.file.import.custom_encoding" }, "あ", 5050, Shortcut::None, @@ -1220,9 +1237,10 @@ namespace hex::plugin::builtin { }); }); }, - ImHexApi::Provider::isValid); + ImHexApi::Provider::isValid, + this); - ContentRegistry::Interface::addMenuItemSeparator({ "hex.builtin.menu.file" }, 1500); + ContentRegistry::Interface::addMenuItemSeparator({ "hex.builtin.menu.file" }, 1500, this); /* Search */ ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.file", "hex.builtin.view.hex_editor.menu.file.search" }, ICON_VS_SEARCH, 1550, @@ -1230,7 +1248,8 @@ namespace hex::plugin::builtin { [this] { this->openPopup(this); }, - ImHexApi::Provider::isValid); + ImHexApi::Provider::isValid, + this); /* Goto */ ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.file", "hex.builtin.view.hex_editor.menu.file.goto" }, ICON_VS_DEBUG_STEP_INTO, 1600, @@ -1238,11 +1257,12 @@ namespace hex::plugin::builtin { [this] { this->openPopup(); }, - ImHexApi::Provider::isValid); + ImHexApi::Provider::isValid, + this); - ContentRegistry::Interface::addMenuItemSeparator({ "hex.builtin.menu.edit" }, 1100); + ContentRegistry::Interface::addMenuItemSeparator({ "hex.builtin.menu.edit" }, 1100, this); /* Copy */ ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.copy" }, ICON_VS_COPY, 1150, @@ -1255,7 +1275,7 @@ namespace hex::plugin::builtin { ImHexApi::HexEditor::isSelectionValid, this); - ContentRegistry::Interface::addMenuItemSubMenu({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.copy_as" }, ICON_VS_PREVIEW, 1190, []{}, ImHexApi::HexEditor::isSelectionValid); + ContentRegistry::Interface::addMenuItemSubMenu({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.copy_as" }, ICON_VS_PREVIEW, 1190, []{}, ImHexApi::HexEditor::isSelectionValid, this); /* Copy As */ ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.copy_as", "hex.builtin.view.hex_editor.copy.ascii" }, ICON_VS_SYMBOL_TEXT, 1200, @@ -1276,7 +1296,8 @@ namespace hex::plugin::builtin { if (selection.has_value() && selection != Region::Invalid()) ImGui::SetClipboardText(hex::format("0x{:08X}", selection->getStartAddress()).c_str()); }, - ImHexApi::HexEditor::isSelectionValid); + ImHexApi::HexEditor::isSelectionValid, + this); /* Copy custom encoding */ ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.copy_as", "hex.builtin.view.hex_editor.copy.custom_encoding" }, "あ", 1300, @@ -1289,9 +1310,10 @@ namespace hex::plugin::builtin { }, [this] { return ImHexApi::HexEditor::isSelectionValid() && m_hexEditor.getCustomEncoding().has_value(); - }); + }, + this); - ContentRegistry::Interface::addMenuItemSeparator({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.copy_as" }, 1350); + ContentRegistry::Interface::addMenuItemSeparator({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.copy_as" }, 1350, this); /* Copy as... */ ContentRegistry::Interface::addMenuItemSubMenu({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.copy_as" }, ICON_VS_FILE_CODE, 1400, []{ @@ -1331,7 +1353,7 @@ namespace hex::plugin::builtin { }, [] { return ImHexApi::Provider::isValid() && ImHexApi::HexEditor::isSelectionValid(); - }); + }, this); /* Paste */ ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.paste" }, ICON_VS_OUTPUT, 1450, CurrentView + CTRLCMD + Keys::V, @@ -1342,7 +1364,7 @@ namespace hex::plugin::builtin { this); /* Paste... */ - ContentRegistry::Interface::addMenuItemSubMenu({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.paste_as" }, ICON_VS_CLIPPY, 1490, []{}, ImHexApi::HexEditor::isSelectionValid); + ContentRegistry::Interface::addMenuItemSubMenu({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.paste_as" }, ICON_VS_CLIPPY, 1490, []{}, ImHexApi::HexEditor::isSelectionValid, this); /* Paste... > Paste all */ ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.paste_as", "hex.builtin.view.hex_editor.menu.edit.paste_all" }, ICON_VS_CLIPPY, 1500, CurrentView + CTRLCMD + SHIFT + Keys::V, @@ -1368,7 +1390,8 @@ namespace hex::plugin::builtin { auto selection = ImHexApi::HexEditor::getSelection().value_or(ImHexApi::HexEditor::ProviderRegion{ { 0, 1 }, nullptr }); this->openPopup(selection.getStartAddress(), selection.getSize()); }, - ImHexApi::Provider::isValid); + ImHexApi::Provider::isValid, + this); /* Select All */ ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.select_all" }, ICON_VS_LIST_FLAT, 1550, CurrentView + CTRLCMD + Keys::A, @@ -1380,7 +1403,7 @@ namespace hex::plugin::builtin { this); - ContentRegistry::Interface::addMenuItemSeparator({ "hex.builtin.menu.edit" }, 1600); + ContentRegistry::Interface::addMenuItemSeparator({ "hex.builtin.menu.edit" }, 1600, this); /* Set Base Address */ ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.set_base" }, ICON_VS_LOCATION, 1650, Shortcut::None, @@ -1388,7 +1411,8 @@ namespace hex::plugin::builtin { auto provider = ImHexApi::Provider::get(); this->openPopup(provider->getBaseAddress()); }, - [] { return ImHexApi::Provider::isValid() && ImHexApi::Provider::get()->isReadable(); }); + [] { return ImHexApi::Provider::isValid() && ImHexApi::Provider::get()->isReadable(); }, + this); /* Resize */ ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.resize" }, ICON_VS_ARROW_BOTH, 1700, Shortcut::None, @@ -1396,7 +1420,8 @@ namespace hex::plugin::builtin { auto provider = ImHexApi::Provider::get(); this->openPopup(provider->getActualSize()); }, - [] { return ImHexApi::Provider::isValid() && ImHexApi::Provider::get()->isResizable(); }); + [] { return ImHexApi::Provider::isValid() && ImHexApi::Provider::get()->isResizable(); }, + this); /* Insert */ ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.insert" }, ICON_VS_INSERT, 1750, Shortcut::None, @@ -1405,7 +1430,8 @@ namespace hex::plugin::builtin { this->openPopup(selection->getStartAddress(), 0x00); }, - [] { return ImHexApi::HexEditor::isSelectionValid() && ImHexApi::Provider::isValid() && ImHexApi::Provider::get()->isResizable(); }); + [] { return ImHexApi::HexEditor::isSelectionValid() && ImHexApi::Provider::isValid() && ImHexApi::Provider::get()->isResizable(); }, + this); /* Remove */ ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.remove" }, ICON_VS_CLEAR_ALL, 1800, Shortcut::None, @@ -1414,7 +1440,8 @@ namespace hex::plugin::builtin { this->openPopup(selection->getStartAddress(), selection->getSize()); }, - [] { return ImHexApi::HexEditor::isSelectionValid() && ImHexApi::Provider::isValid() && ImHexApi::Provider::get()->isResizable(); }); + [] { return ImHexApi::HexEditor::isSelectionValid() && ImHexApi::Provider::isValid() && ImHexApi::Provider::get()->isResizable(); }, + this); /* Fill */ ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.fill" }, ICON_VS_PAINTCAN, 1810, Shortcut::None, @@ -1423,7 +1450,8 @@ namespace hex::plugin::builtin { this->openPopup(selection->getStartAddress(), selection->getSize()); }, - [] { return ImHexApi::HexEditor::isSelectionValid() && ImHexApi::Provider::isValid() && ImHexApi::Provider::get()->isWritable(); }); + [] { return ImHexApi::HexEditor::isSelectionValid() && ImHexApi::Provider::isValid() && ImHexApi::Provider::get()->isWritable(); }, + this); /* Toggle Overwrite/Insert mode */ ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.insert_mode" }, ICON_VS_PENCIL, 1820, Shortcut::None, @@ -1441,7 +1469,8 @@ namespace hex::plugin::builtin { }, [this] { return m_hexEditor.getMode() == ui::HexEditor::Mode::Insert; - }); + }, + this); /* Jump to */ ContentRegistry::Interface::addMenuItemSubMenu({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.jump_to" }, ICON_VS_DEBUG_STEP_OUT, 1850, @@ -1486,7 +1515,8 @@ namespace hex::plugin::builtin { RequestJumpToPattern::post(patterns.front()); } }, - [] { return ImHexApi::Provider::isValid() && ImHexApi::HexEditor::isSelectionValid() && ImHexApi::HexEditor::getSelection()->getSize() <= sizeof(u64); }); + [] { return ImHexApi::Provider::isValid() && ImHexApi::HexEditor::isSelectionValid() && ImHexApi::HexEditor::getSelection()->getSize() <= sizeof(u64); }, + this); /* Set Page Size */ ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.set_page_size" }, ICON_VS_BROWSER, 1860, Shortcut::None, @@ -1494,9 +1524,10 @@ namespace hex::plugin::builtin { auto provider = ImHexApi::Provider::get(); this->openPopup(provider->getPageSize()); }, - [] { return ImHexApi::Provider::isValid() && ImHexApi::Provider::get()->isReadable(); }); + [] { return ImHexApi::Provider::isValid() && ImHexApi::Provider::get()->isReadable(); }, + this); - ContentRegistry::Interface::addMenuItemSeparator({ "hex.builtin.menu.edit" }, 1900); + ContentRegistry::Interface::addMenuItemSeparator({ "hex.builtin.menu.edit" }, 1900, this); /* Open in new provider */ ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.open_in_new_provider" }, ICON_VS_GO_TO_FILE, 1950, Shortcut::None, @@ -1510,7 +1541,8 @@ namespace hex::plugin::builtin { EventProviderOpened::post(viewProvider); } }, - [] { return ImHexApi::HexEditor::isSelectionValid() && ImHexApi::Provider::isValid(); }); + [] { return ImHexApi::HexEditor::isSelectionValid() && ImHexApi::Provider::isValid(); }, + this); } } diff --git a/plugins/builtin/source/content/views/view_highlight_rules.cpp b/plugins/builtin/source/content/views/view_highlight_rules.cpp index 4cb04062f..8e07be772 100644 --- a/plugins/builtin/source/content/views/view_highlight_rules.cpp +++ b/plugins/builtin/source/content/views/view_highlight_rules.cpp @@ -113,9 +113,10 @@ namespace hex::plugin::builtin { ViewHighlightRules::ViewHighlightRules() : View::Floating("hex.builtin.view.highlight_rules.name") { - ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.file", "hex.builtin.view.highlight_rules.menu.file.rules" }, ICON_VS_TAG, 1650, Shortcut::None, [&, this] { + ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.highlight_rules.menu.edit.rules" }, ICON_VS_TAG, 1950, Shortcut::None, [&, this] { this->getWindowOpenState() = true; - }, ImHexApi::Provider::isValid); + }, ImHexApi::Provider::isValid, + ContentRegistry::Views::getViewByName("hex.builtin.view.hex_editor.name")); ProjectFile::registerPerProviderHandler({ .basePath = "highlight_rules.json", diff --git a/plugins/builtin/source/content/views/view_pattern_editor.cpp b/plugins/builtin/source/content/views/view_pattern_editor.cpp index cd03f0f74..81c30e570 100644 --- a/plugins/builtin/source/content/views/view_pattern_editor.cpp +++ b/plugins/builtin/source/content/views/view_pattern_editor.cpp @@ -36,6 +36,7 @@ #include #include +#include #include namespace hex::plugin::builtin { @@ -359,10 +360,13 @@ namespace hex::plugin::builtin { m_textEditorHoverBox = ImRect(windowPosition,windowPosition+textEditorSize); m_consoleHoverBox = ImRect(ImVec2(windowPosition.x,windowPosition.y+textEditorSize.y),windowPosition+availableSize); - TextEditor::FindReplaceHandler *findReplaceHandler = m_textEditor.get(provider).GetFindReplaceHandler(); + if (m_textEditor.get(provider).RaiseContextMenu()) { - ImGui::OpenPopup("##text_editor_context_menu"); + RequestOpenPopup::post("hex.builtin.menu.edit"); m_textEditor.get(provider).ClearRaiseContextMenu(); + + if (!m_textEditor.get(provider).HasSelection()) + m_textEditor.get(provider).SelectWordUnderCursor(); } if (m_cursorNeedsUpdate.get(provider)) { @@ -370,74 +374,6 @@ namespace hex::plugin::builtin { m_cursorNeedsUpdate.get(provider) = false; } - if (ImGui::BeginPopup("##text_editor_context_menu")) { - // no shortcut for this - if (ImGui::MenuItemEx("hex.builtin.menu.file.import.pattern_file"_lang, ICON_VS_SIGN_IN, nullptr, false)) - m_importPatternFile(); - if (ImGui::MenuItemEx("hex.builtin.menu.file.export.pattern_file"_lang, ICON_VS_SIGN_OUT, nullptr, false)) - m_exportPatternFile(); - - ImGui::Separator(); - - if (!m_textEditor.get(provider).HasSelection()) - m_textEditor.get(provider).SelectWordUnderCursor(); - const bool hasSelection = m_textEditor.get(provider).HasSelection(); - if (ImGui::MenuItemEx("hex.builtin.view.hex_editor.menu.edit.cut"_lang, ICON_VS_COMBINE, Shortcut(CTRLCMD + Keys::X).toString().c_str(), false, hasSelection)) { - m_textEditor.get(provider).Cut(); - } - 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_textEditor.get(provider).Copy(); - } - if (ImGui::MenuItemEx("hex.builtin.view.hex_editor.menu.edit.paste"_lang, ICON_VS_OUTPUT, Shortcut(CTRLCMD + Keys::V).toString().c_str())) { - m_textEditor.get(provider).Paste(); - } - - ImGui::Separator(); - - if (ImGui::MenuItemEx("hex.builtin.menu.edit.undo"_lang, ICON_VS_DISCARD, Shortcut(CTRLCMD + Keys::Z).toString().c_str(), false, m_textEditor.get(provider).CanUndo())) { - m_textEditor.get(provider).Undo(); - } - if (ImGui::MenuItemEx("hex.builtin.menu.edit.redo"_lang, ICON_VS_REDO, Shortcut(CTRLCMD + Keys::Y).toString().c_str(), false, m_textEditor.get(provider).CanRedo())) { - m_textEditor.get(provider).Redo(); - } - - ImGui::Separator(); - // Search and replace entries - if (ImGui::MenuItemEx("hex.builtin.view.pattern_editor.menu.find"_lang, ICON_VS_SEARCH, Shortcut(CTRLCMD + Keys::F).toString().c_str())){ - 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.get(provider),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_textEditor.get(provider),false); - - if (ImGui::MenuItemEx("hex.builtin.view.pattern_editor.menu.replace"_lang, ICON_VS_REPLACE, Shortcut(CTRLCMD + Keys::H).toString().c_str())) { - 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.get(provider),true); - - if (ImGui::MenuItem("hex.builtin.view.pattern_editor.menu.replace_previous"_lang, "",false,!findReplaceHandler->GetReplaceWord().empty())) - findReplaceHandler->Replace(&m_textEditor.get(provider),false); - - if (ImGui::MenuItemEx("hex.builtin.view.pattern_editor.menu.replace_all"_lang, ICON_VS_REPLACE_ALL, "",false,!findReplaceHandler->GetReplaceWord().empty())) - findReplaceHandler->ReplaceAll(&m_textEditor.get(provider)); - - 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; - - if (ImGui::IsKeyPressed(ImGuiKey_Escape, false)) - ImGui::CloseCurrentPopup(); - - ImGui::EndPopup(); - } - if (auto editor = getEditorFromFocusedWindow(); editor != nullptr) { setupFindReplace(editor); setupGotoLine(editor); @@ -2076,6 +2012,101 @@ namespace hex::plugin::builtin { } void ViewPatternEditor::registerMenuItems() { + /*if (ImGui::MenuItemEx("hex.builtin.menu.file.import.pattern_file"_lang, ICON_VS_SIGN_IN, nullptr, false)) + m_importPatternFile(); + if (ImGui::MenuItemEx("hex.builtin.menu.file.export.pattern_file"_lang, ICON_VS_SIGN_OUT, nullptr, false)) + m_exportPatternFile(); + + ImGui::Separator();*/ + + /* Undo */ + ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.menu.edit.undo" }, ICON_VS_DISCARD, 1000, CTRLCMD + Keys::Z, [this] { + m_textEditor->Undo(); + }, [this] { return ImHexApi::Provider::isValid() && m_textEditor->CanUndo(); }, + this); + + /* Redo */ + ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.menu.edit.redo" }, ICON_VS_REDO, 1100, CTRLCMD + Keys::Y, [this] { + m_textEditor->Redo(); + }, [this] { return ImHexApi::Provider::isValid() &&m_textEditor->CanRedo(); }, + this); + + ContentRegistry::Interface::addMenuItemSeparator({ "hex.builtin.menu.edit" }, 1200, this); + + + /* Cut */ + ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.cut" }, ICON_VS_COMBINE, 1300, CTRLCMD + Keys::X, [this] { + m_textEditor->Cut(); + }, [this] { return ImHexApi::Provider::isValid() &&m_textEditor->HasSelection(); }, + this); + + /* Copy */ + ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.copy" }, ICON_VS_COPY, 1400, CTRLCMD + Keys::C, [this] { + m_textEditor->Copy(); + }, [this] { return ImHexApi::Provider::isValid() &&m_textEditor->HasSelection(); }, + this); + + /* Paste */ + ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.paste" }, ICON_VS_OUTPUT, 1500, CTRLCMD + Keys::V, [this] { + m_textEditor->Paste(); + }, [] { return true; }, + this); + + ContentRegistry::Interface::addMenuItemSeparator({ "hex.builtin.menu.edit" }, 1600, this); + + /* Find */ + ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.pattern_editor.menu.find" }, ICON_VS_SEARCH, 1700, CTRLCMD + Keys::F, [this] { + m_replaceMode = false; + m_openFindReplacePopUp = true; + }, [] { return true; }, + this); + + /* Find Next */ + ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.pattern_editor.menu.find_next" }, 1800, Keys::F3, [this] { + m_consoleEditor->GetFindReplaceHandler()->FindMatch(&*m_textEditor, true); + }, [this] { return ImHexApi::Provider::isValid() && !m_consoleEditor->GetFindReplaceHandler()->GetFindWord().empty(); }, + []{ return false; }, + this); + + /* Find Previous */ + ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.pattern_editor.menu.find_previous" }, 1900, Keys::F3, [this] { + m_consoleEditor->GetFindReplaceHandler()->FindMatch(&*m_textEditor, true); + }, [this] { return ImHexApi::Provider::isValid() && !m_consoleEditor->GetFindReplaceHandler()->GetFindWord().empty(); }, + []{ return false; }, + this); + + /* Replace */ + ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.pattern_editor.menu.replace" }, ICON_VS_REPLACE, 2000, CTRLCMD + Keys::H, [this] { + m_replaceMode = true; + m_openFindReplacePopUp = true; + }, [] { return true; }, + this); + + /* Replace Next */ + ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.pattern_editor.menu.replace_next" }, 2100, Shortcut::None, [this] { + m_consoleEditor->GetFindReplaceHandler()->Replace(&*m_textEditor, true); + }, [this] { return ImHexApi::Provider::isValid() && !m_consoleEditor->GetFindReplaceHandler()->GetReplaceWord().empty(); }, + []{ return false; }, + this); + + /* Replace Previous */ + ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.pattern_editor.menu.replace_previous" }, 2200, Shortcut::None, [this] { + m_consoleEditor->GetFindReplaceHandler()->Replace(&*m_textEditor, false); + }, [this] { return ImHexApi::Provider::isValid() && !m_consoleEditor->GetFindReplaceHandler()->GetReplaceWord().empty(); }, + []{ return false; }, + this); + + /* Replace All */ + ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.pattern_editor.menu.replace_all" }, ICON_VS_REPLACE_ALL, 2300, Shortcut::None, [this] { + m_consoleEditor->GetFindReplaceHandler()->ReplaceAll(&*m_textEditor); + }, [this] { return ImHexApi::Provider::isValid() && !m_consoleEditor->GetFindReplaceHandler()->GetReplaceWord().empty(); }, + this); + + ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.edit", "hex.builtin.view.pattern_editor.menu.goto_line" }, ICON_VS_DEBUG_STEP_INTO, 2400, CTRLCMD + Keys::G, [this] { + m_openGotoLinePopUp = true; + }, [] { return true; }, + this); + /* 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, m_importPatternFile, ImHexApi::Provider::isValid); @@ -2141,7 +2172,7 @@ namespace hex::plugin::builtin { } }, [this] { return ImHexApi::Provider::isValid() && ImHexApi::HexEditor::isSelectionValid() && m_runningParsers == 0; - }); + }, ContentRegistry::Views::getViewByName("hex.builtin.view.hex_editor.name")); } void ViewPatternEditor::registerHandlers() { diff --git a/plugins/builtin/source/content/window_decoration.cpp b/plugins/builtin/source/content/window_decoration.cpp index 00b197c6c..afc329a5b 100644 --- a/plugins/builtin/source/content/window_decoration.cpp +++ b/plugins/builtin/source/content/window_decoration.cpp @@ -25,7 +25,7 @@ namespace hex::plugin::builtin { - // Function that draws the provider popup, defiend in the ui_items.cpp file + // Function that draws the provider popup, defined in the ui_items.cpp file void drawProviderTooltip(const prv::Provider *provider); namespace { @@ -296,6 +296,32 @@ namespace hex::plugin::builtin { } } + bool isMenuItemVisible(const ContentRegistry::Interface::impl::MenuItem &menuItem) { + const auto lastFocusedView = View::getLastFocusedView(); + if (lastFocusedView == nullptr && menuItem.view != nullptr) { + return false; + } + + if (lastFocusedView != nullptr && menuItem.view != nullptr) { + if (menuItem.view != lastFocusedView && menuItem.view != lastFocusedView->getMenuItemInheritView()) { + return false; + } + } + + return true; + } + + std::set getVisibleMainMenus() { + std::set result; + for (auto &[priority, menuItem] : ContentRegistry::Interface::impl::getMenuItems()) { + if (isMenuItemVisible(menuItem)) { + result.emplace(menuItem.unlocalizedNames.front()); + } + } + + return result; + } + void populateMenu(const UnlocalizedString &menuName) { for (auto &[priority, menuItem] : ContentRegistry::Interface::impl::getMenuItems()) { if (!menuName.empty()) { @@ -303,6 +329,10 @@ namespace hex::plugin::builtin { continue; } + if (!isMenuItemVisible(menuItem)) { + continue; + } + const auto &[ unlocalizedNames, icon, @@ -310,11 +340,11 @@ namespace hex::plugin::builtin { view, callback, enabledCallback, - selectedCallack, + selectedCallback, toolbarIndex ] = menuItem; - createNestedMenu(unlocalizedNames | std::views::drop(1), icon.glyph.c_str(), shortcut, view, callback, enabledCallback, selectedCallack); + createNestedMenu(unlocalizedNames | std::views::drop(1), icon.glyph.c_str(), shortcut, view, callback, enabledCallback, selectedCallback); } } @@ -336,20 +366,25 @@ namespace hex::plugin::builtin { void drawMenu() { const auto &menuItems = ContentRegistry::Interface::impl::getMainMenuItems(); + const auto visibleMainMenus = getVisibleMainMenus(); if (menu::isNativeMenuBarUsed()) { for (const auto &[priority, menuItem] : menuItems) { - defineMenu(menuItem.unlocalizedName); + if (visibleMainMenus.contains(menuItem.unlocalizedName)) + defineMenu(menuItem.unlocalizedName); } } else { auto cursorPos = ImGui::GetCursorPosX(); u32 fittingItems = 0; for (const auto &[priority, menuItem] : menuItems) { + if (!visibleMainMenus.contains(menuItem.unlocalizedName)) + continue; + auto menuName = Lang(menuItem.unlocalizedName); const auto padding = ImGui::GetStyle().FramePadding.x; - bool lastItem = (fittingItems + 1) == menuItems.size(); + bool lastItem = (fittingItems + 1) == visibleMainMenus.size(); auto width = ImGui::CalcTextSize(menuName).x + padding * (lastItem ? -3.0F : 4.0F); if ((cursorPos + width) > (s_searchBarPosition - ImGui::CalcTextSize(ICON_VS_ELLIPSIS).x - padding * 2)) @@ -367,6 +402,8 @@ namespace hex::plugin::builtin { for (const auto &[priority, menuItem] : menuItems) { if (count >= fittingItems) break; + if (!visibleMainMenus.contains(menuItem.unlocalizedName)) + continue; defineMenu(menuItem.unlocalizedName); @@ -377,17 +414,20 @@ namespace hex::plugin::builtin { if (fittingItems == 0) { if (ImGui::BeginMenu(ICON_VS_MENU)) { for (const auto &[priority, menuItem] : menuItems) { - defineMenu(menuItem.unlocalizedName); + if (visibleMainMenus.contains(menuItem.unlocalizedName)) + defineMenu(menuItem.unlocalizedName); } ImGui::EndMenu(); } - } else if (fittingItems < menuItems.size()) { + } else if (fittingItems < visibleMainMenus.size()) { u32 count = 0; if (ImGui::BeginMenu(ICON_VS_ELLIPSIS)) { for (const auto &[priority, menuItem] : menuItems) { ON_SCOPE_EXIT { count += 1; }; if (count < fittingItems) continue; + if (!visibleMainMenus.contains(menuItem.unlocalizedName)) + continue; defineMenu(menuItem.unlocalizedName); } @@ -602,11 +642,10 @@ namespace hex::plugin::builtin { ImGui::PopStyleVar(2); // Draw main menu popups - for (auto &[priority, menuItem] : ContentRegistry::Interface::impl::getMenuItems()) { - const auto &[unlocalizedNames, icon, shortcut, view, callback, enabledCallback, selectedCallback, toolbarIndex] = menuItem; - - if (ImGui::BeginPopup(unlocalizedNames.front().get().c_str())) { - createNestedMenu({ unlocalizedNames.begin() + 1, unlocalizedNames.end() }, icon.glyph.c_str(), shortcut, view, callback, enabledCallback, selectedCallback); + for (auto &[priority, menuItem] : ContentRegistry::Interface::impl::getMainMenuItems()) { + const auto &unlocalizedNames = menuItem.unlocalizedName; + if (ImGui::BeginPopup(unlocalizedNames.get().c_str())) { + populateMenu(unlocalizedNames); ImGui::EndPopup(); } } diff --git a/plugins/disassembler/source/content/views/view_disassembler.cpp b/plugins/disassembler/source/content/views/view_disassembler.cpp index d0a1c4981..aa0de0657 100644 --- a/plugins/disassembler/source/content/views/view_disassembler.cpp +++ b/plugins/disassembler/source/content/views/view_disassembler.cpp @@ -30,7 +30,7 @@ namespace hex::plugin::disasm { this->disassemble(); }, [this]{ return ImHexApi::HexEditor::isSelectionValid() && !m_disassemblerTask.isRunning() && *m_currArchitecture != nullptr; - }); + }, ContentRegistry::Views::getViewByName("hex.builtin.view.hex_editor.name")); } ViewDisassembler::~ViewDisassembler() {