Merge remote-tracking branch

'origin/GP-759_ghidravore_actions_on_secondary_windows--SQUASHED'
This commit is contained in:
ghidra1 2021-05-19 12:06:59 -04:00
commit 36b32721c6
51 changed files with 366 additions and 697 deletions

View File

@ -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<Class<?>> contextTypes) {
for (Class<?> class1 : contextTypes) {
if (ListingActionContext.class.isAssignableFrom(class1)) {
return true;
}
}
return false;
}
}

View File

@ -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<Class<?>> contextTypes) {
for (Class<?> class1 : contextTypes) {
if (NavigatableActionContext.class.isAssignableFrom(class1)) {
return true;
}
}
return false;
}
}

View File

@ -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<Class<?>> contextTypes) {
for (Class<?> class1 : contextTypes) {
if (ProgramActionContext.class.isAssignableFrom(class1)) {
return true;
}
}
return false;
}
@Override
public boolean isAddToPopup(ActionContext context) {
if (!(context instanceof ProgramActionContext)) {

View File

@ -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<Class<?>> contextTypes) {
for (Class<?> class1 : contextTypes) {
if (ProgramLocationActionContext.class.isAssignableFrom(class1)) {
return true;
}
}
return false;
}
}

View File

@ -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<Class<?>> contextTypes) {
for (Class<?> class1 : contextTypes) {
if (NavigatableRangeActionContext.class.isAssignableFrom(class1)) {
return true;
}
}
return false;
}
}

View File

@ -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<Class<?>> contextTypes) {
for (Class<?> class1 : contextTypes) {
if (NavigatableRangeActionContext.class.isAssignableFrom(class1)) {
return true;
}
}
return false;
}
}

View File

@ -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);

View File

@ -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,12 +209,53 @@ 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) {
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);
@ -236,102 +271,9 @@ public class ClearPlugin extends Plugin {
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);
}
/**
* Pop up the clear with options dialog.
*/

View File

@ -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) {

View File

@ -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());
}
}

View File

@ -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<Class<?>> contextTypes) {
for (Class<?> class1 : contextTypes) {
if (CodeViewerActionContext.class.isAssignableFrom(class1)) {
return true;
}
}
return false;
}
}

View File

@ -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

View File

@ -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) {

View File

@ -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) {

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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()

View File

@ -115,6 +115,7 @@ public class AboutProgramPlugin extends Plugin implements FrontEndable {
return false;
}
};
aboutAction.addToWindowWhen(ProgramActionContext.class);
aboutAction.setSupportsDefaultToolContext(true);
aboutAction.setMenuBarData(

View File

@ -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) {

View File

@ -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" },

View File

@ -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

View File

@ -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();

View File

@ -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",

View File

@ -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<Class<?>> 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<Class<?>> contextTypes) {
for (Class<?> class1 : contextTypes) {
if (NavigationActionContext.class.isAssignableFrom(class1)) {
return true;
}
}
return false;
}
@Override
public List<DockingActionIf> 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<Class<?>> contextTypes) {
for (Class<?> class1 : contextTypes) {
if (NavigationActionContext.class.isAssignableFrom(class1)) {
return true;
}
}
return false;
}
}
}

View File

@ -135,6 +135,7 @@ public class NextPrevCodeUnitPlugin extends Plugin {
setHelpLocation(
new HelpLocation(HelpTopics.NAVIGATION, longName));
setDescription(longName);
addToWindowWhen(NavigatableActionContext.class);
}

View File

@ -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<String>
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<String>
public boolean isEnabledForContext(ActionContext context) {
return context instanceof ListingActionContext;
}
@Override
public boolean shouldAddToWindow(boolean isMainWindow, Set<Class<?>> contextTypes) {
for (Class<?> class1 : contextTypes) {
if (CodeViewerActionContext.class.isAssignableFrom(class1)) {
return true;
}
}
return false;
}
}

View File

@ -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<String> {
setMenuBarData(menuData);
setKeyBindingData(new KeyBindingData(getKeyStroke()));
addToWindowWhen(CodeViewerActionContext.class);
setHelpLocation(new HelpLocation(HelpTopics.NAVIGATION, getName()));
setDescription("Set marker options");
addToWindowWhen(CodeViewerActionContext.class);
ActionState<String> allMarkers =
new ActionState<String>("All Types", markerIcon, "All Types");
@ -310,13 +311,4 @@ public class NextPreviousMarkerAction extends MultiStateDockingAction<String> {
return isEnabledForContext(context);
}
@Override
public boolean shouldAddToWindow(boolean isMainWindow, Set<Class<?>> contextTypes) {
for (Class<?> class1 : contextTypes) {
if (CodeViewerActionContext.class.isAssignableFrom(class1)) {
return true;
}
}
return false;
}
}

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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);
//

View File

@ -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<Class<?>> 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());
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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());

View File

@ -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.");

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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"));

View File

@ -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<Class<?>> 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<Class<?>> 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));

View File

@ -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);

View File

@ -50,6 +50,7 @@ public class WindowActionManager {
public void setActions(List<DockingActionIf> actionList) {
menuBarMgr.clearActions();
toolBarMgr.clearActions();
actionToProxyMap.clear();
for (DockingActionIf action : actionList) {
addAction(action);
}

View File

@ -15,8 +15,6 @@
*/
package docking.action;
import java.util.Set;
import docking.ActionContext;
/**
@ -68,16 +66,6 @@ public abstract class ContextSpecificAction<T> extends DockingAction {
return false;
}
@Override
public boolean shouldAddToWindow(boolean isMainWindow, Set<Class<?>> contextTypes) {
for (Class<?> class1 : contextTypes) {
if (contextClass.isAssignableFrom(class1)) {
return true;
}
}
return false;
}
@Override
public void actionPerformed(ActionContext actionContext) {
actionPerformed(contextClass.cast(actionContext));

View File

@ -83,6 +83,8 @@ public abstract class DockingAction implements DockingActionIf {
private Predicate<ActionContext> enabledPredicate;
private Predicate<ActionContext> popupPredicate;
private Predicate<ActionContext> validContextPredicate;
private boolean shouldAddToAllWindows = false;
private Class<? extends ActionContext> addToWindowWhenContextClass = null;
private boolean supportsDefaultToolContext;
@ -193,17 +195,44 @@ public abstract class DockingAction implements DockingActionIf {
}
/**
* Default behavior is to add to main window;
* Determines if this action should be added to a window.
* <P>
* If the client wants the action on all windows, then they can call {@link #shouldAddToAllWindows}
* <P>
* 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)}
* <P>
* Otherwise, by default, the action will only be on the main window.
*
*/
@Override
public boolean shouldAddToWindow(boolean isMainWindow, Set<Class<?>> 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<Class<?>> contextTypes) {
// this method only applies to actions with top level menus or tool bars.
if (menuBarData == null && toolBarData == null) {
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;
}
/**
* Set a specific Help location for this action.
* This will replace the default help location
@ -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
* <P>
* 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.
* <P>
* @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<? extends ActionContext> contextClass) {
addToWindowWhenContextClass = contextClass;
}
/**
* Tells this action to add itself to all windows
* <P>
* @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;
}
}

View File

@ -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.

View File

@ -177,6 +177,22 @@ public abstract class AbstractActionBuilder<T extends DockingActionIf, C extends
*/
private boolean supportsDefaultToolContext;
/**
* Specifies when the action should appear in a window.
*/
private When windowWhen;
/**
* For use with the {@link AbstractActionBuilder#inWindow(When)} method to specify which windows (main window
* or secondary windows) a global tool bar or menu action will appear in.
*
*/
public enum When {
MAIN_WINDOW, // action should only appear in the main window
ALWAYS, // action should appear in all windows
CONTEXT_MATCHES // action should appear if and only if the window has
} // has a provider that generates the appropriate context.
/**
* Builder constructor
* @param name the name of the action to be built
@ -197,7 +213,7 @@ public abstract class AbstractActionBuilder<T extends DockingActionIf, C extends
/**
* Builds the action. To build and install the action in one step, use
* {@link #buildAndInstall(Tool)} or {@link #buildAndInstallLocal(ComponentProvider)}.
*
* {@link #inWindow(When)}
* @return the newly build action
*/
public abstract T build();
@ -593,6 +609,29 @@ public abstract class AbstractActionBuilder<T extends DockingActionIf, C extends
return self();
}
/**
* Specifies when a global action should appear in a window (main or secondary).
* <P>
* 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.
* <P>
*
* 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
* ({@link #validContextWhen(Predicate)}, {@link #enabledWhen(Predicate)}, and
@ -669,6 +708,11 @@ public abstract class AbstractActionBuilder<T extends DockingActionIf, C extends
throw new IllegalStateException(
"Can't build a DockingAction without an action callback");
}
if (windowWhen == When.CONTEXT_MATCHES && actionContextClass == null) {
throw new IllegalStateException("The InWindow state was set to "
+ "\"CONTEXT_MATCHES\", but no context class was set. Use"
+ " the \"withContext\" method");
}
}
protected void decorateAction(DockingAction action) {
@ -691,6 +735,14 @@ public abstract class AbstractActionBuilder<T extends DockingActionIf, C extends
action.validContextWhen(adaptPredicate(validContextPredicate));
action.popupWhen(adaptPredicate(popupPredicate));
if (windowWhen == When.ALWAYS) {
action.setAddToAllWindows(true);
}
else if (windowWhen == When.CONTEXT_MATCHES) {
action.addToWindowWhen(actionContextClass);
}
// else action defaults to main window only
}
/**

View File

@ -32,6 +32,7 @@ import org.jdom.Element;
import docking.*;
import docking.action.*;
import docking.action.builder.ActionBuilder;
import docking.actions.PopupActionProvider;
import docking.actions.ToolActions;
import docking.framework.AboutDialog;
@ -921,11 +922,8 @@ public abstract class PluginTool extends AbstractDockingTool {
optionsMgr.editOptions();
}
@Override
public boolean shouldAddToWindow(boolean isMainWindow, Set<Class<?>> 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<Class<?>> 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<Class<?>> 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<Class<?>> 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<Class<?>> 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);
}
/**