Merge branch 'GT-3485-ghidravore_action_context'

This commit is contained in:
ghidravore 2020-01-31 15:29:45 -05:00
commit 16f050f901
7 changed files with 112 additions and 78 deletions

View File

@ -17,11 +17,9 @@ package ghidra.app.context;
import java.util.Set;
import docking.*;
import docking.ActionContext;
import docking.action.DockingAction;
import docking.action.KeyBindingType;
import ghidra.app.nav.Navigatable;
import ghidra.app.services.GoToService;
public abstract class NavigatableContextAction extends DockingAction {
@ -52,7 +50,11 @@ public abstract class NavigatableContextAction extends DockingAction {
isValidNavigationContext((NavigatableActionContext) context)) {
return (NavigatableActionContext) context;
}
return getGlobalNavigationContext(context);
ActionContext globalContext = context.getGlobalContext();
if (globalContext instanceof NavigatableActionContext) {
return (NavigatableActionContext) globalContext;
}
return null;
}
@Override
@ -64,34 +66,6 @@ public abstract class NavigatableContextAction extends DockingAction {
return true;
}
private NavigatableActionContext getGlobalNavigationContext(ActionContext context) {
Tool tool = getTool(context.getComponentProvider());
if (tool == null) {
return null;
}
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 Tool getTool(ComponentProvider provider) {
if (provider != null) {
return provider.getTool();
}
DockingWindowManager manager = DockingWindowManager.getActiveInstance();
if (manager != null) {
return manager.getTool();
}
return null;
}
@Override
public boolean isAddToPopup(ActionContext context) {
if (!(context instanceof NavigatableActionContext)) {

View File

@ -21,12 +21,13 @@ import javax.swing.SwingUtilities;
import docking.ActionContext;
import docking.DockingWindowManager;
import docking.action.*;
import docking.action.DockingAction;
import docking.action.MenuData;
import docking.action.builder.ActionBuilder;
import docking.widgets.dialogs.MultiLineMessageDialog;
import ghidra.GhidraOptions;
import ghidra.app.CorePluginPackage;
import ghidra.app.context.ListingActionContext;
import ghidra.app.context.ListingContextAction;
import ghidra.app.events.*;
import ghidra.app.plugin.PluginCategoryNames;
import ghidra.app.services.Analyzer;
@ -107,53 +108,57 @@ public class AutoAnalysisPlugin extends Plugin implements AutoAnalysisManagerLis
// use this index to make sure that the following actions are ordered in the way that
// they are inserted
int subGroupIndex = 0;
autoAnalyzeAction = new ActionBuilder("Auto Analyze", getName())
.menuPath("&Analysis", "&Auto Analyze...")
.menuGroup(ANALYZE_GROUP_NAME, "" + subGroupIndex++)
.keyBinding("A")
.onAction(this::analyzeCallback)
.enabledWhen(this::canAnalyze)
.buildAndInstall(tool);
autoAnalyzeAction = new ListingContextAction("Auto Analyze", getName()) {
@Override
protected void actionPerformed(ListingActionContext programContext) {
analyzeCallback(programContext.getProgram(), programContext.getSelection());
}
@Override
public boolean isEnabledForContext(ListingActionContext context) {
Program program = context.getProgram();
getMenuBarData().setMenuItemName(
"&Auto Analyze '" + program.getDomainFile().getName() + "'...");
return true;
}
};
String[] menuPath = { "&Analysis", "&Auto Analyze..." };
MenuData menuData = new MenuData(menuPath, null, ANALYZE_GROUP_NAME);
menuData.setMenuSubGroup("" + subGroupIndex++);
autoAnalyzeAction.setMenuBarData(menuData);
autoAnalyzeAction.setKeyBindingData(new KeyBindingData('A', 0));
tool.addAction(autoAnalyzeAction);
analyzeAllAction = new DockingAction("Analyze All Open", getName()) {
@Override
public void actionPerformed(ActionContext context) {
analyzeAllCallback();
}
@Override
public boolean isEnabledForContext(ActionContext context) {
return context.getContextObject() instanceof ListingActionContext;
}
};
analyzeAllAction.setEnabled(false);
menuData =
new MenuData(new String[] { "&Analysis", "Analyze All &Open..." }, ANALYZE_GROUP_NAME);
menuData.setMenuSubGroup("" + subGroupIndex++);
analyzeAllAction.setMenuBarData(menuData);
tool.addAction(analyzeAllAction);
analyzeAllAction = new ActionBuilder("Analyze All Open", getName())
.menuPath("&Analysis", "Analyze All &Open...")
.menuGroup(ANALYZE_GROUP_NAME, "" + subGroupIndex++)
.onAction(c -> analyzeAllCallback())
.enabledWhen(c -> getListingContext(c) != null)
.buildAndInstall(tool);
tool.setMenuGroup(new String[] { "Analysis", "One Shot" }, ANALYZE_GROUP_NAME);
}
private boolean canAnalyze(ActionContext context) {
ListingActionContext listingContext = getListingContext(context);
updateActionName(listingContext);
return listingContext != null;
}
private void updateActionName(ListingActionContext listingContext) {
String programName = "";
if (listingContext != null) {
programName = listingContext.getProgram().getDomainFile().getName();
}
MenuData menuBarData = autoAnalyzeAction.getMenuBarData();
menuBarData.setMenuItemName("&Auto Analyze '" + programName + "'...");
}
private ListingActionContext getListingContext(ActionContext context) {
if (context instanceof ListingActionContext) {
return (ListingActionContext) context;
}
ActionContext globalContext = context.getGlobalContext();
if (globalContext instanceof ListingActionContext) {
return (ListingActionContext) globalContext;
}
return null;
}
private void analyzeCallback(ActionContext context) {
ListingActionContext listingContext = getListingContext(context);
analyzeCallback(listingContext.getProgram(), listingContext.getSelection());
}
private void addOneShotActions(Program program) {
removeOneShotActions();
for (Analyzer analyzer : analyzers) {
@ -322,7 +327,7 @@ public class AutoAnalysisPlugin extends Plugin implements AutoAnalysisManagerLis
}
}
class OneShotAnalyzerAction extends ListingContextAction {
class OneShotAnalyzerAction extends DockingAction {
private Analyzer analyzer;
private Program canAnalyzeProgram;
private boolean canAnalyze;
@ -338,7 +343,8 @@ public class AutoAnalysisPlugin extends Plugin implements AutoAnalysisManagerLis
}
@Override
public void actionPerformed(ListingActionContext programContext) {
public void actionPerformed(ActionContext context) {
ListingActionContext programContext = getListingContext(context);
AddressSetView set;
if (programContext.hasSelection()) {
set = programContext.getSelection();
@ -363,7 +369,8 @@ public class AutoAnalysisPlugin extends Plugin implements AutoAnalysisManagerLis
}
@Override
protected boolean isEnabledForContext(ListingActionContext programContext) {
public boolean isEnabledForContext(ActionContext context) {
ListingActionContext programContext = getListingContext(context);
Program p = programContext.getProgram();
if (p != canAnalyzeProgram) {
canAnalyzeProgram = p;

View File

@ -78,6 +78,7 @@ public class ActionContext {
private MouseEvent mouseEvent;
private Object contextObject;
private Object sourceObject;
private ActionContext globalContext;
// Note: the setting of this object is delayed. This allows clients to build-up the state
// of this context. This object will be set when getSourceComponent() is called if it
@ -243,4 +244,29 @@ public class ActionContext {
//@formatter:on
}
/**
* Returns the global action context for the tool. The global context is the context of
* the default focused component, instead of the normal action context which is the current
* focused component.
* @return the global action context for the tool
*/
public ActionContext getGlobalContext() {
if (globalContext == null) {
Tool tool = getTool();
globalContext = tool == null ? new ActionContext() : tool.getGlobalActionContext();
}
return globalContext;
}
private Tool getTool() {
if (provider != null) {
return provider.getTool();
}
DockingWindowManager manager = DockingWindowManager.getActiveInstance();
if (manager != null) {
return manager.getTool();
}
return null;
}
}

View File

@ -2140,6 +2140,15 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
contextListeners.remove(listener);
}
/**
* Returns the global action context for the tool
* @return the global action context for the tool
*/
public ActionContext getGlobalActionContext() {
return defaultProvider == null ? new ActionContext()
: defaultProvider.getActionContext(null);
}
void notifyContextListeners(ComponentPlaceholder placeHolder, ActionContext actionContext) {
if (placeHolder == focusedPlaceholder) {

View File

@ -304,4 +304,12 @@ public interface Tool extends ServiceProvider {
*/
public void close();
/**
* Returns the global action context for the tool. The global context is the context of
* the default focused component, instead of the normal action context which is the current
* focused component.
* @return the global action context for the tool
*/
public ActionContext getGlobalActionContext();
}

View File

@ -78,4 +78,9 @@ public class FakeDockingTool extends AbstractDockingTool {
public void removeServiceListener(ServiceListener listener) {
// stub
}
@Override
public ActionContext getGlobalActionContext() {
return null;
}
}

View File

@ -1471,6 +1471,11 @@ public abstract class PluginTool extends AbstractDockingTool {
winMgr.removePreferenceState(name);
}
@Override
public ActionContext getGlobalActionContext() {
return winMgr.getGlobalActionContext();
}
//==================================================================================================
// Inner Classes
//==================================================================================================