mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
GT-3485 Removed Secondary "default" action context to prevent actions
from triggering unexpectedly
This commit is contained in:
parent
db7803144a
commit
26d7d0da5f
33 changed files with 128 additions and 288 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
//==================================================================================================
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -152,11 +152,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
|
||||
|
@ -517,22 +512,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(
|
||||
|
@ -558,9 +537,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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue