mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-29 03:45:30 +08:00
Merge branch 'GT-3485_action_context'
Conflicts: Ghidra/Framework/Docking/src/main/java/docking/action/MultipleKeyAction.java
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,25 +15,26 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.context;
|
package ghidra.app.context;
|
||||||
|
|
||||||
|
import docking.ComponentProvider;
|
||||||
import ghidra.app.nav.Navigatable;
|
import ghidra.app.nav.Navigatable;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.util.ProgramLocation;
|
import ghidra.program.util.ProgramLocation;
|
||||||
import ghidra.program.util.ProgramSelection;
|
import ghidra.program.util.ProgramSelection;
|
||||||
import docking.ComponentProvider;
|
|
||||||
|
|
||||||
public class ListingActionContext extends NavigatableActionContext {
|
public class ListingActionContext extends NavigatableActionContext {
|
||||||
|
|
||||||
public ListingActionContext(ComponentProvider provider, Navigatable navigatable) {
|
public ListingActionContext(ComponentProvider provider, Navigatable navigatable) {
|
||||||
super(provider, navigatable);
|
super(provider, navigatable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListingActionContext(ComponentProvider provider, Navigatable navigatable, ProgramLocation location) {
|
public ListingActionContext(ComponentProvider provider, Navigatable navigatable,
|
||||||
|
ProgramLocation location) {
|
||||||
super(provider, navigatable, location);
|
super(provider, navigatable, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListingActionContext(ComponentProvider provider, Navigatable navigatable,
|
public ListingActionContext(ComponentProvider provider, Navigatable navigatable,
|
||||||
Program program, ProgramLocation location, ProgramSelection selection,
|
Program program, ProgramLocation location, ProgramSelection selection,
|
||||||
ProgramSelection highlight ) {
|
ProgramSelection highlight) {
|
||||||
super( provider, navigatable, program, location, selection, highlight );
|
super(provider, navigatable, program, location, selection, highlight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-21
@@ -25,45 +25,32 @@ public abstract class NavigatableContextAction extends DockingAction {
|
|||||||
|
|
||||||
public NavigatableContextAction(String name, String owner) {
|
public NavigatableContextAction(String name, String owner) {
|
||||||
super(name, owner);
|
super(name, owner);
|
||||||
|
setSupportsDefaultToolContext(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public NavigatableContextAction(String name, String owner, KeyBindingType type) {
|
public NavigatableContextAction(String name, String owner, KeyBindingType type) {
|
||||||
super(name, owner, type);
|
super(name, owner, type);
|
||||||
|
setSupportsDefaultToolContext(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEnabledForContext(ActionContext context) {
|
public boolean isEnabledForContext(ActionContext context) {
|
||||||
NavigatableActionContext appropriateContext = getAppropriateContext(context);
|
if (context instanceof NavigatableActionContext) {
|
||||||
if (appropriateContext == null) {
|
return isEnabledForContext((NavigatableActionContext) context);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return isEnabledForContext(appropriateContext);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionContext context) {
|
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
|
@Override
|
||||||
public final boolean isValidContext(ActionContext context) {
|
public final boolean isValidContext(ActionContext context) {
|
||||||
return true;
|
return context instanceof NavigatableActionContext;
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean isValidNavigationContext(NavigatableActionContext context) {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -30,23 +30,14 @@ public abstract class NextRangeAction extends NavigatableContextAction {
|
|||||||
private PluginTool tool;
|
private PluginTool tool;
|
||||||
private NavigationOptions navOptions;
|
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);
|
super(name, owner);
|
||||||
this.tool = tool;
|
this.tool = tool;
|
||||||
this.navOptions = navOptions;
|
this.navOptions = navOptions;
|
||||||
setEnabled(false);
|
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
|
@Override
|
||||||
public boolean isEnabledForContext(NavigatableActionContext context) {
|
public boolean isEnabledForContext(NavigatableActionContext context) {
|
||||||
Address currentAddress = context.getAddress();
|
Address currentAddress = context.getAddress();
|
||||||
|
|||||||
@@ -37,16 +37,6 @@ public abstract class PreviousRangeAction extends NavigatableContextAction {
|
|||||||
setEnabled(false);
|
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
|
@Override
|
||||||
public void actionPerformed(NavigatableActionContext context) {
|
public void actionPerformed(NavigatableActionContext context) {
|
||||||
Address goToAddress = getGoToAddress(context);
|
Address goToAddress = getGoToAddress(context);
|
||||||
|
|||||||
+25
-27
@@ -22,6 +22,7 @@ import docking.ActionContext;
|
|||||||
import docking.ComponentProvider;
|
import docking.ComponentProvider;
|
||||||
import docking.action.DockingAction;
|
import docking.action.DockingAction;
|
||||||
import docking.action.MenuData;
|
import docking.action.MenuData;
|
||||||
|
import docking.action.builder.ActionBuilder;
|
||||||
import docking.tool.ToolConstants;
|
import docking.tool.ToolConstants;
|
||||||
import ghidra.app.CorePluginPackage;
|
import ghidra.app.CorePluginPackage;
|
||||||
import ghidra.app.context.*;
|
import ghidra.app.context.*;
|
||||||
@@ -96,33 +97,28 @@ public class FindPossibleReferencesPlugin extends Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void createActions() {
|
private void createActions() {
|
||||||
action = new ListingContextAction(SEARCH_DIRECT_REFS_ACTION_NAME, getName()) {
|
action = new ActionBuilder(SEARCH_DIRECT_REFS_ACTION_NAME, getName())
|
||||||
@Override
|
.menuPath(ToolConstants.MENU_SEARCH, "For Direct References")
|
||||||
protected void actionPerformed(ListingActionContext context) {
|
.menuGroup("search for")
|
||||||
findReferences(context);
|
.supportsDefaultToolContext(true)
|
||||||
}
|
.helpLocation(new HelpLocation(HelpTopics.SEARCH, SEARCH_DIRECT_REFS_ACTION_NAME))
|
||||||
|
.description(getPluginDescription().getDescription())
|
||||||
|
.withContext(ListingActionContext.class)
|
||||||
|
.onAction(this::findReferences)
|
||||||
|
.enabledWhen(this::hasCorrectAddressSize)
|
||||||
|
.buildAndInstall(tool);
|
||||||
|
|
||||||
@Override
|
}
|
||||||
protected boolean isEnabledForContext(ListingActionContext context) {
|
|
||||||
int size =
|
|
||||||
context.getProgram().getAddressFactory().getDefaultAddressSpace().getSize();
|
|
||||||
if ((size == 64) || (size == 32) || (size == 24) || (size == 16) || (size == 20) ||
|
|
||||||
(size == 21)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
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());
|
private boolean hasCorrectAddressSize(ListingActionContext context) {
|
||||||
//enableOnLocation(action);
|
int size =
|
||||||
tool.addAction(action);
|
context.getProgram().getAddressFactory().getDefaultAddressSpace().getSize();
|
||||||
|
if ((size == 64) || (size == 32) || (size == 24) || (size == 16) || (size == 20) ||
|
||||||
} // end of createActions()
|
(size == 21)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private void createLocalActions(ProgramLocationActionContext context, ComponentProvider p,
|
private void createLocalActions(ProgramLocationActionContext context, ComponentProvider p,
|
||||||
FindReferencesTableModel model) {
|
FindReferencesTableModel model) {
|
||||||
@@ -196,8 +192,10 @@ public class FindPossibleReferencesPlugin extends Plugin {
|
|||||||
"Could not find memory associated with " + fromAddr);
|
"Could not find memory associated with " + fromAddr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (currentProgram.getMemory().getBlock(
|
if (currentProgram.getMemory()
|
||||||
fromAddr).getType() == MemoryBlockType.BIT_MAPPED) {
|
.getBlock(
|
||||||
|
fromAddr)
|
||||||
|
.getType() == MemoryBlockType.BIT_MAPPED) {
|
||||||
Msg.showWarn(getClass(), null, "Search For Direct References",
|
Msg.showWarn(getClass(), null, "Search For Direct References",
|
||||||
"Cannot search for direct references on bit memory!");
|
"Cannot search for direct references on bit memory!");
|
||||||
return;
|
return;
|
||||||
|
|||||||
+1
@@ -30,6 +30,7 @@ public class ClearSelectionAction extends CodeViewerContextAction {
|
|||||||
|
|
||||||
public ClearSelectionAction(String owner) {
|
public ClearSelectionAction(String owner) {
|
||||||
super("Clear Selection", owner);
|
super("Clear Selection", owner);
|
||||||
|
setSupportsDefaultToolContext(true);
|
||||||
setMenuBarData(new MenuData(
|
setMenuBarData(new MenuData(
|
||||||
new String[] { ToolConstants.MENU_SELECTION, "&Clear Selection" }, null, "Select"));
|
new String[] { ToolConstants.MENU_SELECTION, "&Clear Selection" }, null, "Select"));
|
||||||
|
|
||||||
|
|||||||
+5
-4
@@ -23,8 +23,9 @@ import javax.swing.KeyStroke;
|
|||||||
import docking.action.KeyBindingData;
|
import docking.action.KeyBindingData;
|
||||||
import docking.action.MenuData;
|
import docking.action.MenuData;
|
||||||
import docking.tool.ToolConstants;
|
import docking.tool.ToolConstants;
|
||||||
|
import ghidra.app.context.NavigatableActionContext;
|
||||||
|
import ghidra.app.context.NavigatableContextAction;
|
||||||
import ghidra.app.nav.Navigatable;
|
import ghidra.app.nav.Navigatable;
|
||||||
import ghidra.app.plugin.core.codebrowser.CodeViewerActionContext;
|
|
||||||
import ghidra.app.services.GoToService;
|
import ghidra.app.services.GoToService;
|
||||||
import ghidra.app.util.HelpTopics;
|
import ghidra.app.util.HelpTopics;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
@@ -33,7 +34,7 @@ import ghidra.program.model.listing.*;
|
|||||||
import ghidra.program.util.FunctionSignatureFieldLocation;
|
import ghidra.program.util.FunctionSignatureFieldLocation;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
|
|
||||||
public class GotoNextFunctionAction extends CodeViewerContextAction {
|
public class GotoNextFunctionAction extends NavigatableContextAction {
|
||||||
|
|
||||||
private PluginTool tool;
|
private PluginTool tool;
|
||||||
|
|
||||||
@@ -67,7 +68,7 @@ public class GotoNextFunctionAction extends CodeViewerContextAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void actionPerformed(CodeViewerActionContext context) {
|
protected void actionPerformed(NavigatableActionContext context) {
|
||||||
Address address = context.getAddress();
|
Address address = context.getAddress();
|
||||||
Program program = context.getProgram();
|
Program program = context.getProgram();
|
||||||
Function function = getNextFunction(program, address);
|
Function function = getNextFunction(program, address);
|
||||||
@@ -79,7 +80,7 @@ public class GotoNextFunctionAction extends CodeViewerContextAction {
|
|||||||
if (service != null) {
|
if (service != null) {
|
||||||
FunctionSignatureFieldLocation location =
|
FunctionSignatureFieldLocation location =
|
||||||
new FunctionSignatureFieldLocation(program, function.getEntryPoint(), null, 0,
|
new FunctionSignatureFieldLocation(program, function.getEntryPoint(), null, 0,
|
||||||
function.getPrototypeString(false, false));
|
function.getPrototypeString(false, false));
|
||||||
|
|
||||||
Navigatable navigatable = context.getNavigatable();
|
Navigatable navigatable = context.getNavigatable();
|
||||||
service.goTo(navigatable, location, navigatable.getProgram());
|
service.goTo(navigatable, location, navigatable.getProgram());
|
||||||
|
|||||||
+4
-3
@@ -23,8 +23,9 @@ import javax.swing.KeyStroke;
|
|||||||
import docking.action.KeyBindingData;
|
import docking.action.KeyBindingData;
|
||||||
import docking.action.MenuData;
|
import docking.action.MenuData;
|
||||||
import docking.tool.ToolConstants;
|
import docking.tool.ToolConstants;
|
||||||
|
import ghidra.app.context.NavigatableActionContext;
|
||||||
|
import ghidra.app.context.NavigatableContextAction;
|
||||||
import ghidra.app.nav.Navigatable;
|
import ghidra.app.nav.Navigatable;
|
||||||
import ghidra.app.plugin.core.codebrowser.CodeViewerActionContext;
|
|
||||||
import ghidra.app.services.GoToService;
|
import ghidra.app.services.GoToService;
|
||||||
import ghidra.app.util.HelpTopics;
|
import ghidra.app.util.HelpTopics;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
@@ -33,7 +34,7 @@ import ghidra.program.model.listing.*;
|
|||||||
import ghidra.program.util.FunctionSignatureFieldLocation;
|
import ghidra.program.util.FunctionSignatureFieldLocation;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
|
|
||||||
public class GotoPreviousFunctionAction extends CodeViewerContextAction {
|
public class GotoPreviousFunctionAction extends NavigatableContextAction {
|
||||||
|
|
||||||
private PluginTool tool;
|
private PluginTool tool;
|
||||||
|
|
||||||
@@ -67,7 +68,7 @@ public class GotoPreviousFunctionAction extends CodeViewerContextAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void actionPerformed(CodeViewerActionContext context) {
|
protected void actionPerformed(NavigatableActionContext context) {
|
||||||
Address address = context.getAddress();
|
Address address = context.getAddress();
|
||||||
Program program = context.getProgram();
|
Program program = context.getProgram();
|
||||||
Function function = getPreviousFunction(program, address);
|
Function function = getPreviousFunction(program, address);
|
||||||
|
|||||||
+20
-19
@@ -15,10 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.codebrowser.actions;
|
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.InputEvent;
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
|
|
||||||
@@ -26,27 +22,32 @@ import docking.ActionContext;
|
|||||||
import docking.action.KeyBindingData;
|
import docking.action.KeyBindingData;
|
||||||
import docking.action.MenuData;
|
import docking.action.MenuData;
|
||||||
import docking.tool.ToolConstants;
|
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.
|
* Action for adding all fields to the current format.
|
||||||
*/
|
*/
|
||||||
public class SelectAllAction extends CodeViewerContextAction {
|
public class SelectAllAction extends CodeViewerContextAction {
|
||||||
|
|
||||||
public SelectAllAction(String owner) {
|
|
||||||
super("Select All", owner);
|
|
||||||
setMenuBarData(
|
|
||||||
new MenuData(
|
|
||||||
new String[] {ToolConstants.MENU_SELECTION, "&All in View" },null,"Select" ) );
|
|
||||||
|
|
||||||
setKeyBindingData( new KeyBindingData(
|
public SelectAllAction(String owner) {
|
||||||
KeyEvent.VK_A, InputEvent.CTRL_DOWN_MASK ) );
|
super("Select All", owner);
|
||||||
|
// this is in the main tool menu, so make it a tool action
|
||||||
|
setSupportsDefaultToolContext(true);
|
||||||
|
setMenuBarData(
|
||||||
|
new MenuData(
|
||||||
|
new String[] { ToolConstants.MENU_SELECTION, "&All in View" }, null, "Select"));
|
||||||
|
|
||||||
|
setKeyBindingData(new KeyBindingData(
|
||||||
|
KeyEvent.VK_A, InputEvent.CTRL_DOWN_MASK));
|
||||||
|
|
||||||
setHelpLocation(new HelpLocation(HelpTopics.SELECTION, getName()));
|
setHelpLocation(new HelpLocation(HelpTopics.SELECTION, getName()));
|
||||||
}
|
}
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionContext context) {
|
|
||||||
CodeViewerProvider provider = (CodeViewerProvider) context.getComponentProvider();
|
|
||||||
provider.selectAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionContext context) {
|
||||||
|
CodeViewerProvider provider = (CodeViewerProvider) context.getComponentProvider();
|
||||||
|
provider.selectAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+30
-25
@@ -14,14 +14,15 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.codebrowser.actions;
|
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.CodeViewerActionContext;
|
||||||
import ghidra.app.plugin.core.codebrowser.CodeViewerProvider;
|
import ghidra.app.plugin.core.codebrowser.CodeViewerProvider;
|
||||||
import ghidra.app.util.HelpTopics;
|
import ghidra.app.util.HelpTopics;
|
||||||
import ghidra.program.util.ProgramSelection;
|
import ghidra.program.util.ProgramSelection;
|
||||||
import ghidra.util.HelpLocation;
|
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
|
* Action for changing the selection to the complement of all the currently
|
||||||
@@ -29,29 +30,33 @@ import docking.tool.ToolConstants;
|
|||||||
*/
|
*/
|
||||||
public class SelectComplementAction extends CodeViewerContextAction {
|
public class SelectComplementAction extends CodeViewerContextAction {
|
||||||
|
|
||||||
public SelectComplementAction(String owner) {
|
public SelectComplementAction(String owner) {
|
||||||
super("Select Complement", owner);
|
super("Select Complement", owner);
|
||||||
setMenuBarData( new MenuData(
|
|
||||||
new String[]{ToolConstants.MENU_SELECTION, "&Complement" },
|
|
||||||
null,
|
|
||||||
"Select" ) );
|
|
||||||
|
|
||||||
setEnabled(false);
|
// this is in the main tool menu, so make it a tool action
|
||||||
|
setSupportsDefaultToolContext(true);
|
||||||
|
|
||||||
|
setMenuBarData(new MenuData(
|
||||||
|
new String[] { ToolConstants.MENU_SELECTION, "&Complement" },
|
||||||
|
null,
|
||||||
|
"Select"));
|
||||||
|
|
||||||
|
setEnabled(false);
|
||||||
setHelpLocation(new HelpLocation(HelpTopics.SELECTION, getName()));
|
setHelpLocation(new HelpLocation(HelpTopics.SELECTION, getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionContext context) {
|
public void actionPerformed(ActionContext context) {
|
||||||
CodeViewerProvider provider = (CodeViewerProvider) context.getComponentProvider();
|
CodeViewerProvider provider = (CodeViewerProvider) context.getComponentProvider();
|
||||||
provider.selectComplement();
|
provider.selectComplement();
|
||||||
}
|
}
|
||||||
@Override
|
|
||||||
public boolean isEnabledForContext(CodeViewerActionContext context) {
|
@Override
|
||||||
ProgramSelection selection = context.getSelection();
|
public boolean isEnabledForContext(CodeViewerActionContext context) {
|
||||||
if (selection != null && selection.getInteriorSelection() != null) {
|
ProgramSelection selection = context.getSelection();
|
||||||
return false;
|
if (selection != null && selection.getInteriorSelection() != null) {
|
||||||
}
|
return false;
|
||||||
return true;
|
}
|
||||||
}
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -245,9 +245,10 @@ public class InstructionSearchPlugin extends ProgramPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isValidNavigationContext(NavigatableActionContext context) {
|
protected boolean isEnabledForContext(NavigatableActionContext context) {
|
||||||
return !(context instanceof RestrictedAddressSetContext);
|
return !(context instanceof RestrictedAddressSetContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
searchAction.setHelpLocation(new HelpLocation("Search", "Instruction_Pattern_Search"));
|
searchAction.setHelpLocation(new HelpLocation("Search", "Instruction_Pattern_Search"));
|
||||||
searchAction.setMenuBarData(
|
searchAction.setMenuBarData(
|
||||||
|
|||||||
+5
-8
@@ -17,9 +17,10 @@ package ghidra.app.plugin.core.navigation;
|
|||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
||||||
import docking.action.*;
|
import docking.action.KeyBindingData;
|
||||||
|
import docking.action.ToolBarData;
|
||||||
import docking.tool.ToolConstants;
|
import docking.tool.ToolConstants;
|
||||||
import ghidra.app.context.ListingActionContext;
|
import ghidra.app.context.NavigatableActionContext;
|
||||||
import ghidra.app.nav.Navigatable;
|
import ghidra.app.nav.Navigatable;
|
||||||
import ghidra.app.plugin.core.codebrowser.CodeViewerActionContext;
|
import ghidra.app.plugin.core.codebrowser.CodeViewerActionContext;
|
||||||
import ghidra.app.plugin.core.codebrowser.actions.CodeViewerContextAction;
|
import ghidra.app.plugin.core.codebrowser.actions.CodeViewerContextAction;
|
||||||
@@ -41,16 +42,12 @@ public abstract class AbstractNextPreviousAction extends CodeViewerContextAction
|
|||||||
public AbstractNextPreviousAction(PluginTool tool, String name, String owner, String subGroup) {
|
public AbstractNextPreviousAction(PluginTool tool, String name, String owner, String subGroup) {
|
||||||
super(name, owner);
|
super(name, owner);
|
||||||
this.tool = tool;
|
this.tool = tool;
|
||||||
|
setSupportsDefaultToolContext(true);
|
||||||
|
|
||||||
ToolBarData toolBarData =
|
ToolBarData toolBarData =
|
||||||
new ToolBarData(getIcon(), ToolConstants.TOOLBAR_GROUP_FOUR);
|
new ToolBarData(getIcon(), ToolConstants.TOOLBAR_GROUP_FOUR);
|
||||||
toolBarData.setToolBarSubGroup(subGroup);
|
toolBarData.setToolBarSubGroup(subGroup);
|
||||||
setToolBarData(toolBarData);
|
setToolBarData(toolBarData);
|
||||||
MenuData menuData =
|
|
||||||
new MenuData(new String[] { ToolConstants.MENU_NAVIGATION, getMenuName() }, getIcon(),
|
|
||||||
ToolConstants.MENU_GROUP_NEXT_CODE_UNIT_NAV);
|
|
||||||
menuData.setMenuSubGroup(subGroup);
|
|
||||||
setMenuBarData(menuData);
|
|
||||||
setKeyBindingData(new KeyBindingData(getKeyStroke()));
|
setKeyBindingData(new KeyBindingData(getKeyStroke()));
|
||||||
setHelpLocation(new HelpLocation(HelpTopics.NAVIGATION, name));
|
setHelpLocation(new HelpLocation(HelpTopics.NAVIGATION, name));
|
||||||
setDescription(getDescriptionString());
|
setDescription(getDescriptionString());
|
||||||
@@ -90,7 +87,7 @@ public abstract class AbstractNextPreviousAction extends CodeViewerContextAction
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void gotoAddress(ListingActionContext actionContext, Address address) {
|
private void gotoAddress(NavigatableActionContext actionContext, Address address) {
|
||||||
if (address == null) {
|
if (address == null) {
|
||||||
tool.setStatusInfo("Unable to locate another \"" + getNavigationTypeName() +
|
tool.setStatusInfo("Unable to locate another \"" + getNavigationTypeName() +
|
||||||
"\" past the current range, in the current direction.");
|
"\" past the current range, in the current direction.");
|
||||||
|
|||||||
+4
-9
@@ -23,9 +23,9 @@ import javax.swing.Icon;
|
|||||||
import docking.action.*;
|
import docking.action.*;
|
||||||
import docking.tool.ToolConstants;
|
import docking.tool.ToolConstants;
|
||||||
import ghidra.app.CorePluginPackage;
|
import ghidra.app.CorePluginPackage;
|
||||||
|
import ghidra.app.context.NavigatableActionContext;
|
||||||
|
import ghidra.app.context.NavigatableContextAction;
|
||||||
import ghidra.app.plugin.PluginCategoryNames;
|
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.services.GoToService;
|
||||||
import ghidra.app.util.HelpTopics;
|
import ghidra.app.util.HelpTopics;
|
||||||
import ghidra.framework.plugintool.*;
|
import ghidra.framework.plugintool.*;
|
||||||
@@ -119,18 +119,13 @@ public class NextPrevCodeUnitPlugin extends Plugin {
|
|||||||
bookmarkAction.setDirection(searchForward);
|
bookmarkAction.setDirection(searchForward);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ToggleDirectionAction extends CodeViewerContextAction {
|
private class ToggleDirectionAction extends NavigatableContextAction {
|
||||||
Icon forwardIcon = ResourceManager.loadImage("images/down.png");
|
Icon forwardIcon = ResourceManager.loadImage("images/down.png");
|
||||||
Icon backwardIcon = ResourceManager.loadImage("images/up.png");
|
Icon backwardIcon = ResourceManager.loadImage("images/up.png");
|
||||||
private boolean isForward = true;
|
private boolean isForward = true;
|
||||||
|
|
||||||
ToggleDirectionAction(String subGroup) {
|
ToggleDirectionAction(String subGroup) {
|
||||||
super("Toggle Search Direction", NextPrevCodeUnitPlugin.this.getName());
|
super("Toggle Search Direction", NextPrevCodeUnitPlugin.this.getName());
|
||||||
MenuData menuData =
|
|
||||||
new MenuData(new String[] { ToolConstants.MENU_NAVIGATION, getName() },
|
|
||||||
forwardIcon, ToolConstants.MENU_GROUP_NEXT_CODE_UNIT_NAV);
|
|
||||||
menuData.setMenuSubGroup(subGroup);
|
|
||||||
setMenuBarData(menuData);
|
|
||||||
setToolBarData(new ToolBarData(forwardIcon,
|
setToolBarData(new ToolBarData(forwardIcon,
|
||||||
ToolConstants.TOOLBAR_GROUP_FOUR, subGroup));
|
ToolConstants.TOOLBAR_GROUP_FOUR, subGroup));
|
||||||
setKeyBindingData(new KeyBindingData(KeyEvent.VK_T, InputEvent.CTRL_DOWN_MASK |
|
setKeyBindingData(new KeyBindingData(KeyEvent.VK_T, InputEvent.CTRL_DOWN_MASK |
|
||||||
@@ -144,7 +139,7 @@ public class NextPrevCodeUnitPlugin extends Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(CodeViewerActionContext context) {
|
public void actionPerformed(NavigatableActionContext context) {
|
||||||
isForward = !isForward;
|
isForward = !isForward;
|
||||||
getMenuBarData().setIcon(isForward ? forwardIcon : backwardIcon);
|
getMenuBarData().setIcon(isForward ? forwardIcon : backwardIcon);
|
||||||
getToolBarData().setIcon(isForward ? forwardIcon : backwardIcon);
|
getToolBarData().setIcon(isForward ? forwardIcon : backwardIcon);
|
||||||
|
|||||||
+10
-52
@@ -29,6 +29,7 @@ import docking.menu.MultiStateDockingAction;
|
|||||||
import docking.tool.ToolConstants;
|
import docking.tool.ToolConstants;
|
||||||
import docking.widgets.EventTrigger;
|
import docking.widgets.EventTrigger;
|
||||||
import ghidra.app.context.ListingActionContext;
|
import ghidra.app.context.ListingActionContext;
|
||||||
|
import ghidra.app.context.NavigatableActionContext;
|
||||||
import ghidra.app.nav.Navigatable;
|
import ghidra.app.nav.Navigatable;
|
||||||
import ghidra.app.plugin.core.codebrowser.CodeViewerActionContext;
|
import ghidra.app.plugin.core.codebrowser.CodeViewerActionContext;
|
||||||
import ghidra.app.services.GoToService;
|
import ghidra.app.services.GoToService;
|
||||||
@@ -56,18 +57,13 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction<String>
|
|||||||
public NextPreviousBookmarkAction(PluginTool tool, String owner, String subGroup) {
|
public NextPreviousBookmarkAction(PluginTool tool, String owner, String subGroup) {
|
||||||
super("Next Bookmark", owner);
|
super("Next Bookmark", owner);
|
||||||
this.tool = tool;
|
this.tool = tool;
|
||||||
|
setSupportsDefaultToolContext(true);
|
||||||
|
|
||||||
ToolBarData toolBarData =
|
ToolBarData toolBarData =
|
||||||
new ToolBarData(bookmarkIcon, ToolConstants.TOOLBAR_GROUP_FOUR);
|
new ToolBarData(bookmarkIcon, ToolConstants.TOOLBAR_GROUP_FOUR);
|
||||||
toolBarData.setToolBarSubGroup(subGroup);
|
toolBarData.setToolBarSubGroup(subGroup);
|
||||||
setToolBarData(toolBarData);
|
setToolBarData(toolBarData);
|
||||||
|
|
||||||
MenuData menuData =
|
|
||||||
new MenuData(new String[] { ToolConstants.MENU_NAVIGATION, getMenuName() },
|
|
||||||
bookmarkIcon, ToolConstants.MENU_GROUP_NEXT_CODE_UNIT_NAV);
|
|
||||||
menuData.setMenuSubGroup(subGroup);
|
|
||||||
setMenuBarData(menuData);
|
|
||||||
|
|
||||||
setKeyBindingData(new KeyBindingData(getKeyStroke()));
|
setKeyBindingData(new KeyBindingData(getKeyStroke()));
|
||||||
|
|
||||||
setHelpLocation(new HelpLocation(HelpTopics.NAVIGATION, getName()));
|
setHelpLocation(new HelpLocation(HelpTopics.NAVIGATION, getName()));
|
||||||
@@ -93,19 +89,6 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction<String>
|
|||||||
addActionState(warning);
|
addActionState(warning);
|
||||||
addActionState(custom);
|
addActionState(custom);
|
||||||
|
|
||||||
/*BookmarkPlugin bookmarkPlugin = new BookmarkPlugin(tool);
|
|
||||||
Program program = bookmarkPlugin.getCurrentProgram();
|
|
||||||
BookmarkManager bookmarkManager = program.getBookmarkManager();
|
|
||||||
BookmarkType[] bookmarkTypes = bookmarkManager.getBookmarkTypes();
|
|
||||||
|
|
||||||
for (BookmarkType bookmarkType : bookmarkTypes) {
|
|
||||||
ActionState<String> tempBookmarkType =
|
|
||||||
new ActionState<String>(bookmarkType.getTypeString(), bookmarkUnknownIcon,
|
|
||||||
bookmarkType.getTypeString());
|
|
||||||
|
|
||||||
addActionState(tempBookmarkType);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
setCurrentActionState(allBookmarks); // default
|
setCurrentActionState(allBookmarks); // default
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,8 +102,8 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction<String>
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doActionPerformed(ActionContext context) {
|
protected void doActionPerformed(ActionContext context) {
|
||||||
if (context instanceof ListingActionContext) {
|
if (context instanceof NavigatableActionContext) {
|
||||||
gotoNextPrevious((ListingActionContext) context, this.getCurrentUserData());
|
gotoNextPrevious((NavigatableActionContext) context, this.getCurrentUserData());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,7 +195,8 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction<String>
|
|||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
// AbstractNextPreviousAction Methods
|
// AbstractNextPreviousAction Methods
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
private void gotoNextPrevious(final ListingActionContext context, final String bookmarkType) {
|
private void gotoNextPrevious(final NavigatableActionContext context,
|
||||||
|
final String bookmarkType) {
|
||||||
final Address address =
|
final Address address =
|
||||||
isForward ? getNextAddress(context.getProgram(), context.getAddress(), bookmarkType)
|
isForward ? getNextAddress(context.getProgram(), context.getAddress(), bookmarkType)
|
||||||
: getPreviousAddress(context.getProgram(), context.getAddress(), bookmarkType);
|
: getPreviousAddress(context.getProgram(), context.getAddress(), bookmarkType);
|
||||||
@@ -225,7 +209,7 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction<String>
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void gotoAddress(ListingActionContext listingActionContext, Address address) {
|
private void gotoAddress(NavigatableActionContext listingActionContext, Address address) {
|
||||||
if (address == null) {
|
if (address == null) {
|
||||||
tool.setStatusInfo("Unable to locate another " + getNavigationTypeName() +
|
tool.setStatusInfo("Unable to locate another " + getNavigationTypeName() +
|
||||||
" past the current range, in the current direction.");
|
" past the current range, in the current direction.");
|
||||||
@@ -264,40 +248,14 @@ public class NextPreviousBookmarkAction extends MultiStateDockingAction<String>
|
|||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
// CodeViewerContextAction Methods
|
// CodeViewerContextAction Methods
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
@Override
|
|
||||||
public boolean isEnabledForContext(ActionContext context) {
|
|
||||||
if (!(context instanceof CodeViewerActionContext)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return isEnabledForContext((CodeViewerActionContext) context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isValidContext(ActionContext context) {
|
public boolean isValidContext(ActionContext context) {
|
||||||
if (!(context instanceof CodeViewerActionContext)) {
|
return context instanceof ListingActionContext;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return isValidContext((CodeViewerActionContext) context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAddToPopup(ActionContext context) {
|
public boolean isEnabledForContext(ActionContext context) {
|
||||||
if (!(context instanceof CodeViewerActionContext)) {
|
return context instanceof ListingActionContext;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+120
-213
@@ -17,7 +17,6 @@ package ghidra.app.plugin.core.progmgr;
|
|||||||
|
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.KeyEvent;
|
|
||||||
import java.beans.PropertyEditor;
|
import java.beans.PropertyEditor;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
@@ -26,16 +25,12 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
import javax.swing.Icon;
|
import docking.action.DockingAction;
|
||||||
|
import docking.action.builder.ActionBuilder;
|
||||||
import docking.ActionContext;
|
|
||||||
import docking.DockingUtils;
|
|
||||||
import docking.action.*;
|
|
||||||
import docking.options.editor.*;
|
import docking.options.editor.*;
|
||||||
import docking.tool.ToolConstants;
|
import docking.tool.ToolConstants;
|
||||||
import ghidra.app.CorePluginPackage;
|
import ghidra.app.CorePluginPackage;
|
||||||
import ghidra.app.context.ProgramActionContext;
|
import ghidra.app.context.ProgramActionContext;
|
||||||
import ghidra.app.context.ProgramContextAction;
|
|
||||||
import ghidra.app.events.*;
|
import ghidra.app.events.*;
|
||||||
import ghidra.app.plugin.PluginCategoryNames;
|
import ghidra.app.plugin.PluginCategoryNames;
|
||||||
import ghidra.app.services.ProgramManager;
|
import ghidra.app.services.ProgramManager;
|
||||||
@@ -59,7 +54,6 @@ import ghidra.program.util.*;
|
|||||||
import ghidra.util.*;
|
import ghidra.util.*;
|
||||||
import ghidra.util.exception.NotFoundException;
|
import ghidra.util.exception.NotFoundException;
|
||||||
import ghidra.util.task.TaskLauncher;
|
import ghidra.util.task.TaskLauncher;
|
||||||
import resources.ResourceManager;
|
|
||||||
|
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
@PluginInfo(
|
@PluginInfo(
|
||||||
@@ -86,13 +80,15 @@ import resources.ResourceManager;
|
|||||||
//@formatter:on
|
//@formatter:on
|
||||||
public class ProgramManagerPlugin extends Plugin implements ProgramManager {
|
public class ProgramManagerPlugin extends Plugin implements ProgramManager {
|
||||||
|
|
||||||
|
private static final String SAVE_GROUP = "DomainObjectSave";
|
||||||
|
private static final String OPEN_GROUP = "DomainObjectOpen";
|
||||||
private MultiProgramManager programMgr;
|
private MultiProgramManager programMgr;
|
||||||
private ProgramSaveManager programSaveMgr;
|
private ProgramSaveManager programSaveMgr;
|
||||||
private DockingAction openAction;
|
private DockingAction openAction;
|
||||||
private DockingAction saveAllAction;
|
private DockingAction saveAllAction;
|
||||||
private ProgramContextAction closeAction;
|
private DockingAction closeAction;
|
||||||
private ProgramContextAction saveAction;
|
private DockingAction saveAction;
|
||||||
private ProgramContextAction saveAsAction;
|
private DockingAction saveAsAction;
|
||||||
private DockingAction optionsAction;
|
private DockingAction optionsAction;
|
||||||
private DockingAction closeOthersAction;
|
private DockingAction closeOthersAction;
|
||||||
private DockingAction closeAllAction;
|
private DockingAction closeAllAction;
|
||||||
@@ -101,7 +97,6 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager {
|
|||||||
private boolean locked = false;
|
private boolean locked = false;
|
||||||
private UndoAction undoAction;
|
private UndoAction undoAction;
|
||||||
private RedoAction redoAction;
|
private RedoAction redoAction;
|
||||||
private ProgramActionContext lastProgramContext;
|
|
||||||
private ProgramLocation currentLocation;
|
private ProgramLocation currentLocation;
|
||||||
|
|
||||||
public ProgramManagerPlugin(PluginTool tool) {
|
public ProgramManagerPlugin(PluginTool tool) {
|
||||||
@@ -527,206 +522,72 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager {
|
|||||||
|
|
||||||
int subMenuGroupOrder = 1;
|
int subMenuGroupOrder = 1;
|
||||||
|
|
||||||
openAction = new DockingAction("Open File", getName()) {
|
openAction = new ActionBuilder("Open File", getName())
|
||||||
@Override
|
.onAction(c -> open())
|
||||||
public void actionPerformed(ActionContext context) {
|
.menuPath(ToolConstants.MENU_FILE, "&Open...")
|
||||||
open();
|
.menuGroup(OPEN_GROUP, Integer.toString(subMenuGroupOrder++))
|
||||||
}
|
.keyBinding("ctrl O")
|
||||||
};
|
.buildAndInstall(tool);
|
||||||
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));
|
|
||||||
|
|
||||||
closeAction = new ProgramContextAction("Close File", getName()) {
|
closeAction = new ActionBuilder("Close File", getName())
|
||||||
@Override
|
.menuPath(ToolConstants.MENU_FILE, "&Close")
|
||||||
public void actionPerformed(ProgramActionContext programContext) {
|
.menuGroup(OPEN_GROUP, Integer.toString(subMenuGroupOrder++))
|
||||||
closeProgram(programContext.getProgram(), false);
|
.withContext(ProgramActionContext.class)
|
||||||
}
|
.onAction(c -> closeProgram(c.getProgram(), false))
|
||||||
|
.buildAndInstall(tool);
|
||||||
|
|
||||||
@Override
|
closeOthersAction = new ActionBuilder("Close Others", getName())
|
||||||
public boolean isValidContext(ActionContext context) {
|
.menuPath(ToolConstants.MENU_FILE, "Close &Others")
|
||||||
if (!super.isValidContext(context)) {
|
.menuGroup(OPEN_GROUP, Integer.toString(subMenuGroupOrder++))
|
||||||
getMenuBarData().setMenuItemName("&Close");
|
.enabled(false)
|
||||||
setDescription("Close Program");
|
.onAction(c -> closeOtherPrograms(false))
|
||||||
return false;
|
.buildAndInstall(tool);
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
closeAllAction = new ActionBuilder("Close All", getName())
|
||||||
public boolean isEnabledForContext(ProgramActionContext context) {
|
.menuPath(ToolConstants.MENU_FILE, "Close &All")
|
||||||
Program program = context.getProgram();
|
.menuGroup(OPEN_GROUP, Integer.toString(subMenuGroupOrder++))
|
||||||
String programName = "'" + program.getDomainFile().getName() + "'";
|
.onAction(c -> closeAllPrograms(false))
|
||||||
getMenuBarData().setMenuItemName("&Close " + programName);
|
.enabled(false)
|
||||||
setDescription("<html>Close " + HTMLUtilities.escapeHTML(programName));
|
.buildAndInstall(tool);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
String[] closeActionMenuPath = { ToolConstants.MENU_FILE, "&Close" };
|
|
||||||
menuData = new MenuData(closeActionMenuPath, null, "DomainObjectOpen");
|
|
||||||
menuData.setMenuSubGroup(Integer.toString(subMenuGroupOrder++));
|
|
||||||
closeAction.setMenuBarData(menuData);
|
|
||||||
|
|
||||||
closeOthersAction = new DockingAction("Close Others", getName()) {
|
saveAction = new ActionBuilder("Save File", "&Save")
|
||||||
@Override
|
.menuPath(ToolConstants.MENU_FILE, "Close &All")
|
||||||
public void actionPerformed(ActionContext context) {
|
.description("Save Program")
|
||||||
closeOtherPrograms(false);
|
.menuGroup(SAVE_GROUP, Integer.toString(subMenuGroupOrder++))
|
||||||
}
|
.menuIcon(null)
|
||||||
};
|
.toolBarIcon("images/disk.png")
|
||||||
closeOthersAction.setEnabled(false);
|
.toolBarGroup(ToolConstants.TOOLBAR_GROUP_ONE)
|
||||||
String[] menuPath = { ToolConstants.MENU_FILE, "Close &Others" };
|
.keyBinding("ctrl S")
|
||||||
menuData = new MenuData(menuPath, null, "DomainObjectOpen");
|
.withContext(ProgramActionContext.class)
|
||||||
menuData.setMenuSubGroup(Integer.toString(subMenuGroupOrder++));
|
.enabledWhen(c -> c.getProgram().isChanged())
|
||||||
closeOthersAction.setMenuBarData(menuData);
|
.onAction(c -> programSaveMgr.saveProgram(c.getProgram()))
|
||||||
|
.buildAndInstall(tool);
|
||||||
|
|
||||||
closeAllAction = new DockingAction("Close All", getName()) {
|
saveAsAction = new ActionBuilder("Save As File", getName())
|
||||||
@Override
|
.menuPath(ToolConstants.MENU_FILE, "Save &As...")
|
||||||
public void actionPerformed(ActionContext context) {
|
.menuGroup(SAVE_GROUP, Integer.toString(subMenuGroupOrder++))
|
||||||
closeAllPrograms(false);
|
.withContext(ProgramActionContext.class)
|
||||||
}
|
.onAction(c -> programSaveMgr.saveAs(c.getProgram()))
|
||||||
};
|
.buildAndInstall(tool);
|
||||||
closeAllAction.setEnabled(false);
|
|
||||||
String[] nenuPath = { ToolConstants.MENU_FILE, "Close &All" };
|
|
||||||
menuData = new MenuData(nenuPath, null, "DomainObjectOpen");
|
|
||||||
menuData.setMenuSubGroup(Integer.toString(subMenuGroupOrder++));
|
|
||||||
closeAllAction.setMenuBarData(menuData);
|
|
||||||
|
|
||||||
saveAction = new ProgramContextAction("Save File", getName()) {
|
saveAllAction = new ActionBuilder("Save All Files", getName())
|
||||||
@Override
|
.menuPath(ToolConstants.MENU_FILE, "Save All")
|
||||||
public void actionPerformed(ProgramActionContext programContext) {
|
.description("Save All Programs")
|
||||||
programSaveMgr.saveProgram(programContext.getProgram());
|
.menuGroup(SAVE_GROUP, Integer.toString(subMenuGroupOrder++))
|
||||||
// setEnabled(false);
|
.onAction(c -> programSaveMgr.saveChangedPrograms())
|
||||||
}
|
.buildAndInstall(tool);
|
||||||
|
|
||||||
@Override
|
optionsAction = new ActionBuilder("Program Options", getName())
|
||||||
public boolean isValidContext(ActionContext context) {
|
.menuPath(ToolConstants.MENU_EDIT, "P&rogram Options...")
|
||||||
lastProgramContext = null;
|
.description("Edit Options for current program")
|
||||||
if (!super.isValidContext(context)) {
|
.menuGroup(ToolConstants.TOOL_OPTIONS_MENU_GROUP,
|
||||||
getMenuBarData().setMenuItemName("&Save");
|
ToolConstants.TOOL_OPTIONS_MENU_GROUP + "b")
|
||||||
setDescription("Save Program");
|
.withContext(ProgramActionContext.class)
|
||||||
return false;
|
.onAction(c -> showProgramOptions(c.getProgram()))
|
||||||
}
|
.buildAndInstall(tool);
|
||||||
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");
|
|
||||||
|
|
||||||
undoAction = new UndoAction(tool, getName());
|
undoAction = new UndoAction(tool, getName());
|
||||||
redoAction = new RedoAction(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(undoAction);
|
||||||
tool.addAction(redoAction);
|
tool.addAction(redoAction);
|
||||||
}
|
}
|
||||||
@@ -791,6 +652,10 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager {
|
|||||||
|
|
||||||
private void updateActions() {
|
private void updateActions() {
|
||||||
Program p = programMgr.getCurrentProgram();
|
Program p = programMgr.getCurrentProgram();
|
||||||
|
updateCloseAction(p);
|
||||||
|
updateProgramOptionsAction(p);
|
||||||
|
updateSaveAction(p);
|
||||||
|
updateSaveAsAction(p);
|
||||||
closeAllAction.setEnabled(p != null);
|
closeAllAction.setEnabled(p != null);
|
||||||
optionsAction.setEnabled(p != null);
|
optionsAction.setEnabled(p != null);
|
||||||
Program[] programList = programMgr.getAllPrograms();
|
Program[] programList = programMgr.getAllPrograms();
|
||||||
@@ -805,6 +670,54 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager {
|
|||||||
tool.contextChanged(null);
|
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() {
|
private void open() {
|
||||||
if (openDialog == null) {
|
if (openDialog == null) {
|
||||||
ActionListener listener = e -> {
|
ActionListener listener = e -> {
|
||||||
@@ -875,17 +788,11 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager {
|
|||||||
|
|
||||||
void updateProgramActions() {
|
void updateProgramActions() {
|
||||||
updateSaveAllAction();
|
updateSaveAllAction();
|
||||||
if (lastProgramContext != null) {
|
Program p = getCurrentProgram();
|
||||||
updateProgramAction(undoAction);
|
updateSaveAction(getCurrentProgram());
|
||||||
updateProgramAction(redoAction);
|
updateSaveAsAction(getCurrentProgram());
|
||||||
updateProgramAction(saveAction);
|
undoAction.update(p);
|
||||||
updateProgramAction(saveAsAction);
|
redoAction.update(p);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateProgramAction(ProgramContextAction action) {
|
|
||||||
boolean isEnabled = action.isEnabledForContext(lastProgramContext);
|
|
||||||
action.setEnabled(isEnabled);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateSaveAllAction() {
|
private void updateSaveAllAction() {
|
||||||
|
|||||||
@@ -15,12 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.progmgr;
|
package ghidra.app.plugin.core.progmgr;
|
||||||
|
|
||||||
import java.awt.event.InputEvent;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
|
|
||||||
import docking.ActionContext;
|
|
||||||
import docking.action.*;
|
import docking.action.*;
|
||||||
import docking.tool.ToolConstants;
|
import docking.tool.ToolConstants;
|
||||||
import ghidra.app.context.ProgramActionContext;
|
import ghidra.app.context.ProgramActionContext;
|
||||||
@@ -46,7 +44,7 @@ public class RedoAction extends ProgramContextAction {
|
|||||||
menuData.setMenuSubGroup("2Redo"); // make this appear below the undo menu item
|
menuData.setMenuSubGroup("2Redo"); // make this appear below the undo menu item
|
||||||
setMenuBarData(menuData);
|
setMenuBarData(menuData);
|
||||||
setToolBarData(new ToolBarData(icon, group));
|
setToolBarData(new ToolBarData(icon, group));
|
||||||
setKeyBindingData(new KeyBindingData('Z', InputEvent.CTRL_MASK | InputEvent.SHIFT_MASK));
|
setKeyBindingData(new KeyBindingData("ctrl shift Z"));
|
||||||
setDescription("Redo");
|
setDescription("Redo");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,18 +60,41 @@ public class RedoAction extends ProgramContextAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
protected boolean isEnabledForContext(ProgramActionContext context) {
|
* updates the menu name of the action as the undo stack changes
|
||||||
Program program = context.getProgram();
|
* <P>
|
||||||
if (program.canRedo()) {
|
* NOTE: currently, we must manage the enablement explicitly
|
||||||
|
* because contextChanged is not called for data changes. Ideally, the enablement
|
||||||
|
* would be handled by the context, but for now it doesn't work
|
||||||
|
*
|
||||||
|
* @param program the program
|
||||||
|
*/
|
||||||
|
public void update(Program program) {
|
||||||
|
|
||||||
|
if (program == null) {
|
||||||
|
getMenuBarData().setMenuItemName("Redo ");
|
||||||
|
setDescription("");
|
||||||
|
setEnabled(false);
|
||||||
|
}
|
||||||
|
else if (program.canRedo()) {
|
||||||
String programName = program.getDomainFile().getName();
|
String programName = program.getDomainFile().getName();
|
||||||
getMenuBarData().setMenuItemName("Redo " + programName);
|
getMenuBarData().setMenuItemName("Redo " + programName);
|
||||||
String tip = HTMLUtilities.toWrappedHTML(
|
String tip = HTMLUtilities.toWrappedHTML(
|
||||||
"Redo " + HTMLUtilities.escapeHTML(program.getRedoName()));
|
"Redo " + HTMLUtilities.escapeHTML(program.getRedoName()));
|
||||||
setDescription(tip);
|
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() {
|
private void saveCurrentLocationToHistory() {
|
||||||
@@ -84,13 +105,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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,12 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.progmgr;
|
package ghidra.app.plugin.core.progmgr;
|
||||||
|
|
||||||
import java.awt.event.InputEvent;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
|
|
||||||
import docking.ActionContext;
|
|
||||||
import docking.action.*;
|
import docking.action.*;
|
||||||
import docking.tool.ToolConstants;
|
import docking.tool.ToolConstants;
|
||||||
import ghidra.app.context.ProgramActionContext;
|
import ghidra.app.context.ProgramActionContext;
|
||||||
@@ -46,7 +44,7 @@ public class UndoAction extends ProgramContextAction {
|
|||||||
setMenuBarData(menuData);
|
setMenuBarData(menuData);
|
||||||
setToolBarData(new ToolBarData(icon, "Undo"));
|
setToolBarData(new ToolBarData(icon, "Undo"));
|
||||||
setDescription("Undo");
|
setDescription("Undo");
|
||||||
setKeyBindingData(new KeyBindingData('Z', InputEvent.CTRL_MASK));
|
setKeyBindingData(new KeyBindingData("ctrl Z"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -69,27 +67,39 @@ public class UndoAction extends ProgramContextAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
protected boolean isEnabledForContext(ProgramActionContext context) {
|
* updates the menu name of the action as the undo stack changes
|
||||||
Program program = context.getProgram();
|
* <P>
|
||||||
if (program.canUndo()) {
|
* NOTE: currently, we must manage the enablement explicitly
|
||||||
|
* because contextChanged is not called for data changes. Ideally, the enablement
|
||||||
|
* would be handled by the context, but for now it doesn't work
|
||||||
|
*
|
||||||
|
* @param program the program
|
||||||
|
*/
|
||||||
|
public void update(Program program) {
|
||||||
|
|
||||||
|
if (program == null) {
|
||||||
|
getMenuBarData().setMenuItemName("Undo ");
|
||||||
|
setDescription("");
|
||||||
|
setEnabled(false);
|
||||||
|
}
|
||||||
|
if (program != null && program.canUndo()) {
|
||||||
String programName = program.getDomainFile().getName();
|
String programName = program.getDomainFile().getName();
|
||||||
getMenuBarData().setMenuItemName("Undo " + programName);
|
getMenuBarData().setMenuItemName("Undo " + programName);
|
||||||
String tip = HTMLUtilities.toWrappedHTML(
|
String tip = HTMLUtilities.toWrappedHTML(
|
||||||
"Undo " + HTMLUtilities.escapeHTML(program.getUndoName()));
|
"Undo " + HTMLUtilities.escapeHTML(program.getUndoName()));
|
||||||
setDescription(tip);
|
setDescription(tip);
|
||||||
return true;
|
setEnabled(true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setDescription("Undo");
|
||||||
|
setEnabled(false);
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEnabledForContext(ActionContext actionContext) {
|
protected boolean isEnabledForContext(ProgramActionContext context) {
|
||||||
if (!super.isEnabledForContext(actionContext)) {
|
Program program = context.getProgram();
|
||||||
setDescription("Undo");
|
return program.canUndo();
|
||||||
getMenuBarData().setMenuItemName("Undo");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -145,7 +145,7 @@ public class ScalarSearchPlugin extends ProgramPlugin implements DomainObjectLis
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isValidNavigationContext(NavigatableActionContext context) {
|
protected boolean isEnabledForContext(NavigatableActionContext context) {
|
||||||
return !(context instanceof RestrictedAddressSetContext);
|
return !(context instanceof RestrictedAddressSetContext);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+3
-8
@@ -350,7 +350,7 @@ public class MemSearchPlugin extends Plugin implements OptionsChangeListener,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isValidNavigationContext(NavigatableActionContext context) {
|
protected boolean isEnabledForContext(NavigatableActionContext context) {
|
||||||
return !(context instanceof RestrictedAddressSetContext);
|
return !(context instanceof RestrictedAddressSetContext);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -369,13 +369,8 @@ public class MemSearchPlugin extends Plugin implements OptionsChangeListener,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEnabledForContext(NavigatableActionContext context) {
|
protected boolean isEnabledForContext(NavigatableActionContext context) {
|
||||||
return searchInfo != null;
|
return !(context instanceof RestrictedAddressSetContext) && searchInfo != null;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isValidNavigationContext(NavigatableActionContext context) {
|
|
||||||
return !(context instanceof RestrictedAddressSetContext);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
searchAgainAction.setHelpLocation(
|
searchAgainAction.setHelpLocation(
|
||||||
|
|||||||
+31
-46
@@ -16,8 +16,6 @@
|
|||||||
package ghidra.app.plugin.core.searchtext;
|
package ghidra.app.plugin.core.searchtext;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.InputEvent;
|
|
||||||
import java.awt.event.KeyEvent;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
@@ -26,13 +24,15 @@ import java.util.regex.Pattern;
|
|||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
|
|
||||||
import docking.*;
|
import docking.*;
|
||||||
import docking.action.*;
|
import docking.action.DockingAction;
|
||||||
|
import docking.action.builder.ActionBuilder;
|
||||||
import docking.tool.ToolConstants;
|
import docking.tool.ToolConstants;
|
||||||
import docking.widgets.fieldpanel.support.Highlight;
|
import docking.widgets.fieldpanel.support.Highlight;
|
||||||
import docking.widgets.table.threaded.*;
|
import docking.widgets.table.threaded.*;
|
||||||
import ghidra.GhidraOptions;
|
import ghidra.GhidraOptions;
|
||||||
import ghidra.app.CorePluginPackage;
|
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.Navigatable;
|
||||||
import ghidra.app.nav.NavigatableRemovalListener;
|
import ghidra.app.nav.NavigatableRemovalListener;
|
||||||
import ghidra.app.plugin.PluginCategoryNames;
|
import ghidra.app.plugin.PluginCategoryNames;
|
||||||
@@ -379,49 +379,34 @@ public class SearchTextPlugin extends ProgramPlugin implements OptionsChangeList
|
|||||||
private void createActions() {
|
private void createActions() {
|
||||||
String subGroup = getClass().getName();
|
String subGroup = getClass().getName();
|
||||||
|
|
||||||
searchAction = new ListingContextAction("Search Text", getName()) {
|
searchAction = new ActionBuilder("Search Text", getName())
|
||||||
@Override
|
.menuPath("&Search", "Program &Text...")
|
||||||
public void actionPerformed(ListingActionContext context) {
|
.menuGroup("search", subGroup)
|
||||||
setNavigatable(context.getNavigatable());
|
.keyBinding("ctrl shift E")
|
||||||
displayDialog(context);
|
.description(DESCRIPTION)
|
||||||
}
|
.helpLocation(new HelpLocation(HelpTopics.SEARCH, "Search Text"))
|
||||||
};
|
.withContext(NavigatableActionContext.class)
|
||||||
searchAction.setHelpLocation(new HelpLocation(HelpTopics.SEARCH, searchAction.getName()));
|
.supportsDefaultToolContext(true)
|
||||||
String[] menuPath = new String[] { "&Search", "Program &Text..." };
|
.onAction(c -> {
|
||||||
MenuData menuData = new MenuData(menuPath, "search");
|
setNavigatable(c.getNavigatable());
|
||||||
menuData.setMenuSubGroup(subGroup);
|
displayDialog(c);
|
||||||
searchAction.setMenuBarData(menuData);
|
})
|
||||||
searchAction.setKeyBindingData(new KeyBindingData(KeyEvent.VK_E,
|
.buildAndInstall(tool);
|
||||||
InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK));
|
|
||||||
|
|
||||||
searchAction.setDescription(DESCRIPTION);
|
searchAgainAction = new ActionBuilder("Repeat Text Search", getName())
|
||||||
searchAction.setEnabled(false);
|
.menuPath("&Search", "Repeat Text Search")
|
||||||
//searchAction.setAddToPopup(false);
|
.menuGroup("search", subGroup)
|
||||||
tool.addAction(searchAction);
|
.keyBinding("ctrl shift F3")
|
||||||
|
.description(DESCRIPTION)
|
||||||
searchAgainAction = new ListingContextAction("Repeat Text Search", getName()) {
|
.supportsDefaultToolContext(true)
|
||||||
@Override
|
.helpLocation(new HelpLocation(HelpTopics.SEARCH, "Repeat Text Search"))
|
||||||
public void actionPerformed(ListingActionContext context) {
|
.withContext(NavigatableActionContext.class)
|
||||||
setNavigatable(context.getNavigatable());
|
.enabledWhen(c -> searchedOnce)
|
||||||
searchDialog.repeatSearch();
|
.onAction(c -> {
|
||||||
}
|
setNavigatable(c.getNavigatable());
|
||||||
|
searchDialog.repeatSearch();
|
||||||
@Override
|
})
|
||||||
public boolean isEnabledForContext(ListingActionContext context) {
|
.buildAndInstall(tool);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void updateNavigatable(ActionContext context) {
|
protected void updateNavigatable(ActionContext context) {
|
||||||
|
|||||||
+5
-7
@@ -15,14 +15,14 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.select.flow;
|
package ghidra.app.plugin.core.select.flow;
|
||||||
|
|
||||||
|
import docking.action.MenuData;
|
||||||
|
import docking.tool.ToolConstants;
|
||||||
import ghidra.app.context.ListingActionContext;
|
import ghidra.app.context.ListingActionContext;
|
||||||
import ghidra.app.context.ListingContextAction;
|
import ghidra.app.context.ListingContextAction;
|
||||||
import ghidra.app.util.HelpTopics;
|
import ghidra.app.util.HelpTopics;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.listing.CodeUnit;
|
import ghidra.program.model.listing.CodeUnit;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import docking.action.MenuData;
|
|
||||||
import docking.tool.ToolConstants;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <CODE>SelectByFlowAction</CODE> allows the user to Select Code By Flowing from
|
* <CODE>SelectByFlowAction</CODE> allows the user to Select Code By Flowing from
|
||||||
@@ -63,6 +63,9 @@ class SelectByFlowAction extends ListingContextAction {
|
|||||||
this.selectByFlowPlugin = plugin;
|
this.selectByFlowPlugin = plugin;
|
||||||
this.selectionType = selectionType;
|
this.selectionType = selectionType;
|
||||||
|
|
||||||
|
// this is in the main tool menu, so make it a tool action
|
||||||
|
setSupportsDefaultToolContext(true);
|
||||||
|
|
||||||
String[] menuPath = null;
|
String[] menuPath = null;
|
||||||
if (selectionType == SelectByFlowPlugin.SELECT_FUNCTIONS) {
|
if (selectionType == SelectByFlowPlugin.SELECT_FUNCTIONS) {
|
||||||
menuPath = new String[] { ToolConstants.MENU_SELECTION, "Function" };
|
menuPath = new String[] { ToolConstants.MENU_SELECTION, "Function" };
|
||||||
@@ -91,11 +94,6 @@ class SelectByFlowAction extends ListingContextAction {
|
|||||||
setHelpLocation(new HelpLocation(HelpTopics.SELECTION, getName()));
|
setHelpLocation(new HelpLocation(HelpTopics.SELECTION, getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method called when the action is invoked.
|
|
||||||
*
|
|
||||||
* @param ActionEvent details regarding the invocation of this action
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ListingActionContext context) {
|
public void actionPerformed(ListingActionContext context) {
|
||||||
// Either select by following all flows or all flows except calls
|
// Either select by following all flows or all flows except calls
|
||||||
|
|||||||
+29
-31
@@ -1,6 +1,5 @@
|
|||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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;
|
package ghidra.app.plugin.core.select.reference;
|
||||||
|
|
||||||
import ghidra.app.context.ListingContextAction;
|
import java.awt.event.InputEvent;
|
||||||
import ghidra.app.context.ListingActionContext;
|
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.nav.NavigationUtils;
|
||||||
import ghidra.app.util.HelpTopics;
|
import ghidra.app.util.HelpTopics;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
@@ -27,13 +31,7 @@ import ghidra.program.model.symbol.Reference;
|
|||||||
import ghidra.program.util.ProgramSelection;
|
import ghidra.program.util.ProgramSelection;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
|
|
||||||
import java.awt.event.InputEvent;
|
public class SelectForwardRefsAction extends NavigatableContextAction {
|
||||||
import java.awt.event.KeyEvent;
|
|
||||||
|
|
||||||
import docking.action.KeyBindingData;
|
|
||||||
import docking.action.MenuData;
|
|
||||||
|
|
||||||
public class SelectForwardRefsAction extends ListingContextAction {
|
|
||||||
|
|
||||||
private final PluginTool tool;
|
private final PluginTool tool;
|
||||||
|
|
||||||
@@ -42,47 +40,47 @@ public class SelectForwardRefsAction extends ListingContextAction {
|
|||||||
this.tool = tool;
|
this.tool = tool;
|
||||||
|
|
||||||
String group = "references";
|
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"));
|
setHelpLocation(new HelpLocation(HelpTopics.SELECTION, "Forward"));
|
||||||
// setKeyBindingData( new KeyBindingData(KeyEvent.VK_SEMICOLON, InputEvent.CTRL_MASK ) );
|
// setKeyBindingData( new KeyBindingData(KeyEvent.VK_SEMICOLON, InputEvent.CTRL_MASK ) );
|
||||||
// setHelpLocation(new HelpLocation(HelpTopics.SELECTION, "Backward"));
|
// setHelpLocation(new HelpLocation(HelpTopics.SELECTION, "Backward"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isEnabledForContext(ListingActionContext context) {
|
protected boolean isEnabledForContext(NavigatableActionContext context) {
|
||||||
return context.getAddress() != null || context.hasSelection();
|
return context.getAddress() != null || context.hasSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method called when the action is invoked.
|
* Method called when the action is invoked.
|
||||||
* @param ActionEvent details regarding the invocation of this action
|
* @param ActionEvent details regarding the invocation of this action
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ListingActionContext context) {
|
public void actionPerformed(NavigatableActionContext context) {
|
||||||
|
|
||||||
AddressSetView addressSet = context.hasSelection() ?
|
AddressSetView addressSet =
|
||||||
context.getSelection() :
|
context.hasSelection() ? context.getSelection() : new AddressSet(context.getAddress());
|
||||||
new AddressSet(context.getAddress());
|
|
||||||
|
|
||||||
ProgramSelection selection = getSelection(context.getProgram(), addressSet);
|
ProgramSelection selection = getSelection(context.getProgram(), addressSet);
|
||||||
NavigationUtils.setSelection(tool, context.getNavigatable(), selection);
|
NavigationUtils.setSelection(tool, context.getNavigatable(), selection);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ProgramSelection getSelection(Program program, AddressSetView addressSetView){
|
private ProgramSelection getSelection(Program program, AddressSetView addressSetView) {
|
||||||
AddressSet addressSet = new AddressSet();
|
AddressSet addressSet = new AddressSet();
|
||||||
|
|
||||||
CodeUnitIterator iter = program.getListing().getCodeUnits(addressSetView,true);
|
CodeUnitIterator iter = program.getListing().getCodeUnits(addressSetView, true);
|
||||||
|
|
||||||
while (iter.hasNext()){
|
while (iter.hasNext()) {
|
||||||
CodeUnit cu=iter.next();
|
CodeUnit cu = iter.next();
|
||||||
Reference[] memRef=cu.getReferencesFrom();
|
Reference[] memRef = cu.getReferencesFrom();
|
||||||
for (int i=0;i<memRef.length;i++){
|
for (Reference element : memRef) {
|
||||||
Address addr = memRef[i].getToAddress();
|
Address addr = element.getToAddress();
|
||||||
if ( addr.isMemoryAddress() ) {
|
if (addr.isMemoryAddress()) {
|
||||||
addressSet.addRange(addr,addr);
|
addressSet.addRange(addr, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new ProgramSelection(addressSet);
|
return new ProgramSelection(addressSet);
|
||||||
|
|||||||
+4
-1
@@ -220,7 +220,10 @@ public class DecompilerProvider extends NavigatableComponentProviderAdapter
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Function function = controller.getFunction();
|
Function function = controller.getFunction();
|
||||||
Address entryPoint = function != null ? function.getEntryPoint() : null;
|
if (function == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Address entryPoint = function.getEntryPoint();
|
||||||
boolean isDecompiling = controller.isDecompiling();
|
boolean isDecompiling = controller.isDecompiling();
|
||||||
return new DecompilerActionContext(this, entryPoint, isDecompiling);
|
return new DecompilerActionContext(this, entryPoint, isDecompiling);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -253,7 +253,7 @@ public class ActionContext {
|
|||||||
public ActionContext getGlobalContext() {
|
public ActionContext getGlobalContext() {
|
||||||
if (globalContext == null) {
|
if (globalContext == null) {
|
||||||
Tool tool = getTool();
|
Tool tool = getTool();
|
||||||
globalContext = tool == null ? new ActionContext() : tool.getGlobalActionContext();
|
globalContext = tool == null ? new ActionContext() : tool.getDefaultToolContext();
|
||||||
}
|
}
|
||||||
return globalContext;
|
return globalContext;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -228,4 +228,14 @@ public class DockingActionProxy
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return dockingAction.toString();
|
return dockingAction.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSupportsDefaultToolContext(boolean newValue) {
|
||||||
|
dockingAction.setSupportsDefaultToolContext(newValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsDefaultToolContext() {
|
||||||
|
return dockingAction.supportsDefaultToolContext();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2161,14 +2161,45 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the global action context for the tool
|
* Returns the default action context for the tool
|
||||||
* @return the global action context for the tool
|
* @return the default action context for the tool
|
||||||
*/
|
*/
|
||||||
public ActionContext getGlobalActionContext() {
|
public ActionContext getDefaultToolContext() {
|
||||||
return defaultProvider == null ? new ActionContext()
|
return defaultProvider == null ? new ActionContext()
|
||||||
: defaultProvider.getActionContext(null);
|
: defaultProvider.getActionContext(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the {@link ActionContext} appropriate for the given action. This will normally
|
||||||
|
* be the context from the currently focused {@link ComponentProvider}. If that
|
||||||
|
* context is not valid for the given action and the action supports using the default
|
||||||
|
* tool context, then the default tool context will be returned. Otherwise, returns null.
|
||||||
|
*
|
||||||
|
* @param action the action for which to get an {@link ActionContext}
|
||||||
|
* @return the {@link ActionContext} appropriate for the given action or null
|
||||||
|
*/
|
||||||
|
public ActionContext getActionContext(DockingActionIf action) {
|
||||||
|
ComponentProvider provider = getActiveComponentProvider();
|
||||||
|
ActionContext context = provider == null ? null : provider.getActionContext(null);
|
||||||
|
|
||||||
|
if (context == null) {
|
||||||
|
context = new ActionContext(provider, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action.isValidContext(context)) {
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action.supportsDefaultToolContext()) {
|
||||||
|
ActionContext toolContext = getDefaultToolContext();
|
||||||
|
if (action.isValidContext(toolContext)) {
|
||||||
|
return toolContext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void notifyContextListeners(ComponentPlaceholder placeHolder, ActionContext actionContext) {
|
void notifyContextListeners(ComponentPlaceholder placeHolder, ActionContext actionContext) {
|
||||||
|
|
||||||
if (placeHolder == focusedPlaceholder) {
|
if (placeHolder == focusedPlaceholder) {
|
||||||
|
|||||||
+2
-2
@@ -19,12 +19,12 @@ import docking.action.DockingActionIf;
|
|||||||
import docking.action.ToggleDockingActionIf;
|
import docking.action.ToggleDockingActionIf;
|
||||||
import generic.json.Json;
|
import generic.json.Json;
|
||||||
|
|
||||||
public class ExecutableKeyActionAdapter {
|
public class ExecutableAction {
|
||||||
|
|
||||||
DockingActionIf action;
|
DockingActionIf action;
|
||||||
ActionContext context;
|
ActionContext context;
|
||||||
|
|
||||||
public ExecutableKeyActionAdapter(DockingActionIf action, ActionContext context) {
|
public ExecutableAction(DockingActionIf action, ActionContext context) {
|
||||||
this.action = action;
|
this.action = action;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
@@ -46,9 +46,10 @@ public class MenuBarMenuHandler extends MenuHandler {
|
|||||||
|
|
||||||
DockingWindowManager.clearMouseOverHelp();
|
DockingWindowManager.clearMouseOverHelp();
|
||||||
|
|
||||||
ComponentProvider provider = windowManager.getActiveComponentProvider();
|
ActionContext context = windowManager.getActionContext(action);
|
||||||
ActionContext providerContext = provider == null ? null : provider.getActionContext(null);
|
if (context == null) {
|
||||||
ActionContext context = providerContext == null ? new ActionContext() : providerContext;
|
return; // nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
context.setSourceObject(event.getSource());
|
context.setSourceObject(event.getSource());
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import docking.widgets.label.GLabel;
|
|||||||
public class MultiActionDialog extends DialogComponentProvider {
|
public class MultiActionDialog extends DialogComponentProvider {
|
||||||
|
|
||||||
private String keystrokeName;
|
private String keystrokeName;
|
||||||
private List<ExecutableKeyActionAdapter> list;
|
private List<ExecutableAction> list;
|
||||||
private JList<String> actionList;
|
private JList<String> actionList;
|
||||||
private DefaultListModel<String> listModel;
|
private DefaultListModel<String> listModel;
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ public class MultiActionDialog extends DialogComponentProvider {
|
|||||||
* @param keystrokeName keystroke name
|
* @param keystrokeName keystroke name
|
||||||
* @param list list of actions
|
* @param list list of actions
|
||||||
*/
|
*/
|
||||||
public MultiActionDialog(String keystrokeName, List<ExecutableKeyActionAdapter> list) {
|
public MultiActionDialog(String keystrokeName, List<ExecutableAction> list) {
|
||||||
super("Select Action", true);
|
super("Select Action", true);
|
||||||
this.keystrokeName = keystrokeName;
|
this.keystrokeName = keystrokeName;
|
||||||
init();
|
init();
|
||||||
@@ -65,7 +65,7 @@ public class MultiActionDialog extends DialogComponentProvider {
|
|||||||
|
|
||||||
close();
|
close();
|
||||||
|
|
||||||
ExecutableKeyActionAdapter actionProxy = list.get(index);
|
ExecutableAction actionProxy = list.get(index);
|
||||||
actionProxy.execute();
|
actionProxy.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,12 +73,12 @@ public class MultiActionDialog extends DialogComponentProvider {
|
|||||||
* Set the list of actions that are enabled
|
* Set the list of actions that are enabled
|
||||||
* @param list list of actions selected
|
* @param list list of actions selected
|
||||||
*/
|
*/
|
||||||
public void setActionList(List<ExecutableKeyActionAdapter> list) {
|
public void setActionList(List<ExecutableAction> list) {
|
||||||
okButton.setEnabled(false);
|
okButton.setEnabled(false);
|
||||||
this.list = list;
|
this.list = list;
|
||||||
listModel.clear();
|
listModel.clear();
|
||||||
for (int i = 0; i < list.size(); i++) {
|
for (int i = 0; i < list.size(); i++) {
|
||||||
ExecutableKeyActionAdapter actionProxy = list.get(i);
|
ExecutableAction actionProxy = list.get(i);
|
||||||
DockingActionIf action = actionProxy.getAction();
|
DockingActionIf action = actionProxy.getAction();
|
||||||
listModel.addElement(action.getName() + " (" + action.getOwnerDescription() + ")");
|
listModel.addElement(action.getName() + " (" + action.getOwnerDescription() + ")");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -305,11 +305,10 @@ 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
|
* Returns the default {@link ActionContext} for the tool. The default context is the context
|
||||||
* the default focused component, instead of the normal action context which is the current
|
* the default ComponentProvider for the tool.
|
||||||
* focused component.
|
* @return the default {@link ActionContext} for the tool
|
||||||
* @return the global action context for the tool
|
|
||||||
*/
|
*/
|
||||||
public ActionContext getGlobalActionContext();
|
public ActionContext getDefaultToolContext();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,12 +120,8 @@ public class WindowActionManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ComponentProvider provider = placeHolderForScheduledActionUpdate == null ? null
|
ActionContext localContext = getContext();
|
||||||
: placeHolderForScheduledActionUpdate.getProvider();
|
ActionContext globalContext = winMgr.getDefaultToolContext();
|
||||||
ActionContext localContext = provider == null ? null : provider.getActionContext(null);
|
|
||||||
if (localContext == null) {
|
|
||||||
localContext = new ActionContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update actions - make a copy so that we don't get concurrent modification exceptions
|
// Update actions - make a copy so that we don't get concurrent modification exceptions
|
||||||
List<DockingActionIf> list = new ArrayList<>(actionToProxyMap.values());
|
List<DockingActionIf> list = new ArrayList<>(actionToProxyMap.values());
|
||||||
@@ -133,6 +129,9 @@ public class WindowActionManager {
|
|||||||
if (action.isValidContext(localContext)) {
|
if (action.isValidContext(localContext)) {
|
||||||
action.setEnabled(action.isEnabledForContext(localContext));
|
action.setEnabled(action.isEnabledForContext(localContext));
|
||||||
}
|
}
|
||||||
|
else if (isValidDefaultToolContext(action, globalContext)) {
|
||||||
|
action.setEnabled(action.isEnabledForContext(globalContext));
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
action.setEnabled(false);
|
action.setEnabled(false);
|
||||||
}
|
}
|
||||||
@@ -140,4 +139,21 @@ public class WindowActionManager {
|
|||||||
// Notify listeners if the context provider is the focused provider
|
// Notify listeners if the context provider is the focused provider
|
||||||
winMgr.notifyContextListeners(placeHolderForScheduledActionUpdate, localContext);
|
winMgr.notifyContextListeners(placeHolderForScheduledActionUpdate, localContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isValidDefaultToolContext(DockingActionIf action, ActionContext toolContext) {
|
||||||
|
return action.supportsDefaultToolContext() &&
|
||||||
|
action.isValidContext(toolContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
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> popupPredicate;
|
||||||
private Predicate<ActionContext> validContextPredicate;
|
private Predicate<ActionContext> validContextPredicate;
|
||||||
|
|
||||||
|
private boolean supportsDefaultToolContext;
|
||||||
|
|
||||||
public DockingAction(String name, String owner) {
|
public DockingAction(String name, String owner) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
@@ -224,6 +226,16 @@ public abstract class DockingAction implements DockingActionIf {
|
|||||||
return !isEnabled;
|
return !isEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSupportsDefaultToolContext(boolean newValue) {
|
||||||
|
supportsDefaultToolContext = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsDefaultToolContext() {
|
||||||
|
return supportsDefaultToolContext;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final JButton createButton() {
|
public final JButton createButton() {
|
||||||
JButton button = doCreateButton();
|
JButton button = doCreateButton();
|
||||||
|
|||||||
@@ -33,6 +33,26 @@ import docking.help.HelpDescriptor;
|
|||||||
* client actions will use the default setting of {@link KeyBindingType#INDIVIDUAL}. To control
|
* client actions will use the default setting of {@link KeyBindingType#INDIVIDUAL}. To control
|
||||||
* the level of key binding support, you can pass the desired {@link KeyBindingType} to the
|
* the level of key binding support, you can pass the desired {@link KeyBindingType} to the
|
||||||
* base implementation of this interface.
|
* base implementation of this interface.
|
||||||
|
*
|
||||||
|
* <p>ActionContext is a key concept for tool actions so that they can be context sensitive if
|
||||||
|
* appropriate. The context provides a
|
||||||
|
* consistent way for plugins and components to share tool state with actions. Actions can then
|
||||||
|
* use that context to make decisions, such as if they should be enabled or added to a popup menu.
|
||||||
|
* The context information is also typically used when the action is invoked. For example, an
|
||||||
|
* action context from a table element may provide the row in a table component that is selected and
|
||||||
|
* then a "delete table row" action can use that information to be enabled when a table selection
|
||||||
|
* exists and then delete that row if the action is invoked.
|
||||||
|
*
|
||||||
|
* <p> To make the overall action experience more convenient for the user, action processing
|
||||||
|
* supports the concept of a "default tool context". This allows actions to work on a more global
|
||||||
|
* level than just the component that is focused. The idea is that if an action is not valid for
|
||||||
|
* the current focused context (and it has be declared to work this way using
|
||||||
|
* the {@link #setSupportsDefaultToolContext(boolean)}), then it can be validated against the default
|
||||||
|
* tool context. The "default tool context" is defined to be the action context of the tool's
|
||||||
|
* primary component. This is primarily intended for tool-level actions which are the ones that appear
|
||||||
|
* in the tool's main menu bar or toolbar. This allows the tool actions to mostly work on the
|
||||||
|
* tool's main component context regardless of what has focus, and yet still work on the
|
||||||
|
* focused component if appropriate (such as a snapshot of the main component).
|
||||||
*/
|
*/
|
||||||
public interface DockingActionIf extends HelpDescriptor {
|
public interface DockingActionIf extends HelpDescriptor {
|
||||||
public static final String ENABLEMENT_PROPERTY = "enabled";
|
public static final String ENABLEMENT_PROPERTY = "enabled";
|
||||||
@@ -97,6 +117,26 @@ public interface DockingActionIf extends HelpDescriptor {
|
|||||||
*/
|
*/
|
||||||
public boolean setEnabled(boolean newValue);
|
public boolean setEnabled(boolean newValue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether or not this action should be activated using the default tool context if the
|
||||||
|
* current focused provider's context is not valid for this action. Typically, this should
|
||||||
|
* be set on actions that are mostly independent of which component has focus such as those
|
||||||
|
* on the tool's main toolbar.
|
||||||
|
*
|
||||||
|
* @param newValue if true, the action will be activated using the default tool context if the
|
||||||
|
* local context is not valid for this action. If false, the action will only ever be
|
||||||
|
* activated using the focused context.
|
||||||
|
*/
|
||||||
|
public void setSupportsDefaultToolContext(boolean newValue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this action can be activated using the default tool context if the focused
|
||||||
|
* context is invalid for this action. See {@link #setSupportsDefaultToolContext(boolean)}
|
||||||
|
* @return true if this action can be activated using the default tool context if the local
|
||||||
|
* context is invalid for this action.
|
||||||
|
*/
|
||||||
|
public boolean supportsDefaultToolContext();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the action is enabled.
|
* Returns true if the action is enabled.
|
||||||
*
|
*
|
||||||
@@ -120,7 +160,7 @@ public interface DockingActionIf extends HelpDescriptor {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link ToolBarData} to be used to put this action in a toolbar. The ToolBarData will be
|
* Returns the {@link ToolBarData} to be used to put this action in a toolbar. The ToolBarData will be
|
||||||
* null if the action in not set to be in a tool bar.
|
* null if the action in not set to be in a toolbar.
|
||||||
* @return the {@link ToolBarData} for the popup menu or null if the action is not in a popup menu.
|
* @return the {@link ToolBarData} for the popup menu or null if the action is not in a popup menu.
|
||||||
*/
|
*/
|
||||||
public ToolBarData getToolBarData();
|
public ToolBarData getToolBarData();
|
||||||
|
|||||||
@@ -36,6 +36,18 @@ public class KeyBindingData {
|
|||||||
this(KeyStroke.getKeyStroke(keyCode, modifiers));
|
this(KeyStroke.getKeyStroke(keyCode, modifiers));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public KeyBindingData(String keyStrokeString) {
|
||||||
|
this(parseKeyStrokeString(keyStrokeString));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static KeyStroke parseKeyStrokeString(String keyStrokeString) {
|
||||||
|
KeyStroke keyStroke = KeyBindingUtils.parseKeyStroke(keyStrokeString);
|
||||||
|
if (keyStroke == null) {
|
||||||
|
throw new IllegalArgumentException("Invalid keystroke string: " + keyStrokeString);
|
||||||
|
}
|
||||||
|
return keyStroke;
|
||||||
|
}
|
||||||
|
|
||||||
public KeyBindingData(KeyStroke keyStroke, KeyBindingPrecedence precedence) {
|
public KeyBindingData(KeyStroke keyStroke, KeyBindingPrecedence precedence) {
|
||||||
if (precedence == KeyBindingPrecedence.ReservedActionsLevel) {
|
if (precedence == KeyBindingPrecedence.ReservedActionsLevel) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
|
|||||||
@Override
|
@Override
|
||||||
public void actionPerformed(final ActionEvent event) {
|
public void actionPerformed(final ActionEvent event) {
|
||||||
// Build list of actions which are valid in current context
|
// Build list of actions which are valid in current context
|
||||||
List<ExecutableKeyActionAdapter> list = getActionsForCurrentContext(event.getSource());
|
List<ExecutableAction> list = getActionsForCurrentOrDefaultContext(event.getSource());
|
||||||
|
|
||||||
// If menu active, disable all key bindings
|
// If menu active, disable all key bindings
|
||||||
if (ignoreActionWhileMenuShowing()) {
|
if (ignoreActionWhileMenuShowing()) {
|
||||||
@@ -137,7 +137,7 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
|
|||||||
Swing.runLater(() -> DockingWindowManager.showDialog(dialog));
|
Swing.runLater(() -> DockingWindowManager.showDialog(dialog));
|
||||||
}
|
}
|
||||||
else if (list.size() == 1) {
|
else if (list.size() == 1) {
|
||||||
final ExecutableKeyActionAdapter actionProxy = list.get(0);
|
ExecutableAction actionProxy = list.get(0);
|
||||||
tool.setStatusInfo("");
|
tool.setStatusInfo("");
|
||||||
actionProxy.execute();
|
actionProxy.execute();
|
||||||
}
|
}
|
||||||
@@ -156,8 +156,9 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
|
|||||||
return menuManager.getSelectedPath().length != 0;
|
return menuManager.getSelectedPath().length != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ExecutableKeyActionAdapter> getValidContextActions(ActionContext localContext) {
|
private List<ExecutableAction> getValidContextActions(ActionContext localContext,
|
||||||
List<ExecutableKeyActionAdapter> list = new ArrayList<>();
|
ActionContext globalContext) {
|
||||||
|
List<ExecutableAction> list = new ArrayList<>();
|
||||||
boolean hasLocalActionsForKeyBinding = false;
|
boolean hasLocalActionsForKeyBinding = false;
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -167,14 +168,15 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
|
|||||||
if (actionData.isMyProvider(localContext)) {
|
if (actionData.isMyProvider(localContext)) {
|
||||||
hasLocalActionsForKeyBinding = true;
|
hasLocalActionsForKeyBinding = true;
|
||||||
if (isValidAndEnabled(actionData, localContext)) {
|
if (isValidAndEnabled(actionData, localContext)) {
|
||||||
list.add(new ExecutableKeyActionAdapter(actionData.action, localContext));
|
list.add(new ExecutableAction(actionData.action, localContext));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasLocalActionsForKeyBinding) {
|
if (hasLocalActionsForKeyBinding) {
|
||||||
// We have locals, ignore the globals. This prevents global actions from processing
|
// At this point, we have local actions that may or may not be enabled. Return here
|
||||||
// the given keybinding when a local action exits, regardless of enablement.
|
// so that any component specific actions found below will not interfere with the
|
||||||
|
// provider's local actions
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +193,7 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
|
|||||||
if (componentAction.isValidComponentContext(localContext)) {
|
if (componentAction.isValidComponentContext(localContext)) {
|
||||||
hasLocalActionsForKeyBinding = true;
|
hasLocalActionsForKeyBinding = true;
|
||||||
if (isValidAndEnabled(actionData, localContext)) {
|
if (isValidAndEnabled(actionData, localContext)) {
|
||||||
list.add(new ExecutableKeyActionAdapter(actionData.action, localContext));
|
list.add(new ExecutableAction(actionData.action, localContext));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -211,16 +213,28 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
|
|||||||
// is a 'global' action. This allows more specific context to be used when
|
// is a 'global' action. This allows more specific context to be used when
|
||||||
// available
|
// available
|
||||||
if (isValidAndEnabled(actionData, localContext)) {
|
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;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isValidAndEnabled(ActionData actionData, ActionContext localContext) {
|
private boolean isValidAndEnabled(ActionData actionData, ActionContext context) {
|
||||||
DockingActionIf a = actionData.action;
|
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.supportsDefaultToolContext() && isValidAndEnabled(actionData, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -242,7 +256,7 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
|
|||||||
*/
|
*/
|
||||||
public KeyBindingPrecedence geValidKeyBindingPrecedence(Component source) {
|
public KeyBindingPrecedence geValidKeyBindingPrecedence(Component source) {
|
||||||
|
|
||||||
List<ExecutableKeyActionAdapter> validActions = getActionsForCurrentContext(source);
|
List<ExecutableAction> validActions = getActionsForCurrentOrDefaultContext(source);
|
||||||
if (validActions.isEmpty()) {
|
if (validActions.isEmpty()) {
|
||||||
return null; // a signal that no actions are valid for the current context
|
return null; // a signal that no actions are valid for the current context
|
||||||
}
|
}
|
||||||
@@ -251,31 +265,36 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
|
|||||||
return KeyBindingPrecedence.DefaultLevel;
|
return KeyBindingPrecedence.DefaultLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExecutableKeyActionAdapter actionProxy = validActions.get(0);
|
ExecutableAction actionProxy = validActions.get(0);
|
||||||
DockingActionIf action = actionProxy.getAction();
|
DockingActionIf action = actionProxy.getAction();
|
||||||
return action.getKeyBindingData().getKeyBindingPrecedence();
|
return action.getKeyBindingData().getKeyBindingPrecedence();
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ExecutableKeyActionAdapter> getActionsForCurrentContext(Object eventSource) {
|
private List<ExecutableAction> getActionsForCurrentOrDefaultContext(Object eventSource) {
|
||||||
|
|
||||||
DockingWindowManager dwm = tool.getWindowManager();
|
DockingWindowManager dwm = tool.getWindowManager();
|
||||||
Window window = getWindow(dwm, eventSource);
|
Window window = getWindow(dwm, eventSource);
|
||||||
if (window instanceof DockingDialog) {
|
if (window instanceof DockingDialog) {
|
||||||
DockingDialog dockingDialog = (DockingDialog) window;
|
return getDialogActions(window);
|
||||||
DialogComponentProvider provider = dockingDialog.getDialogComponent();
|
|
||||||
if (provider == null) {
|
|
||||||
// this can happen if the dialog is closed during key event processing
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
ActionContext context = provider.getActionContext(null);
|
|
||||||
List<ExecutableKeyActionAdapter> validActions = getValidContextActions(context);
|
|
||||||
return validActions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ComponentProvider localProvider = getProvider(dwm, eventSource);
|
ComponentProvider localProvider = getProvider(dwm, eventSource);
|
||||||
ActionContext localContext = getLocalContext(localProvider);
|
ActionContext localContext = getLocalContext(localProvider);
|
||||||
localContext.setSourceObject(eventSource);
|
localContext.setSourceObject(eventSource);
|
||||||
List<ExecutableKeyActionAdapter> validActions = getValidContextActions(localContext);
|
ActionContext globalContext = tool.getDefaultToolContext();
|
||||||
|
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) {
|
||||||
|
// this can happen if the dialog is closed during key event processing
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
ActionContext context = provider.getActionContext(null);
|
||||||
|
List<ExecutableAction> validActions = getValidContextActions(context, null);
|
||||||
return validActions;
|
return validActions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,10 +356,15 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
|
|||||||
return provider == otherProvider;
|
return provider == otherProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean supportsDefaultToolContext() {
|
||||||
|
return action.supportsDefaultToolContext();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
String providerString = provider == null ? "" : provider.toString() + " - ";
|
String providerString = provider == null ? "" : provider.toString() + " - ";
|
||||||
return providerString + action;
|
return providerString + action;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+39
-17
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package docking.action.builder;
|
package docking.action.builder;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
@@ -23,6 +24,7 @@ import javax.swing.KeyStroke;
|
|||||||
|
|
||||||
import docking.*;
|
import docking.*;
|
||||||
import docking.action.*;
|
import docking.action.*;
|
||||||
|
import docking.actions.KeyBindingUtils;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import resources.ResourceManager;
|
import resources.ResourceManager;
|
||||||
@@ -50,7 +52,7 @@ import resources.ResourceManager;
|
|||||||
* the {@link #withContext(Class)} call.
|
* the {@link #withContext(Class)} call.
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractActionBuilder<T extends DockingActionIf, C extends ActionContext, B extends AbstractActionBuilder<T, C, B>> {
|
public abstract class AbstractActionBuilder<T extends DockingActionIf, C extends ActionContext, B extends AbstractActionBuilder<T, C, B>> {
|
||||||
|
private final Predicate<C> ALWAYS_TRUE = e -> true;
|
||||||
/**
|
/**
|
||||||
* Name for the {@code DockingAction}
|
* Name for the {@code DockingAction}
|
||||||
*/
|
*/
|
||||||
@@ -159,17 +161,22 @@ public abstract class AbstractActionBuilder<T extends DockingActionIf, C extends
|
|||||||
/**
|
/**
|
||||||
* Predicate for determining if an action is enabled for a given context
|
* Predicate for determining if an action is enabled for a given context
|
||||||
*/
|
*/
|
||||||
private Predicate<C> enabledPredicate;
|
private Predicate<C> enabledPredicate = ALWAYS_TRUE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Predicate for determining if an action should be included on the pop-up menu
|
* Predicate for determining if an action should be included on the pop-up menu
|
||||||
*/
|
*/
|
||||||
private Predicate<C> popupPredicate;
|
private Predicate<C> popupPredicate = ALWAYS_TRUE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Predicate for determining if an action is applicable for a given context
|
* Predicate for determining if an action is applicable for a given context
|
||||||
*/
|
*/
|
||||||
private Predicate<C> validContextPredicate;
|
private Predicate<C> validContextPredicate = ALWAYS_TRUE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set to true if the action supports using the default tool context if the local context is invalid
|
||||||
|
*/
|
||||||
|
private boolean supportsDefaultToolContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builder constructor
|
* Builder constructor
|
||||||
@@ -484,7 +491,7 @@ public abstract class AbstractActionBuilder<T extends DockingActionIf, C extends
|
|||||||
* @return this builder (for chaining)
|
* @return this builder (for chaining)
|
||||||
*/
|
*/
|
||||||
public B keyBinding(String keyStrokeString) {
|
public B keyBinding(String keyStrokeString) {
|
||||||
this.keyBinding = KeyStroke.getKeyStroke(keyStrokeString);
|
this.keyBinding = KeyBindingUtils.parseKeyStroke(keyStrokeString);
|
||||||
if (keyBinding == null && keyStrokeString != null) {
|
if (keyBinding == null && keyStrokeString != null) {
|
||||||
Msg.warn(this, "Can't parse KeyStroke: " + keyStrokeString);
|
Msg.warn(this, "Can't parse KeyStroke: " + keyStrokeString);
|
||||||
}
|
}
|
||||||
@@ -517,7 +524,7 @@ public abstract class AbstractActionBuilder<T extends DockingActionIf, C extends
|
|||||||
* @return this builder (for chaining)
|
* @return this builder (for chaining)
|
||||||
*/
|
*/
|
||||||
public B enabledWhen(Predicate<C> predicate) {
|
public B enabledWhen(Predicate<C> predicate) {
|
||||||
enabledPredicate = predicate;
|
enabledPredicate = Objects.requireNonNull(predicate);
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -540,7 +547,7 @@ public abstract class AbstractActionBuilder<T extends DockingActionIf, C extends
|
|||||||
* @see #popupMenuPath(String...)
|
* @see #popupMenuPath(String...)
|
||||||
*/
|
*/
|
||||||
public B popupWhen(Predicate<C> predicate) {
|
public B popupWhen(Predicate<C> predicate) {
|
||||||
popupPredicate = predicate;
|
popupPredicate = Objects.requireNonNull(predicate);
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -556,7 +563,23 @@ public abstract class AbstractActionBuilder<T extends DockingActionIf, C extends
|
|||||||
* @return this builder (for chaining)
|
* @return this builder (for chaining)
|
||||||
*/
|
*/
|
||||||
public B validContextWhen(Predicate<C> predicate) {
|
public B validContextWhen(Predicate<C> predicate) {
|
||||||
validContextPredicate = predicate;
|
validContextPredicate = Objects.requireNonNull(predicate);
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the action will support using the default tool context if the focused provider's
|
||||||
|
* context is invalid.
|
||||||
|
* <P>
|
||||||
|
* By default, actions only work on the current focused provider's context. Setting this
|
||||||
|
* to true will cause the action to be evaluated against the default tool context if the
|
||||||
|
* focused context is not valid for this action.
|
||||||
|
*
|
||||||
|
* @param b the new value
|
||||||
|
* @return this builder (for chaining)
|
||||||
|
*/
|
||||||
|
public B supportsDefaultToolContext(boolean b) {
|
||||||
|
supportsDefaultToolContext = b;
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -603,6 +626,10 @@ public abstract class AbstractActionBuilder<T extends DockingActionIf, C extends
|
|||||||
public <AC2 extends ActionContext, B2 extends AbstractActionBuilder<T, AC2, B2>> B2 withContext(
|
public <AC2 extends ActionContext, B2 extends AbstractActionBuilder<T, AC2, B2>> B2 withContext(
|
||||||
Class<AC2> newActionContextClass) {
|
Class<AC2> newActionContextClass) {
|
||||||
|
|
||||||
|
if (actionContextClass != ActionContext.class) {
|
||||||
|
throw new IllegalStateException("Can't set the ActionContext type more than once");
|
||||||
|
}
|
||||||
|
|
||||||
// To make this work, we need to return a builder whose ActionContext is AC2 and not AC
|
// To make this work, we need to return a builder whose ActionContext is AC2 and not AC
|
||||||
// (which is what this builder is now)
|
// (which is what this builder is now)
|
||||||
//
|
//
|
||||||
@@ -627,6 +654,7 @@ public abstract class AbstractActionBuilder<T extends DockingActionIf, C extends
|
|||||||
protected void decorateAction(DockingAction action) {
|
protected void decorateAction(DockingAction action) {
|
||||||
action.setEnabled(isEnabled);
|
action.setEnabled(isEnabled);
|
||||||
action.setDescription(description);
|
action.setDescription(description);
|
||||||
|
action.setSupportsDefaultToolContext(supportsDefaultToolContext);
|
||||||
|
|
||||||
setMenuData(action);
|
setMenuData(action);
|
||||||
setToolbarData(action);
|
setToolbarData(action);
|
||||||
@@ -637,15 +665,9 @@ public abstract class AbstractActionBuilder<T extends DockingActionIf, C extends
|
|||||||
action.setHelpLocation(helpLocation);
|
action.setHelpLocation(helpLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enabledPredicate != null) {
|
action.enabledWhen(adaptPredicate(enabledPredicate));
|
||||||
action.enabledWhen(adaptPredicate(enabledPredicate));
|
action.validContextWhen(adaptPredicate(validContextPredicate));
|
||||||
}
|
action.popupWhen(adaptPredicate(popupPredicate));
|
||||||
if (validContextPredicate != null) {
|
|
||||||
action.validContextWhen(adaptPredicate(validContextPredicate));
|
|
||||||
}
|
|
||||||
if (popupPredicate != null) {
|
|
||||||
action.popupWhen(adaptPredicate(popupPredicate));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package docking.action.builder;
|
package docking.action.builder;
|
||||||
|
|
||||||
import docking.ActionContext;
|
import docking.ActionContext;
|
||||||
import docking.action.DockingAction;
|
import docking.action.DockingAction;
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ import java.util.List;
|
|||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
|
|
||||||
import docking.*;
|
import docking.ActionContext;
|
||||||
|
import docking.DockingWindowManager;
|
||||||
import docking.action.*;
|
import docking.action.*;
|
||||||
import docking.widgets.EventTrigger;
|
import docking.widgets.EventTrigger;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
@@ -148,10 +149,13 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
|||||||
|
|
||||||
private ActionContext getActionContext() {
|
private ActionContext getActionContext() {
|
||||||
DockingWindowManager manager = DockingWindowManager.getActiveInstance();
|
DockingWindowManager manager = DockingWindowManager.getActiveInstance();
|
||||||
ComponentProvider provider = manager.getActiveComponentProvider();
|
|
||||||
ActionContext localContext = provider == null ? null : provider.getActionContext(null);
|
ActionContext context = manager.getActionContext(this);
|
||||||
ActionContext actionContext = localContext == null ? new ActionContext() : localContext;
|
|
||||||
return actionContext;
|
if (context == null) {
|
||||||
|
context = new ActionContext();
|
||||||
|
}
|
||||||
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<DockingActionIf> getStateActions() {
|
protected List<DockingActionIf> getStateActions() {
|
||||||
|
|||||||
@@ -113,11 +113,7 @@ public class ToolBarItemManager implements PropertyChangeListener, ActionListene
|
|||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent event) {
|
public void actionPerformed(ActionEvent event) {
|
||||||
DockingWindowManager.clearMouseOverHelp();
|
DockingWindowManager.clearMouseOverHelp();
|
||||||
ActionContext context = getActionContext();
|
ActionContext context = windowManager.getActionContext(toolBarAction);
|
||||||
|
|
||||||
if (!toolBarAction.isValidContext(context)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
context.setSourceObject(event.getSource());
|
context.setSourceObject(event.getSource());
|
||||||
|
|
||||||
@@ -139,14 +135,6 @@ public class ToolBarItemManager implements PropertyChangeListener, ActionListene
|
|||||||
return toolBarAction.getName();
|
return toolBarAction.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ActionContext getActionContext() {
|
|
||||||
ComponentProvider provider = getComponentProvider();
|
|
||||||
ActionContext context = provider == null ? null : provider.getActionContext(null);
|
|
||||||
final ActionContext actionContext =
|
|
||||||
context == null ? new ActionContext(provider, null) : context;
|
|
||||||
return actionContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ComponentProvider getComponentProvider() {
|
private ComponentProvider getComponentProvider() {
|
||||||
DockingWindowManager manager = windowManager;
|
DockingWindowManager manager = windowManager;
|
||||||
if (manager == null) {
|
if (manager == null) {
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ public class FakeDockingTool extends AbstractDockingTool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ActionContext getGlobalActionContext() {
|
public ActionContext getDefaultToolContext() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1472,8 +1472,8 @@ public abstract class PluginTool extends AbstractDockingTool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ActionContext getGlobalActionContext() {
|
public ActionContext getDefaultToolContext() {
|
||||||
return winMgr.getGlobalActionContext();
|
return winMgr.getDefaultToolContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+5
-2
@@ -95,10 +95,13 @@ class DataComponent extends DataDB {
|
|||||||
}
|
}
|
||||||
DataType pdt = parent.getBaseDataType();
|
DataType pdt = parent.getBaseDataType();
|
||||||
if (pdt instanceof Composite) {
|
if (pdt instanceof Composite) {
|
||||||
DataTypeComponent c = ((Composite) pdt).getComponent(indexInParent);
|
Composite composite = (Composite) pdt;
|
||||||
if (c == null) {
|
// if we are deleted, the parent may not have as many components as it used to,
|
||||||
|
// so if our index is bigger than the number of components, then we are deleted.
|
||||||
|
if (indexInParent >= composite.getNumComponents()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
DataTypeComponent c = composite.getComponent(indexInParent);
|
||||||
component = c;
|
component = c;
|
||||||
dataType = c.getDataType();
|
dataType = c.getDataType();
|
||||||
offset = component.getOffset();
|
offset = component.getOffset();
|
||||||
|
|||||||
Reference in New Issue
Block a user