Merge branch 'GT-3485_ghidravore_action_context'

Conflicts:
	Ghidra/Framework/Docking/src/main/java/docking/action/builder/AbstractActionBuilder.java
This commit is contained in:
ghidravore 2020-01-24 17:28:47 -05:00
commit 5dc7df71b3
33 changed files with 128 additions and 289 deletions

View file

@ -17,9 +17,11 @@ package ghidra.app.context;
import java.util.Set;
import docking.ActionContext;
import docking.*;
import docking.action.DockingAction;
import docking.action.KeyBindingType;
import ghidra.app.nav.Navigatable;
import ghidra.app.services.GoToService;
public abstract class NavigatableContextAction extends DockingAction {
@ -33,23 +35,61 @@ public abstract class NavigatableContextAction extends DockingAction {
@Override
public boolean isEnabledForContext(ActionContext context) {
if (!(context instanceof NavigatableActionContext)) {
NavigatableActionContext appropriateContext = getAppropriateContext(context);
if (appropriateContext == null) {
return false;
}
return isEnabledForContext((NavigatableActionContext) context);
return isEnabledForContext(appropriateContext);
}
@Override
public void actionPerformed(ActionContext context) {
actionPerformed((NavigatableActionContext) context);
actionPerformed(getAppropriateContext(context));
}
private NavigatableActionContext getAppropriateContext(ActionContext context) {
if (context instanceof NavigatableActionContext &&
isValidNavigationContext((NavigatableActionContext) context)) {
return (NavigatableActionContext) context;
}
return getGlobalNavigationContext(context);
}
@Override
public boolean isValidContext(ActionContext context) {
if (!(context instanceof NavigatableActionContext)) {
return false;
public final boolean isValidContext(ActionContext context) {
return true;
}
protected boolean isValidNavigationContext(NavigatableActionContext context) {
return true;
}
private NavigatableActionContext getGlobalNavigationContext(ActionContext context) {
DockingTool tool = getTool(context.getComponentProvider());
if (tool == null) {
return null;
}
return isValidContext((NavigatableActionContext) context);
GoToService service = tool.getService(GoToService.class);
if (service == null) {
return null;
}
Navigatable defaultNavigatable = service.getDefaultNavigatable();
if (defaultNavigatable.getProgram() == null) {
return null;
}
return new NavigatableActionContext(null, defaultNavigatable);
}
private DockingTool getTool(ComponentProvider provider) {
if (provider != null) {
return provider.getTool();
}
DockingWindowManager manager = DockingWindowManager.getActiveInstance();
if (manager != null) {
return manager.getTool();
}
return null;
}
@Override
@ -60,10 +100,6 @@ public abstract class NavigatableContextAction extends DockingAction {
return isAddToPopup((NavigatableActionContext) context);
}
protected boolean isValidContext(NavigatableActionContext context) {
return true;
}
protected boolean isEnabledForContext(NavigatableActionContext context) {
return true;
}

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,6 +15,8 @@
*/
package ghidra.app.nav;
import java.util.Set;
import ghidra.app.context.*;
import ghidra.app.plugin.core.navigation.NavigationOptions;
import ghidra.app.services.GoToService;
@ -24,8 +25,6 @@ import ghidra.program.model.address.*;
import ghidra.program.model.listing.CodeUnit;
import ghidra.program.util.ProgramSelection;
import java.util.Set;
public abstract class NextRangeAction extends NavigatableContextAction {
private PluginTool tool;
@ -39,7 +38,7 @@ public abstract class NextRangeAction extends NavigatableContextAction {
}
@Override
protected boolean isValidContext(NavigatableActionContext context) {
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
@ -51,13 +50,12 @@ public abstract class NextRangeAction extends NavigatableContextAction {
@Override
public boolean isEnabledForContext(NavigatableActionContext context) {
Address currentAddress = context.getAddress();
ListingActionContext listingContext = (ListingActionContext) context;
ProgramSelection selection = getSelection(listingContext);
ProgramSelection selection = getSelection(context);
if (selection == null || selection.isEmpty() || currentAddress == null) {
return false;
}
CodeUnit cu = listingContext.getProgram().getListing().getCodeUnitAt(currentAddress);
CodeUnit cu = context.getProgram().getListing().getCodeUnitAt(currentAddress);
if (cu != null) {
currentAddress = cu.getMaxAddress();
}
@ -71,13 +69,10 @@ public abstract class NextRangeAction extends NavigatableContextAction {
@Override
public void actionPerformed(NavigatableActionContext context) {
// Note: we verified above that the context we are grabbing here is the correct type
ListingActionContext listingContext = (ListingActionContext) context;
Address goToAddress = getGoToAddress(listingContext);
Address goToAddress = getGoToAddress(context);
GoToService service = tool.getService(GoToService.class);
if (service != null) {
service.goTo(listingContext.getNavigatable(), goToAddress);
service.goTo(context.getNavigatable(), goToAddress);
}
}

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,6 +15,8 @@
*/
package ghidra.app.nav;
import java.util.Set;
import ghidra.app.context.*;
import ghidra.app.plugin.core.navigation.NavigationOptions;
import ghidra.app.services.GoToService;
@ -23,8 +24,6 @@ import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.*;
import ghidra.program.util.ProgramSelection;
import java.util.Set;
public abstract class PreviousRangeAction extends NavigatableContextAction {
private PluginTool tool;
@ -39,7 +38,7 @@ public abstract class PreviousRangeAction extends NavigatableContextAction {
}
@Override
protected boolean isValidContext(NavigatableActionContext context) {
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
@ -58,9 +57,8 @@ public abstract class PreviousRangeAction extends NavigatableContextAction {
}
private Address getGoToAddress(NavigatableActionContext context) {
ListingActionContext listingContext = (ListingActionContext) context;
ProgramSelection selection = getSelection(listingContext);
Address currentAddress = listingContext.getAddress();
ProgramSelection selection = getSelection(context);
Address currentAddress = context.getAddress();
AddressRangeIterator it = selection.getAddressRanges(currentAddress, false);
if (!it.hasNext()) {
@ -94,8 +92,7 @@ public abstract class PreviousRangeAction extends NavigatableContextAction {
@Override
public boolean isEnabledForContext(NavigatableActionContext context) {
Address currentAddress = context.getAddress();
ListingActionContext listingContext = (ListingActionContext) context;
ProgramSelection selection = getSelection(listingContext);
ProgramSelection selection = getSelection(context);
if (selection == null || selection.isEmpty() || currentAddress == null) {
return false;
}

View file

@ -26,7 +26,7 @@ import ghidra.app.context.ListingContextAction;
import ghidra.app.plugin.PluginCategoryNames;
import ghidra.framework.cmd.Command;
import ghidra.framework.plugintool.*;
import ghidra.framework.plugintool.util.*;
import ghidra.framework.plugintool.util.PluginStatus;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSet;
import ghidra.program.model.data.*;
@ -264,12 +264,6 @@ public class ClearPlugin extends Plugin {
}
return false;
}
@Override
public boolean isValidGlobalContext(ActionContext context) {
// it's too dangerous to let the clear action work globally
return false;
}
};
int menuOrdinal = 1;

View file

@ -17,7 +17,6 @@ package ghidra.app.plugin.core.comments;
import java.awt.event.KeyEvent;
import docking.ActionContext;
import docking.action.*;
import ghidra.app.CorePluginPackage;
import ghidra.app.cmd.comments.SetCommentCmd;
@ -187,11 +186,6 @@ public class CommentsPlugin extends Plugin implements OptionsChangeListener {
getPopupMenuData().setMenuPath(new String[] { "Comments", "Delete" });
return false;
}
@Override
public boolean isValidGlobalContext(ActionContext globalContext) {
return false; // only work on active provider context.
}
};
deleteAction.setPopupMenuData(new MenuData(DELETE_MENUPATH, null, "comments"));
deleteAction.setKeyBindingData(new KeyBindingData(KeyEvent.VK_DELETE, 0));

View file

@ -19,7 +19,6 @@ import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import docking.ActionContext;
import docking.action.*;
import docking.widgets.OptionDialog;
import ghidra.app.CorePluginPackage;
@ -374,8 +373,8 @@ public class EquatePlugin extends Plugin {
Program program = context.getProgram();
List<Integer> opIndices = getInstructionMatches(program, inst, equate);
Address addr = inst.getAddress();
for (int i = 0; i < opIndices.size(); i++) {
bgCmd.add(createRenameCmd(oldName, newName, addr, opIndices.get(i)));
for (Integer opIndice : opIndices) {
bgCmd.add(createRenameCmd(oldName, newName, addr, opIndice));
}
}
else if (cu instanceof Data) {
@ -429,9 +428,9 @@ public class EquatePlugin extends Plugin {
Program program = context.getProgram();
List<Integer> opIndexes = getInstructionMatches(program, instr, equate);
for (int i = 0; i < opIndexes.size(); i++) {
for (Integer opIndexe : opIndexes) {
bckCmd.add(
new ClearEquateCmd(equate.getName(), instr.getAddress(), opIndexes.get(i)));
new ClearEquateCmd(equate.getName(), instr.getAddress(), opIndexe));
}
}
else if (cu instanceof Data) {
@ -728,12 +727,6 @@ public class EquatePlugin extends Plugin {
protected boolean isEnabledForContext(ListingActionContext context) {
return getEquate(context) != null;
}
@Override
public boolean isValidGlobalContext(ActionContext globalContext) {
return false; // only work on active provider context.
}
};
removeAction.setPopupMenuData(new MenuData(REMOVE_MENUPATH, null, GROUP_NAME));
removeAction.setKeyBindingData(new KeyBindingData(KeyEvent.VK_DELETE, 0));

View file

@ -17,7 +17,6 @@ package ghidra.app.plugin.core.function;
import java.awt.event.KeyEvent;
import docking.ActionContext;
import docking.action.KeyBindingData;
import docking.action.MenuData;
import ghidra.app.cmd.function.DeleteFunctionCmd;
@ -71,9 +70,4 @@ class DeleteFunctionAction extends ListingContextAction {
return false;
}
@Override
public boolean isValidGlobalContext(ActionContext globalContext) {
return false; // only work on active provider context.
}
}

View file

@ -17,7 +17,6 @@ package ghidra.app.plugin.core.function;
import java.awt.event.KeyEvent;
import docking.ActionContext;
import docking.action.KeyBindingData;
import docking.action.MenuData;
import ghidra.app.cmd.function.CallDepthChangeInfo;
@ -73,9 +72,4 @@ class RemoveStackDepthChangeAction extends ListingContextAction {
context.getAddress()) != null;
}
@Override
public boolean isValidGlobalContext(ActionContext globalContext) {
return false; // only work on active provider context.
}
}

View file

@ -17,7 +17,6 @@ package ghidra.app.plugin.core.function;
import java.awt.event.KeyEvent;
import docking.ActionContext;
import docking.action.KeyBindingData;
import docking.action.KeyBindingType;
import ghidra.app.cmd.function.SetVariableCommentCmd;
@ -89,8 +88,4 @@ class VariableCommentDeleteAction extends ListingContextAction {
return (loc instanceof VariableCommentFieldLocation);
}
@Override
public boolean isValidGlobalContext(ActionContext globalContext) {
return false; // only work on active provider context.
}
}

View file

@ -17,7 +17,6 @@ package ghidra.app.plugin.core.function;
import java.awt.event.KeyEvent;
import docking.ActionContext;
import docking.action.KeyBindingData;
import docking.action.MenuData;
import ghidra.app.cmd.function.DeleteVariableCmd;
@ -105,9 +104,4 @@ class VariableDeleteAction extends ListingContextAction {
}
return null;
}
@Override
public boolean isValidGlobalContext(ActionContext globalContext) {
return false; // only work on active provider context.
}
}

View file

@ -60,7 +60,7 @@ public final class GoToServicePlugin extends ProgramPlugin {
* Creates a new instance of the <CODE>GoToServicePlugin</CODE>
*/
public GoToServicePlugin(PluginTool plugintool) {
super(plugintool, true, false);
super(plugintool, true, true);
gotoService = new GoToServiceImpl(this, new DefaultNavigatable());

View file

@ -245,7 +245,7 @@ public class InstructionSearchPlugin extends ProgramPlugin {
}
@Override
protected boolean isValidContext(NavigatableActionContext context) {
protected boolean isValidNavigationContext(NavigatableActionContext context) {
return !(context instanceof RestrictedAddressSetContext);
}
};

View file

@ -19,7 +19,6 @@ import java.awt.event.KeyEvent;
import javax.swing.KeyStroke;
import docking.ActionContext;
import docking.action.*;
import ghidra.app.context.ListingActionContext;
import ghidra.app.context.ListingContextAction;
@ -66,11 +65,6 @@ class RemoveLabelAction extends ListingContextAction {
return !plugin.isOnExternalReference(context) && isOnSymbol(context);
}
@Override
public boolean isValidGlobalContext(ActionContext globalContext) {
return false; // only work on active provider context.
}
boolean isOnSymbol(ListingActionContext context) {
Symbol s = plugin.getSymbol(context);
return ((s instanceof CodeSymbol) && !s.isDynamic()) ||

View file

@ -316,16 +316,6 @@ public class NextPrevAddressPlugin extends Plugin {
setDescription(isNext ? "Go to next location" : "Go to previous location");
}
@Override
public boolean isValidContext(ActionContext context) {
return false;
}
@Override
public boolean isValidGlobalContext(ActionContext globalContext) {
return (globalContext instanceof NavigatableActionContext);
}
@Override
public boolean isEnabledForContext(ActionContext context) {
Navigatable navigatable = getNavigatable(context);
@ -426,16 +416,6 @@ public class NextPrevAddressPlugin extends Plugin {
setMenuBarData(menuData);
}
@Override
public boolean isValidContext(ActionContext context) {
return false;
}
@Override
public boolean isValidGlobalContext(ActionContext globalContext) {
return (globalContext instanceof NavigatableActionContext);
}
@Override
public boolean isEnabledForContext(ActionContext context) {
Navigatable navigatable = getNavigatable(context);

View file

@ -17,7 +17,6 @@ package ghidra.app.plugin.core.references;
import java.awt.event.KeyEvent;
import docking.ActionContext;
import docking.action.KeyBindingData;
import docking.action.MenuData;
import ghidra.app.cmd.refs.RemoveAllReferencesCmd;
@ -116,10 +115,4 @@ public class DeleteReferencesAction extends ListingContextAction {
}
return actionOK;
}
@Override
public boolean isValidGlobalContext(ActionContext globalContext) {
return false; // only work on active provider context.
}
}

View file

@ -167,11 +167,6 @@ public class RegisterPlugin extends ProgramPlugin {
}
return false;
}
@Override
public boolean isValidGlobalContext(ActionContext globalContext) {
return false; // only work on active provider context.
}
};
deleteRegisterRangeAction.setKeyBindingData(new KeyBindingData(KeyEvent.VK_DELETE, 0));

View file

@ -145,7 +145,7 @@ public class ScalarSearchPlugin extends ProgramPlugin implements DomainObjectLis
}
@Override
protected boolean isValidContext(NavigatableActionContext context) {
protected boolean isValidNavigationContext(NavigatableActionContext context) {
return !(context instanceof RestrictedAddressSetContext);
}
};

View file

@ -350,7 +350,7 @@ public class MemSearchPlugin extends Plugin implements OptionsChangeListener,
}
@Override
protected boolean isValidContext(NavigatableActionContext context) {
protected boolean isValidNavigationContext(NavigatableActionContext context) {
return !(context instanceof RestrictedAddressSetContext);
}
};
@ -374,7 +374,7 @@ public class MemSearchPlugin extends Plugin implements OptionsChangeListener,
}
@Override
protected boolean isValidContext(NavigatableActionContext context) {
protected boolean isValidNavigationContext(NavigatableActionContext context) {
return !(context instanceof RestrictedAddressSetContext);
}
};

View file

@ -209,11 +209,6 @@ public abstract class AbstractDockingTool implements DockingTool {
winMgr.contextChanged(provider);
}
@Override
public ActionContext getGlobalContext() {
return winMgr.getGlobalContext();
}
@Override
public void addContextListener(DockingContextListener listener) {
winMgr.addContextListener(listener);

View file

@ -117,11 +117,6 @@ public class DockingActionProxy
return dockingAction.isValidContext(context);
}
@Override
public boolean isValidGlobalContext(ActionContext context) {
return dockingAction.isValidGlobalContext(context);
}
@Override
public void removePropertyChangeListener(PropertyChangeListener listener) {
propertyListeners.remove(listener);

View file

@ -24,12 +24,13 @@ import docking.action.DockingActionIf;
import docking.actions.DockingToolActions;
import docking.actions.PopupActionProvider;
import ghidra.framework.options.ToolOptions;
import ghidra.framework.plugintool.ServiceProvider;
/**
* Generic tool interface for managing {@link ComponentProvider}s and
* {@link DockingActionIf actions}
*/
public interface DockingTool {
public interface DockingTool extends ServiceProvider {
/**
* Returns a combination of the tool name and the instance name of the form
@ -247,15 +248,6 @@ public interface DockingTool {
*/
public void contextChanged(ComponentProvider provider);
/**
* Returns this tool's notion of the current action context, which is based upon the active
* {@link ComponentProvider}. If there is not active provider, then a generic context will
* be returned.
*
* @return the context
*/
public ActionContext getGlobalContext();
/**
* Adds the given context listener to this tool
* @param listener the listener to add

View file

@ -353,23 +353,6 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
defaultProvider = provider;
}
/**
* Returns this tool's notion of the current action context, which is based upon the active
* {@link ComponentProvider}. If there is not active provider, then a generic context will
* be returned.
*
* @return the context
*/
public ActionContext getGlobalContext() {
if (defaultProvider != null) {
ActionContext actionContext = defaultProvider.getActionContext(null);
if (actionContext != null) {
return actionContext;
}
}
return new ActionContext();
}
/**
* Get the window which contains the specified Provider's component.
* @param provider component provider

View file

@ -47,36 +47,20 @@ public class MenuBarMenuHandler extends MenuHandler {
DockingWindowManager.clearMouseOverHelp();
ComponentProvider provider = windowManager.getActiveComponentProvider();
ActionContext context = provider == null ? null : provider.getActionContext(null);
ActionContext localContext = context == null ? new ActionContext() : context;
ActionContext globalContext = windowManager.getGlobalContext();
ActionContext providerContext = provider == null ? null : provider.getActionContext(null);
ActionContext context = providerContext == null ? new ActionContext() : providerContext;
ActionContext tempContext = null;
if (action.isValidContext(localContext)) {
tempContext = localContext; // we prefer the local over the global context if valid
}
else if (action.isValidGlobalContext(globalContext)) {
tempContext = globalContext;
}
else {
return; // context is not valid, nothing to do
}
tempContext.setSourceObject(event.getSource());
final ActionContext finalContext = tempContext;
context.setSourceObject(event.getSource());
// this gives the UI some time to repaint before executing the action
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
windowManager.setStatusText("");
if (action.isEnabledForContext(finalContext)) {
if (action instanceof ToggleDockingActionIf) {
ToggleDockingActionIf toggleAction = ((ToggleDockingActionIf) action);
toggleAction.setSelected(!toggleAction.isSelected());
}
action.actionPerformed(finalContext);
SwingUtilities.invokeLater(() -> {
windowManager.setStatusText("");
if (action.isValidContext(context) && action.isEnabledForContext(context)) {
if (action instanceof ToggleDockingActionIf) {
ToggleDockingActionIf toggleAction = ((ToggleDockingActionIf) action);
toggleAction.setSelected(!toggleAction.isSelected());
}
action.actionPerformed(context);
}
});
}

View file

@ -121,7 +121,6 @@ public class WindowActionManager {
ComponentProvider provider = placeHolderForScheduledActionUpdate == null ? null
: placeHolderForScheduledActionUpdate.getProvider();
ActionContext localContext = provider == null ? null : provider.getActionContext(null);
ActionContext globalContext = winMgr.getGlobalContext();
if (localContext == null) {
localContext = new ActionContext();
}
@ -132,9 +131,6 @@ public class WindowActionManager {
if (action.isValidContext(localContext)) {
action.setEnabled(action.isEnabledForContext(localContext));
}
else if (action.isValidGlobalContext(globalContext)) {
action.setEnabled(action.isEnabledForContext(globalContext));
}
else {
action.setEnabled(false);
}

View file

@ -76,7 +76,6 @@ public abstract class DockingAction implements DockingActionIf {
private Predicate<ActionContext> enabledPredicate;
private Predicate<ActionContext> popupPredicate;
private Predicate<ActionContext> validContextPredicate;
private Predicate<ActionContext> validGlobalContextPredicate;
public DockingAction(String name, String owner) {
this.name = name;
@ -184,14 +183,6 @@ public abstract class DockingAction implements DockingActionIf {
return true;
}
@Override
public boolean isValidGlobalContext(ActionContext globalContext) {
if (validGlobalContextPredicate != null) {
return validGlobalContextPredicate.test(globalContext);
}
return isValidContext(globalContext);
}
/**
* Default behavior is to add to main window;
*/
@ -572,17 +563,6 @@ public abstract class DockingAction implements DockingActionIf {
validContextPredicate = predicate;
}
/**
* Sets a predicate for dynamically determining if this action is valid for the current global
* {@link ActionContext}. See {@link DockingActionIf#isValidGlobalContext(ActionContext)}
*
* @param predicate the predicate that will be used to dynamically determine an action's
* validity for a given global {@link ActionContext}
*/
public void validGlobalContextWhen(Predicate<ActionContext> predicate) {
validGlobalContextPredicate = predicate;
}
//==================================================================================================
// Non-public methods
//==================================================================================================

View file

@ -193,19 +193,6 @@ public interface DockingActionIf extends HelpDescriptor {
*/
public boolean isValidContext(ActionContext context);
/**
* Method that actions implement to indicate if this action is valid (knows how to work with, is
* appropriate for) for the given global context. This method is just like the isValidContext
* and in fact calls that method by default. Many actions will work with either the active
* provider context or the global (the main listing) context if the local context is not valid.
* If you want a global action to only work on the global context, then override this method
* and return false.
*
* @param globalContext the global {@link ActionContext} from the active provider.
* @return true if this action is appropriate for the given context.
*/
public boolean isValidGlobalContext(ActionContext globalContext);
/**
* Method used to determine if this action should be enabled for the given context.
* <p>

View file

@ -121,8 +121,7 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
ActionContext localContext = getLocalContext(localProvider);
localContext.setSourceObject(event.getSource());
ActionContext globalContext = tool.getGlobalContext();
List<ExecutableKeyActionAdapter> list = getValidContextActions(localContext, globalContext);
List<ExecutableKeyActionAdapter> list = getValidContextActions(localContext);
// If menu active, disable all key bindings
if (ignoreActionWhileMenuShowing()) {
@ -164,8 +163,7 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
return menuManager.getSelectedPath().length != 0;
}
private List<ExecutableKeyActionAdapter> getValidContextActions(ActionContext localContext,
ActionContext globalContext) {
private List<ExecutableKeyActionAdapter> getValidContextActions(ActionContext localContext) {
List<ExecutableKeyActionAdapter> list = new ArrayList<>();
boolean hasLocalActionsForKeyBinding = false;
@ -222,9 +220,6 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
if (isValidAndEnabled(actionData, localContext)) {
list.add(new ExecutableKeyActionAdapter(actionData.action, localContext));
}
else if (isValidAndEnabledGlobally(actionData, globalContext)) {
list.add(new ExecutableKeyActionAdapter(actionData.action, globalContext));
}
}
}
return list;
@ -235,11 +230,6 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
return a.isValidContext(localContext) && a.isEnabledForContext(localContext);
}
private boolean isValidAndEnabledGlobally(ActionData actionData, ActionContext globalContext) {
DockingActionIf a = actionData.action;
return a.isValidGlobalContext(globalContext) && a.isEnabledForContext(globalContext);
}
@Override
public boolean isReservedKeybindingPrecedence() {
return false; // MultipleKeyActions can never be reserved
@ -249,9 +239,7 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
public KeyBindingPrecedence getKeyBindingPrecedence() {
ComponentProvider localProvider = tool.getActiveComponentProvider();
ActionContext localContext = getLocalContext(localProvider);
ActionContext globalContext = tool.getGlobalContext();
List<ExecutableKeyActionAdapter> validActions =
getValidContextActions(localContext, globalContext);
List<ExecutableKeyActionAdapter> validActions = getValidContextActions(localContext);
if (validActions.isEmpty()) {
return null; // a signal that no actions are valid for the current context

View file

@ -159,12 +159,6 @@ public abstract class AbstractActionBuilder<T extends DockingActionIf, B extends
*/
private Predicate<ActionContext> validContextPredicate;
/**
* Predicate for determining if an action is applicable for a given global context
*/
private Predicate<ActionContext> validGlobalContextPredicate;
/**
* Builder constructor
* @param name the name of the action to be built
@ -551,22 +545,6 @@ public abstract class AbstractActionBuilder<T extends DockingActionIf, B extends
return self();
}
/**
* Sets a predicate for dynamically determining if this action is valid for the current global
* {@link ActionContext}. See {@link DockingActionIf#isValidGlobalContext(ActionContext)}.
*
* <p>Note: most actions will not use this method, but rely instead on
* {@link #enabledWhen(Predicate)}.
*
* @param predicate the predicate that will be used to dynamically determine an action's
* validity for a given global {@link ActionContext}
* @return this builder (for chaining)
*/
public B validGlobalContextWhen(Predicate<ActionContext> predicate) {
validGlobalContextPredicate = predicate;
return self();
}
protected void validate() {
if (actionCallback == null) {
throw new IllegalStateException(
@ -593,9 +571,6 @@ public abstract class AbstractActionBuilder<T extends DockingActionIf, B extends
if (validContextPredicate != null) {
action.validContextWhen(validContextPredicate);
}
if (validGlobalContextPredicate != null) {
action.validGlobalContextWhen(validGlobalContextPredicate);
}
if (popupPredicate != null) {
action.popupWhen(enabledPredicate);
}

View file

@ -150,8 +150,7 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
DockingWindowManager manager = DockingWindowManager.getActiveInstance();
ComponentProvider provider = manager.getActiveComponentProvider();
ActionContext localContext = provider == null ? null : provider.getActionContext(null);
final ActionContext actionContext =
localContext == null ? manager.getGlobalContext() : localContext;
ActionContext actionContext = localContext == null ? new ActionContext() : localContext;
return actionContext;
}

View file

@ -189,33 +189,23 @@ public class ToolBarItemManager implements PropertyChangeListener, ActionListene
@Override
public void actionPerformed(ActionEvent event) {
DockingWindowManager.clearMouseOverHelp();
ActionContext localContext = getActionContext();
ActionContext globalContext = null;
if (windowManager != null) {
globalContext = windowManager.getGlobalContext();
ActionContext context = getActionContext();
if (!toolBarAction.isValidContext(context)) {
return;
}
ActionContext tempContext = null;
if (toolBarAction.isValidContext(localContext)) {
tempContext = localContext; // we prefer the local over the global context if valid
}
else if (toolBarAction.isValidGlobalContext(globalContext)) {
tempContext = globalContext;
}
else {
return; // context is not valid, nothing to do
}
tempContext.setSourceObject(event.getSource());
final ActionContext finalContext = tempContext;
context.setSourceObject(event.getSource());
// this gives the UI some time to repaint before executing the action
SwingUtilities.invokeLater(() -> {
if (toolBarAction.isEnabledForContext(finalContext)) {
if (toolBarAction.isValidContext(context) &&
toolBarAction.isEnabledForContext(context)) {
if (toolBarAction instanceof ToggleDockingActionIf) {
ToggleDockingActionIf toggleAction = (ToggleDockingActionIf) toolBarAction;
toggleAction.setSelected(!toggleAction.isSelected());
}
toolBarAction.actionPerformed(finalContext);
toolBarAction.actionPerformed(context);
}
});
}

View file

@ -23,6 +23,7 @@ import javax.swing.ImageIcon;
import docking.actions.ToolActions;
import docking.framework.ApplicationInformationDisplayFactory;
import ghidra.framework.options.ToolOptions;
import ghidra.framework.plugintool.util.ServiceListener;
/**
* A Test Double of the {@link DockingTool} that provides minimal tool functionality, such
@ -62,4 +63,19 @@ public class FakeDockingTool extends AbstractDockingTool {
public void close() {
// stub
}
@Override
public <T> T getService(Class<T> serviceClass) {
return null;
}
@Override
public void addServiceListener(ServiceListener listener) {
// stub
}
@Override
public void removeServiceListener(ServiceListener listener) {
// stub
}
}

View file

@ -73,7 +73,7 @@ import ghidra.util.task.*;
* <p>The PluginTool also manages tasks that run in the background, and options used by the plugins.
*
*/
public abstract class PluginTool extends AbstractDockingTool implements Tool, ServiceProvider {
public abstract class PluginTool extends AbstractDockingTool implements Tool {
private static final String DOCKING_WINDOWS_ON_TOP = "Docking Windows On Top";

View file

@ -34,6 +34,7 @@ import docking.util.image.ToolIconURL;
import ghidra.framework.model.*;
import ghidra.framework.options.ToolOptions;
import ghidra.framework.plugintool.PluginEvent;
import ghidra.framework.plugintool.util.ServiceListener;
import ghidra.program.model.listing.Program;
public class DummyTool implements Tool {
@ -369,11 +370,6 @@ public class DummyTool implements Tool {
//do nothing
}
@Override
public ActionContext getGlobalContext() {
return null;
}
@Override
public void setStatusInfo(String text) {
//do nothing
@ -423,4 +419,19 @@ public class DummyTool implements Tool {
public DockingToolActions getToolActions() {
return toolActions;
}
@Override
public <T> T getService(Class<T> serviceClass) {
return null;
}
@Override
public void addServiceListener(ServiceListener listener) {
//do nothing
}
@Override
public void removeServiceListener(ServiceListener listener) {
//do nothing
}
}