From 1f3f086ac9d26e1da3226febf7a79992970236b4 Mon Sep 17 00:00:00 2001 From: ghidravore Date: Wed, 19 May 2021 11:20:12 -0400 Subject: [PATCH] GP-759 - providing control when using the ActionBuilder for actions to determine which windows they should appear on. Also, cleaned up various actions to take advantage of this. --- .../app/context/ListingContextAction.java | 13 -- .../app/context/NavigatableContextAction.java | 12 -- .../app/context/ProgramContextAction.java | 13 +- .../context/ProgramLocationContextAction.java | 12 -- .../java/ghidra/app/nav/NextRangeAction.java | 13 +- .../ghidra/app/nav/PreviousRangeAction.java | 13 +- .../FindPossibleReferencesPlugin.java | 9 +- .../app/plugin/core/clear/ClearPlugin.java | 184 ++++++------------ .../core/codebrowser/CodeBrowserPlugin.java | 40 +++- .../actions/ClearSelectionAction.java | 45 ----- .../actions/CodeViewerContextAction.java | 85 -------- .../actions/ExpandAllDataAction.java | 3 + .../actions/GotoNextFunctionAction.java | 1 + .../actions/GotoPreviousFunctionAction.java | 1 + .../codebrowser/actions/SelectAllAction.java | 53 ----- .../actions/SelectComplementAction.java | 62 ------ .../AutoTableDisassemblerPlugin.java | 3 +- .../plugin/core/help/AboutProgramPlugin.java | 1 + .../core/highlight/SetHighlightPlugin.java | 12 +- .../InstructionSearchPlugin.java | 1 + .../plugin/core/label/AllHistoryAction.java | 9 +- .../AbstractNextPreviousAction.java | 1 + .../navigation/GoToAddressLabelPlugin.java | 1 + .../navigation/NextPrevAddressPlugin.java | 39 +--- .../navigation/NextPrevCodeUnitPlugin.java | 1 + .../NextPreviousBookmarkAction.java | 12 +- .../navigation/NextPreviousMarkerAction.java | 12 +- .../core/progmgr/ProgramManagerPlugin.java | 14 +- .../app/plugin/core/progmgr/RedoAction.java | 3 + .../app/plugin/core/progmgr/UndoAction.java | 3 + .../core/scalartable/ScalarSearchPlugin.java | 1 + .../script/GhidraScriptActionManager.java | 26 +-- .../core/searchmem/MemSearchPlugin.java | 2 + .../searchmem/mask/MnemonicSearchPlugin.java | 6 + .../core/searchtext/SearchTextPlugin.java | 2 + .../plugin/core/select/SelectBlockPlugin.java | 16 +- .../core/select/flow/SelectByFlowPlugin.java | 23 ++- .../select/flow/SelectByScopedFlowPlugin.java | 4 +- .../qualified/QualifiedSelectionPlugin.java | 6 +- .../reference/SelectBackRefsAction.java | 15 +- .../reference/SelectForwardRefsAction.java | 1 + .../plugin/core/string/StringTablePlugin.java | 2 +- .../core/validator/ValidateProgramPlugin.java | 5 +- .../prototype/debug/ScreenshotPlugin.java | 28 +-- .../core/diff/DiffSaveSettingsTest.java | 4 +- .../java/docking/WindowActionManager.java | 1 + .../docking/action/ContextSpecificAction.java | 12 -- .../java/docking/action/DockingAction.java | 66 ++++++- .../java/docking/action/DockingActionIf.java | 7 +- .../action/builder/AbstractActionBuilder.java | 54 ++++- .../framework/plugintool/PluginTool.java | 111 +++-------- 51 files changed, 366 insertions(+), 697 deletions(-) delete mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/ClearSelectionAction.java delete mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/CodeViewerContextAction.java delete mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/SelectAllAction.java delete mode 100644 Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/SelectComplementAction.java diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/context/ListingContextAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/context/ListingContextAction.java index cb1ab0b817..872d9548a2 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/context/ListingContextAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/context/ListingContextAction.java @@ -15,8 +15,6 @@ */ package ghidra.app.context; -import java.util.Set; - import docking.ActionContext; import docking.action.DockingAction; import docking.action.KeyBindingType; @@ -75,15 +73,4 @@ public abstract class ListingContextAction extends DockingAction { protected void actionPerformed(ListingActionContext context) { // clients need to override this method } - - @Override - public boolean shouldAddToWindow(boolean isMainWindow, Set> contextTypes) { - for (Class class1 : contextTypes) { - if (ListingActionContext.class.isAssignableFrom(class1)) { - return true; - } - } - return false; - } - } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/context/NavigatableContextAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/context/NavigatableContextAction.java index 914130ea82..ba2e5d8815 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/context/NavigatableContextAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/context/NavigatableContextAction.java @@ -15,8 +15,6 @@ */ package ghidra.app.context; -import java.util.Set; - import docking.ActionContext; import docking.action.DockingAction; import docking.action.KeyBindingType; @@ -71,14 +69,4 @@ public abstract class NavigatableContextAction extends DockingAction { } protected abstract void actionPerformed(NavigatableActionContext context); - - @Override - public boolean shouldAddToWindow(boolean isMainWindow, Set> contextTypes) { - for (Class class1 : contextTypes) { - if (NavigatableActionContext.class.isAssignableFrom(class1)) { - return true; - } - } - return false; - } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/context/ProgramContextAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/context/ProgramContextAction.java index 39e6e6b410..605a1a621b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/context/ProgramContextAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/context/ProgramContextAction.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,8 +15,6 @@ */ package ghidra.app.context; -import java.util.Set; - import docking.ActionContext; import docking.action.DockingAction; @@ -51,15 +48,7 @@ public abstract class ProgramContextAction extends DockingAction { } return isValidContext((ProgramActionContext)context); } - @Override - public boolean shouldAddToWindow(boolean isMainWindow, Set> contextTypes) { - for (Class class1 : contextTypes) { - if (ProgramActionContext.class.isAssignableFrom(class1)) { - return true; - } - } - return false; - } + @Override public boolean isAddToPopup(ActionContext context) { if (!(context instanceof ProgramActionContext)) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/context/ProgramLocationContextAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/context/ProgramLocationContextAction.java index 44a1c8d09f..0533d517f1 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/context/ProgramLocationContextAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/context/ProgramLocationContextAction.java @@ -15,8 +15,6 @@ */ package ghidra.app.context; -import java.util.Set; - import docking.ActionContext; import docking.action.DockingAction; @@ -71,14 +69,4 @@ public abstract class ProgramLocationContextAction extends DockingAction { // a version of actionPerformed() that takes a more specific context than our parent protected abstract void actionPerformed(ProgramLocationActionContext context); - - @Override - public boolean shouldAddToWindow(boolean isMainWindow, Set> contextTypes) { - for (Class class1 : contextTypes) { - if (ProgramLocationActionContext.class.isAssignableFrom(class1)) { - return true; - } - } - return false; - } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/nav/NextRangeAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/nav/NextRangeAction.java index 4c26827ec9..986a05a3a7 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/nav/NextRangeAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/nav/NextRangeAction.java @@ -15,8 +15,6 @@ */ package ghidra.app.nav; -import java.util.Set; - import ghidra.app.context.*; import ghidra.app.plugin.core.navigation.NavigationOptions; import ghidra.app.services.GoToService; @@ -36,6 +34,7 @@ public abstract class NextRangeAction extends NavigatableContextAction { this.tool = tool; this.navOptions = navOptions; setEnabled(false); + addToWindowWhen(NavigatableActionContext.class); } @Override @@ -99,14 +98,4 @@ public abstract class NextRangeAction extends NavigatableContextAction { } abstract protected ProgramSelection getSelection(ProgramLocationActionContext context); - - @Override - public boolean shouldAddToWindow(boolean isMainWindow, Set> contextTypes) { - for (Class class1 : contextTypes) { - if (NavigatableRangeActionContext.class.isAssignableFrom(class1)) { - return true; - } - } - return false; - } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/nav/PreviousRangeAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/nav/PreviousRangeAction.java index c069d48499..e3e060515c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/nav/PreviousRangeAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/nav/PreviousRangeAction.java @@ -15,8 +15,6 @@ */ package ghidra.app.nav; -import java.util.Set; - import ghidra.app.context.*; import ghidra.app.plugin.core.navigation.NavigationOptions; import ghidra.app.services.GoToService; @@ -35,6 +33,7 @@ public abstract class PreviousRangeAction extends NavigatableContextAction { this.tool = tool; this.navOptions = navOptions; setEnabled(false); + addToWindowWhen(NavigatableActionContext.class); } @Override @@ -91,14 +90,4 @@ public abstract class PreviousRangeAction extends NavigatableContextAction { } abstract protected ProgramSelection getSelection(ProgramLocationActionContext context); - - @Override - public boolean shouldAddToWindow(boolean isMainWindow, Set> contextTypes) { - for (Class class1 : contextTypes) { - if (NavigatableRangeActionContext.class.isAssignableFrom(class1)) { - return true; - } - } - return false; - } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/FindPossibleReferencesPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/FindPossibleReferencesPlugin.java index ab30ba4989..a6ef6a3e9f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/FindPossibleReferencesPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/FindPossibleReferencesPlugin.java @@ -25,7 +25,7 @@ import docking.action.MenuData; import docking.action.builder.ActionBuilder; import docking.tool.ToolConstants; import ghidra.app.CorePluginPackage; -import ghidra.app.context.*; +import ghidra.app.context.NavigatableActionContext; import ghidra.app.events.ProgramClosedPluginEvent; import ghidra.app.events.ProgramSelectionPluginEvent; import ghidra.app.plugin.PluginCategoryNames; @@ -103,14 +103,15 @@ public class FindPossibleReferencesPlugin extends Plugin { .supportsDefaultToolContext(true) .helpLocation(new HelpLocation(HelpTopics.SEARCH, SEARCH_DIRECT_REFS_ACTION_NAME)) .description(getPluginDescription().getDescription()) - .withContext(ListingActionContext.class) + .withContext(NavigatableActionContext.class) + .inWindow(ActionBuilder.When.CONTEXT_MATCHES) .onAction(this::findReferences) .enabledWhen(this::hasCorrectAddressSize) .buildAndInstall(tool); } - private boolean hasCorrectAddressSize(ListingActionContext context) { + private boolean hasCorrectAddressSize(NavigatableActionContext context) { int size = context.getProgram().getAddressFactory().getDefaultAddressSpace().getSize(); if ((size == 64) || (size == 32) || (size == 24) || (size == 16) || (size == 20) || @@ -120,7 +121,7 @@ public class FindPossibleReferencesPlugin extends Plugin { return false; } - private void createLocalActions(ProgramLocationActionContext context, ComponentProvider p, + private void createLocalActions(NavigatableActionContext context, ComponentProvider p, FindReferencesTableModel model) { addLocalAlignment(p, model, 1); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clear/ClearPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clear/ClearPlugin.java index c9e3371ee0..193e6bcf2a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clear/ClearPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/clear/ClearPlugin.java @@ -15,14 +15,10 @@ */ package ghidra.app.plugin.core.clear; -import java.awt.event.KeyEvent; - -import docking.ActionContext; -import docking.action.*; +import docking.action.builder.ActionBuilder; import docking.tool.ToolConstants; import ghidra.app.CorePluginPackage; import ghidra.app.context.ListingActionContext; -import ghidra.app.context.ListingContextAction; import ghidra.app.plugin.PluginCategoryNames; import ghidra.framework.cmd.Command; import ghidra.framework.plugintool.*; @@ -46,12 +42,10 @@ import ghidra.program.util.*; ) //@formatter:on public class ClearPlugin extends Plugin { + private static final String CLEAR_WITH_OPTIONS_NAME = "Clear With Options"; private static final String CLEAR_CODE_BYTES_NAME = "Clear Code Bytes"; private static final String CLEAR_FLOW_AND_REPAIR = "Clear Flow and Repair"; - private DockingAction clearAllAction; - private DockingAction clearAction; - private DockingAction clearAndRepairAction; private ClearDialog clearDialog; private ClearFlowDialog clearFlowDialog; @@ -215,123 +209,71 @@ public class ClearPlugin extends Plugin { * Create the actions. */ private void createActions() { + new ActionBuilder(CLEAR_CODE_BYTES_NAME, getName()) + .menuPath(ToolConstants.MENU_EDIT, CLEAR_CODE_BYTES_NAME) + .menuGroup(CLEAR_CODE_BYTES_NAME, "1") + .popupMenuPath(CLEAR_CODE_BYTES_NAME) + .popupMenuGroup(CLEAR_CODE_BYTES_NAME, "1") + .keyBinding("C") + .withContext(ListingActionContext.class) + .inWindow(ActionBuilder.When.CONTEXT_MATCHES) + .enabledWhen(this::isClearCodeBytesEnabled) + .onAction(this::clearCodeBytes) + .buildAndInstall(tool); - // new context aware version - clearAction = new ListingContextAction(CLEAR_CODE_BYTES_NAME, getName()) { + new ActionBuilder(CLEAR_WITH_OPTIONS_NAME, getName()) + .menuPath(ToolConstants.MENU_EDIT, CLEAR_WITH_OPTIONS_NAME + "...") + .menuGroup(CLEAR_CODE_BYTES_NAME, "2") + .popupMenuPath(CLEAR_WITH_OPTIONS_NAME) + .popupMenuGroup(CLEAR_CODE_BYTES_NAME, "2") + .withContext(ListingActionContext.class) + .inWindow(ActionBuilder.When.CONTEXT_MATCHES) + .onAction(this::showClearAllDialog) + .buildAndInstall(tool); - @Override - public void actionPerformed(ListingActionContext context) { - ClearOptions opts = new ClearOptions(); - - opts.setClearCode(true); - opts.setClearSymbols(false); - opts.setClearComments(false); - opts.setClearProperties(false); - opts.setClearFunctions(false); - opts.setClearRegisters(false); - opts.setClearEquates(false); - opts.setClearUserReferences(true); - opts.setClearAnalysisReferences(true); - opts.setClearImportReferences(true); - opts.setClearDefaultReferences(false); - opts.setClearBookmarks(false); - - if (clearWithContext(context, opts)) { - return; - } - } - - private boolean clearWithContext(ListingActionContext context, ClearOptions opts) { - clear(opts, context); - return true; - } - - @Override - public boolean isAddToPopup(ListingActionContext context) { - return true; - } - - @Override - public boolean isEnabledForContext(ListingActionContext context) { - ProgramLocation loc = context.getLocation(); - ProgramSelection currentSelection = context.getSelection(); - if (currentSelection != null && !currentSelection.isEmpty()) { - return true; - } - else if ((loc != null) && (loc.getAddress() != null) && - (loc instanceof CodeUnitLocation)) { - return true; - } - return false; - } - }; - - int menuOrdinal = 1; - MenuData menuData = - new MenuData(new String[] { ToolConstants.MENU_EDIT, CLEAR_CODE_BYTES_NAME }, null, - "Clear Code Bytes"); - - menuData.setMenuSubGroup(Integer.toString(menuOrdinal)); - clearAction.setMenuBarData(menuData); - MenuData popupMenuData = - new MenuData(new String[] { CLEAR_CODE_BYTES_NAME }, null, "Clear Code Bytes"); - popupMenuData.setMenuSubGroup(Integer.toString(menuOrdinal)); - clearAction.setPopupMenuData(popupMenuData); - clearAction.setKeyBindingData(new KeyBindingData(KeyEvent.VK_C, 0)); - - String clearWithOptionsName = "Clear With Options"; - clearAllAction = new DockingAction(clearWithOptionsName, getName()) { - @Override - public void actionPerformed(ActionContext context) { - showClearAllDialog((ListingActionContext) context.getContextObject()); - } - - @Override - public boolean isEnabledForContext(ActionContext context) { - return context.getContextObject() instanceof ListingActionContext; - } - }; - - menuOrdinal++; - menuData = - new MenuData(new String[] { ToolConstants.MENU_EDIT, clearWithOptionsName + "..." }, - null, "Clear Code Bytes"); - menuData.setMenuSubGroup(Integer.toString(menuOrdinal)); - clearAllAction.setMenuBarData(menuData); - popupMenuData = - new MenuData(new String[] { clearWithOptionsName + "..." }, null, "Clear Code Bytes"); - popupMenuData.setMenuSubGroup(Integer.toString(menuOrdinal)); - clearAllAction.setPopupMenuData(popupMenuData); - - clearAndRepairAction = new DockingAction(CLEAR_FLOW_AND_REPAIR, getName()) { - @Override - public void actionPerformed(ActionContext context) { - showClearFlowDialog((ListingActionContext) context.getContextObject()); - } - - @Override - public boolean isEnabledForContext(ActionContext context) { - return context.getContextObject() instanceof ListingActionContext; - } - }; - - menuOrdinal++; - menuData = new MenuData(new String[] { ToolConstants.MENU_EDIT, CLEAR_FLOW_AND_REPAIR }, - null, "Clear Code Bytes"); - menuData.setMenuSubGroup(Integer.toString(menuOrdinal)); - clearAndRepairAction.setMenuBarData(menuData); - popupMenuData = - new MenuData(new String[] { CLEAR_FLOW_AND_REPAIR + "..." }, null, "Clear Code Bytes"); - popupMenuData.setMenuSubGroup(Integer.toString(menuOrdinal)); - clearAndRepairAction.setPopupMenuData(popupMenuData); - - //clearAndRepairAction.setAcceleratorKey(KeyStroke.getKeyStroke(KeyEvent.VK_C, 0)); - - tool.addAction(clearAction); - tool.addAction(clearAllAction); - tool.addAction(clearAndRepairAction); + new ActionBuilder(CLEAR_FLOW_AND_REPAIR, getName()) + .menuPath(ToolConstants.MENU_EDIT, CLEAR_FLOW_AND_REPAIR + "...") + .menuGroup(CLEAR_CODE_BYTES_NAME, "3") + .popupMenuPath(CLEAR_FLOW_AND_REPAIR) + .popupMenuGroup(CLEAR_CODE_BYTES_NAME, "3") + .withContext(ListingActionContext.class) + .inWindow(ActionBuilder.When.CONTEXT_MATCHES) + .onAction(this::showClearFlowDialog) + .buildAndInstall(tool); } + private boolean isClearCodeBytesEnabled(ListingActionContext context) { + ProgramLocation loc = context.getLocation(); + ProgramSelection currentSelection = context.getSelection(); + if (currentSelection != null && !currentSelection.isEmpty()) { + return true; + } + else if ((loc != null) && (loc.getAddress() != null) && (loc instanceof CodeUnitLocation)) { + return true; + } + return false; + + } + + private void clearCodeBytes(ListingActionContext context) { + ClearOptions opts = new ClearOptions(); + + opts.setClearCode(true); + opts.setClearSymbols(false); + opts.setClearComments(false); + opts.setClearProperties(false); + opts.setClearFunctions(false); + opts.setClearRegisters(false); + opts.setClearEquates(false); + opts.setClearUserReferences(true); + opts.setClearAnalysisReferences(true); + opts.setClearImportReferences(true); + opts.setClearDefaultReferences(false); + opts.setClearBookmarks(false); + + clear(opts, context); + + } /** * Pop up the clear with options dialog. */ diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeBrowserPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeBrowserPlugin.java index 0d49124425..ba4851d23a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeBrowserPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeBrowserPlugin.java @@ -43,7 +43,6 @@ import ghidra.app.context.ListingActionContext; import ghidra.app.events.*; import ghidra.app.nav.Navigatable; import ghidra.app.plugin.PluginCategoryNames; -import ghidra.app.plugin.core.codebrowser.actions.*; import ghidra.app.plugin.core.codebrowser.hover.ListingHoverService; import ghidra.app.plugin.core.table.TableComponentProvider; import ghidra.app.services.*; @@ -169,17 +168,38 @@ public class CodeBrowserPlugin extends Plugin } private void createActions() { - DockingAction selectAllAction = new SelectAllAction(getName()); - selectAllAction.getMenuBarData().setMenuSubGroup("a"); - tool.addAction(selectAllAction); + new ActionBuilder("Select All", getName()) + .menuPath(ToolConstants.MENU_SELECTION, "&All in View") + .menuGroup("Select Group", "a") + .keyBinding("ctrl A") + .supportsDefaultToolContext(true) + .helpLocation(new HelpLocation(HelpTopics.SELECTION, getName())) + .withContext(CodeViewerActionContext.class) + .inWindow(ActionBuilder.When.CONTEXT_MATCHES) + .onAction(c -> ((CodeViewerProvider) c.getComponentProvider()).selectAll()) + .buildAndInstall(tool); - DockingAction selectNoneAction = new ClearSelectionAction(getName()); - selectNoneAction.getMenuBarData().setMenuSubGroup("a"); - tool.addAction(selectNoneAction); + new ActionBuilder("Clear Selection", getName()) + .menuPath(ToolConstants.MENU_SELECTION, "&Clear Selection") + .menuGroup("Select Group", "b") + .supportsDefaultToolContext(true) + .helpLocation(new HelpLocation(HelpTopics.SELECTION, getName())) + .withContext(CodeViewerActionContext.class) + .inWindow(ActionBuilder.When.CONTEXT_MATCHES) + .onAction(c -> ((CodeViewerProvider) c.getComponentProvider()) + .setSelection(new ProgramSelection())) + .buildAndInstall(tool); + + new ActionBuilder("Select Complement", getName()) + .menuPath(ToolConstants.MENU_SELECTION, "&Complement") + .menuGroup("Select Group", "c") + .supportsDefaultToolContext(true) + .helpLocation(new HelpLocation(HelpTopics.SELECTION, getName())) + .withContext(CodeViewerActionContext.class) + .inWindow(ActionBuilder.When.CONTEXT_MATCHES) + .onAction(c -> ((CodeViewerProvider) c.getComponentProvider()).selectComplement()) + .buildAndInstall(tool); - DockingAction selectComplementAction = new SelectComplementAction(getName()); - selectComplementAction.getMenuBarData().setMenuSubGroup("b"); - tool.addAction(selectComplementAction); } protected void viewChanged(AddressSetView addrSet) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/ClearSelectionAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/ClearSelectionAction.java deleted file mode 100644 index 342e154ae1..0000000000 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/ClearSelectionAction.java +++ /dev/null @@ -1,45 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ghidra.app.plugin.core.codebrowser.actions; - -import docking.ActionContext; -import docking.action.MenuData; -import docking.tool.ToolConstants; -import ghidra.app.plugin.core.codebrowser.CodeViewerProvider; -import ghidra.app.util.HelpTopics; -import ghidra.program.util.ProgramSelection; -import ghidra.util.HelpLocation; - -/** - * Action for clearing the current selection - */ -public class ClearSelectionAction extends CodeViewerContextAction { - - public ClearSelectionAction(String owner) { - super("Clear Selection", owner); - setSupportsDefaultToolContext(true); - setMenuBarData(new MenuData( - new String[] { ToolConstants.MENU_SELECTION, "&Clear Selection" }, null, "Select")); - - setHelpLocation(new HelpLocation(HelpTopics.SELECTION, getName())); - } - - @Override - public void actionPerformed(ActionContext context) { - CodeViewerProvider provider = (CodeViewerProvider) context.getComponentProvider(); - provider.setSelection(new ProgramSelection()); - } -} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/CodeViewerContextAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/CodeViewerContextAction.java deleted file mode 100644 index 0ecf8218d8..0000000000 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/CodeViewerContextAction.java +++ /dev/null @@ -1,85 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ghidra.app.plugin.core.codebrowser.actions; - -import java.util.Set; - -import docking.ActionContext; -import docking.action.DockingAction; -import ghidra.app.plugin.core.codebrowser.CodeViewerActionContext; - -public abstract class CodeViewerContextAction extends DockingAction { - - public CodeViewerContextAction(String name, String owner) { - super(name, owner); - } - - @Override - public boolean isEnabledForContext(ActionContext context) { - if (!(context instanceof CodeViewerActionContext)) { - return false; - } - return isEnabledForContext((CodeViewerActionContext) context); - } - - @Override - public boolean isValidContext(ActionContext context) { - if (!(context instanceof CodeViewerActionContext)) { - return false; - } - return isValidContext((CodeViewerActionContext) context); - } - - @Override - public boolean isAddToPopup(ActionContext context) { - if (!(context instanceof CodeViewerActionContext)) { - return false; - } - return isAddToPopup((CodeViewerActionContext) context); - } - - @Override - public void actionPerformed(ActionContext context) { - actionPerformed((CodeViewerActionContext) context); - } - - protected boolean isAddToPopup(CodeViewerActionContext context) { - return isEnabledForContext(context); - } - - protected boolean isValidContext(CodeViewerActionContext context) { - return true; - } - - protected boolean isEnabledForContext(CodeViewerActionContext context) { - return true; - } - - protected void actionPerformed(CodeViewerActionContext context) { - - } - - @Override - public boolean shouldAddToWindow(boolean isMainWindow, Set> contextTypes) { - for (Class class1 : contextTypes) { - if (CodeViewerActionContext.class.isAssignableFrom(class1)) { - return true; - } - } - return false; - } - -} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/ExpandAllDataAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/ExpandAllDataAction.java index 47e02c433e..284292031d 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/ExpandAllDataAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/ExpandAllDataAction.java @@ -45,6 +45,9 @@ public class ExpandAllDataAction extends ProgramLocationContextAction { setHelpLocation(new HelpLocation("CodeBrowserPlugin", "ExpandCollapseActions")); setEnabled(true); + + // make sure the action is in all windows that can provide the needed context + addToWindowWhen(ProgramLocationActionContext.class); } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/GotoNextFunctionAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/GotoNextFunctionAction.java index 6ff1bb3b44..246b1d0bf4 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/GotoNextFunctionAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/GotoNextFunctionAction.java @@ -50,6 +50,7 @@ public class GotoNextFunctionAction extends NavigatableContextAction { KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.CTRL_DOWN_MASK); setKeyBindingData(new KeyBindingData(keyStroke)); setHelpLocation(new HelpLocation(HelpTopics.NAVIGATION, "Next_Previous_Function")); + addToWindowWhen(NavigatableActionContext.class); } private Function getNextFunction(Program program, Address address) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/GotoPreviousFunctionAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/GotoPreviousFunctionAction.java index 14506e62f0..4f9780ae4c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/GotoPreviousFunctionAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/GotoPreviousFunctionAction.java @@ -50,6 +50,7 @@ public class GotoPreviousFunctionAction extends NavigatableContextAction { KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.CTRL_DOWN_MASK); setKeyBindingData(new KeyBindingData(keyStroke)); setHelpLocation(new HelpLocation(HelpTopics.NAVIGATION, "Next_Previous_Function")); + addToWindowWhen(NavigatableActionContext.class); } private Function getPreviousFunction(Program program, Address address) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/SelectAllAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/SelectAllAction.java deleted file mode 100644 index e0a40e20a1..0000000000 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/SelectAllAction.java +++ /dev/null @@ -1,53 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ghidra.app.plugin.core.codebrowser.actions; - -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; - -import docking.ActionContext; -import docking.action.KeyBindingData; -import docking.action.MenuData; -import docking.tool.ToolConstants; -import ghidra.app.plugin.core.codebrowser.CodeViewerProvider; -import ghidra.app.util.HelpTopics; -import ghidra.util.HelpLocation; - -/** - * Action for adding all fields to the current format. - */ -public class SelectAllAction extends CodeViewerContextAction { - - public SelectAllAction(String owner) { - super("Select All", owner); - // this is in the main tool menu, so make it a tool action - setSupportsDefaultToolContext(true); - setMenuBarData( - new MenuData( - new String[] { ToolConstants.MENU_SELECTION, "&All in View" }, null, "Select")); - - setKeyBindingData(new KeyBindingData( - KeyEvent.VK_A, InputEvent.CTRL_DOWN_MASK)); - - setHelpLocation(new HelpLocation(HelpTopics.SELECTION, getName())); - } - - @Override - public void actionPerformed(ActionContext context) { - CodeViewerProvider provider = (CodeViewerProvider) context.getComponentProvider(); - provider.selectAll(); - } -} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/SelectComplementAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/SelectComplementAction.java deleted file mode 100644 index 284594f96f..0000000000 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/actions/SelectComplementAction.java +++ /dev/null @@ -1,62 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ghidra.app.plugin.core.codebrowser.actions; - -import docking.ActionContext; -import docking.action.MenuData; -import docking.tool.ToolConstants; -import ghidra.app.plugin.core.codebrowser.CodeViewerActionContext; -import ghidra.app.plugin.core.codebrowser.CodeViewerProvider; -import ghidra.app.util.HelpTopics; -import ghidra.program.util.ProgramSelection; -import ghidra.util.HelpLocation; - -/** - * Action for changing the selection to the complement of all the currently - * selected addresses and restricting this new selection to the current view. - */ -public class SelectComplementAction extends CodeViewerContextAction { - - public SelectComplementAction(String owner) { - super("Select Complement", owner); - - // this is in the main tool menu, so make it a tool action - setSupportsDefaultToolContext(true); - - setMenuBarData(new MenuData( - new String[] { ToolConstants.MENU_SELECTION, "&Complement" }, - null, - "Select")); - - setEnabled(false); - setHelpLocation(new HelpLocation(HelpTopics.SELECTION, getName())); - } - - @Override - public void actionPerformed(ActionContext context) { - CodeViewerProvider provider = (CodeViewerProvider) context.getComponentProvider(); - provider.selectComplement(); - } - - @Override - public boolean isEnabledForContext(CodeViewerActionContext context) { - ProgramSelection selection = context.getSelection(); - if (selection != null && selection.getInteriorSelection() != null) { - return false; - } - return true; - } -} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/disassembler/AutoTableDisassemblerPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/disassembler/AutoTableDisassemblerPlugin.java index 6377560a94..f20a72c577 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/disassembler/AutoTableDisassemblerPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/disassembler/AutoTableDisassemblerPlugin.java @@ -23,6 +23,7 @@ import docking.widgets.table.GTable; import docking.widgets.table.threaded.ThreadedTableModelListener; import ghidra.app.CorePluginPackage; import ghidra.app.cmd.disassemble.DisassembleCommand; +import ghidra.app.context.NavigatableActionContext; import ghidra.app.plugin.PluginCategoryNames; import ghidra.app.plugin.ProgramPlugin; import ghidra.app.services.GoToService; @@ -151,7 +152,7 @@ public class AutoTableDisassemblerPlugin extends ProgramPlugin implements Domain findTableAction.setMenuBarData(new MenuData( new String[] { ToolConstants.MENU_SEARCH, "For Address Tables" }, null, "search for")); findTableAction.setDescription(getPluginDescription().getDescription()); - + findTableAction.addToWindowWhen(NavigatableActionContext.class); tool.addAction(findTableAction); } // end of createActions() diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/help/AboutProgramPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/help/AboutProgramPlugin.java index 3819a3d611..9201079e8b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/help/AboutProgramPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/help/AboutProgramPlugin.java @@ -115,6 +115,7 @@ public class AboutProgramPlugin extends Plugin implements FrontEndable { return false; } }; + aboutAction.addToWindowWhen(ProgramActionContext.class); aboutAction.setSupportsDefaultToolContext(true); aboutAction.setMenuBarData( diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/highlight/SetHighlightPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/highlight/SetHighlightPlugin.java index 752f828b43..bbf67b279e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/highlight/SetHighlightPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/highlight/SetHighlightPlugin.java @@ -101,6 +101,8 @@ public class SetHighlightPlugin extends Plugin { HIGHLIGHT_GROUP)); setHighlightFromSelectionAction.setKeyBindingData(new KeyBindingData(KeyEvent.VK_H, InputEvent.CTRL_DOWN_MASK)); + setHighlightFromSelectionAction + .addToWindowWhen(NavigatableActionContext.class); tool.addAction(setHighlightFromSelectionAction); clearHighlightAction = new NavigatableContextAction("Remove Highlight", getName()) { @@ -121,6 +123,7 @@ public class SetHighlightPlugin extends Plugin { clearHighlightAction.setMenuBarData(menuData); clearHighlightAction.setPopupMenuData(new MenuData(CLEAR_HIGHLIGHT_POPUPPATH, HIGHLIGHT_GROUP)); + clearHighlightAction.addToWindowWhen(NavigatableActionContext.class); tool.addAction(clearHighlightAction); addSelectionAction = new NavigatableContextAction("Add Selection To Highlight", getName()) { @@ -142,7 +145,7 @@ public class SetHighlightPlugin extends Plugin { menuData.setMenuSubGroup(Integer.toString(programHighlightSubMenuPosition++)); addSelectionAction.setMenuBarData(menuData); addSelectionAction.setPopupMenuData(new MenuData(ADD_SELECTION_POPUPPATH, HIGHLIGHT_GROUP)); - + addSelectionAction.addToWindowWhen(NavigatableActionContext.class); tool.addAction(addSelectionAction); subtractSelectionAction = @@ -163,6 +166,7 @@ public class SetHighlightPlugin extends Plugin { new MenuData(new String[] { ToolConstants.MENU_SELECTION, MENU_HIGHLIGHT, "Subtract Selection" }, HIGHLIGHT_GROUP); menuData.setMenuSubGroup(Integer.toString(programHighlightSubMenuPosition++)); + subtractSelectionAction.addToWindowWhen(NavigatableActionContext.class); subtractSelectionAction.setMenuBarData(menuData); subtractSelectionAction.setPopupMenuData(new MenuData(SUBTRACT_SELECTION_POPUPPATH, HIGHLIGHT_GROUP)); @@ -185,11 +189,11 @@ public class SetHighlightPlugin extends Plugin { ToolConstants.MENU_SELECTION, "From Highlight" }, HIGHLIGHT_GROUP)); setSelectionFromHighlightAction.setPopupMenuData(new MenuData(SET_SELECTION_POPUPPATH, HIGHLIGHT_GROUP)); - + setSelectionFromHighlightAction + .addToWindowWhen(NavigatableActionContext.class); tool.addAction(setSelectionFromHighlightAction); - tool.setMenuGroup(new String[] { MENU_HIGHLIGHT }, HIGHLIGHT_GROUP); - tool.setMenuGroup(new String[] { MENU_SELECTION }, HIGHLIGHT_GROUP); + tool.setMenuGroup(new String[] { MENU_SELECTION, MENU_HIGHLIGHT }, HIGHLIGHT_GROUP); } protected void setHighlight(Navigatable navigatable, ProgramSelection highlight) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/InstructionSearchPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/InstructionSearchPlugin.java index c6497ce602..5e94d95c7f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/InstructionSearchPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/InstructionSearchPlugin.java @@ -250,6 +250,7 @@ public class InstructionSearchPlugin extends ProgramPlugin { } }; + searchAction.addToWindowWhen(NavigatableActionContext.class); searchAction.setHelpLocation(new HelpLocation("Search", "Instruction_Pattern_Search")); searchAction.setMenuBarData( new MenuData(new String[] { ToolConstants.MENU_SEARCH, "For Instruction Patterns" }, diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/label/AllHistoryAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/label/AllHistoryAction.java index cc5f5060a2..a26689b662 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/label/AllHistoryAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/label/AllHistoryAction.java @@ -15,15 +15,14 @@ */ package ghidra.app.plugin.core.label; -import ghidra.app.context.ListingActionContext; -import ghidra.app.context.ListingContextAction; -import ghidra.framework.plugintool.PluginTool; - import java.awt.event.KeyEvent; import docking.action.KeyBindingData; import docking.action.MenuData; import docking.tool.ToolConstants; +import ghidra.app.context.ListingActionContext; +import ghidra.app.context.ListingContextAction; +import ghidra.framework.plugintool.PluginTool; public class AllHistoryAction extends ListingContextAction { @@ -36,7 +35,7 @@ public class AllHistoryAction extends ListingContextAction { null, "Search")); setKeyBindingData(new KeyBindingData(KeyEvent.VK_H, 0)); - + addToWindowWhen(ListingActionContext.class); } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/AbstractNextPreviousAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/AbstractNextPreviousAction.java index 64edce3281..a49bc214fd 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/AbstractNextPreviousAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/AbstractNextPreviousAction.java @@ -50,6 +50,7 @@ public abstract class AbstractNextPreviousAction extends NavigatableContextActio setKeyBindingData(new KeyBindingData(getKeyStroke())); setHelpLocation(new HelpLocation(HelpTopics.NAVIGATION, name)); setDescription(getDescriptionString()); + addToWindowWhen(NavigatableActionContext.class); } protected abstract Icon getIcon(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/GoToAddressLabelPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/GoToAddressLabelPlugin.java index b77dafd9f5..ab6e0839f3 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/GoToAddressLabelPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/GoToAddressLabelPlugin.java @@ -103,6 +103,7 @@ public class GoToAddressLabelPlugin extends Plugin implements OptionsChangeListe return true; } }; + action.addToWindowWhen(NavigatableActionContext.class); action.setHelpLocation(new HelpLocation(HelpTopics.NAVIGATION, action.getName())); action.setMenuBarData( new MenuData(new String[] { ToolConstants.MENU_NAVIGATION, "Go To..." }, null, "GoTo", diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPrevAddressPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPrevAddressPlugin.java index 6fef5ce938..9830bc6ba9 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPrevAddressPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPrevAddressPlugin.java @@ -17,7 +17,8 @@ package ghidra.app.plugin.core.navigation; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; -import java.util.*; +import java.util.ArrayList; +import java.util.List; import javax.swing.Icon; import javax.swing.ImageIcon; @@ -27,7 +28,8 @@ import docking.action.*; import docking.menu.MultiActionDockingAction; import docking.tool.ToolConstants; import ghidra.app.CorePluginPackage; -import ghidra.app.context.*; +import ghidra.app.context.NavigatableActionContext; +import ghidra.app.context.ProgramActionContext; import ghidra.app.nav.LocationMemento; import ghidra.app.nav.Navigatable; import ghidra.app.plugin.PluginCategoryNames; @@ -182,16 +184,6 @@ public class NextPrevAddressPlugin extends Plugin { historyService.clear(getNavigatable(context)); } - @Override - public boolean shouldAddToWindow(boolean isMainWindow, Set> contextTypes) { - for (Class class1 : contextTypes) { - if (NavigationActionContext.class.isAssignableFrom(class1)) { - return true; - } - } - return false; - } - @Override public boolean isEnabledForContext(ActionContext context) { if (!(context instanceof ProgramActionContext)) { @@ -204,6 +196,7 @@ public class NextPrevAddressPlugin extends Plugin { return hasNext || hasPrevious; } }; + clearAction.addToWindowWhen(NavigatableActionContext.class); clearAction.setHelpLocation(new HelpLocation(HelpTopics.NAVIGATION, clearAction.getName())); MenuData menuData = new MenuData(CLEAR_MENUPATH, HISTORY_MENU_GROUP); menuData.setMenuSubGroup("1"); // first in menu! @@ -314,6 +307,7 @@ public class NextPrevAddressPlugin extends Plugin { int keycode = isNext ? KeyEvent.VK_RIGHT : KeyEvent.VK_LEFT; setKeyBindingData(new KeyBindingData(keycode, InputEvent.ALT_DOWN_MASK)); setDescription(isNext ? "Go to next location" : "Go to previous location"); + addToWindowWhen(NavigatableActionContext.class); } @Override @@ -339,16 +333,6 @@ public class NextPrevAddressPlugin extends Plugin { } } - @Override - public boolean shouldAddToWindow(boolean isMainWindow, Set> contextTypes) { - for (Class class1 : contextTypes) { - if (NavigationActionContext.class.isAssignableFrom(class1)) { - return true; - } - } - return false; - } - @Override public List getActionList(ActionContext context) { Navigatable navigatable = getNavigatable(context); @@ -414,6 +398,7 @@ public class NextPrevAddressPlugin extends Plugin { new MenuData(new String[] { "Navigation", menuItemName }, HISTORY_MENU_GROUP); menuData.setMenuSubGroup("2"); // after clear setMenuBarData(menuData); + addToWindowWhen(NavigatableActionContext.class); } @Override @@ -438,16 +423,6 @@ public class NextPrevAddressPlugin extends Plugin { historyService.previousFunction(navigatable); } } - - @Override - public boolean shouldAddToWindow(boolean isMainWindow, Set> contextTypes) { - for (Class class1 : contextTypes) { - if (NavigationActionContext.class.isAssignableFrom(class1)) { - return true; - } - } - return false; - } } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPrevCodeUnitPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPrevCodeUnitPlugin.java index 3958ab885b..d9cdcd55e8 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPrevCodeUnitPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPrevCodeUnitPlugin.java @@ -135,6 +135,7 @@ public class NextPrevCodeUnitPlugin extends Plugin { setHelpLocation( new HelpLocation(HelpTopics.NAVIGATION, longName)); setDescription(longName); + addToWindowWhen(NavigatableActionContext.class); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousBookmarkAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousBookmarkAction.java index dcdf37bc9d..e3ead7cc26 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousBookmarkAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousBookmarkAction.java @@ -18,7 +18,6 @@ package ghidra.app.plugin.core.navigation; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.util.Iterator; -import java.util.Set; import javax.swing.*; @@ -64,6 +63,7 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction toolBarData.setToolBarSubGroup(subGroup); setToolBarData(toolBarData); + addToWindowWhen(CodeViewerActionContext.class); setKeyBindingData(new KeyBindingData(getKeyStroke())); setHelpLocation(new HelpLocation(HelpTopics.NAVIGATION, getName())); @@ -258,14 +258,4 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction public boolean isEnabledForContext(ActionContext context) { return context instanceof ListingActionContext; } - - @Override - public boolean shouldAddToWindow(boolean isMainWindow, Set> contextTypes) { - for (Class class1 : contextTypes) { - if (CodeViewerActionContext.class.isAssignableFrom(class1)) { - return true; - } - } - return false; - } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousMarkerAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousMarkerAction.java index 14c6738d22..e839e98ccb 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousMarkerAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/NextPreviousMarkerAction.java @@ -17,7 +17,6 @@ package ghidra.app.plugin.core.navigation; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; -import java.util.Set; import javax.swing.ImageIcon; import javax.swing.KeyStroke; @@ -83,9 +82,11 @@ public class NextPreviousMarkerAction extends MultiStateDockingAction { setMenuBarData(menuData); setKeyBindingData(new KeyBindingData(getKeyStroke())); + addToWindowWhen(CodeViewerActionContext.class); setHelpLocation(new HelpLocation(HelpTopics.NAVIGATION, getName())); setDescription("Set marker options"); + addToWindowWhen(CodeViewerActionContext.class); ActionState allMarkers = new ActionState("All Types", markerIcon, "All Types"); @@ -310,13 +311,4 @@ public class NextPreviousMarkerAction extends MultiStateDockingAction { return isEnabledForContext(context); } - @Override - public boolean shouldAddToWindow(boolean isMainWindow, Set> contextTypes) { - for (Class class1 : contextTypes) { - if (CodeViewerActionContext.class.isAssignableFrom(class1)) { - return true; - } - } - return false; - } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramManagerPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramManagerPlugin.java index 7f2278f9b4..7aa443f3c6 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramManagerPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramManagerPlugin.java @@ -523,10 +523,12 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager { int subMenuGroupOrder = 1; openAction = new ActionBuilder("Open File", getName()) - .onAction(c -> open()) .menuPath(ToolConstants.MENU_FILE, "&Open...") .menuGroup(OPEN_GROUP, Integer.toString(subMenuGroupOrder++)) .keyBinding("ctrl O") + .withContext(ProgramActionContext.class) + .inWindow(ActionBuilder.When.CONTEXT_MATCHES) + .onAction(c -> open()) .buildAndInstall(tool); closeAction = new ActionBuilder("Close File", getName()) @@ -534,6 +536,7 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager { .menuGroup(OPEN_GROUP, Integer.toString(subMenuGroupOrder++)) .withContext(ProgramActionContext.class) .supportsDefaultToolContext(true) + .inWindow(ActionBuilder.When.CONTEXT_MATCHES) .onAction(c -> closeProgram(c.getProgram(), false)) .keyBinding("ctrl W") .buildAndInstall(tool); @@ -542,12 +545,16 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager { .menuPath(ToolConstants.MENU_FILE, "Close &Others") .menuGroup(OPEN_GROUP, Integer.toString(subMenuGroupOrder++)) .enabled(false) + .withContext(ProgramActionContext.class) + .inWindow(ActionBuilder.When.CONTEXT_MATCHES) .onAction(c -> closeOtherPrograms(false)) .buildAndInstall(tool); closeAllAction = new ActionBuilder("Close All", getName()) .menuPath(ToolConstants.MENU_FILE, "Close &All") .menuGroup(OPEN_GROUP, Integer.toString(subMenuGroupOrder++)) + .withContext(ProgramActionContext.class) + .inWindow(ActionBuilder.When.CONTEXT_MATCHES) .onAction(c -> closeAllPrograms(false)) .enabled(false) .buildAndInstall(tool); @@ -561,6 +568,7 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager { .toolBarGroup(ToolConstants.TOOLBAR_GROUP_ONE) .keyBinding("ctrl S") .withContext(ProgramActionContext.class) + .inWindow(ActionBuilder.When.CONTEXT_MATCHES) .supportsDefaultToolContext(true) .enabledWhen(c -> c.getProgram() != null && c.getProgram().isChanged()) .onAction(c -> programSaveMgr.saveProgram(c.getProgram())) @@ -570,6 +578,7 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager { .menuPath(ToolConstants.MENU_FILE, "Save &As...") .menuGroup(SAVE_GROUP, Integer.toString(subMenuGroupOrder++)) .withContext(ProgramActionContext.class) + .inWindow(ActionBuilder.When.CONTEXT_MATCHES) .supportsDefaultToolContext(true) .onAction(c -> programSaveMgr.saveAs(c.getProgram())) .buildAndInstall(tool); @@ -578,6 +587,8 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager { .menuPath(ToolConstants.MENU_FILE, "Save All") .description("Save All Programs") .menuGroup(SAVE_GROUP, Integer.toString(subMenuGroupOrder++)) + .withContext(ProgramActionContext.class) + .inWindow(ActionBuilder.When.CONTEXT_MATCHES) .onAction(c -> programSaveMgr.saveChangedPrograms()) .buildAndInstall(tool); @@ -587,6 +598,7 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager { .menuGroup(ToolConstants.TOOL_OPTIONS_MENU_GROUP, ToolConstants.TOOL_OPTIONS_MENU_GROUP + "b") .withContext(ProgramActionContext.class) + .inWindow(ActionBuilder.When.CONTEXT_MATCHES) .supportsDefaultToolContext(true) .onAction(c -> showProgramOptions(c.getProgram())) .buildAndInstall(tool); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/RedoAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/RedoAction.java index 7aff46df1a..707ae1448c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/RedoAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/RedoAction.java @@ -47,6 +47,9 @@ public class RedoAction extends ProgramContextAction { setKeyBindingData(new KeyBindingData("ctrl shift Z")); setDescription("Redo"); setSupportsDefaultToolContext(true); + + // we want this action to appear in all windows that can produce a program context + addToWindowWhen(ProgramActionContext.class); } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/UndoAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/UndoAction.java index b9431e1ba2..777fc870e2 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/UndoAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/UndoAction.java @@ -46,6 +46,9 @@ public class UndoAction extends ProgramContextAction { setDescription("Undo"); setKeyBindingData(new KeyBindingData("ctrl Z")); setSupportsDefaultToolContext(true); + + // we want this action to appear in all windows that can produce a program context + addToWindowWhen(ProgramActionContext.class); } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/scalartable/ScalarSearchPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/scalartable/ScalarSearchPlugin.java index 4c43ad5d8a..2c425eda58 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/scalartable/ScalarSearchPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/scalartable/ScalarSearchPlugin.java @@ -154,6 +154,7 @@ public class ScalarSearchPlugin extends ProgramPlugin implements DomainObjectLis searchAction.setMenuBarData(new MenuData( new String[] { ToolConstants.MENU_SEARCH, "For Scalars..." }, null, "search for")); searchAction.setDescription("Search program for scalars"); + searchAction.addToWindowWhen(NavigatableActionContext.class); tool.addAction(searchAction); // diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptActionManager.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptActionManager.java index e8b57cbfa4..c3b56b2dbb 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptActionManager.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptActionManager.java @@ -263,31 +263,11 @@ class GhidraScriptActionManager { .onAction(context -> showGhidraScriptJavadoc()) .buildAndInstallLocal(provider); - // XXX In order to override a method of the new DockingAction and use the builder, we - // need to override the build method of the ActionBuilder. When the ActionBuilder is - // updated, this code can be cleaned up. - new ActionBuilder("Ghidra API Help", plugin.getName()) { - @Override - public DockingAction build() { - validate(); - DockingAction action = new DockingAction(name, owner, keyBindingType) { - @Override - public void actionPerformed(ActionContext context) { - actionCallback.accept(context); - } - - @Override - public boolean shouldAddToWindow(boolean isMainWindow, - Set> contextTypes) { - return true; - } - }; - decorateAction(action); - return action; - } - }.menuGroup(ToolConstants.HELP_CONTENTS_MENU_GROUP) + new ActionBuilder("Ghidra API Help", plugin.getName()) + .menuGroup(ToolConstants.HELP_CONTENTS_MENU_GROUP) .menuPath(ToolConstants.MENU_HELP, "Ghidra API Help") .helpLocation(new HelpLocation("Misc", "Welcome_to_Ghidra_Help")) + .inWindow(ActionBuilder.When.ALWAYS) .onAction(context -> showGhidraScriptJavadoc()) .buildAndInstall(plugin.getTool()); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/searchmem/MemSearchPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/searchmem/MemSearchPlugin.java index 3096e204a8..a7d4f47ce7 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/searchmem/MemSearchPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/searchmem/MemSearchPlugin.java @@ -359,6 +359,7 @@ public class MemSearchPlugin extends Plugin implements OptionsChangeListener, searchAction.setMenuBarData(new MenuData(menuPath, "search")); searchAction.setKeyBindingData(new KeyBindingData('S', 0)); searchAction.setDescription("Search Memory for byte sequence"); + searchAction.addToWindowWhen(NavigatableActionContext.class); tool.addAction(searchAction); searchAgainAction = new NavigatableContextAction("Repeat Memory Search", getName()) { @@ -379,6 +380,7 @@ public class MemSearchPlugin extends Plugin implements OptionsChangeListener, searchAgainAction.setMenuBarData(new MenuData(menuPath, "search")); searchAgainAction.setKeyBindingData(new KeyBindingData(KeyEvent.VK_F3, 0)); searchAgainAction.setDescription("Search Memory for byte sequence"); + searchAgainAction.addToWindowWhen(NavigatableActionContext.class); tool.addAction(searchAgainAction); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/searchmem/mask/MnemonicSearchPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/searchmem/mask/MnemonicSearchPlugin.java index 2ea6968f31..485fcef049 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/searchmem/mask/MnemonicSearchPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/searchmem/mask/MnemonicSearchPlugin.java @@ -153,6 +153,8 @@ public class MnemonicSearchPlugin extends Plugin { MENU_PULLRIGHT, "Include Operands (except constants)" }, null, group, MenuData.NO_MNEMONIC, "3")); setSearchMnemonicOpsNoConstAction.setHelpLocation(helpLocation); + setSearchMnemonicOpsNoConstAction + .addToWindowWhen(NavigatableActionContext.class); // // ACTION 2: Search for instructions, including operands. @@ -174,6 +176,8 @@ public class MnemonicSearchPlugin extends Plugin { setSearchMnemonicOpsConstAction.setMenuBarData(new MenuData(new String[] { "&Search", MENU_PULLRIGHT, "Include Operands" }, null, group, MenuData.NO_MNEMONIC, "2")); setSearchMnemonicOpsConstAction.setHelpLocation(helpLocation); + setSearchMnemonicOpsConstAction + .addToWindowWhen(NavigatableActionContext.class); // // ACTION 3: Search for instructions, excluding constants. @@ -195,6 +199,8 @@ public class MnemonicSearchPlugin extends Plugin { setSearchMnemonicNoOpsNoConstAction.setMenuBarData(new MenuData(new String[] { "&Search", MENU_PULLRIGHT, "Exclude Operands" }, null, group, MenuData.NO_MNEMONIC, "1")); setSearchMnemonicNoOpsNoConstAction.setHelpLocation(helpLocation); + setSearchMnemonicNoOpsNoConstAction + .addToWindowWhen(NavigatableActionContext.class); // Add the actions to the tool... tool.addAction(setSearchMnemonicOpsNoConstAction); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/searchtext/SearchTextPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/searchtext/SearchTextPlugin.java index 6de8e44b8b..2ebe5f557a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/searchtext/SearchTextPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/searchtext/SearchTextPlugin.java @@ -383,6 +383,7 @@ public class SearchTextPlugin extends ProgramPlugin implements OptionsChangeList .description(DESCRIPTION) .helpLocation(new HelpLocation(HelpTopics.SEARCH, "Search Text")) .withContext(NavigatableActionContext.class) + .inWindow(ActionBuilder.When.CONTEXT_MATCHES) .supportsDefaultToolContext(true) .onAction(c -> { setNavigatable(c.getNavigatable()); @@ -398,6 +399,7 @@ public class SearchTextPlugin extends ProgramPlugin implements OptionsChangeList .supportsDefaultToolContext(true) .helpLocation(new HelpLocation(HelpTopics.SEARCH, "Repeat Text Search")) .withContext(NavigatableActionContext.class) + .inWindow(ActionBuilder.When.CONTEXT_MATCHES) .enabledWhen(c -> searchedOnce) .onAction(c -> { setNavigatable(c.getNavigatable()); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/select/SelectBlockPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/select/SelectBlockPlugin.java index 04c80bf542..d7aa4d2d7b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/select/SelectBlockPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/select/SelectBlockPlugin.java @@ -15,19 +15,19 @@ */ package ghidra.app.plugin.core.select; +import docking.ActionContext; +import docking.ComponentProvider; +import docking.action.DockingAction; +import docking.action.MenuData; +import docking.tool.ToolConstants; import ghidra.app.CorePluginPackage; import ghidra.app.context.NavigatableActionContext; import ghidra.app.context.NavigatableContextAction; import ghidra.app.nav.Navigatable; import ghidra.app.plugin.PluginCategoryNames; import ghidra.framework.plugintool.*; -import ghidra.framework.plugintool.util.*; +import ghidra.framework.plugintool.util.PluginStatus; import ghidra.util.HelpLocation; -import docking.ActionContext; -import docking.ComponentProvider; -import docking.action.DockingAction; -import docking.action.MenuData; -import docking.tool.ToolConstants; /** * This plugin class contains the structure needed for the user to @@ -72,9 +72,11 @@ public class SelectBlockPlugin extends Plugin { } }; MenuData menuData = - new MenuData(new String[] { ToolConstants.MENU_SELECTION, "Bytes..." }, null, "Select"); + new MenuData(new String[] { ToolConstants.MENU_SELECTION, "Bytes..." }, null, + "Select Group 2"); menuData.setMenuSubGroup("1"); toolBarAction.setMenuBarData(menuData); + toolBarAction.addToWindowWhen(NavigatableActionContext.class); toolBarAction.setEnabled(false); toolBarAction.setDescription("Allows user to select blocks of data."); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/select/flow/SelectByFlowPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/select/flow/SelectByFlowPlugin.java index 637779c8fa..2a846283bc 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/select/flow/SelectByFlowPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/select/flow/SelectByFlowPlugin.java @@ -15,10 +15,14 @@ */ package ghidra.app.plugin.core.select.flow; +import java.util.ArrayList; +import java.util.Iterator; + +import docking.action.DockingAction; +import docking.action.MenuData; import ghidra.GhidraOptions; import ghidra.app.CorePluginPackage; -import ghidra.app.context.NavigatableActionContext; -import ghidra.app.context.NavigatableContextAction; +import ghidra.app.context.*; import ghidra.app.events.ProgramSelectionPluginEvent; import ghidra.app.nav.NavigationUtils; import ghidra.app.plugin.PluginCategoryNames; @@ -38,12 +42,6 @@ import ghidra.util.exception.CancelledException; import ghidra.util.exception.InvalidInputException; import ghidra.util.task.*; -import java.util.ArrayList; -import java.util.Iterator; - -import docking.action.DockingAction; -import docking.action.MenuData; - /** * The SelectByFlowPlugin adds selection of code based on program flow to a * tool. Selection is based on the initial selection or if there is no selection @@ -484,9 +482,9 @@ public class SelectByFlowPlugin extends Plugin implements OptionsChangeListener selectProgramChangesAction.setHelpLocation(new HelpLocation(HelpTopics.SELECTION, selectProgramChangesAction.getName())); - selectProgramChangesAction.getMenuBarData().setMenuSubGroup( Integer.toString(subMenuGroupPosition++)); + selectProgramChangesAction.addToWindowWhen(NavigatableActionContext.class); tool.addAction(selectProgramChangesAction); /** @@ -496,6 +494,7 @@ public class SelectByFlowPlugin extends Plugin implements OptionsChangeListener new SelectByFlowAction("Select All Flows From", this, SELECT_ALL_FLOWS_FROM); selectAllFlowsFromAction.getMenuBarData().setMenuSubGroup( Integer.toString(subMenuGroupPosition++)); + selectAllFlowsFromAction.addToWindowWhen(ListingActionContext.class); tool.addAction(selectAllFlowsFromAction); /** @@ -505,6 +504,7 @@ public class SelectByFlowPlugin extends Plugin implements OptionsChangeListener new SelectByFlowAction("Select All Flows To", this, SELECT_ALL_FLOWS_TO); selectAllFlowsToAction.getMenuBarData().setMenuSubGroup( Integer.toString(subMenuGroupPosition++)); + selectAllFlowsToAction.addToWindowWhen(ListingActionContext.class); tool.addAction(selectAllFlowsToAction); /** @@ -514,6 +514,7 @@ public class SelectByFlowPlugin extends Plugin implements OptionsChangeListener new SelectByFlowAction("Select Limited Flows From", this, SELECT_LIMITED_FLOWS_FROM); selectLimitedFlowsFromAction.getMenuBarData().setMenuSubGroup( Integer.toString(subMenuGroupPosition++)); + selectLimitedFlowsFromAction.addToWindowWhen(ListingActionContext.class); tool.addAction(selectLimitedFlowsFromAction); /** @@ -523,6 +524,7 @@ public class SelectByFlowPlugin extends Plugin implements OptionsChangeListener new SelectByFlowAction("Select Limited Flows To", this, SELECT_LIMITED_FLOWS_TO); selectLimitedFlowsToAction.getMenuBarData().setMenuSubGroup( Integer.toString(subMenuGroupPosition++)); + selectLimitedFlowsToAction.addToWindowWhen(ListingActionContext.class); tool.addAction(selectLimitedFlowsToAction); /** @@ -532,6 +534,7 @@ public class SelectByFlowPlugin extends Plugin implements OptionsChangeListener new SelectByFlowAction("Select Subroutine", this, SELECT_SUBROUTINES); selectSubroutineAction.getMenuBarData().setMenuSubGroup( Integer.toString(subMenuGroupPosition++)); + selectSubroutineAction.addToWindowWhen(ListingActionContext.class); tool.addAction(selectSubroutineAction); /** @@ -541,6 +544,7 @@ public class SelectByFlowPlugin extends Plugin implements OptionsChangeListener new SelectByFlowAction("Select Dead Subroutine", this, SELECT_DEAD_SUBROUTINES); selectDeadSubroutineAction.getMenuBarData().setMenuSubGroup( Integer.toString(subMenuGroupPosition++)); + selectDeadSubroutineAction.addToWindowWhen(ListingActionContext.class); tool.addAction(selectDeadSubroutineAction); /** @@ -549,6 +553,7 @@ public class SelectByFlowPlugin extends Plugin implements OptionsChangeListener selectFunctionAction = new SelectByFlowAction("Select Function", this, SELECT_FUNCTIONS); selectFunctionAction.getMenuBarData().setMenuSubGroup( Integer.toString(subMenuGroupPosition++)); + selectFunctionAction.addToWindowWhen(ListingActionContext.class); tool.addAction(selectFunctionAction); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/select/flow/SelectByScopedFlowPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/select/flow/SelectByScopedFlowPlugin.java index b4974d246b..6fff8e4147 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/select/flow/SelectByScopedFlowPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/select/flow/SelectByScopedFlowPlugin.java @@ -98,7 +98,7 @@ public class SelectByScopedFlowPlugin extends ProgramPlugin { action.setMenuBarData(new MenuData( new String[] { ToolConstants.MENU_SELECTION, "Scoped Flow", "Forward Scoped Flow" }, null, "Select")); - + action.addToWindowWhen(NavigatableActionContext.class); action.setDescription("Allows user to select scoped flow from current location."); action.setHelpLocation(new HelpLocation("FlowSelection", "Scoped_Flow")); tool.addAction(action); @@ -131,7 +131,7 @@ public class SelectByScopedFlowPlugin extends ProgramPlugin { action.setMenuBarData(new MenuData( new String[] { ToolConstants.MENU_SELECTION, "Scoped Flow", "Reverse Scoped Flow" }, null, "Select")); - + action.addToWindowWhen(NavigatableActionContext.class); action.setDescription("Allows user to select scoped flow to the current location."); action.setHelpLocation(new HelpLocation("FlowSelection", "Scoped_Flow")); tool.addAction(action); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/select/qualified/QualifiedSelectionPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/select/qualified/QualifiedSelectionPlugin.java index c670f4316a..b128c572e7 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/select/qualified/QualifiedSelectionPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/select/qualified/QualifiedSelectionPlugin.java @@ -25,7 +25,7 @@ import ghidra.app.nav.NavigationUtils; import ghidra.app.plugin.PluginCategoryNames; import ghidra.app.util.HelpTopics; import ghidra.framework.plugintool.*; -import ghidra.framework.plugintool.util.*; +import ghidra.framework.plugintool.util.PluginStatus; import ghidra.program.model.address.*; import ghidra.program.model.listing.*; import ghidra.program.util.ProgramSelection; @@ -301,8 +301,8 @@ public class QualifiedSelectionPlugin extends Plugin { setHelpLocation(new HelpLocation(HelpTopics.SELECTION, name)); setEnabled(false); setMenuBarData(new MenuData(new String[] { ToolConstants.MENU_SELECTION, name }, null, - "Select")); - + "Select Group 2")); + addToWindowWhen(NavigatableActionContext.class); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/select/reference/SelectBackRefsAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/select/reference/SelectBackRefsAction.java index 2657356d6d..95157545b7 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/select/reference/SelectBackRefsAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/select/reference/SelectBackRefsAction.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,24 +15,23 @@ */ package ghidra.app.plugin.core.select.reference; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; + +import docking.action.KeyBindingData; +import docking.action.MenuData; import ghidra.app.context.NavigatableActionContext; import ghidra.app.context.NavigatableContextAction; import ghidra.app.nav.NavigationUtils; import ghidra.app.util.HelpTopics; import ghidra.framework.plugintool.PluginTool; import ghidra.program.model.address.*; -import ghidra.program.model.listing.*; +import ghidra.program.model.listing.Program; import ghidra.program.model.symbol.Reference; import ghidra.program.model.symbol.ReferenceIterator; import ghidra.program.util.ProgramSelection; import ghidra.util.HelpLocation; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; - -import docking.action.KeyBindingData; -import docking.action.MenuData; - public class SelectBackRefsAction extends NavigatableContextAction { private final PluginTool tool; @@ -47,6 +45,7 @@ public class SelectBackRefsAction extends NavigatableContextAction { setKeyBindingData( new KeyBindingData(KeyEvent.VK_SEMICOLON, InputEvent.CTRL_MASK ) ); setHelpLocation(new HelpLocation(HelpTopics.SELECTION, "Backward")); + addToWindowWhen(NavigatableActionContext.class); } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/select/reference/SelectForwardRefsAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/select/reference/SelectForwardRefsAction.java index 9b533ce472..7865f16771 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/select/reference/SelectForwardRefsAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/select/reference/SelectForwardRefsAction.java @@ -46,6 +46,7 @@ public class SelectForwardRefsAction extends NavigatableContextAction { setHelpLocation(new HelpLocation(HelpTopics.SELECTION, "Forward")); // setKeyBindingData( new KeyBindingData(KeyEvent.VK_SEMICOLON, InputEvent.CTRL_MASK ) ); // setHelpLocation(new HelpLocation(HelpTopics.SELECTION, "Backward")); + addToWindowWhen(NavigatableActionContext.class); } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/string/StringTablePlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/string/StringTablePlugin.java index 18949e4631..07841124cc 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/string/StringTablePlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/string/StringTablePlugin.java @@ -80,7 +80,7 @@ public class StringTablePlugin extends ProgramPlugin { new String[] { ToolConstants.MENU_SEARCH, "For &Strings..." }, null, "search for")); stringSearchAction.setDescription(getPluginDescription().getDescription()); - + stringSearchAction.addToWindowWhen(NavigatableActionContext.class); tool.addAction(stringSearchAction); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/validator/ValidateProgramPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/validator/ValidateProgramPlugin.java index 4307cfceb9..d00bea2534 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/validator/ValidateProgramPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/validator/ValidateProgramPlugin.java @@ -24,8 +24,7 @@ import docking.action.MenuData; import docking.tool.ToolConstants; import docking.widgets.conditiontestpanel.ConditionTester; import ghidra.app.CorePluginPackage; -import ghidra.app.context.ProgramActionContext; -import ghidra.app.context.ProgramContextAction; +import ghidra.app.context.*; import ghidra.app.plugin.PluginCategoryNames; import ghidra.app.plugin.core.analysis.validator.PostAnalysisValidator; import ghidra.framework.plugintool.*; @@ -95,7 +94,7 @@ public class ValidateProgramPlugin extends Plugin { return true; } }; - + validateAction.addToWindowWhen(ListingActionContext.class); validateAction.setMenuBarData(new MenuData(new String[] { ToolConstants.MENU_ANALYSIS, ACTION_NAME }, null, "ZZZ")); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/prototype/debug/ScreenshotPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/prototype/debug/ScreenshotPlugin.java index 4da0cee727..34603d1cf2 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/prototype/debug/ScreenshotPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/prototype/debug/ScreenshotPlugin.java @@ -15,19 +15,11 @@ */ package ghidra.app.plugin.prototype.debug; -import ghidra.app.DeveloperPluginPackage; -import ghidra.app.plugin.PluginCategoryNames; -import ghidra.app.plugin.ProgramPlugin; -import ghidra.framework.plugintool.PluginInfo; -import ghidra.framework.plugintool.PluginTool; -import ghidra.framework.plugintool.util.*; - import java.awt.*; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.image.RenderedImage; import java.io.File; -import java.util.Set; import javax.imageio.ImageIO; import javax.swing.*; @@ -36,6 +28,12 @@ import javax.swing.filechooser.FileNameExtensionFilter; import docking.*; import docking.action.*; import docking.tool.ToolConstants; +import ghidra.app.DeveloperPluginPackage; +import ghidra.app.plugin.PluginCategoryNames; +import ghidra.app.plugin.ProgramPlugin; +import ghidra.framework.plugintool.PluginInfo; +import ghidra.framework.plugintool.PluginTool; +import ghidra.framework.plugintool.util.PluginStatus; //@formatter:off @PluginInfo( @@ -93,13 +91,8 @@ public class ScreenshotPlugin extends ProgramPlugin { writeFile(image, file); } } - - @Override - public boolean shouldAddToWindow(boolean isMainWindow, Set> contextTypes) { - return true;// this is a global-level action - } }; - + captureActiveWindowAction.setAddToAllWindows(true); captureActiveWindowAction.setDescription("Takes a screenshot of the active component provider and exports it to PNG format."); captureActiveWindowAction.setKeyBindingData(new KeyBindingData(KeyEvent.VK_F11, InputEvent.ALT_DOWN_MASK)); @@ -123,13 +116,8 @@ public class ScreenshotPlugin extends ProgramPlugin { writeFile(image, file); } } - - @Override - public boolean shouldAddToWindow(boolean isMainWindow, Set> contextTypes) { - return true;// this is a global-level action - } }; - + captureToolFrameAction.setAddToAllWindows(true); captureToolFrameAction.setDescription("Takes a screenshot of the active tool and exports it to PNG format."); captureToolFrameAction.setKeyBindingData(new KeyBindingData(KeyEvent.VK_F12, InputEvent.ALT_DOWN_MASK)); diff --git a/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffSaveSettingsTest.java b/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffSaveSettingsTest.java index 869f07cf44..2987ff4916 100644 --- a/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffSaveSettingsTest.java +++ b/Ghidra/Features/ProgramDiff/src/test.slow/java/ghidra/app/plugin/core/diff/DiffSaveSettingsTest.java @@ -21,6 +21,7 @@ import java.awt.Window; import org.junit.*; +import docking.ActionContext; import docking.action.DockingActionIf; import docking.action.ToggleDockingAction; import docking.util.image.ToolIconURL; @@ -175,7 +176,8 @@ public class DiffSaveSettingsTest extends DiffApplyTestAdapter { ProgramManagerPlugin pm = getPlugin(tool, ProgramManagerPlugin.class); DockingActionIf closeAllProgramAction = getAction(pm, "Close All"); assertNotNull(closeAllProgramAction); - performAction(closeAllProgramAction, true); + ActionContext defaultContext = tool.getDefaultToolContext(); + performAction(closeAllProgramAction, defaultContext, true); openProgram(p3); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/WindowActionManager.java b/Ghidra/Framework/Docking/src/main/java/docking/WindowActionManager.java index 9e93d2d521..356c38ede6 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/WindowActionManager.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/WindowActionManager.java @@ -50,6 +50,7 @@ public class WindowActionManager { public void setActions(List actionList) { menuBarMgr.clearActions(); toolBarMgr.clearActions(); + actionToProxyMap.clear(); for (DockingActionIf action : actionList) { addAction(action); } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/action/ContextSpecificAction.java b/Ghidra/Framework/Docking/src/main/java/docking/action/ContextSpecificAction.java index f657d85877..40c1761025 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/action/ContextSpecificAction.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/action/ContextSpecificAction.java @@ -15,8 +15,6 @@ */ package docking.action; -import java.util.Set; - import docking.ActionContext; /** @@ -68,16 +66,6 @@ public abstract class ContextSpecificAction extends DockingAction { return false; } - @Override - public boolean shouldAddToWindow(boolean isMainWindow, Set> contextTypes) { - for (Class class1 : contextTypes) { - if (contextClass.isAssignableFrom(class1)) { - return true; - } - } - return false; - } - @Override public void actionPerformed(ActionContext actionContext) { actionPerformed(contextClass.cast(actionContext)); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/action/DockingAction.java b/Ghidra/Framework/Docking/src/main/java/docking/action/DockingAction.java index 43a922e58a..cc40f5a6c5 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/action/DockingAction.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/action/DockingAction.java @@ -83,6 +83,8 @@ public abstract class DockingAction implements DockingActionIf { private Predicate enabledPredicate; private Predicate popupPredicate; private Predicate validContextPredicate; + private boolean shouldAddToAllWindows = false; + private Class addToWindowWhenContextClass = null; private boolean supportsDefaultToolContext; @@ -193,15 +195,42 @@ public abstract class DockingAction implements DockingActionIf { } /** - * Default behavior is to add to main window; + * Determines if this action should be added to a window. + *

+ * If the client wants the action on all windows, then they can call {@link #shouldAddToAllWindows} + *

+ * If the client wants the action to be on a window only when the window can produce + * a certain context type, the the client should call + * {@link #addToWindowWhen(Class)} + *

+ * Otherwise, by default, the action will only be on the main window. + * */ @Override - public boolean shouldAddToWindow(boolean isMainWindow, Set> contextTypes) { - if (isMainWindow) { - // only return true if it is a tool menu or toolbar action - return menuBarData != null || toolBarData != null; + public final boolean shouldAddToWindow(boolean isMainWindow, Set> contextTypes) { + // this method only applies to actions with top level menus or tool bars. + if (menuBarData == null && toolBarData == null) { + return false; } - return false; + + // clients can specify that the action should be on all windows. + if (shouldAddToAllWindows) { + return true; + } + + // clients can specify a context class that determines if an action should + // be added to a window. + if (addToWindowWhenContextClass != null) { + for (Class class1 : contextTypes) { + if (addToWindowWhenContextClass.isAssignableFrom(class1)) { + return true; + } + } + return false; + } + + // default to only appearing in main window + return isMainWindow; } /** @@ -584,6 +613,30 @@ public abstract class DockingAction implements DockingActionIf { validContextPredicate = predicate; } + /** + * Sets the ActionContext class for when this action should be added to a window + *

+ * If this is set, the the action will only be added to windows that have providers + * that can produce an ActionContext that is appropriate for this action. + *

+ * @param contextClass the ActionContext class required to be producible by a + * provider that is hosted in that window before this action is added to that + * window. + * + */ + public void addToWindowWhen(Class contextClass) { + addToWindowWhenContextClass = contextClass; + } + + /** + * Tells this action to add itself to all windows + *

+ * @param b to add to all windows or not + */ + public void setAddToAllWindows(boolean b) { + shouldAddToAllWindows = b; + } + //================================================================================================== // Non-public methods //================================================================================================== @@ -611,4 +664,5 @@ public abstract class DockingAction implements DockingActionIf { String classInfo = trace[0].toString(); return classInfo; } + } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/action/DockingActionIf.java b/Ghidra/Framework/Docking/src/main/java/docking/action/DockingActionIf.java index fff4b87ebc..c038bd7865 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/action/DockingActionIf.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/action/DockingActionIf.java @@ -284,10 +284,9 @@ public interface DockingActionIf extends HelpDescriptor { /** * Determines whether this action should be added to a window (either the main window or a * secondary detached window). By default, this method will return true for the main window - * and false otherwise. Actions that want to also appear in other windows should override this - * method to return true when appropriate for the context types - * @param isMainWindow true if the window in question is the main window. Otherwise, the window - * is a secondary window. + * and false otherwise. + * + * @param isMainWindow true if the window in question is the main window * @param contextTypes a list of contextTypes (Classes) based on the providers that are currently * in the window. * @return true if this action should be added to the window, false otherwise. diff --git a/Ghidra/Framework/Docking/src/main/java/docking/action/builder/AbstractActionBuilder.java b/Ghidra/Framework/Docking/src/main/java/docking/action/builder/AbstractActionBuilder.java index 5c4f49ffec..eee4b56163 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/action/builder/AbstractActionBuilder.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/action/builder/AbstractActionBuilder.java @@ -176,7 +176,23 @@ public abstract class AbstractActionBuilder + * Global menu or toolbar actions can be configured to appear in 1) only the main + * window, or 2) all windows, or 3) any window that has a provider that + * generates an action context that matches the context that this action + * consumes. If the "context matches" options is chosen, then the + * {@link #withContext(Class)} method must also be called to specify the matching + * context; otherwise an exception will be thrown when the action is built. + *

+ * + * The default is that the action will only appear in the main window. + * + * @param when use the {@link When} enum to specify the windowing behavior + * of the action. + * + * @return this builder (for chaining) + */ + public B inWindow(When when) { + this.windowWhen = when; + return self(); + } /** * Sets the specific ActionContext type to use for the various predicate calls @@ -669,6 +708,11 @@ public abstract class AbstractActionBuilder> contextTypes) { - return isMainWindow || !contextTypes.isEmpty(); - } }; + optionsAction.setAddToAllWindows(true); optionsAction.setHelpLocation( new HelpLocation(ToolConstants.FRONT_END_HELP_TOPIC, "Tool Options")); MenuData menuData = @@ -1016,90 +1014,43 @@ public abstract class PluginTool extends AbstractDockingTool { } protected void addHelpActions() { + new ActionBuilder("About Ghidra", ToolConstants.TOOL_OWNER) + .menuPath(ToolConstants.MENU_HELP, "&About Ghidra") + .menuGroup("ZZA") + .helpLocation(new HelpLocation(ToolConstants.ABOUT_HELP_TOPIC, "About_Ghidra")) + .inWindow(ActionBuilder.When.ALWAYS) + .onAction(c -> DockingWindowManager.showDialog(new AboutDialog())) + .buildAndInstall(this); - DockingAction action = new DockingAction("About Ghidra", ToolConstants.TOOL_OWNER) { - - @Override - public void actionPerformed(ActionContext context) { - DockingWindowManager.showDialog(new AboutDialog()); - } - - @Override - public boolean shouldAddToWindow(boolean isMainWindow, Set> contextTypes) { - return true; - } - }; - action.setMenuBarData( - new MenuData(new String[] { ToolConstants.MENU_HELP, "&About Ghidra" }, null, "ZZA")); - - action.setHelpLocation(new HelpLocation(ToolConstants.ABOUT_HELP_TOPIC, "About_Ghidra")); - action.setEnabled(true); - addAction(action); - - DockingAction userAgreementAction = new DockingAction("User Agreement", - ToolConstants.TOOL_OWNER, KeyBindingType.UNSUPPORTED) { - - @Override - public void actionPerformed(ActionContext context) { - DockingWindowManager.showDialog(new UserAgreementDialog(false, false)); - } - - @Override - public boolean shouldAddToWindow(boolean isMainWindow, Set> contextTypes) { - return true; - } - }; - userAgreementAction.setMenuBarData( - new MenuData(new String[] { ToolConstants.MENU_HELP, "&User Agreement" }, null, - ToolConstants.HELP_CONTENTS_MENU_GROUP)); - userAgreementAction.setHelpLocation( - new HelpLocation(ToolConstants.ABOUT_HELP_TOPIC, "User_Agreement")); - - userAgreementAction.setEnabled(true); - addAction(userAgreementAction); + new ActionBuilder("User Agreement", ToolConstants.TOOL_OWNER) + .menuPath(ToolConstants.MENU_HELP, "&User Agreement") + .menuGroup(ToolConstants.HELP_CONTENTS_MENU_GROUP) + .helpLocation(new HelpLocation(ToolConstants.ABOUT_HELP_TOPIC, "User_Agreement")) + .inWindow(ActionBuilder.When.ALWAYS) + .onAction( + c -> DockingWindowManager.showDialog(new UserAgreementDialog(false, false))) + .buildAndInstall(this); final ErrorReporter reporter = ErrLogDialog.getErrorReporter(); if (reporter != null) { - action = new DockingAction("Report Bug", ToolConstants.TOOL_OWNER) { - - @Override - public void actionPerformed(ActionContext context) { - reporter.report(getToolFrame(), "User Bug Report", null); - } - - @Override - public boolean shouldAddToWindow(boolean isMainWindow, Set> contextTypes) { - return true; - } - }; - action.setMenuBarData(new MenuData( - new String[] { ToolConstants.MENU_HELP, "&Report Bug..." }, null, "BBB")); - - action.setHelpLocation(new HelpLocation("ErrorReporting", "Report_Bug")); - action.setEnabled(true); - addAction(action); + new ActionBuilder("Report Bug", ToolConstants.TOOL_OWNER) + .menuPath(ToolConstants.MENU_HELP, "&Report Bug...") + .menuGroup("BBB") + .helpLocation(new HelpLocation("ErrorReporting", "Report_Bug")) + .inWindow(ActionBuilder.When.ALWAYS) + .onAction(c -> reporter.report(getToolFrame(), "User Bug Report", null)) + .buildAndInstall(this); } HelpService help = Help.getHelpService(); - action = new DockingAction("Contents", ToolConstants.TOOL_OWNER) { - @Override - public void actionPerformed(ActionContext context) { - help.showHelp(null, false, getToolFrame()); - } - - @Override - public boolean shouldAddToWindow(boolean isMainWindow, Set> contextTypes) { - return true; - } - }; - action.setMenuBarData(new MenuData(new String[] { ToolConstants.MENU_HELP, "&Contents" }, - null, ToolConstants.HELP_CONTENTS_MENU_GROUP)); - - action.setEnabled(true); - action.setHelpLocation(new HelpLocation("Misc", "Welcome_to_Ghidra_Help")); - - addAction(action); + new ActionBuilder("Contents", ToolConstants.TOOL_OWNER) + .menuPath(ToolConstants.MENU_HELP, "&Contents") + .menuGroup(ToolConstants.HELP_CONTENTS_MENU_GROUP) + .helpLocation(new HelpLocation("Misc", "Welcome_to_Ghidra_Help")) + .inWindow(ActionBuilder.When.ALWAYS) + .onAction(c -> help.showHelp(null, false, getToolFrame())) + .buildAndInstall(this); } /**