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

View File

@ -21,12 +21,13 @@ import javax.swing.SwingUtilities;
import docking.ActionContext; import docking.ActionContext;
import docking.DockingWindowManager; 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 docking.widgets.dialogs.MultiLineMessageDialog;
import ghidra.GhidraOptions; import ghidra.GhidraOptions;
import ghidra.app.CorePluginPackage; import ghidra.app.CorePluginPackage;
import ghidra.app.context.ListingActionContext; import ghidra.app.context.ListingActionContext;
import ghidra.app.context.ListingContextAction;
import ghidra.app.events.*; import ghidra.app.events.*;
import ghidra.app.plugin.PluginCategoryNames; import ghidra.app.plugin.PluginCategoryNames;
import ghidra.app.services.Analyzer; 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 // use this index to make sure that the following actions are ordered in the way that
// they are inserted // they are inserted
int subGroupIndex = 0; 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()) { analyzeAllAction = new ActionBuilder("Analyze All Open", getName())
@Override .menuPath("&Analysis", "Analyze All &Open...")
protected void actionPerformed(ListingActionContext programContext) { .menuGroup(ANALYZE_GROUP_NAME, "" + subGroupIndex++)
analyzeCallback(programContext.getProgram(), programContext.getSelection()); .onAction(c -> analyzeAllCallback())
} .enabledWhen(c -> getListingContext(c) != null)
.buildAndInstall(tool);
@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);
tool.setMenuGroup(new String[] { "Analysis", "One Shot" }, ANALYZE_GROUP_NAME); 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) { private void addOneShotActions(Program program) {
removeOneShotActions(); removeOneShotActions();
for (Analyzer analyzer : analyzers) { 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 Analyzer analyzer;
private Program canAnalyzeProgram; private Program canAnalyzeProgram;
private boolean canAnalyze; private boolean canAnalyze;
@ -338,7 +343,8 @@ public class AutoAnalysisPlugin extends Plugin implements AutoAnalysisManagerLis
} }
@Override @Override
public void actionPerformed(ListingActionContext programContext) { public void actionPerformed(ActionContext context) {
ListingActionContext programContext = getListingContext(context);
AddressSetView set; AddressSetView set;
if (programContext.hasSelection()) { if (programContext.hasSelection()) {
set = programContext.getSelection(); set = programContext.getSelection();
@ -363,7 +369,8 @@ public class AutoAnalysisPlugin extends Plugin implements AutoAnalysisManagerLis
} }
@Override @Override
protected boolean isEnabledForContext(ListingActionContext programContext) { public boolean isEnabledForContext(ActionContext context) {
ListingActionContext programContext = getListingContext(context);
Program p = programContext.getProgram(); Program p = programContext.getProgram();
if (p != canAnalyzeProgram) { if (p != canAnalyzeProgram) {
canAnalyzeProgram = p; canAnalyzeProgram = p;

View File

@ -78,6 +78,7 @@ public class ActionContext {
private MouseEvent mouseEvent; private MouseEvent mouseEvent;
private Object contextObject; private Object contextObject;
private Object sourceObject; private Object sourceObject;
private ActionContext globalContext;
// Note: the setting of this object is delayed. This allows clients to build-up the state // 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 // of this context. This object will be set when getSourceComponent() is called if it
@ -243,4 +244,29 @@ public class ActionContext {
//@formatter:on //@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); 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) { void notifyContextListeners(ComponentPlaceholder placeHolder, ActionContext actionContext) {
if (placeHolder == focusedPlaceholder) { if (placeHolder == focusedPlaceholder) {

View File

@ -304,4 +304,12 @@ public interface Tool extends ServiceProvider {
*/ */
public void close(); 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) { public void removeServiceListener(ServiceListener listener) {
// stub // stub
} }
@Override
public ActionContext getGlobalActionContext() {
return null;
}
} }

View File

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