mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 19:42:36 +02:00
GT-3485 fixed issue where some global listing and navigation actions
were not enabled when providers other than the listing had focus. This was unintentionally broken with the original ticket
This commit is contained in:
parent
83e0ce4091
commit
641745c6e0
36 changed files with 541 additions and 552 deletions
|
@ -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,11 +15,11 @@
|
|||
*/
|
||||
package ghidra.app.context;
|
||||
|
||||
import docking.ComponentProvider;
|
||||
import ghidra.app.nav.Navigatable;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.program.util.ProgramSelection;
|
||||
import docking.ComponentProvider;
|
||||
|
||||
public class ListingActionContext extends NavigatableActionContext {
|
||||
|
||||
|
@ -28,13 +27,14 @@ public class ListingActionContext extends NavigatableActionContext {
|
|||
super(provider, navigatable);
|
||||
}
|
||||
|
||||
public ListingActionContext(ComponentProvider provider, Navigatable navigatable, ProgramLocation location) {
|
||||
public ListingActionContext(ComponentProvider provider, Navigatable navigatable,
|
||||
ProgramLocation location) {
|
||||
super(provider, navigatable, location);
|
||||
}
|
||||
|
||||
public ListingActionContext(ComponentProvider provider, Navigatable navigatable,
|
||||
Program program, ProgramLocation location, ProgramSelection selection,
|
||||
ProgramSelection highlight ) {
|
||||
super( provider, navigatable, program, location, selection, highlight );
|
||||
ProgramSelection highlight) {
|
||||
super(provider, navigatable, program, location, selection, highlight);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,46 +24,32 @@ import docking.action.KeyBindingType;
|
|||
public abstract class NavigatableContextAction extends DockingAction {
|
||||
|
||||
public NavigatableContextAction(String name, String owner) {
|
||||
super(name, owner);
|
||||
this(name, owner, KeyBindingType.INDIVIDUAL);
|
||||
}
|
||||
|
||||
public NavigatableContextAction(String name, String owner, KeyBindingType type) {
|
||||
super(name, owner, type);
|
||||
setFallbackToGlobalContext(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabledForContext(ActionContext context) {
|
||||
NavigatableActionContext appropriateContext = getAppropriateContext(context);
|
||||
if (appropriateContext == null) {
|
||||
return false;
|
||||
if (context instanceof NavigatableActionContext) {
|
||||
return isEnabledForContext((NavigatableActionContext) context);
|
||||
}
|
||||
return isEnabledForContext(appropriateContext);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionContext context) {
|
||||
actionPerformed(getAppropriateContext(context));
|
||||
if (context instanceof NavigatableActionContext) {
|
||||
actionPerformed((NavigatableActionContext) context);
|
||||
}
|
||||
|
||||
private NavigatableActionContext getAppropriateContext(ActionContext context) {
|
||||
if (context instanceof NavigatableActionContext &&
|
||||
isValidNavigationContext((NavigatableActionContext) context)) {
|
||||
return (NavigatableActionContext) context;
|
||||
}
|
||||
ActionContext globalContext = context.getGlobalContext();
|
||||
if (globalContext instanceof NavigatableActionContext) {
|
||||
return (NavigatableActionContext) globalContext;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isValidContext(ActionContext context) {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean isValidNavigationContext(NavigatableActionContext context) {
|
||||
return true;
|
||||
return context instanceof NavigatableActionContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -30,23 +30,14 @@ public abstract class NextRangeAction extends NavigatableContextAction {
|
|||
private PluginTool tool;
|
||||
private NavigationOptions navOptions;
|
||||
|
||||
public NextRangeAction(PluginTool tool, String name, String owner, NavigationOptions navOptions) {
|
||||
public NextRangeAction(PluginTool tool, String name, String owner,
|
||||
NavigationOptions navOptions) {
|
||||
super(name, owner);
|
||||
this.tool = tool;
|
||||
this.navOptions = navOptions;
|
||||
setEnabled(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isValidNavigationContext(NavigatableActionContext context) {
|
||||
//
|
||||
// We want the nav actions to work in the current view that supports this, which right
|
||||
// now is the ListingActionContext. If the current context does not support that, then
|
||||
// we will be called later with the global context, which does support navigation.
|
||||
//
|
||||
return context instanceof ListingActionContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabledForContext(NavigatableActionContext context) {
|
||||
Address currentAddress = context.getAddress();
|
||||
|
|
|
@ -37,16 +37,6 @@ public abstract class PreviousRangeAction extends NavigatableContextAction {
|
|||
setEnabled(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isValidNavigationContext(NavigatableActionContext context) {
|
||||
//
|
||||
// We want the nav actions to work in the current view that supports this, which right
|
||||
// now is the ListingActionContext. If the current context does not support that, then
|
||||
// we will be called later with the global context, which does support navigation.
|
||||
//
|
||||
return context instanceof ListingActionContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(NavigatableActionContext context) {
|
||||
Address goToAddress = getGoToAddress(context);
|
||||
|
|
|
@ -22,6 +22,7 @@ import docking.ActionContext;
|
|||
import docking.ComponentProvider;
|
||||
import docking.action.DockingAction;
|
||||
import docking.action.MenuData;
|
||||
import docking.action.builder.ActionBuilder;
|
||||
import docking.tool.ToolConstants;
|
||||
import ghidra.app.CorePluginPackage;
|
||||
import ghidra.app.context.*;
|
||||
|
@ -96,14 +97,20 @@ public class FindPossibleReferencesPlugin extends Plugin {
|
|||
}
|
||||
|
||||
private void createActions() {
|
||||
action = new ListingContextAction(SEARCH_DIRECT_REFS_ACTION_NAME, getName()) {
|
||||
@Override
|
||||
protected void actionPerformed(ListingActionContext context) {
|
||||
findReferences(context);
|
||||
action = new ActionBuilder(SEARCH_DIRECT_REFS_ACTION_NAME, getName())
|
||||
.menuPath(ToolConstants.MENU_SEARCH, "For Direct References")
|
||||
.menuGroup("search for")
|
||||
.fallbackToGlobalContext(true)
|
||||
.helpLocation(new HelpLocation(HelpTopics.SEARCH, SEARCH_DIRECT_REFS_ACTION_NAME))
|
||||
.description(getPluginDescription().getDescription())
|
||||
.withContext(ListingActionContext.class)
|
||||
.onAction(this::findReferences)
|
||||
.enabledWhen(this::checkSize)
|
||||
.buildAndInstall(tool);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabledForContext(ListingActionContext context) {
|
||||
private boolean checkSize(ListingActionContext context) {
|
||||
int size =
|
||||
context.getProgram().getAddressFactory().getDefaultAddressSpace().getSize();
|
||||
if ((size == 64) || (size == 32) || (size == 24) || (size == 16) || (size == 20) ||
|
||||
|
@ -112,17 +119,6 @@ public class FindPossibleReferencesPlugin extends Plugin {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
action.setHelpLocation(new HelpLocation(HelpTopics.SEARCH, SEARCH_DIRECT_REFS_ACTION_NAME));
|
||||
action.setMenuBarData(
|
||||
new MenuData(new String[] { ToolConstants.MENU_SEARCH, "For Direct References" }, null,
|
||||
"search for"));
|
||||
|
||||
action.setDescription(getPluginDescription().getDescription());
|
||||
//enableOnLocation(action);
|
||||
tool.addAction(action);
|
||||
|
||||
} // end of createActions()
|
||||
|
||||
private void createLocalActions(ProgramLocationActionContext context, ComponentProvider p,
|
||||
FindReferencesTableModel model) {
|
||||
|
@ -196,8 +192,10 @@ public class FindPossibleReferencesPlugin extends Plugin {
|
|||
"Could not find memory associated with " + fromAddr);
|
||||
return;
|
||||
}
|
||||
if (currentProgram.getMemory().getBlock(
|
||||
fromAddr).getType() == MemoryBlockType.BIT_MAPPED) {
|
||||
if (currentProgram.getMemory()
|
||||
.getBlock(
|
||||
fromAddr)
|
||||
.getType() == MemoryBlockType.BIT_MAPPED) {
|
||||
Msg.showWarn(getClass(), null, "Search For Direct References",
|
||||
"Cannot search for direct references on bit memory!");
|
||||
return;
|
||||
|
|
|
@ -30,6 +30,7 @@ public class ClearSelectionAction extends CodeViewerContextAction {
|
|||
|
||||
public ClearSelectionAction(String owner) {
|
||||
super("Clear Selection", owner);
|
||||
setFallbackToGlobalContext(true);
|
||||
setMenuBarData(new MenuData(
|
||||
new String[] { ToolConstants.MENU_SELECTION, "&Clear Selection" }, null, "Select"));
|
||||
|
||||
|
|
|
@ -23,8 +23,9 @@ import javax.swing.KeyStroke;
|
|||
import docking.action.KeyBindingData;
|
||||
import docking.action.MenuData;
|
||||
import docking.tool.ToolConstants;
|
||||
import ghidra.app.context.NavigatableActionContext;
|
||||
import ghidra.app.context.NavigatableContextAction;
|
||||
import ghidra.app.nav.Navigatable;
|
||||
import ghidra.app.plugin.core.codebrowser.CodeViewerActionContext;
|
||||
import ghidra.app.services.GoToService;
|
||||
import ghidra.app.util.HelpTopics;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
|
@ -33,7 +34,7 @@ import ghidra.program.model.listing.*;
|
|||
import ghidra.program.util.FunctionSignatureFieldLocation;
|
||||
import ghidra.util.HelpLocation;
|
||||
|
||||
public class GotoNextFunctionAction extends CodeViewerContextAction {
|
||||
public class GotoNextFunctionAction extends NavigatableContextAction {
|
||||
|
||||
private PluginTool tool;
|
||||
|
||||
|
@ -67,7 +68,7 @@ public class GotoNextFunctionAction extends CodeViewerContextAction {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void actionPerformed(CodeViewerActionContext context) {
|
||||
protected void actionPerformed(NavigatableActionContext context) {
|
||||
Address address = context.getAddress();
|
||||
Program program = context.getProgram();
|
||||
Function function = getNextFunction(program, address);
|
||||
|
|
|
@ -23,8 +23,9 @@ import javax.swing.KeyStroke;
|
|||
import docking.action.KeyBindingData;
|
||||
import docking.action.MenuData;
|
||||
import docking.tool.ToolConstants;
|
||||
import ghidra.app.context.NavigatableActionContext;
|
||||
import ghidra.app.context.NavigatableContextAction;
|
||||
import ghidra.app.nav.Navigatable;
|
||||
import ghidra.app.plugin.core.codebrowser.CodeViewerActionContext;
|
||||
import ghidra.app.services.GoToService;
|
||||
import ghidra.app.util.HelpTopics;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
|
@ -33,7 +34,7 @@ import ghidra.program.model.listing.*;
|
|||
import ghidra.program.util.FunctionSignatureFieldLocation;
|
||||
import ghidra.util.HelpLocation;
|
||||
|
||||
public class GotoPreviousFunctionAction extends CodeViewerContextAction {
|
||||
public class GotoPreviousFunctionAction extends NavigatableContextAction {
|
||||
|
||||
private PluginTool tool;
|
||||
|
||||
|
@ -67,7 +68,7 @@ public class GotoPreviousFunctionAction extends CodeViewerContextAction {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void actionPerformed(CodeViewerActionContext context) {
|
||||
protected void actionPerformed(NavigatableActionContext context) {
|
||||
Address address = context.getAddress();
|
||||
Program program = context.getProgram();
|
||||
Function function = getPreviousFunction(program, address);
|
||||
|
|
|
@ -15,10 +15,6 @@
|
|||
*/
|
||||
package ghidra.app.plugin.core.codebrowser.actions;
|
||||
|
||||
import ghidra.app.plugin.core.codebrowser.CodeViewerProvider;
|
||||
import ghidra.app.util.HelpTopics;
|
||||
import ghidra.util.HelpLocation;
|
||||
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
|
||||
|
@ -26,6 +22,9 @@ 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.
|
||||
|
@ -34,19 +33,20 @@ public class SelectAllAction extends CodeViewerContextAction {
|
|||
|
||||
public SelectAllAction(String owner) {
|
||||
super("Select All", owner);
|
||||
setFallbackToGlobalContext(true);
|
||||
setMenuBarData(
|
||||
new MenuData(
|
||||
new String[] {ToolConstants.MENU_SELECTION, "&All in View" },null,"Select" ) );
|
||||
new String[] { ToolConstants.MENU_SELECTION, "&All in View" }, null, "Select"));
|
||||
|
||||
setKeyBindingData( new KeyBindingData(
|
||||
KeyEvent.VK_A, InputEvent.CTRL_DOWN_MASK ) );
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,14 +14,15 @@
|
|||
* 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;
|
||||
import docking.ActionContext;
|
||||
import docking.action.MenuData;
|
||||
import docking.tool.ToolConstants;
|
||||
|
||||
/**
|
||||
* Action for changing the selection to the complement of all the currently
|
||||
|
@ -31,10 +32,11 @@ public class SelectComplementAction extends CodeViewerContextAction {
|
|||
|
||||
public SelectComplementAction(String owner) {
|
||||
super("Select Complement", owner);
|
||||
setMenuBarData( new MenuData(
|
||||
new String[]{ToolConstants.MENU_SELECTION, "&Complement" },
|
||||
setFallbackToGlobalContext(true);
|
||||
setMenuBarData(new MenuData(
|
||||
new String[] { ToolConstants.MENU_SELECTION, "&Complement" },
|
||||
null,
|
||||
"Select" ) );
|
||||
"Select"));
|
||||
|
||||
setEnabled(false);
|
||||
setHelpLocation(new HelpLocation(HelpTopics.SELECTION, getName()));
|
||||
|
@ -45,6 +47,7 @@ public class SelectComplementAction extends CodeViewerContextAction {
|
|||
CodeViewerProvider provider = (CodeViewerProvider) context.getComponentProvider();
|
||||
provider.selectComplement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabledForContext(CodeViewerActionContext context) {
|
||||
ProgramSelection selection = context.getSelection();
|
||||
|
@ -54,4 +57,3 @@ public class SelectComplementAction extends CodeViewerContextAction {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -245,9 +245,10 @@ public class InstructionSearchPlugin extends ProgramPlugin {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected boolean isValidNavigationContext(NavigatableActionContext context) {
|
||||
protected boolean isEnabledForContext(NavigatableActionContext context) {
|
||||
return !(context instanceof RestrictedAddressSetContext);
|
||||
}
|
||||
|
||||
};
|
||||
searchAction.setHelpLocation(new HelpLocation("Search", "Instruction_Pattern_Search"));
|
||||
searchAction.setMenuBarData(
|
||||
|
|
|
@ -19,7 +19,7 @@ import javax.swing.*;
|
|||
|
||||
import docking.action.*;
|
||||
import docking.tool.ToolConstants;
|
||||
import ghidra.app.context.ListingActionContext;
|
||||
import ghidra.app.context.NavigatableActionContext;
|
||||
import ghidra.app.nav.Navigatable;
|
||||
import ghidra.app.plugin.core.codebrowser.CodeViewerActionContext;
|
||||
import ghidra.app.plugin.core.codebrowser.actions.CodeViewerContextAction;
|
||||
|
@ -41,6 +41,7 @@ public abstract class AbstractNextPreviousAction extends CodeViewerContextAction
|
|||
public AbstractNextPreviousAction(PluginTool tool, String name, String owner, String subGroup) {
|
||||
super(name, owner);
|
||||
this.tool = tool;
|
||||
setFallbackToGlobalContext(true);
|
||||
|
||||
ToolBarData toolBarData =
|
||||
new ToolBarData(getIcon(), ToolConstants.TOOLBAR_GROUP_FOUR);
|
||||
|
@ -90,7 +91,7 @@ public abstract class AbstractNextPreviousAction extends CodeViewerContextAction
|
|||
}
|
||||
}
|
||||
|
||||
private void gotoAddress(ListingActionContext actionContext, Address address) {
|
||||
private void gotoAddress(NavigatableActionContext actionContext, Address address) {
|
||||
if (address == null) {
|
||||
tool.setStatusInfo("Unable to locate another \"" + getNavigationTypeName() +
|
||||
"\" past the current range, in the current direction.");
|
||||
|
|
|
@ -23,9 +23,9 @@ import javax.swing.Icon;
|
|||
import docking.action.*;
|
||||
import docking.tool.ToolConstants;
|
||||
import ghidra.app.CorePluginPackage;
|
||||
import ghidra.app.context.NavigatableActionContext;
|
||||
import ghidra.app.context.NavigatableContextAction;
|
||||
import ghidra.app.plugin.PluginCategoryNames;
|
||||
import ghidra.app.plugin.core.codebrowser.CodeViewerActionContext;
|
||||
import ghidra.app.plugin.core.codebrowser.actions.CodeViewerContextAction;
|
||||
import ghidra.app.services.GoToService;
|
||||
import ghidra.app.util.HelpTopics;
|
||||
import ghidra.framework.plugintool.*;
|
||||
|
@ -119,7 +119,7 @@ public class NextPrevCodeUnitPlugin extends Plugin {
|
|||
bookmarkAction.setDirection(searchForward);
|
||||
}
|
||||
|
||||
private class ToggleDirectionAction extends CodeViewerContextAction {
|
||||
private class ToggleDirectionAction extends NavigatableContextAction {
|
||||
Icon forwardIcon = ResourceManager.loadImage("images/down.png");
|
||||
Icon backwardIcon = ResourceManager.loadImage("images/up.png");
|
||||
private boolean isForward = true;
|
||||
|
@ -144,7 +144,7 @@ public class NextPrevCodeUnitPlugin extends Plugin {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(CodeViewerActionContext context) {
|
||||
public void actionPerformed(NavigatableActionContext context) {
|
||||
isForward = !isForward;
|
||||
getMenuBarData().setIcon(isForward ? forwardIcon : backwardIcon);
|
||||
getToolBarData().setIcon(isForward ? forwardIcon : backwardIcon);
|
||||
|
|
|
@ -29,6 +29,7 @@ import docking.menu.MultiStateDockingAction;
|
|||
import docking.tool.ToolConstants;
|
||||
import docking.widgets.EventTrigger;
|
||||
import ghidra.app.context.ListingActionContext;
|
||||
import ghidra.app.context.NavigatableActionContext;
|
||||
import ghidra.app.nav.Navigatable;
|
||||
import ghidra.app.plugin.core.codebrowser.CodeViewerActionContext;
|
||||
import ghidra.app.services.GoToService;
|
||||
|
@ -56,6 +57,7 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction<String>
|
|||
public NextPreviousBookmarkAction(PluginTool tool, String owner, String subGroup) {
|
||||
super("Next Bookmark", owner);
|
||||
this.tool = tool;
|
||||
setFallbackToGlobalContext(true);
|
||||
|
||||
ToolBarData toolBarData =
|
||||
new ToolBarData(bookmarkIcon, ToolConstants.TOOLBAR_GROUP_FOUR);
|
||||
|
@ -119,8 +121,8 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction<String>
|
|||
|
||||
@Override
|
||||
protected void doActionPerformed(ActionContext context) {
|
||||
if (context instanceof ListingActionContext) {
|
||||
gotoNextPrevious((ListingActionContext) context, this.getCurrentUserData());
|
||||
if (context instanceof NavigatableActionContext) {
|
||||
gotoNextPrevious((NavigatableActionContext) context, this.getCurrentUserData());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -212,7 +214,8 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction<String>
|
|||
//==================================================================================================
|
||||
// AbstractNextPreviousAction Methods
|
||||
//==================================================================================================
|
||||
private void gotoNextPrevious(final ListingActionContext context, final String bookmarkType) {
|
||||
private void gotoNextPrevious(final NavigatableActionContext context,
|
||||
final String bookmarkType) {
|
||||
final Address address =
|
||||
isForward ? getNextAddress(context.getProgram(), context.getAddress(), bookmarkType)
|
||||
: getPreviousAddress(context.getProgram(), context.getAddress(), bookmarkType);
|
||||
|
@ -225,7 +228,7 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction<String>
|
|||
});
|
||||
}
|
||||
|
||||
private void gotoAddress(ListingActionContext listingActionContext, Address address) {
|
||||
private void gotoAddress(NavigatableActionContext listingActionContext, Address address) {
|
||||
if (address == null) {
|
||||
tool.setStatusInfo("Unable to locate another " + getNavigationTypeName() +
|
||||
" past the current range, in the current direction.");
|
||||
|
@ -264,40 +267,14 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction<String>
|
|||
//==================================================================================================
|
||||
// CodeViewerContextAction Methods
|
||||
//==================================================================================================
|
||||
@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);
|
||||
return context instanceof ListingActionContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAddToPopup(ActionContext context) {
|
||||
if (!(context instanceof CodeViewerActionContext)) {
|
||||
return false;
|
||||
}
|
||||
return isAddToPopup((CodeViewerActionContext) context);
|
||||
}
|
||||
|
||||
protected boolean isValidContext(CodeViewerActionContext context) {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean isEnabledForContext(CodeViewerActionContext context) {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean isAddToPopup(CodeViewerActionContext context) {
|
||||
return isEnabledForContext(context);
|
||||
public boolean isEnabledForContext(ActionContext context) {
|
||||
return context instanceof ListingActionContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -17,7 +17,6 @@ package ghidra.app.plugin.core.progmgr;
|
|||
|
||||
import java.awt.Component;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.beans.PropertyEditor;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
|
@ -26,16 +25,12 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import javax.swing.Icon;
|
||||
|
||||
import docking.ActionContext;
|
||||
import docking.DockingUtils;
|
||||
import docking.action.*;
|
||||
import docking.action.DockingAction;
|
||||
import docking.action.builder.ActionBuilder;
|
||||
import docking.options.editor.*;
|
||||
import docking.tool.ToolConstants;
|
||||
import ghidra.app.CorePluginPackage;
|
||||
import ghidra.app.context.ProgramActionContext;
|
||||
import ghidra.app.context.ProgramContextAction;
|
||||
import ghidra.app.events.*;
|
||||
import ghidra.app.plugin.PluginCategoryNames;
|
||||
import ghidra.app.services.ProgramManager;
|
||||
|
@ -59,7 +54,6 @@ import ghidra.program.util.*;
|
|||
import ghidra.util.*;
|
||||
import ghidra.util.exception.NotFoundException;
|
||||
import ghidra.util.task.TaskLauncher;
|
||||
import resources.ResourceManager;
|
||||
|
||||
//@formatter:off
|
||||
@PluginInfo(
|
||||
|
@ -90,9 +84,9 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager {
|
|||
private ProgramSaveManager programSaveMgr;
|
||||
private DockingAction openAction;
|
||||
private DockingAction saveAllAction;
|
||||
private ProgramContextAction closeAction;
|
||||
private ProgramContextAction saveAction;
|
||||
private ProgramContextAction saveAsAction;
|
||||
private DockingAction closeAction;
|
||||
private DockingAction saveAction;
|
||||
private DockingAction saveAsAction;
|
||||
private DockingAction optionsAction;
|
||||
private DockingAction closeOthersAction;
|
||||
private DockingAction closeAllAction;
|
||||
|
@ -101,7 +95,6 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager {
|
|||
private boolean locked = false;
|
||||
private UndoAction undoAction;
|
||||
private RedoAction redoAction;
|
||||
private ProgramActionContext lastProgramContext;
|
||||
private ProgramLocation currentLocation;
|
||||
|
||||
public ProgramManagerPlugin(PluginTool tool) {
|
||||
|
@ -527,206 +520,72 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager {
|
|||
|
||||
int subMenuGroupOrder = 1;
|
||||
|
||||
openAction = new DockingAction("Open File", getName()) {
|
||||
@Override
|
||||
public void actionPerformed(ActionContext context) {
|
||||
open();
|
||||
}
|
||||
};
|
||||
MenuData menuData =
|
||||
new MenuData(new String[] { ToolConstants.MENU_FILE, "&Open..." }, "DomainObjectOpen");
|
||||
menuData.setMenuSubGroup(Integer.toString(subMenuGroupOrder++));
|
||||
openAction.setMenuBarData(menuData);
|
||||
openAction.setKeyBindingData(
|
||||
new KeyBindingData(KeyEvent.VK_O, DockingUtils.CONTROL_KEY_MODIFIER_MASK));
|
||||
openAction = new ActionBuilder("Open File", getName())
|
||||
.onAction(c -> open())
|
||||
.menuPath(ToolConstants.MENU_FILE, "&Open...")
|
||||
.menuGroup("DomainObjectOpen", Integer.toString(subMenuGroupOrder++))
|
||||
.keyBinding("ctrl O")
|
||||
.buildAndInstall(tool);
|
||||
|
||||
closeAction = new ProgramContextAction("Close File", getName()) {
|
||||
@Override
|
||||
public void actionPerformed(ProgramActionContext programContext) {
|
||||
closeProgram(programContext.getProgram(), false);
|
||||
}
|
||||
closeAction = new ActionBuilder("Close File", getName())
|
||||
.menuPath(ToolConstants.MENU_FILE, "&Close")
|
||||
.menuGroup("DomainObjectOpen", Integer.toString(subMenuGroupOrder++))
|
||||
.withContext(ProgramActionContext.class)
|
||||
.onAction(c -> closeProgram(c.getProgram(), false))
|
||||
.buildAndInstall(tool);
|
||||
|
||||
@Override
|
||||
public boolean isValidContext(ActionContext context) {
|
||||
if (!super.isValidContext(context)) {
|
||||
getMenuBarData().setMenuItemName("&Close");
|
||||
setDescription("Close Program");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
closeOthersAction = new ActionBuilder("Close Others", getName())
|
||||
.menuPath(ToolConstants.MENU_FILE, "Close &Others")
|
||||
.menuGroup("DomainObjectOpen", Integer.toString(subMenuGroupOrder++))
|
||||
.enabled(false)
|
||||
.onAction(c -> closeOtherPrograms(false))
|
||||
.buildAndInstall(tool);
|
||||
|
||||
@Override
|
||||
public boolean isEnabledForContext(ProgramActionContext context) {
|
||||
Program program = context.getProgram();
|
||||
String programName = "'" + program.getDomainFile().getName() + "'";
|
||||
getMenuBarData().setMenuItemName("&Close " + programName);
|
||||
setDescription("<html>Close " + HTMLUtilities.escapeHTML(programName));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
String[] closeActionMenuPath = { ToolConstants.MENU_FILE, "&Close" };
|
||||
menuData = new MenuData(closeActionMenuPath, null, "DomainObjectOpen");
|
||||
menuData.setMenuSubGroup(Integer.toString(subMenuGroupOrder++));
|
||||
closeAction.setMenuBarData(menuData);
|
||||
closeAllAction = new ActionBuilder("Close All", getName())
|
||||
.menuPath(ToolConstants.MENU_FILE, "Close &All")
|
||||
.menuGroup("DomainObjectOpen", Integer.toString(subMenuGroupOrder++))
|
||||
.onAction(c -> closeAllPrograms(false))
|
||||
.enabled(false)
|
||||
.buildAndInstall(tool);
|
||||
|
||||
closeOthersAction = new DockingAction("Close Others", getName()) {
|
||||
@Override
|
||||
public void actionPerformed(ActionContext context) {
|
||||
closeOtherPrograms(false);
|
||||
}
|
||||
};
|
||||
closeOthersAction.setEnabled(false);
|
||||
String[] menuPath = { ToolConstants.MENU_FILE, "Close &Others" };
|
||||
menuData = new MenuData(menuPath, null, "DomainObjectOpen");
|
||||
menuData.setMenuSubGroup(Integer.toString(subMenuGroupOrder++));
|
||||
closeOthersAction.setMenuBarData(menuData);
|
||||
saveAction = new ActionBuilder("Save File", "&Save")
|
||||
.menuPath(ToolConstants.MENU_FILE, "Close &All")
|
||||
.description("Save Program")
|
||||
.menuGroup("DomainObjectSave", Integer.toString(subMenuGroupOrder++))
|
||||
.menuIcon(null)
|
||||
.toolBarIcon("images/disk.png")
|
||||
.toolBarGroup(ToolConstants.TOOLBAR_GROUP_ONE)
|
||||
.keyBinding("ctrl S")
|
||||
.withContext(ProgramActionContext.class)
|
||||
.enabledWhen(c -> c.getProgram().isChanged())
|
||||
.onAction(c -> programSaveMgr.saveProgram(c.getProgram()))
|
||||
.buildAndInstall(tool);
|
||||
|
||||
closeAllAction = new DockingAction("Close All", getName()) {
|
||||
@Override
|
||||
public void actionPerformed(ActionContext context) {
|
||||
closeAllPrograms(false);
|
||||
}
|
||||
};
|
||||
closeAllAction.setEnabled(false);
|
||||
String[] nenuPath = { ToolConstants.MENU_FILE, "Close &All" };
|
||||
menuData = new MenuData(nenuPath, null, "DomainObjectOpen");
|
||||
menuData.setMenuSubGroup(Integer.toString(subMenuGroupOrder++));
|
||||
closeAllAction.setMenuBarData(menuData);
|
||||
saveAsAction = new ActionBuilder("Save As File", getName())
|
||||
.menuPath(ToolConstants.MENU_FILE, "Save &As...")
|
||||
.menuGroup("DomainObjectSave", Integer.toString(subMenuGroupOrder++))
|
||||
.withContext(ProgramActionContext.class)
|
||||
.onAction(c -> programSaveMgr.saveAs(c.getProgram()))
|
||||
.buildAndInstall(tool);
|
||||
|
||||
saveAction = new ProgramContextAction("Save File", getName()) {
|
||||
@Override
|
||||
public void actionPerformed(ProgramActionContext programContext) {
|
||||
programSaveMgr.saveProgram(programContext.getProgram());
|
||||
// setEnabled(false);
|
||||
}
|
||||
saveAllAction = new ActionBuilder("Save All Files", getName())
|
||||
.menuPath(ToolConstants.MENU_FILE, "Save All")
|
||||
.description("Save All Programs")
|
||||
.menuGroup("DomainObjectSave", Integer.toString(subMenuGroupOrder++))
|
||||
.onAction(c -> programSaveMgr.saveChangedPrograms())
|
||||
.buildAndInstall(tool);
|
||||
|
||||
@Override
|
||||
public boolean isValidContext(ActionContext context) {
|
||||
lastProgramContext = null;
|
||||
if (!super.isValidContext(context)) {
|
||||
getMenuBarData().setMenuItemName("&Save");
|
||||
setDescription("Save Program");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabledForContext(ProgramActionContext context) {
|
||||
lastProgramContext = context;
|
||||
Program program = context.getProgram();
|
||||
String programName = "'" + program.getDomainFile().getName() + "'";
|
||||
getMenuBarData().setMenuItemName("&Save " + programName);
|
||||
setDescription("Save " + programName);
|
||||
return program.isChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isValidContext(ProgramActionContext context) {
|
||||
return super.isValidContext(context);
|
||||
}
|
||||
};
|
||||
String[] saveMenuPath = { ToolConstants.MENU_FILE, "&Save" };
|
||||
Icon saveIcon = ResourceManager.loadImage("images/disk.png");
|
||||
String saveGroup = ToolConstants.TOOLBAR_GROUP_ONE;
|
||||
subMenuGroupOrder = 0;
|
||||
|
||||
menuData = new MenuData(saveMenuPath, saveIcon, saveGroup);
|
||||
menuData.setMenuSubGroup(Integer.toString(subMenuGroupOrder++));
|
||||
saveAction.setMenuBarData(menuData);
|
||||
saveAction.setToolBarData(new ToolBarData(saveIcon, saveGroup));
|
||||
saveAction
|
||||
.setKeyBindingData(new KeyBindingData('S', DockingUtils.CONTROL_KEY_MODIFIER_MASK));
|
||||
saveAction.setDescription("Save Program");
|
||||
|
||||
saveAsAction = new ProgramContextAction("Save As File", getName()) {
|
||||
@Override
|
||||
public void actionPerformed(ProgramActionContext programContext) {
|
||||
programSaveMgr.saveAs(programContext.getProgram());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidContext(ActionContext context) {
|
||||
if (!super.isValidContext(context)) {
|
||||
getMenuBarData().setMenuItemName("Save &As...");
|
||||
setDescription("Save &As...");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabledForContext(ProgramActionContext context) {
|
||||
Program program = context.getProgram();
|
||||
String programName = "'" + program.getDomainFile().getName() + "'";
|
||||
String menuName = "Save " + programName + " &As...";
|
||||
getMenuBarData().setMenuItemName(menuName);
|
||||
setDescription(menuName);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
String[] saveAsPath = { ToolConstants.MENU_FILE, "Save &As..." };
|
||||
menuData = new MenuData(saveAsPath, null, "DomainObjectSave");
|
||||
menuData.setMenuSubGroup(Integer.toString(subMenuGroupOrder++));
|
||||
saveAsAction.setMenuBarData(menuData);
|
||||
|
||||
saveAllAction = new DockingAction("Save All Files", getName()) {
|
||||
@Override
|
||||
public void actionPerformed(ActionContext context) {
|
||||
programSaveMgr.saveChangedPrograms();
|
||||
}
|
||||
};
|
||||
menuData =
|
||||
new MenuData(new String[] { ToolConstants.MENU_FILE, "Save All" }, "DomainObjectSave");
|
||||
menuData.setMenuSubGroup(Integer.toString(subMenuGroupOrder++));
|
||||
saveAllAction.setMenuBarData(menuData);
|
||||
saveAllAction.setDescription("Save All Programs");
|
||||
|
||||
optionsAction = new ProgramContextAction("Program Options", getName()) {
|
||||
@Override
|
||||
public void actionPerformed(ProgramActionContext programContext) {
|
||||
showProgramOptions(programContext.getProgram());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidContext(ActionContext context) {
|
||||
if (!super.isValidContext(context)) {
|
||||
getMenuBarData().setMenuItemName("Program Options");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabledForContext(ProgramActionContext context) {
|
||||
lastProgramContext = context;
|
||||
Program program = context.getProgram();
|
||||
String programName = program.getDomainFile().getName();
|
||||
getMenuBarData().setMenuItemName("Options for " + programName + "...");
|
||||
return true;
|
||||
}
|
||||
};
|
||||
String[] optionsPath = { ToolConstants.MENU_EDIT, "P&rogram Options..." };
|
||||
menuData = new MenuData(optionsPath, null, ToolConstants.TOOL_OPTIONS_MENU_GROUP);
|
||||
|
||||
// update these options to appear below those for the tool, which we know is defined
|
||||
// inside of ToolConstants
|
||||
menuData.setMenuSubGroup(ToolConstants.TOOL_OPTIONS_MENU_GROUP + "b");
|
||||
optionsAction.setMenuBarData(menuData);
|
||||
optionsAction.setDescription("Edit Options for current program");
|
||||
optionsAction = new ActionBuilder("Program Options", getName())
|
||||
.menuPath(ToolConstants.MENU_EDIT, "P&rogram Options...")
|
||||
.description("Edit Options for current program")
|
||||
.menuGroup(ToolConstants.TOOL_OPTIONS_MENU_GROUP,
|
||||
ToolConstants.TOOL_OPTIONS_MENU_GROUP + "b")
|
||||
.withContext(ProgramActionContext.class)
|
||||
.onAction(c -> showProgramOptions(c.getProgram()))
|
||||
.buildAndInstall(tool);
|
||||
|
||||
undoAction = new UndoAction(tool, getName());
|
||||
redoAction = new RedoAction(tool, getName());
|
||||
|
||||
tool.addAction(openAction);
|
||||
tool.addAction(closeAction);
|
||||
tool.addAction(closeOthersAction);
|
||||
tool.addAction(closeAllAction);
|
||||
tool.addAction(saveAction);
|
||||
tool.addAction(saveAsAction);
|
||||
tool.addAction(saveAllAction);
|
||||
tool.addAction(optionsAction);
|
||||
tool.addAction(undoAction);
|
||||
tool.addAction(redoAction);
|
||||
}
|
||||
|
@ -791,6 +650,10 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager {
|
|||
|
||||
private void updateActions() {
|
||||
Program p = programMgr.getCurrentProgram();
|
||||
updateCloseAction(p);
|
||||
updateProgramOptionsAction(p);
|
||||
updateSaveAction(p);
|
||||
updateSaveAsAction(p);
|
||||
closeAllAction.setEnabled(p != null);
|
||||
optionsAction.setEnabled(p != null);
|
||||
Program[] programList = programMgr.getAllPrograms();
|
||||
|
@ -805,6 +668,54 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager {
|
|||
tool.contextChanged(null);
|
||||
}
|
||||
|
||||
private void updateSaveAction(Program p) {
|
||||
if (p == null) {
|
||||
saveAction.getMenuBarData().setMenuItemName("&Save");
|
||||
saveAction.setDescription("Save Program");
|
||||
saveAction.setEnabled(false);
|
||||
}
|
||||
else {
|
||||
String programName = "'" + p.getDomainFile().getName() + "'";
|
||||
saveAction.getMenuBarData().setMenuItemName("&Save " + programName);
|
||||
saveAction.setDescription("Save " + programName);
|
||||
saveAction.setEnabled(p.isChanged());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSaveAsAction(Program p) {
|
||||
if (p == null) {
|
||||
saveAsAction.getMenuBarData().setMenuItemName("Save &As...");
|
||||
}
|
||||
else {
|
||||
String programName = "'" + p.getDomainFile().getName() + "'";
|
||||
saveAsAction.getMenuBarData().setMenuItemName("Save " + programName + " &As...");
|
||||
}
|
||||
}
|
||||
|
||||
private void updateProgramOptionsAction(Program p) {
|
||||
if (p == null) {
|
||||
optionsAction.getMenuBarData().setMenuItemName("Program Options");
|
||||
}
|
||||
else {
|
||||
String programName = "'" + p.getDomainFile().getName() + "'";
|
||||
optionsAction.getMenuBarData().setMenuItemName("Options for " + programName + "...");
|
||||
}
|
||||
optionsAction.setEnabled(p != null);
|
||||
}
|
||||
|
||||
private void updateCloseAction(Program p) {
|
||||
if (p == null) {
|
||||
closeAction.getMenuBarData().setMenuItemName("&Close");
|
||||
closeAction.setDescription("Close Program");
|
||||
}
|
||||
else {
|
||||
String programName = "'" + p.getDomainFile().getName() + "'";
|
||||
closeAction.getMenuBarData().setMenuItemName("&Close " + programName);
|
||||
closeAction.setDescription("<html>Close " + HTMLUtilities.escapeHTML(programName));
|
||||
}
|
||||
closeAction.setEnabled(p != null);
|
||||
}
|
||||
|
||||
private void open() {
|
||||
if (openDialog == null) {
|
||||
ActionListener listener = e -> {
|
||||
|
@ -875,17 +786,11 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager {
|
|||
|
||||
void updateProgramActions() {
|
||||
updateSaveAllAction();
|
||||
if (lastProgramContext != null) {
|
||||
updateProgramAction(undoAction);
|
||||
updateProgramAction(redoAction);
|
||||
updateProgramAction(saveAction);
|
||||
updateProgramAction(saveAsAction);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateProgramAction(ProgramContextAction action) {
|
||||
boolean isEnabled = action.isEnabledForContext(lastProgramContext);
|
||||
action.setEnabled(isEnabled);
|
||||
Program p = getCurrentProgram();
|
||||
updateSaveAction(getCurrentProgram());
|
||||
updateSaveAsAction(getCurrentProgram());
|
||||
undoAction.update(p);
|
||||
redoAction.update(p);
|
||||
}
|
||||
|
||||
private void updateSaveAllAction() {
|
||||
|
|
|
@ -20,7 +20,6 @@ import java.io.IOException;
|
|||
|
||||
import javax.swing.Icon;
|
||||
|
||||
import docking.ActionContext;
|
||||
import docking.action.*;
|
||||
import docking.tool.ToolConstants;
|
||||
import ghidra.app.context.ProgramActionContext;
|
||||
|
@ -62,18 +61,31 @@ public class RedoAction extends ProgramContextAction {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabledForContext(ProgramActionContext context) {
|
||||
Program program = context.getProgram();
|
||||
if (program.canRedo()) {
|
||||
public void update(Program program) {
|
||||
if (program == null) {
|
||||
getMenuBarData().setMenuItemName("Redo ");
|
||||
setDescription("");
|
||||
setEnabled(false);
|
||||
}
|
||||
else if (program.canRedo()) {
|
||||
String programName = program.getDomainFile().getName();
|
||||
getMenuBarData().setMenuItemName("Redo " + programName);
|
||||
String tip = HTMLUtilities.toWrappedHTML(
|
||||
"Redo " + HTMLUtilities.escapeHTML(program.getRedoName()));
|
||||
setDescription(tip);
|
||||
return true;
|
||||
setEnabled(true);
|
||||
}
|
||||
return false;
|
||||
else {
|
||||
setDescription("Redo");
|
||||
setEnabled(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabledForContext(ProgramActionContext context) {
|
||||
Program program = context.getProgram();
|
||||
return program.canRedo();
|
||||
}
|
||||
|
||||
private void saveCurrentLocationToHistory() {
|
||||
|
@ -84,13 +96,4 @@ public class RedoAction extends ProgramContextAction {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabledForContext(ActionContext actionContext) {
|
||||
if (!super.isEnabledForContext(actionContext)) {
|
||||
setDescription("Redo");
|
||||
getMenuBarData().setMenuItemName("Redo");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ import java.io.IOException;
|
|||
|
||||
import javax.swing.Icon;
|
||||
|
||||
import docking.ActionContext;
|
||||
import docking.action.*;
|
||||
import docking.tool.ToolConstants;
|
||||
import ghidra.app.context.ProgramActionContext;
|
||||
|
@ -69,27 +68,29 @@ public class UndoAction extends ProgramContextAction {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabledForContext(ProgramActionContext context) {
|
||||
Program program = context.getProgram();
|
||||
if (program.canUndo()) {
|
||||
public void update(Program program) {
|
||||
if (program == null) {
|
||||
getMenuBarData().setMenuItemName("Undo ");
|
||||
setDescription("");
|
||||
setEnabled(false);
|
||||
}
|
||||
if (program != null && program.canUndo()) {
|
||||
String programName = program.getDomainFile().getName();
|
||||
getMenuBarData().setMenuItemName("Undo " + programName);
|
||||
String tip = HTMLUtilities.toWrappedHTML(
|
||||
"Undo " + HTMLUtilities.escapeHTML(program.getUndoName()));
|
||||
setDescription(tip);
|
||||
return true;
|
||||
setEnabled(true);
|
||||
}
|
||||
else {
|
||||
setDescription("Undo");
|
||||
setEnabled(false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabledForContext(ActionContext actionContext) {
|
||||
if (!super.isEnabledForContext(actionContext)) {
|
||||
setDescription("Undo");
|
||||
getMenuBarData().setMenuItemName("Undo");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
protected boolean isEnabledForContext(ProgramActionContext context) {
|
||||
Program program = context.getProgram();
|
||||
return program.canUndo();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -145,7 +145,7 @@ public class ScalarSearchPlugin extends ProgramPlugin implements DomainObjectLis
|
|||
}
|
||||
|
||||
@Override
|
||||
protected boolean isValidNavigationContext(NavigatableActionContext context) {
|
||||
protected boolean isEnabledForContext(NavigatableActionContext context) {
|
||||
return !(context instanceof RestrictedAddressSetContext);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -350,7 +350,7 @@ public class MemSearchPlugin extends Plugin implements OptionsChangeListener,
|
|||
}
|
||||
|
||||
@Override
|
||||
protected boolean isValidNavigationContext(NavigatableActionContext context) {
|
||||
protected boolean isEnabledForContext(NavigatableActionContext context) {
|
||||
return !(context instanceof RestrictedAddressSetContext);
|
||||
}
|
||||
};
|
||||
|
@ -369,13 +369,8 @@ public class MemSearchPlugin extends Plugin implements OptionsChangeListener,
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabledForContext(NavigatableActionContext context) {
|
||||
return searchInfo != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isValidNavigationContext(NavigatableActionContext context) {
|
||||
return !(context instanceof RestrictedAddressSetContext);
|
||||
protected boolean isEnabledForContext(NavigatableActionContext context) {
|
||||
return !(context instanceof RestrictedAddressSetContext) && searchInfo != null;
|
||||
}
|
||||
};
|
||||
searchAgainAction.setHelpLocation(
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
package ghidra.app.plugin.core.searchtext;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
|
@ -26,13 +24,15 @@ import java.util.regex.Pattern;
|
|||
import javax.swing.ImageIcon;
|
||||
|
||||
import docking.*;
|
||||
import docking.action.*;
|
||||
import docking.action.DockingAction;
|
||||
import docking.action.builder.ActionBuilder;
|
||||
import docking.tool.ToolConstants;
|
||||
import docking.widgets.fieldpanel.support.Highlight;
|
||||
import docking.widgets.table.threaded.*;
|
||||
import ghidra.GhidraOptions;
|
||||
import ghidra.app.CorePluginPackage;
|
||||
import ghidra.app.context.*;
|
||||
import ghidra.app.context.ListingActionContext;
|
||||
import ghidra.app.context.NavigatableActionContext;
|
||||
import ghidra.app.nav.Navigatable;
|
||||
import ghidra.app.nav.NavigatableRemovalListener;
|
||||
import ghidra.app.plugin.PluginCategoryNames;
|
||||
|
@ -379,49 +379,33 @@ public class SearchTextPlugin extends ProgramPlugin implements OptionsChangeList
|
|||
private void createActions() {
|
||||
String subGroup = getClass().getName();
|
||||
|
||||
searchAction = new ListingContextAction("Search Text", getName()) {
|
||||
@Override
|
||||
public void actionPerformed(ListingActionContext context) {
|
||||
setNavigatable(context.getNavigatable());
|
||||
displayDialog(context);
|
||||
}
|
||||
};
|
||||
searchAction.setHelpLocation(new HelpLocation(HelpTopics.SEARCH, searchAction.getName()));
|
||||
String[] menuPath = new String[] { "&Search", "Program &Text..." };
|
||||
MenuData menuData = new MenuData(menuPath, "search");
|
||||
menuData.setMenuSubGroup(subGroup);
|
||||
searchAction.setMenuBarData(menuData);
|
||||
searchAction.setKeyBindingData(new KeyBindingData(KeyEvent.VK_E,
|
||||
InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK));
|
||||
searchAction = new ActionBuilder("Search Text", getName())
|
||||
.menuPath("&Search", "Program &Text...")
|
||||
.menuGroup("search", subGroup)
|
||||
.keyBinding("ctrl shift E")
|
||||
.description(DESCRIPTION)
|
||||
.helpLocation(new HelpLocation(HelpTopics.SEARCH, "Search Text"))
|
||||
.withContext(NavigatableActionContext.class)
|
||||
.fallbackToGlobalContext(true)
|
||||
.onAction(c -> {
|
||||
setNavigatable(c.getNavigatable());
|
||||
displayDialog(c);
|
||||
})
|
||||
.buildAndInstall(tool);
|
||||
|
||||
searchAction.setDescription(DESCRIPTION);
|
||||
searchAction.setEnabled(false);
|
||||
//searchAction.setAddToPopup(false);
|
||||
tool.addAction(searchAction);
|
||||
|
||||
searchAgainAction = new ListingContextAction("Repeat Text Search", getName()) {
|
||||
@Override
|
||||
public void actionPerformed(ListingActionContext context) {
|
||||
setNavigatable(context.getNavigatable());
|
||||
searchAgainAction = new ActionBuilder("Repeat Text Search", getName())
|
||||
.menuPath("&Search", "Repeat Text Search")
|
||||
.menuGroup("search", subGroup)
|
||||
.keyBinding("ctrl shift F3")
|
||||
.description(DESCRIPTION)
|
||||
.helpLocation(new HelpLocation(HelpTopics.SEARCH, "Repeat Text Search"))
|
||||
.withContext(NavigatableActionContext.class)
|
||||
.enabledWhen(c -> searchedOnce)
|
||||
.onAction(c -> {
|
||||
setNavigatable(c.getNavigatable());
|
||||
searchDialog.repeatSearch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabledForContext(ListingActionContext context) {
|
||||
return searchedOnce;
|
||||
}
|
||||
};
|
||||
searchAgainAction.setHelpLocation(
|
||||
new HelpLocation(HelpTopics.SEARCH, searchAgainAction.getName()));
|
||||
menuPath = new String[] { "&Search", "Repeat Text Search" };
|
||||
menuData = new MenuData(menuPath, "search");
|
||||
menuData.setMenuSubGroup(subGroup);
|
||||
searchAgainAction.setMenuBarData(menuData);
|
||||
searchAgainAction.setKeyBindingData(new KeyBindingData(KeyEvent.VK_F3,
|
||||
InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK));
|
||||
|
||||
searchAgainAction.setDescription(DESCRIPTION);
|
||||
tool.addAction(searchAgainAction);
|
||||
})
|
||||
.buildAndInstall(tool);
|
||||
}
|
||||
|
||||
protected void updateNavigatable(ActionContext context) {
|
||||
|
|
|
@ -15,14 +15,14 @@
|
|||
*/
|
||||
package ghidra.app.plugin.core.select.flow;
|
||||
|
||||
import docking.action.MenuData;
|
||||
import docking.tool.ToolConstants;
|
||||
import ghidra.app.context.ListingActionContext;
|
||||
import ghidra.app.context.ListingContextAction;
|
||||
import ghidra.app.util.HelpTopics;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.CodeUnit;
|
||||
import ghidra.util.HelpLocation;
|
||||
import docking.action.MenuData;
|
||||
import docking.tool.ToolConstants;
|
||||
|
||||
/**
|
||||
* <CODE>SelectByFlowAction</CODE> allows the user to Select Code By Flowing from
|
||||
|
@ -62,6 +62,7 @@ class SelectByFlowAction extends ListingContextAction {
|
|||
super(name, plugin.getName());
|
||||
this.selectByFlowPlugin = plugin;
|
||||
this.selectionType = selectionType;
|
||||
setFallbackToGlobalContext(true);
|
||||
|
||||
String[] menuPath = null;
|
||||
if (selectionType == SelectByFlowPlugin.SELECT_FUNCTIONS) {
|
||||
|
|
|
@ -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,13 @@
|
|||
*/
|
||||
package ghidra.app.plugin.core.select.reference;
|
||||
|
||||
import ghidra.app.context.ListingContextAction;
|
||||
import ghidra.app.context.ListingActionContext;
|
||||
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;
|
||||
|
@ -27,13 +31,7 @@ import ghidra.program.model.symbol.Reference;
|
|||
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 SelectForwardRefsAction extends ListingContextAction {
|
||||
public class SelectForwardRefsAction extends NavigatableContextAction {
|
||||
|
||||
private final PluginTool tool;
|
||||
|
||||
|
@ -42,45 +40,45 @@ public class SelectForwardRefsAction extends ListingContextAction {
|
|||
this.tool = tool;
|
||||
|
||||
String group = "references";
|
||||
setMenuBarData( new MenuData( new String[] {"Select", "Forward Refs"}, null, group ) );
|
||||
setMenuBarData(new MenuData(new String[] { "Select", "Forward Refs" }, null, group));
|
||||
|
||||
setKeyBindingData( new KeyBindingData( KeyEvent.VK_PERIOD, InputEvent.CTRL_MASK ) );
|
||||
setKeyBindingData(new KeyBindingData(KeyEvent.VK_PERIOD, InputEvent.CTRL_MASK));
|
||||
setHelpLocation(new HelpLocation(HelpTopics.SELECTION, "Forward"));
|
||||
// setKeyBindingData( new KeyBindingData(KeyEvent.VK_SEMICOLON, InputEvent.CTRL_MASK ) );
|
||||
// setHelpLocation(new HelpLocation(HelpTopics.SELECTION, "Backward"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnabledForContext(ListingActionContext context) {
|
||||
protected boolean isEnabledForContext(NavigatableActionContext context) {
|
||||
return context.getAddress() != null || context.hasSelection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method called when the action is invoked.
|
||||
* @param ActionEvent details regarding the invocation of this action
|
||||
*/
|
||||
@Override
|
||||
public void actionPerformed(ListingActionContext context) {
|
||||
public void actionPerformed(NavigatableActionContext context) {
|
||||
|
||||
AddressSetView addressSet = context.hasSelection() ?
|
||||
context.getSelection() :
|
||||
new AddressSet(context.getAddress());
|
||||
AddressSetView addressSet =
|
||||
context.hasSelection() ? context.getSelection() : new AddressSet(context.getAddress());
|
||||
|
||||
ProgramSelection selection = getSelection(context.getProgram(), addressSet);
|
||||
NavigationUtils.setSelection(tool, context.getNavigatable(), selection);
|
||||
}
|
||||
|
||||
private ProgramSelection getSelection(Program program, AddressSetView addressSetView){
|
||||
private ProgramSelection getSelection(Program program, AddressSetView addressSetView) {
|
||||
AddressSet addressSet = new AddressSet();
|
||||
|
||||
CodeUnitIterator iter = program.getListing().getCodeUnits(addressSetView,true);
|
||||
CodeUnitIterator iter = program.getListing().getCodeUnits(addressSetView, true);
|
||||
|
||||
while (iter.hasNext()){
|
||||
CodeUnit cu=iter.next();
|
||||
Reference[] memRef=cu.getReferencesFrom();
|
||||
for (int i=0;i<memRef.length;i++){
|
||||
Address addr = memRef[i].getToAddress();
|
||||
if ( addr.isMemoryAddress() ) {
|
||||
addressSet.addRange(addr,addr);
|
||||
while (iter.hasNext()) {
|
||||
CodeUnit cu = iter.next();
|
||||
Reference[] memRef = cu.getReferencesFrom();
|
||||
for (Reference element : memRef) {
|
||||
Address addr = element.getToAddress();
|
||||
if (addr.isMemoryAddress()) {
|
||||
addressSet.addRange(addr, addr);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import docking.action.*;
|
|||
import docking.widgets.fieldpanel.support.FieldLocation;
|
||||
import docking.widgets.fieldpanel.support.ViewerPosition;
|
||||
import ghidra.GhidraOptions;
|
||||
import ghidra.app.context.ProgramActionContext;
|
||||
import ghidra.app.decompiler.*;
|
||||
import ghidra.app.decompiler.component.*;
|
||||
import ghidra.app.nav.*;
|
||||
|
@ -220,7 +221,10 @@ public class DecompilerProvider extends NavigatableComponentProviderAdapter
|
|||
return null;
|
||||
}
|
||||
Function function = controller.getFunction();
|
||||
Address entryPoint = function != null ? function.getEntryPoint() : null;
|
||||
if (function == null) {
|
||||
return new ProgramActionContext(this, program);
|
||||
}
|
||||
Address entryPoint = function.getEntryPoint();
|
||||
boolean isDecompiling = controller.isDecompiling();
|
||||
return new DecompilerActionContext(this, entryPoint, isDecompiling);
|
||||
}
|
||||
|
|
|
@ -228,4 +228,14 @@ public class DockingActionProxy
|
|||
public String toString() {
|
||||
return dockingAction.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFallbackToGlobalContext(boolean newValue) {
|
||||
dockingAction.setFallbackToGlobalContext(newValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldFallbackToGlobalContext() {
|
||||
return dockingAction.shouldFallbackToGlobalContext();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,12 +19,12 @@ import docking.action.DockingActionIf;
|
|||
import docking.action.ToggleDockingActionIf;
|
||||
import generic.json.Json;
|
||||
|
||||
public class ExecutableKeyActionAdapter {
|
||||
public class ExecutableAction {
|
||||
|
||||
DockingActionIf action;
|
||||
ActionContext context;
|
||||
|
||||
public ExecutableKeyActionAdapter(DockingActionIf action, ActionContext context) {
|
||||
public ExecutableAction(DockingActionIf action, ActionContext context) {
|
||||
this.action = action;
|
||||
this.context = context;
|
||||
}
|
|
@ -46,9 +46,10 @@ public class MenuBarMenuHandler extends MenuHandler {
|
|||
|
||||
DockingWindowManager.clearMouseOverHelp();
|
||||
|
||||
ComponentProvider provider = windowManager.getActiveComponentProvider();
|
||||
ActionContext providerContext = provider == null ? null : provider.getActionContext(null);
|
||||
ActionContext context = providerContext == null ? new ActionContext() : providerContext;
|
||||
ActionContext context = getActionContext(action);
|
||||
if (context == null) {
|
||||
return; // nothing to do
|
||||
}
|
||||
|
||||
context.setSourceObject(event.getSource());
|
||||
|
||||
|
@ -64,4 +65,22 @@ public class MenuBarMenuHandler extends MenuHandler {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
private ActionContext getActionContext(DockingActionIf action) {
|
||||
ComponentProvider provider = windowManager.getActiveComponentProvider();
|
||||
ActionContext localContext = provider == null ? null : provider.getActionContext(null);
|
||||
if (localContext == null) {
|
||||
localContext = new ActionContext();
|
||||
}
|
||||
if (action.isValidContext(localContext)) {
|
||||
return localContext;
|
||||
}
|
||||
if (action.shouldFallbackToGlobalContext()) {
|
||||
ActionContext globalContext = windowManager.getGlobalActionContext();
|
||||
if (action.isValidContext(globalContext)) {
|
||||
return globalContext;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ import docking.widgets.label.GLabel;
|
|||
public class MultiActionDialog extends DialogComponentProvider {
|
||||
|
||||
private String keystrokeName;
|
||||
private List<ExecutableKeyActionAdapter> list;
|
||||
private List<ExecutableAction> list;
|
||||
private JList<String> actionList;
|
||||
private DefaultListModel<String> listModel;
|
||||
|
||||
|
@ -42,7 +42,7 @@ public class MultiActionDialog extends DialogComponentProvider {
|
|||
* @param keystrokeName keystroke name
|
||||
* @param list list of actions
|
||||
*/
|
||||
public MultiActionDialog(String keystrokeName, List<ExecutableKeyActionAdapter> list) {
|
||||
public MultiActionDialog(String keystrokeName, List<ExecutableAction> list) {
|
||||
super("Select Action", true);
|
||||
this.keystrokeName = keystrokeName;
|
||||
init();
|
||||
|
@ -65,7 +65,7 @@ public class MultiActionDialog extends DialogComponentProvider {
|
|||
|
||||
close();
|
||||
|
||||
ExecutableKeyActionAdapter actionProxy = list.get(index);
|
||||
ExecutableAction actionProxy = list.get(index);
|
||||
actionProxy.execute();
|
||||
}
|
||||
|
||||
|
@ -73,12 +73,12 @@ public class MultiActionDialog extends DialogComponentProvider {
|
|||
* Set the list of actions that are enabled
|
||||
* @param list list of actions selected
|
||||
*/
|
||||
public void setActionList(List<ExecutableKeyActionAdapter> list) {
|
||||
public void setActionList(List<ExecutableAction> list) {
|
||||
okButton.setEnabled(false);
|
||||
this.list = list;
|
||||
listModel.clear();
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
ExecutableKeyActionAdapter actionProxy = list.get(i);
|
||||
ExecutableAction actionProxy = list.get(i);
|
||||
DockingActionIf action = actionProxy.getAction();
|
||||
listModel.addElement(action.getName() + " (" + action.getOwnerDescription() + ")");
|
||||
}
|
||||
|
|
|
@ -118,12 +118,8 @@ public class WindowActionManager {
|
|||
return;
|
||||
}
|
||||
|
||||
ComponentProvider provider = placeHolderForScheduledActionUpdate == null ? null
|
||||
: placeHolderForScheduledActionUpdate.getProvider();
|
||||
ActionContext localContext = provider == null ? null : provider.getActionContext(null);
|
||||
if (localContext == null) {
|
||||
localContext = new ActionContext();
|
||||
}
|
||||
ActionContext localContext = getContext();
|
||||
ActionContext globalContext = winMgr.getGlobalActionContext();
|
||||
|
||||
// Update actions - make a copy so that we don't get concurrent modification exceptions
|
||||
List<DockingActionIf> list = new ArrayList<>(actionToProxyMap.values());
|
||||
|
@ -131,6 +127,9 @@ public class WindowActionManager {
|
|||
if (action.isValidContext(localContext)) {
|
||||
action.setEnabled(action.isEnabledForContext(localContext));
|
||||
}
|
||||
else if (isValidGlobalContext(action, globalContext)) {
|
||||
action.setEnabled(action.isEnabledForContext(globalContext));
|
||||
}
|
||||
else {
|
||||
action.setEnabled(false);
|
||||
}
|
||||
|
@ -138,4 +137,21 @@ public class WindowActionManager {
|
|||
// Notify listeners if the context provider is the focused provider
|
||||
winMgr.notifyContextListeners(placeHolderForScheduledActionUpdate, localContext);
|
||||
}
|
||||
|
||||
private boolean isValidGlobalContext(DockingActionIf action, ActionContext globalContext) {
|
||||
return action.shouldFallbackToGlobalContext() &&
|
||||
action.isValidContext(globalContext);
|
||||
}
|
||||
|
||||
private ActionContext getContext() {
|
||||
ComponentProvider provider = placeHolderForScheduledActionUpdate == null ? null
|
||||
: placeHolderForScheduledActionUpdate.getProvider();
|
||||
|
||||
ActionContext context = provider == null ? null : provider.getActionContext(null);
|
||||
|
||||
if (context == null) {
|
||||
context = new ActionContext();
|
||||
}
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,6 +77,8 @@ public abstract class DockingAction implements DockingActionIf {
|
|||
private Predicate<ActionContext> popupPredicate;
|
||||
private Predicate<ActionContext> validContextPredicate;
|
||||
|
||||
private boolean fallbackToGlobalContext;
|
||||
|
||||
public DockingAction(String name, String owner) {
|
||||
this.name = name;
|
||||
this.owner = owner;
|
||||
|
@ -224,6 +226,16 @@ public abstract class DockingAction implements DockingActionIf {
|
|||
return !isEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFallbackToGlobalContext(boolean newValue) {
|
||||
fallbackToGlobalContext = newValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldFallbackToGlobalContext() {
|
||||
return fallbackToGlobalContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final JButton createButton() {
|
||||
JButton button = doCreateButton();
|
||||
|
|
|
@ -97,6 +97,23 @@ public interface DockingActionIf extends HelpDescriptor {
|
|||
*/
|
||||
public boolean setEnabled(boolean newValue);
|
||||
|
||||
/**
|
||||
* Sets whether or not this action should be activated using the global tool context if the
|
||||
* current focussed provider's context is not valid for this action.
|
||||
* @param newValue if true, the action will be activated using the global context if the local
|
||||
* context is not valid for this action. If false, the action will only ever be activated
|
||||
* using the local context.
|
||||
*/
|
||||
public void setFallbackToGlobalContext(boolean newValue);
|
||||
|
||||
/**
|
||||
* Returns true if this action can be activated using the global context if the local context
|
||||
* is invalid for this action.
|
||||
* @return true if this action can be activated using the global context if the local context
|
||||
* is invalid for this action.
|
||||
*/
|
||||
public boolean shouldFallbackToGlobalContext();
|
||||
|
||||
/**
|
||||
* Returns true if the action is enabled.
|
||||
*
|
||||
|
|
|
@ -112,7 +112,7 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
|
|||
@Override
|
||||
public void actionPerformed(final ActionEvent event) {
|
||||
// Build list of actions which are valid in current context
|
||||
List<ExecutableKeyActionAdapter> list = getActionsForCurrentContext(event.getSource());
|
||||
List<ExecutableAction> list = getActionsForCurrentOrGlobalContext(event.getSource());
|
||||
|
||||
// If menu active, disable all key bindings
|
||||
if (ignoreActionWhileMenuShowing()) {
|
||||
|
@ -135,7 +135,7 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
|
|||
Swing.runLater(() -> DockingWindowManager.showDialog(dialog));
|
||||
}
|
||||
else if (list.size() == 1) {
|
||||
final ExecutableKeyActionAdapter actionProxy = list.get(0);
|
||||
final ExecutableAction actionProxy = list.get(0);
|
||||
tool.setStatusInfo("");
|
||||
actionProxy.execute();
|
||||
}
|
||||
|
@ -154,8 +154,9 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
|
|||
return menuManager.getSelectedPath().length != 0;
|
||||
}
|
||||
|
||||
private List<ExecutableKeyActionAdapter> getValidContextActions(ActionContext localContext) {
|
||||
List<ExecutableKeyActionAdapter> list = new ArrayList<>();
|
||||
private List<ExecutableAction> getValidContextActions(ActionContext localContext,
|
||||
ActionContext globalContext) {
|
||||
List<ExecutableAction> list = new ArrayList<>();
|
||||
boolean hasLocalActionsForKeyBinding = false;
|
||||
|
||||
//
|
||||
|
@ -165,14 +166,15 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
|
|||
if (actionData.isMyProvider(localContext)) {
|
||||
hasLocalActionsForKeyBinding = true;
|
||||
if (isValidAndEnabled(actionData, localContext)) {
|
||||
list.add(new ExecutableKeyActionAdapter(actionData.action, localContext));
|
||||
list.add(new ExecutableAction(actionData.action, localContext));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasLocalActionsForKeyBinding) {
|
||||
// We have locals, ignore the globals. This prevents global actions from processing
|
||||
// the given keybinding when a local action exits, regardless of enablement.
|
||||
// We have locals, ignore the component specific. This prevents component actions
|
||||
// from processing the given keybinding when a local action exits, regardless of
|
||||
// enablement.
|
||||
return list;
|
||||
}
|
||||
|
||||
|
@ -189,7 +191,7 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
|
|||
if (componentAction.isValidComponentContext(localContext)) {
|
||||
hasLocalActionsForKeyBinding = true;
|
||||
if (isValidAndEnabled(actionData, localContext)) {
|
||||
list.add(new ExecutableKeyActionAdapter(actionData.action, localContext));
|
||||
list.add(new ExecutableAction(actionData.action, localContext));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -209,16 +211,28 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
|
|||
// is a 'global' action. This allows more specific context to be used when
|
||||
// available
|
||||
if (isValidAndEnabled(actionData, localContext)) {
|
||||
list.add(new ExecutableKeyActionAdapter(actionData.action, localContext));
|
||||
list.add(new ExecutableAction(actionData.action, localContext));
|
||||
}
|
||||
else if (isValidAndEnabledGlobally(actionData, globalContext)) {
|
||||
list.add(new ExecutableAction(actionData.action, globalContext));
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private boolean isValidAndEnabled(ActionData actionData, ActionContext localContext) {
|
||||
private boolean isValidAndEnabled(ActionData actionData, ActionContext context) {
|
||||
DockingActionIf a = actionData.action;
|
||||
return a.isValidContext(localContext) && a.isEnabledForContext(localContext);
|
||||
return a.isValidContext(context) && a.isEnabledForContext(context);
|
||||
}
|
||||
|
||||
private boolean isValidAndEnabledGlobally(ActionData actionData, ActionContext context) {
|
||||
// the context may be null when we don't want global action such as when getting actions
|
||||
// for a dialog
|
||||
if (context == null) {
|
||||
return false;
|
||||
}
|
||||
return actionData.supportsGlobalContext() && isValidAndEnabled(actionData, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -228,7 +242,7 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
|
|||
|
||||
@Override
|
||||
public KeyBindingPrecedence getKeyBindingPrecedence() {
|
||||
List<ExecutableKeyActionAdapter> validActions = getActionsForCurrentContext(null);
|
||||
List<ExecutableAction> validActions = getActionsForCurrentOrGlobalContext(null);
|
||||
if (validActions.isEmpty()) {
|
||||
return null; // a signal that no actions are valid for the current context
|
||||
}
|
||||
|
@ -237,16 +251,28 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
|
|||
return KeyBindingPrecedence.DefaultLevel;
|
||||
}
|
||||
|
||||
ExecutableKeyActionAdapter actionProxy = validActions.get(0);
|
||||
ExecutableAction actionProxy = validActions.get(0);
|
||||
DockingActionIf action = actionProxy.getAction();
|
||||
return action.getKeyBindingData().getKeyBindingPrecedence();
|
||||
}
|
||||
|
||||
private List<ExecutableKeyActionAdapter> getActionsForCurrentContext(Object eventSource) {
|
||||
private List<ExecutableAction> getActionsForCurrentOrGlobalContext(Object eventSource) {
|
||||
|
||||
DockingWindowManager dwm = tool.getWindowManager();
|
||||
Window window = dwm.getActiveWindow();
|
||||
if (window instanceof DockingDialog) {
|
||||
return getDialogActions(window);
|
||||
}
|
||||
|
||||
ComponentProvider localProvider = dwm.getActiveComponentProvider();
|
||||
ActionContext localContext = getLocalContext(localProvider);
|
||||
localContext.setSourceObject(eventSource);
|
||||
ActionContext globalContext = tool.getGlobalActionContext();
|
||||
List<ExecutableAction> validActions = getValidContextActions(localContext, globalContext);
|
||||
return validActions;
|
||||
}
|
||||
|
||||
private List<ExecutableAction> getDialogActions(Window window) {
|
||||
DockingDialog dockingDialog = (DockingDialog) window;
|
||||
DialogComponentProvider provider = dockingDialog.getDialogComponent();
|
||||
if (provider == null) {
|
||||
|
@ -254,14 +280,7 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
|
|||
return Collections.emptyList();
|
||||
}
|
||||
ActionContext context = provider.getActionContext(null);
|
||||
List<ExecutableKeyActionAdapter> validActions = getValidContextActions(context);
|
||||
return validActions;
|
||||
}
|
||||
|
||||
ComponentProvider localProvider = dwm.getActiveComponentProvider();
|
||||
ActionContext localContext = getLocalContext(localProvider);
|
||||
localContext.setSourceObject(eventSource);
|
||||
List<ExecutableKeyActionAdapter> validActions = getValidContextActions(localContext);
|
||||
List<ExecutableAction> validActions = getValidContextActions(context, null);
|
||||
return validActions;
|
||||
}
|
||||
|
||||
|
@ -309,10 +328,15 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
|
|||
return provider == otherProvider;
|
||||
}
|
||||
|
||||
boolean supportsGlobalContext() {
|
||||
return action.shouldFallbackToGlobalContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String providerString = provider == null ? "" : provider.toString() + " - ";
|
||||
return providerString + action;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ import resources.ResourceManager;
|
|||
* the {@link #withContext(Class)} call.
|
||||
*/
|
||||
public abstract class AbstractActionBuilder<T extends DockingActionIf, C extends ActionContext, B extends AbstractActionBuilder<T, C, B>> {
|
||||
|
||||
private final Predicate<C> TRUE_PREDICATE = e -> true;
|
||||
/**
|
||||
* Name for the {@code DockingAction}
|
||||
*/
|
||||
|
@ -171,6 +171,11 @@ public abstract class AbstractActionBuilder<T extends DockingActionIf, C extends
|
|||
*/
|
||||
private Predicate<C> validContextPredicate;
|
||||
|
||||
/**
|
||||
* Set to true if the action supports using the global context if the local context is invalid
|
||||
*/
|
||||
private boolean fallbackToGlobalContext;
|
||||
|
||||
/**
|
||||
* Builder constructor
|
||||
* @param name the name of the action to be built
|
||||
|
@ -501,6 +506,7 @@ public abstract class AbstractActionBuilder<T extends DockingActionIf, C extends
|
|||
*/
|
||||
public B onAction(Consumer<C> action) {
|
||||
actionCallback = action;
|
||||
// actionCallback = adaptActionConsumer(action);
|
||||
return self();
|
||||
}
|
||||
|
||||
|
@ -560,6 +566,11 @@ public abstract class AbstractActionBuilder<T extends DockingActionIf, C extends
|
|||
return self();
|
||||
}
|
||||
|
||||
public B fallbackToGlobalContext(boolean b) {
|
||||
fallbackToGlobalContext = b;
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the specific ActionContext type to use for the various predicate calls
|
||||
* ({@link #validContextWhen(Predicate)}, {@link #enabledWhen(Predicate)}, and
|
||||
|
@ -613,6 +624,11 @@ public abstract class AbstractActionBuilder<T extends DockingActionIf, C extends
|
|||
|
||||
actionContextClass = newActionContextClass;
|
||||
|
||||
// reset the predicates when changing the action context type
|
||||
validContextWhen(TRUE_PREDICATE);
|
||||
enabledWhen(TRUE_PREDICATE);
|
||||
popupWhen(TRUE_PREDICATE);
|
||||
|
||||
B2 newSelf = (B2) self();
|
||||
return newSelf;
|
||||
}
|
||||
|
@ -627,6 +643,7 @@ public abstract class AbstractActionBuilder<T extends DockingActionIf, C extends
|
|||
protected void decorateAction(DockingAction action) {
|
||||
action.setEnabled(isEnabled);
|
||||
action.setDescription(description);
|
||||
action.setFallbackToGlobalContext(fallbackToGlobalContext);
|
||||
|
||||
setMenuData(action);
|
||||
setToolbarData(action);
|
||||
|
@ -668,6 +685,17 @@ public abstract class AbstractActionBuilder<T extends DockingActionIf, C extends
|
|||
return predicateAdapter;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Consumer<ActionContext> adaptActionConsumer(Consumer<C> consumer) {
|
||||
if (actionContextClass == ActionContext.class) {
|
||||
return (Consumer<ActionContext>) consumer;
|
||||
}
|
||||
Consumer<ActionContext> consumerAdapter = (ac) -> {
|
||||
consumer.accept((C) ac);
|
||||
};
|
||||
return consumerAdapter;
|
||||
}
|
||||
|
||||
protected boolean isPopupAction() {
|
||||
return popupPath != null;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
package docking.action.builder;
|
||||
|
||||
import docking.ActionContext;
|
||||
import docking.action.DockingAction;
|
||||
|
||||
|
|
|
@ -149,9 +149,14 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
|||
private ActionContext getActionContext() {
|
||||
DockingWindowManager manager = DockingWindowManager.getActiveInstance();
|
||||
ComponentProvider provider = manager.getActiveComponentProvider();
|
||||
ActionContext localContext = provider == null ? null : provider.getActionContext(null);
|
||||
ActionContext actionContext = localContext == null ? new ActionContext() : localContext;
|
||||
return actionContext;
|
||||
ActionContext context = provider == null ? null : provider.getActionContext(null);
|
||||
if (context == null && shouldFallbackToGlobalContext()) {
|
||||
context = manager.getGlobalActionContext();
|
||||
}
|
||||
if (context == null) {
|
||||
context = new ActionContext();
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
protected List<DockingActionIf> getStateActions() {
|
||||
|
|
|
@ -113,9 +113,10 @@ public class ToolBarItemManager implements PropertyChangeListener, ActionListene
|
|||
@Override
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
DockingWindowManager.clearMouseOverHelp();
|
||||
ActionContext context = getActionContext();
|
||||
ActionContext context = getValidActionContext();
|
||||
|
||||
if (!toolBarAction.isValidContext(context)) {
|
||||
// no valid context?
|
||||
if (context == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -139,7 +140,22 @@ public class ToolBarItemManager implements PropertyChangeListener, ActionListene
|
|||
return toolBarAction.getName();
|
||||
}
|
||||
|
||||
private ActionContext getActionContext() {
|
||||
private ActionContext getValidActionContext() {
|
||||
ActionContext context = getLocalActionContext();
|
||||
if (toolBarAction.isValidContext(context)) {
|
||||
return context;
|
||||
}
|
||||
|
||||
if (toolBarAction.shouldFallbackToGlobalContext()) {
|
||||
context = windowManager.getGlobalActionContext();
|
||||
if (toolBarAction.isValidContext(context)) {
|
||||
return context;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private ActionContext getLocalActionContext() {
|
||||
ComponentProvider provider = getComponentProvider();
|
||||
ActionContext context = provider == null ? null : provider.getActionContext(null);
|
||||
final ActionContext actionContext =
|
||||
|
|
|
@ -95,10 +95,11 @@ class DataComponent extends DataDB {
|
|||
}
|
||||
DataType pdt = parent.getBaseDataType();
|
||||
if (pdt instanceof Composite) {
|
||||
DataTypeComponent c = ((Composite) pdt).getComponent(indexInParent);
|
||||
if (c == null) {
|
||||
Composite composite = (Composite) pdt;
|
||||
if (indexInParent >= composite.getNumComponents()) {
|
||||
return true;
|
||||
}
|
||||
DataTypeComponent c = composite.getComponent(indexInParent);
|
||||
component = c;
|
||||
dataType = c.getDataType();
|
||||
offset = component.getOffset();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue