GT-2925 - Key Bindings - Support Window Menu Provider Key Bindings -

Step 3 - removed old plugin pattern of creating special actions to show
their respective providers; updated inception information for new action
This commit is contained in:
dragonmacher 2019-06-26 15:30:34 -04:00
parent f510ddf338
commit fa75f7dff6
32 changed files with 296 additions and 425 deletions

View file

@ -22,7 +22,6 @@ import javax.swing.Icon;
import javax.swing.SwingUtilities;
import docking.ActionContext;
import docking.DockingUtils;
import docking.action.*;
import docking.widgets.table.GTable;
import ghidra.app.CorePluginPackage;
@ -72,7 +71,6 @@ public class BookmarkPlugin extends ProgramPlugin
private BookmarkProvider provider;
private DockingAction addAction;
private DockingAction showAction;
private DockingAction deleteAction;
private CreateBookmarkDialog createDialog;
private GoToService goToService;
@ -113,19 +111,6 @@ public class BookmarkPlugin extends ProgramPlugin
addAction.setEnabled(true);
tool.addAction(addAction);
showAction = new DockingAction("Show Bookmarks", getName()) {
@Override
public void actionPerformed(ActionContext context) {
tool.showComponentProvider(provider, true);
}
};
showAction.setKeyBindingData(
new KeyBindingData(KeyEvent.VK_B, DockingUtils.CONTROL_KEY_MODIFIER_MASK));
showAction.setToolBarData(new ToolBarData(BookmarkNavigator.NOTE_ICON, "View"));
showAction.setDescription("Display All Bookmarks");
tool.addAction(showAction);
MultiIconBuilder builder = new MultiIconBuilder(Icons.CONFIGURE_FILTER_ICON);
builder.addLowerRightIcon(ResourceManager.loadImage("images/check.png"));
Icon filterTypesChanged = builder.build();
@ -213,10 +198,6 @@ public class BookmarkPlugin extends ProgramPlugin
addAction.dispose();
addAction = null;
}
if (showAction != null) {
showAction.dispose();
showAction = null;
}
if (provider != null) {
provider.dispose();
provider = null;

View file

@ -17,6 +17,7 @@ package ghidra.app.plugin.core.bookmark;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.util.*;
@ -24,8 +25,8 @@ import javax.swing.*;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableColumn;
import docking.ActionContext;
import docking.WindowPosition;
import docking.*;
import docking.action.KeyBindingData;
import docking.widgets.combobox.GhidraComboBox;
import docking.widgets.table.GTable;
import ghidra.app.context.ProgramActionContext;
@ -57,7 +58,10 @@ public class BookmarkProvider extends ComponentProviderAdapter {
BookmarkProvider(PluginTool tool, BookmarkPlugin plugin) {
super(tool, "Bookmarks", plugin.getName(), ProgramActionContext.class);
setIcon(BookmarkNavigator.NOTE_ICON);
setIcon(BookmarkNavigator.NOTE_ICON, true);
setDefaultKeyBinding(
new KeyBindingData(KeyEvent.VK_B, DockingUtils.CONTROL_KEY_MODIFIER_MASK));
model = new BookmarkTableModel(tool, null);
threadedTablePanel = new GhidraThreadedTablePanel<>(model);

View file

@ -21,7 +21,8 @@ import java.util.List;
import javax.swing.Icon;
import docking.ActionContext;
import docking.action.*;
import docking.action.DockingAction;
import docking.action.MenuData;
import ghidra.app.CorePluginPackage;
import ghidra.app.context.ListingActionContext;
import ghidra.app.plugin.PluginCategoryNames;
@ -62,12 +63,14 @@ public class CallTreePlugin extends ProgramPlugin {
ResourceManager.loadImage("images/arrow_rotate_clockwise.png");
private List<CallTreeProvider> providers = new ArrayList<>();
private DockingAction showProviderAction;
private DockingAction showCallTreeFromMenuAction;
private CallTreeProvider primaryProvider;
public CallTreePlugin(PluginTool tool) {
super(tool, true, false, false);
createActions();
primaryProvider = new CallTreeProvider(this, true);
}
@Override
@ -116,7 +119,10 @@ public class CallTreePlugin extends ProgramPlugin {
}
private void createActions() {
showProviderAction = new DockingAction("Show Function Call Trees", getName()) {
// use the name of the provider so that the shared key binding data will get used
String actionName = CallTreeProvider.TITLE;
showCallTreeFromMenuAction = new DockingAction(actionName, getName()) {
@Override
public void actionPerformed(ActionContext context) {
@ -127,16 +133,27 @@ public class CallTreePlugin extends ProgramPlugin {
public boolean isAddToPopup(ActionContext context) {
return (context instanceof ListingActionContext);
}
@Override
public boolean isKeyBindingManaged() {
return false;
}
@Override
public boolean usesSharedKeyBinding() {
return true;
}
};
showProviderAction.setPopupMenuData(new MenuData(
showCallTreeFromMenuAction.setPopupMenuData(new MenuData(
new String[] { "References", "Show Call Trees" }, PROVIDER_ICON, "ShowReferencesTo"));
showProviderAction.setToolBarData(new ToolBarData(PROVIDER_ICON, "View"));
showProviderAction.setHelpLocation(new HelpLocation("CallTreePlugin", "Call_Tree_Plugin"));
tool.addAction(showProviderAction);
showCallTreeFromMenuAction.setHelpLocation(
new HelpLocation("CallTreePlugin", "Call_Tree_Plugin"));
tool.addAction(showCallTreeFromMenuAction);
}
private void creatAndShowProvider() {
CallTreeProvider provider = new CallTreeProvider(this);
CallTreeProvider provider = new CallTreeProvider(this, false);
providers.add(provider);
provider.initialize(currentProgram, currentLocation);
tool.showComponentProvider(provider, true);

View file

@ -57,7 +57,7 @@ import resources.ResourceManager;
public class CallTreeProvider extends ComponentProviderAdapter implements DomainObjectListener {
static final String EXPAND_ACTION_NAME = "Fully Expand Selected Nodes";
private static final String TITLE = "Function Call Trees";
static final String TITLE = "Function Call Trees";
private static final Icon EMPTY_ICON = ResourceManager.loadImage("images/EmptyIcon16.gif");
private static final Icon EXPAND_ICON = Icons.EXPAND_ALL_ICON;
private static final Icon COLLAPSE_ICON = Icons.COLLAPSE_ALL_ICON;
@ -74,6 +74,7 @@ public class CallTreeProvider extends ComponentProviderAdapter implements Domain
private JSplitPane splitPane;
private GTree incomingTree;
private GTree outgoingTree;
private boolean isPrimary;
private SwingUpdateManager reloadUpdateManager = new SwingUpdateManager(500, () -> doUpdate());
@ -93,20 +94,20 @@ public class CallTreeProvider extends ComponentProviderAdapter implements Domain
private AtomicInteger recurseDepth = new AtomicInteger();
private NumberIcon recurseIcon;
public CallTreeProvider(CallTreePlugin plugin) {
public CallTreeProvider(CallTreePlugin plugin, boolean isPrimary) {
super(plugin.getTool(), TITLE, plugin.getName());
this.plugin = plugin;
this.isPrimary = isPrimary;
component = buildComponent();
// try to give the trees a suitable amount of space by default
component.setPreferredSize(new Dimension(800, 400));
setTransient();
setWindowMenuGroup(TITLE);
setDefaultWindowPosition(WindowPosition.BOTTOM);
setIcon(CallTreePlugin.PROVIDER_ICON);
setIcon(CallTreePlugin.PROVIDER_ICON, true);
setHelpLocation(new HelpLocation(plugin.getName(), "Call_Tree_Plugin"));
addToTool();
@ -430,7 +431,11 @@ public class CallTreeProvider extends ComponentProviderAdapter implements Domain
}
}
};
navigateIncomingToggleAction.setSelected(false);
// note: the default state is to follow navigation events for the primary provider;
// non-primary providers will function like snapshots of the function with
// which they were activated.
navigateIncomingToggleAction.setSelected(isPrimary);
navigateIncomingToggleAction.setToolBarData(new ToolBarData(
Icons.NAVIGATE_ON_INCOMING_EVENT_ICON, navigationOptionsToolbarGroup, "2"));
navigateIncomingToggleAction.setDescription(HTMLUtilities.toHTML("Incoming Navigation" +
@ -818,7 +823,9 @@ public class CallTreeProvider extends ComponentProviderAdapter implements Domain
@Override
public void componentHidden() {
plugin.removeProvider(this);
if (!isPrimary) {
plugin.removeProvider(this);
}
}
private void reload() {

View file

@ -65,7 +65,7 @@ public class ConsoleComponentProvider extends ComponentProviderAdapter
private Program currentProgram;
public ConsoleComponentProvider(PluginTool tool, String name) {
super(tool, name, name);
super(tool, "Console", name);
setDefaultWindowPosition(WindowPosition.BOTTOM);
setHelpLocation(new HelpLocation(getName(), "console"));

View file

@ -23,7 +23,6 @@ import java.io.IOException;
import java.util.*;
import java.util.Map.Entry;
import javax.swing.ImageIcon;
import javax.swing.SwingUtilities;
import javax.swing.tree.TreePath;
@ -60,7 +59,6 @@ import ghidra.util.HelpLocation;
import ghidra.util.Msg;
import ghidra.util.datastruct.LRUMap;
import ghidra.util.task.TaskLauncher;
import resources.ResourceManager;
/**
* Plugin to pop up the dialog to manage data types in the program
@ -82,14 +80,12 @@ import resources.ResourceManager;
public class DataTypeManagerPlugin extends ProgramPlugin
implements DomainObjectListener, DataTypeManagerService, PopupListener {
final static String DATA_TYPES_ICON = "images/dataTypes.png";
private static final String SEACH_PROVIDER_NAME = "Search DataTypes Provider";
private static final int RECENTLY_USED_CACHE_SIZE = 10;
private static final String STANDARD_ARCHIVE_MENU = "Standard Archive";
private static final String RECENTLY_OPENED_MENU = "Recently Opened Archive";
private DockingAction manageDataAction;
private DataTypeManagerHandler dataTypeManagerHandler;
private DataTypesProvider provider;
private OpenVersionedFileDialog openDialog;
@ -126,12 +122,10 @@ public class DataTypeManagerPlugin extends ProgramPlugin
@Override
public void archiveClosed(Archive archive) {
if (archive instanceof ProjectArchive) {
// Program is handled by deactivation event
((ProjectArchive) archive).getDomainObject().removeListener(
DataTypeManagerPlugin.this);
}
// Program is handled by deactivation.
// Otherwise, don't care.
}
@Override
@ -467,21 +461,6 @@ public class DataTypeManagerPlugin extends ProgramPlugin
* Create the actions for the menu on the tool.
*/
private void createActions() {
// create action
manageDataAction = new DockingAction("Data Type Manager", getName()) {
@Override
public void actionPerformed(ActionContext context) {
tool.showComponentProvider(provider, true);
}
};
ImageIcon dtIcon = ResourceManager.loadImage(DATA_TYPES_ICON);
manageDataAction.setToolBarData(new ToolBarData(dtIcon, "View"));
manageDataAction.setDescription("Display Data Types");
manageDataAction.setHelpLocation(provider.getHelpLocation());
tool.addAction(manageDataAction);
createStandardArchivesMenu();
}

View file

@ -57,6 +57,8 @@ import resources.ResourceManager;
import util.HistoryList;
public class DataTypesProvider extends ComponentProviderAdapter {
private static final String DATA_TYPES_ICON = "images/dataTypes.png";
private static final String TITLE = "Data Type Manager";
private static final String POINTER_FILTER_STATE = "PointerFilterState";
private static final String ARRAY_FILTER_STATE = "ArrayFilterState";
@ -95,9 +97,11 @@ public class DataTypesProvider extends ComponentProviderAdapter {
public DataTypesProvider(DataTypeManagerPlugin plugin, String providerName) {
super(plugin.getTool(), providerName, plugin.getName(), DataTypesActionContext.class);
setTitle(TITLE);
this.plugin = plugin;
setTitle(TITLE);
setIcon(ResourceManager.loadImage(DATA_TYPES_ICON), true);
navigationHistory.setAllowDuplicates(true);
buildComponent();
@ -106,11 +110,6 @@ public class DataTypesProvider extends ComponentProviderAdapter {
createLocalActions();
}
@Override
public ImageIcon getIcon() {
return ResourceManager.loadImage(DataTypeManagerPlugin.DATA_TYPES_ICON);
}
/**
* This creates all the actions for opening/creating data type archives.
* It also creates the action for refreshing the built-in data types

View file

@ -54,12 +54,7 @@ public class EquateTablePlugin extends ProgramPlugin implements DomainObjectList
public EquateTablePlugin(PluginTool tool) {
super(tool, true, false);
updateMgr = new SwingUpdateManager(1000, 3000, new Runnable() {
@Override
public void run() {
provider.updateEquates();
}
});
updateMgr = new SwingUpdateManager(1000, 3000, () -> provider.updateEquates());
provider = new EquateTableProvider(this);
}
@ -131,10 +126,10 @@ public class EquateTablePlugin extends ProgramPlugin implements DomainObjectList
ev.containsEvent(ChangeManager.DOCR_CODE_ADDED) ||
ev.containsEvent(ChangeManager.DOCR_CODE_MOVED) ||
ev.containsEvent(ChangeManager.DOCR_CODE_REMOVED) ||
ev.containsEvent(ChangeManager.DOCR_CODE_REMOVED) ||
ev.containsEvent(ChangeManager.DOCR_DATA_TYPE_CHANGED)) {
updateMgr.update();
}
@ -154,9 +149,6 @@ public class EquateTablePlugin extends ProgramPlugin implements DomainObjectList
provider.programClosed();
}
/**
* Delete the list of equates.
*/
void deleteEquates(List<Equate> equates) {
if (equates.isEmpty()) {
return;
@ -173,13 +165,11 @@ public class EquateTablePlugin extends ProgramPlugin implements DomainObjectList
}
}
String title = "Delete Equate" + (equates.size() > 1 ? "s" : "") + "?";
String msg =
"Do you really want to delete the equate" + (equates.size() > 1 ? "s" : "") + ": " +
equates + " ?" + "\n\n NOTE: All references will be removed.";
String msg = "Do you really want to delete the equate" + (equates.size() > 1 ? "s" : "") +
": " + equates + " ?" + "\n\n NOTE: All references will be removed.";
int option =
OptionDialog.showOptionDialog(provider.getComponent(), title, msg, "Delete",
OptionDialog.QUESTION_MESSAGE);
int option = OptionDialog.showOptionDialog(provider.getComponent(), title, msg, "Delete",
OptionDialog.QUESTION_MESSAGE);
if (option != OptionDialog.CANCEL_OPTION) {
tool.execute(new RemoveEquateCmd(equateNames, getTool()), currentProgram);
@ -236,26 +226,24 @@ public class EquateTablePlugin extends ProgramPlugin implements DomainObjectList
}
/**
* If the equate exists, checks to make sure the value matches the
* current scalar value.
* If the equate exists, checks to make sure the value matches the current scalar value
*
* @param dialog the dialog whose status area should be set with any error messages.
* @param equateStr the candidate equate name for the set or rename operation.
* @param equate the equate to check
* @param equateStr the candidate equate name for the set or rename operation
* @return true if valid
*/
boolean isValid(Equate equate, String equateStr) {
// these are valid in the sense that they represent a clear or remove operation.
// these are valid in the sense that they represent a clear or remove operation
if (equateStr == null || equateStr.length() <= 0) {
return false;
}
// look up the new equate string
EquateTable equateTable = currentProgram.getEquateTable();
Equate newEquate = equateTable.getEquate(equateStr);
if (newEquate != null && !newEquate.equals(equate)) {
Msg.showInfo(getClass(), provider.getComponent(), "Rename Equate Failed!", "Equate " +
equateStr + " exists with value 0x" + Long.toHexString(newEquate.getValue()) +
" (" + newEquate.getValue() + ")");
Msg.showInfo(getClass(), provider.getComponent(), "Rename Equate Failed!",
"Equate " + equateStr + " exists with value 0x" +
Long.toHexString(newEquate.getValue()) + " (" + newEquate.getValue() + ")");
return false;
}
return true;

View file

@ -19,7 +19,8 @@ import java.io.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import javax.swing.Icon;
import javax.swing.JComponent;
import docking.ActionContext;
import docking.action.DockingAction;
@ -33,12 +34,12 @@ import utility.function.Callback;
public class InterpreterComponentProvider extends ComponentProviderAdapter
implements InterpreterConsole {
private static final String CONSOLE_GIF = "images/monitor.png";
private static final String CLEAR_GIF = "images/erase16.png";
private InterpreterPanel panel;
private InterpreterConnection interpreter;
private ImageIcon icon;
private List<Callback> firstActivationCallbacks;
public InterpreterComponentProvider(InterpreterPanelPlugin plugin,
@ -54,9 +55,9 @@ public class InterpreterComponentProvider extends ComponentProviderAdapter
addToTool();
createActions();
icon = interpreter.getIcon();
Icon icon = interpreter.getIcon();
if (icon == null) {
ResourceManager.loadImage(CONSOLE_GIF);
icon = ResourceManager.loadImage(CONSOLE_GIF);
}
setIcon(icon);
@ -107,11 +108,6 @@ public class InterpreterComponentProvider extends ComponentProviderAdapter
addLocalAction(disposeAction);
}
@Override
public Icon getIcon() {
return icon;
}
@Override
public String getWindowSubMenuName() {
return interpreter.getTitle();

View file

@ -15,6 +15,8 @@
*/
package ghidra.app.plugin.core.memory;
import java.awt.Cursor;
import ghidra.app.CorePluginPackage;
import ghidra.app.events.ProgramLocationPluginEvent;
import ghidra.app.plugin.PluginCategoryNames;
@ -31,15 +33,6 @@ import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.util.ChangeManager;
import ghidra.program.util.ProgramLocation;
import java.awt.Cursor;
import javax.swing.ImageIcon;
import resources.ResourceManager;
import docking.ActionContext;
import docking.action.DockingAction;
import docking.action.ToolBarData;
/**
* <CODE>MemoryMapPlugin</CODE> displays a memory map of all blocks in
* the current program's memory. Options for Adding, Editing, and Deleting
@ -61,20 +54,15 @@ public class MemoryMapPlugin extends ProgramPlugin implements DomainObjectListen
final static Cursor WAIT_CURSOR = new Cursor(Cursor.WAIT_CURSOR);
final static Cursor NORM_CURSOR = new Cursor(Cursor.DEFAULT_CURSOR);
private DockingAction memViewAction;
private MemoryMapProvider provider;
private GoToService goToService;
private MemoryMapManager memManager;
/**
* Constructor
*/
public MemoryMapPlugin(PluginTool tool) {
super(tool, true, false);
memManager = new MemoryMapManager(this);
provider = new MemoryMapProvider(this);
createActions();
}
/**
@ -83,9 +71,6 @@ public class MemoryMapPlugin extends ProgramPlugin implements DomainObjectListen
*/
@Override
public void dispose() {
if (memViewAction != null) {
memViewAction.dispose();
}
if (provider != null) {
provider.dispose();
provider = null;
@ -122,8 +107,9 @@ public class MemoryMapPlugin extends ProgramPlugin implements DomainObjectListen
@Override
protected void init() {
goToService = tool.getService(GoToService.class);
if (currentProgram != null)
if (currentProgram != null) {
programActivated(currentProgram);
}
}
/**
@ -168,29 +154,4 @@ public class MemoryMapPlugin extends ProgramPlugin implements DomainObjectListen
ProgramLocation loc = new ProgramLocation(currentProgram, addr);
goToService.goTo(loc);
}
/**
* Create the action for toolbar.
*/
private void createActions() {
memViewAction = new DockingAction("View Memory Map", getName()) {
@Override
public void actionPerformed(ActionContext context) {
showMemory();
}
};
ImageIcon tableImage = ResourceManager.loadImage(MemoryMapProvider.MEMORY_IMAGE);
memViewAction.setToolBarData(new ToolBarData(tableImage, "View"));
memViewAction.setDescription("Display Memory Map");
tool.addAction(memViewAction);
}
/**
* Callback for the View memory Action
*/
private void showMemory() {
tool.showComponentProvider(provider, true);
}
}

View file

@ -81,9 +81,10 @@ class MemoryMapProvider extends ComponentProviderAdapter {
MemoryMapProvider(MemoryMapPlugin plugin) {
super(plugin.getTool(), "Memory Map", plugin.getName(), ProgramActionContext.class);
this.plugin = plugin;
setHelpLocation(new HelpLocation(plugin.getName(), getName()));
memManager = plugin.getMemoryMapManager();
setIcon(ResourceManager.loadImage(MEMORY_IMAGE));
setIcon(ResourceManager.loadImage(MEMORY_IMAGE), true);
mainPanel = buildMainPanel();
addToTool();
addLocalActions();
@ -107,9 +108,6 @@ class MemoryMapProvider extends ComponentProviderAdapter {
return new ProgramActionContext(this, program);
}
/**
* Set the status text on this dialog.
*/
void setStatusText(String msg) {
tool.setStatusInfo(msg);
}
@ -367,9 +365,6 @@ class MemoryMapProvider extends ComponentProviderAdapter {
}
}
/**
* @return
*/
JTable getTable() {
return memTable;
}
@ -462,7 +457,8 @@ class MemoryMapProvider extends ComponentProviderAdapter {
public void mousePressed(MouseEvent e) {
setStatusText("");
if (!e.isPopupTrigger()) {
if ((e.getModifiers() & (InputEvent.CTRL_MASK | InputEvent.SHIFT_MASK)) == 0) {
if ((e.getModifiersEx() &
(InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK)) == 0) {
selectAddress();
}
}

View file

@ -64,8 +64,9 @@ public class RegisterManagerProvider extends ComponentProviderAdapter {
RegisterManagerProvider(PluginTool tool, String owner) {
super(tool, "Register Manager", owner, ProgramActionContext.class);
buildComponent();
setHelpLocation(new HelpLocation("RegisterPlugin", "RegisterManager"));
setIcon(REGISTER_ICON);
setIcon(REGISTER_ICON, true);
setDefaultWindowPosition(WindowPosition.WINDOW);
updateMgr = new SwingUpdateManager(500, () -> update());

View file

@ -43,7 +43,6 @@ import ghidra.program.model.listing.*;
import ghidra.program.util.*;
import ghidra.util.HelpLocation;
import ghidra.util.Msg;
import resources.ResourceManager;
/**
* Shows the registers available in a program along with any values that are set.
@ -63,7 +62,6 @@ public class RegisterPlugin extends ProgramPlugin {
private RegisterManagerProvider registerMgrProvider;
private Register[] registers = new Register[0];
private DockingAction showRegistersAction;
private DockingAction deleteRegisterRangeAction;
private DockingAction deleteRegisterAtFunctionAction;
private DockingAction clearRegisterAction;
@ -94,21 +92,6 @@ public class RegisterPlugin extends ProgramPlugin {
}
private void createActions() {
showRegistersAction = new DockingAction("Display Register Values", getName()) {
@Override
public void actionPerformed(ActionContext context) {
tool.showComponentProvider(registerMgrProvider, true);
}
};
showRegistersAction.setToolBarData(new ToolBarData(
ResourceManager.loadImage("images/registerGroup.png"), "View"));
showRegistersAction.setKeyBindingData(new KeyBindingData(KeyEvent.VK_V, 0));
showRegistersAction.setDescription("Display Register Values");
showRegistersAction.setHelpLocation(new HelpLocation("RegisterPlugin", "RegisterManager"));
showRegistersAction.setEnabled(true);
tool.addAction(showRegistersAction);
setRegisterAction = new DockingAction("Set Register Values", getName()) {
@Override
@ -125,10 +108,10 @@ public class RegisterPlugin extends ProgramPlugin {
(contextObject instanceof RegisterManagerProvider);
}
};
setRegisterAction.setPopupMenuData(new MenuData(new String[] { "Set Register Values..." },
null, "Registers"));
setRegisterAction.setKeyBindingData(new KeyBindingData(KeyEvent.VK_R,
InputEvent.CTRL_DOWN_MASK));
setRegisterAction.setPopupMenuData(
new MenuData(new String[] { "Set Register Values..." }, null, "Registers"));
setRegisterAction.setKeyBindingData(
new KeyBindingData(KeyEvent.VK_R, InputEvent.CTRL_DOWN_MASK));
setRegisterAction.setDescription("Set register values in a program.");
setRegisterAction.setHelpLocation(new HelpLocation("RegisterPlugin", "SetRegisterValues"));
@ -151,12 +134,12 @@ public class RegisterPlugin extends ProgramPlugin {
(contextObject instanceof RegisterManagerProvider);
}
};
clearRegisterAction.setPopupMenuData(new MenuData(
new String[] { "Clear Register Values..." }, null, "Registers"));
clearRegisterAction.setPopupMenuData(
new MenuData(new String[] { "Clear Register Values..." }, null, "Registers"));
clearRegisterAction.setDescription("Clear register values in a program.");
clearRegisterAction.setHelpLocation(new HelpLocation("RegisterPlugin",
"ClearRegisterValues"));
clearRegisterAction.setHelpLocation(
new HelpLocation("RegisterPlugin", "ClearRegisterValues"));
clearRegisterAction.setEnabled(true);
tool.addAction(clearRegisterAction);
@ -193,8 +176,8 @@ public class RegisterPlugin extends ProgramPlugin {
deleteRegisterRangeAction.setKeyBindingData(new KeyBindingData(KeyEvent.VK_DELETE, 0));
deleteRegisterRangeAction.setDescription("Delete register value at Function.");
deleteRegisterRangeAction.setHelpLocation(new HelpLocation("RegisterPlugin",
"DeleteRegisterValueRange"));
deleteRegisterRangeAction.setHelpLocation(
new HelpLocation("RegisterPlugin", "DeleteRegisterValueRange"));
deleteRegisterRangeAction.setEnabled(true);
tool.addAction(deleteRegisterRangeAction);
@ -222,13 +205,13 @@ public class RegisterPlugin extends ProgramPlugin {
return false;
}
};
deleteRegisterAtFunctionAction.setPopupMenuData(new MenuData(
new String[] { "Delete Register Value Range..." }, null, "Registers"));
deleteRegisterAtFunctionAction.setPopupMenuData(
new MenuData(new String[] { "Delete Register Value Range..." }, null, "Registers"));
deleteRegisterAtFunctionAction.setKeyBindingData(new KeyBindingData(KeyEvent.VK_DELETE, 0));
deleteRegisterAtFunctionAction.setDescription("Delete register value range.");
deleteRegisterAtFunctionAction.setHelpLocation(new HelpLocation("RegisterPlugin",
"DeleteRegisterValueRange"));
deleteRegisterAtFunctionAction.setHelpLocation(
new HelpLocation("RegisterPlugin", "DeleteRegisterValueRange"));
deleteRegisterAtFunctionAction.setEnabled(true);
tool.addAction(deleteRegisterAtFunctionAction);
@ -254,8 +237,8 @@ public class RegisterPlugin extends ProgramPlugin {
while (it.hasNext()) {
AddressRange range = it.next();
if (range.contains(addr)) {
Command cmd =
new SetRegisterCmd(register, range.getMinAddress(), range.getMaxAddress(), null);
Command cmd = new SetRegisterCmd(register, range.getMinAddress(),
range.getMaxAddress(), null);
if (!tool.execute(cmd, context.getProgram())) {
Msg.showError(this, tool.getToolFrame(), "Register Context Error",
cmd.getStatusMsg());
@ -356,7 +339,7 @@ public class RegisterPlugin extends ProgramPlugin {
@Override
protected void programActivated(Program program) {
registerMgrProvider.setProgram(program);
ArrayList<Register> list = new ArrayList<Register>();
ArrayList<Register> list = new ArrayList<>();
for (Register reg : program.getProgramContext().getRegisters()) {
if (!reg.isHidden()) {
list.add(reg);
@ -442,7 +425,8 @@ public class RegisterPlugin extends ProgramPlugin {
@Override
public Class<?>[] getSupportedProgramLocations() {
return new Class[] { RegisterTransitionFieldLocation.class, RegisterFieldLocation.class };
return new Class[] { RegisterTransitionFieldLocation.class,
RegisterFieldLocation.class };
}
}

View file

@ -102,7 +102,7 @@ public class GhidraScriptComponentProvider extends ComponentProviderAdapter {
this.plugin = plugin;
setHelpLocation(new HelpLocation(plugin.getName(), plugin.getName()));
setIcon(ResourceManager.loadImage("images/play.png"));
setIcon(ResourceManager.loadImage("images/play.png"), true);
setWindowGroup(WINDOW_GROUP);
build();

View file

@ -19,9 +19,6 @@ import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import docking.ActionContext;
import docking.action.DockingAction;
import docking.action.ToolBarData;
import generic.jar.ResourceFile;
import ghidra.app.CorePluginPackage;
import ghidra.app.plugin.PluginCategoryNames;
@ -36,9 +33,7 @@ import ghidra.framework.plugintool.PluginInfo;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.util.PluginStatus;
import ghidra.program.model.listing.Program;
import ghidra.util.HelpLocation;
import ghidra.util.task.TaskListener;
import resources.ResourceManager;
//@formatter:off
@PluginInfo(
@ -54,7 +49,6 @@ import resources.ResourceManager;
public class GhidraScriptMgrPlugin extends ProgramPlugin implements GhidraScriptService {
private GhidraScriptComponentProvider provider;
private DockingAction action;
public GhidraScriptMgrPlugin(PluginTool tool) {
super(tool, true, true, true);
@ -62,31 +56,9 @@ public class GhidraScriptMgrPlugin extends ProgramPlugin implements GhidraScript
provider = new GhidraScriptComponentProvider(this);
}
@Override
protected void init() {
super.init();
action = new DockingAction("Display Script Manager", getName()) {
@Override
public void actionPerformed(ActionContext context) {
tool.showComponentProvider(provider, true);
}
};
// ACTIONS - auto generated
action.setToolBarData(
new ToolBarData(ResourceManager.loadImage("images/play.png"), "View"));
action.setEnabled(true);
action.setHelpLocation(new HelpLocation(getName(), "Script_Manager"));
tool.addAction(action);
}
@Override
protected void dispose() {
super.dispose();
action.dispose();
provider.dispose();
}

View file

@ -15,11 +15,6 @@
*/
package ghidra.app.plugin.core.symboltree;
import javax.swing.ImageIcon;
import docking.ActionContext;
import docking.action.DockingAction;
import docking.action.ToolBarData;
import ghidra.app.CorePluginPackage;
import ghidra.app.events.*;
import ghidra.app.plugin.PluginCategoryNames;
@ -30,8 +25,6 @@ import ghidra.framework.plugintool.util.PluginStatus;
import ghidra.program.model.listing.Program;
import ghidra.program.model.symbol.*;
import ghidra.program.util.ProgramLocation;
import ghidra.util.HelpLocation;
import resources.ResourceManager;
//@formatter:off
@PluginInfo(
@ -50,17 +43,13 @@ public class SymbolTreePlugin extends Plugin {
public static final String PLUGIN_NAME = "SymbolTreePlugin";
private DockingAction symTreeAction;
private SymbolTreeProvider provider;
private Program program;
private GoToService goToService;
private boolean processingGoTo;
final static ImageIcon SYMBOL_TREE_ICON = ResourceManager.loadImage("images/sitemap_color.png");
public SymbolTreePlugin(PluginTool tool) {
super(tool);
createAction();
provider = new SymbolTreeProvider(tool, this);
}
@ -151,26 +140,6 @@ public class SymbolTreePlugin extends Plugin {
goToService.goToExternalLocation(extLoc, false);
}
private void createAction() {
symTreeAction = new DockingAction("Display Symbol Tree", getName()) {
@Override
public void actionPerformed(ActionContext context) {
showProvider();
}
};
symTreeAction.setToolBarData(new ToolBarData(SYMBOL_TREE_ICON, "View"));
symTreeAction.setDescription("Display Symbol Tree");
symTreeAction.setHelpLocation(new HelpLocation(getName(), "SymbolTree"));
tool.addAction(symTreeAction);
}
private void showProvider() {
provider.showComponent(program);
}
public Program getProgram() {
return program;
}

View file

@ -45,9 +45,11 @@ import ghidra.util.*;
import ghidra.util.exception.*;
import ghidra.util.task.SwingUpdateManager;
import ghidra.util.task.TaskMonitor;
import resources.ResourceManager;
public class SymbolTreeProvider extends ComponentProviderAdapter {
private static final ImageIcon ICON = ResourceManager.loadImage("images/sitemap_color.png");
private final static String NAME = "Symbol Tree";
private ClipboardOwner clipboardOwner;
@ -101,6 +103,8 @@ public class SymbolTreeProvider extends ComponentProviderAdapter {
super(tool, NAME, plugin.getName());
this.plugin = plugin;
setIcon(ICON, true);
domainObjectListener = new SymbolTreeProviderDomainObjectListener();
localClipboard = new Clipboard(NAME);
@ -231,11 +235,6 @@ public class SymbolTreeProvider extends ComponentProviderAdapter {
setProgram(program);
}
@Override
public ImageIcon getIcon() {
return SymbolTreePlugin.SYMBOL_TREE_ICON;
}
//==================================================================================================
// Class Methods
//==================================================================================================

View file

@ -29,8 +29,12 @@ import ghidra.program.model.listing.Program;
import ghidra.program.model.symbol.Symbol;
import ghidra.util.HelpLocation;
import ghidra.util.table.GhidraTable;
import resources.ResourceManager;
class ReferenceProvider extends ComponentProviderAdapter {
private static final ImageIcon ICON = ResourceManager.loadImage("images/table_go.png");
private SymbolTablePlugin plugin;
private SymbolReferenceModel referenceKeyModel;
private ReferencePanel referencePanel;
@ -39,15 +43,20 @@ class ReferenceProvider extends ComponentProviderAdapter {
ReferenceProvider(SymbolTablePlugin plugin) {
super(plugin.getTool(), "Symbol References", plugin.getName(), ProgramActionContext.class);
this.plugin = plugin;
setIcon(ICON, true);
setHelpLocation(new HelpLocation(plugin.getName(), "Symbol_References"));
setWindowGroup("symbolTable");
setIntraGroupPosition(WindowPosition.RIGHT);
renderer = new SymbolRenderer();
referenceKeyModel =
new SymbolReferenceModel(plugin.getBlockModelService(), plugin.getTool());
referencePanel =
new ReferencePanel(this, referenceKeyModel, renderer, plugin.getGoToService());
addToTool();
}
void dispose() {
@ -119,11 +128,6 @@ class ReferenceProvider extends ComponentProviderAdapter {
return "(" + referenceKeyModel.getDescription() + ")";
}
@Override
public ImageIcon getIcon() {
return SymbolTablePlugin.REF_GIF;
}
void open() {
setVisible(true);
}

View file

@ -15,6 +15,7 @@
*/
package ghidra.app.plugin.core.symtable;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.util.List;
@ -22,6 +23,8 @@ import javax.swing.ImageIcon;
import javax.swing.JComponent;
import docking.ActionContext;
import docking.DockingUtils;
import docking.action.KeyBindingData;
import ghidra.app.context.ProgramActionContext;
import ghidra.app.context.ProgramSymbolActionContext;
import ghidra.app.events.ProgramSelectionPluginEvent;
@ -34,8 +37,12 @@ import ghidra.program.model.symbol.Symbol;
import ghidra.program.util.ProgramSelection;
import ghidra.util.HelpLocation;
import ghidra.util.table.GhidraTable;
import resources.ResourceManager;
class SymbolProvider extends ComponentProviderAdapter {
private static final ImageIcon ICON = ResourceManager.loadImage("images/table.png");
private SymbolTablePlugin plugin;
private SymbolRenderer renderer;
private SymbolTableModel symbolKeyModel;
@ -44,6 +51,10 @@ class SymbolProvider extends ComponentProviderAdapter {
SymbolProvider(SymbolTablePlugin plugin) {
super(plugin.getTool(), "Symbol Table", plugin.getName(), ProgramActionContext.class);
this.plugin = plugin;
setIcon(ICON, true);
setDefaultKeyBinding(
new KeyBindingData(KeyEvent.VK_T, DockingUtils.CONTROL_KEY_MODIFIER_MASK));
setHelpLocation(new HelpLocation(plugin.getName(), "Symbol_Table"));
setWindowGroup("symbolTable");
renderer = new SymbolRenderer();
@ -51,6 +62,8 @@ class SymbolProvider extends ComponentProviderAdapter {
symbolKeyModel = new SymbolTableModel(this, plugin.getTool());
symbolPanel = new SymbolPanel(this, symbolKeyModel, renderer, plugin.getTool(),
plugin.getGoToService());
addToTool();
}
void updateTitle() {
@ -164,11 +177,6 @@ class SymbolProvider extends ComponentProviderAdapter {
}
@Override
public ImageIcon getIcon() {
return SymbolTablePlugin.SYM_GIF;
}
void open() {
if (!isVisible()) {
setVisible(true);

View file

@ -16,7 +16,6 @@
package ghidra.app.plugin.core.symtable;
import java.awt.Cursor;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
@ -74,12 +73,6 @@ public class SymbolTablePlugin extends Plugin implements DomainObjectListener {
final static Cursor WAIT_CURSOR = new Cursor(Cursor.WAIT_CURSOR);
final static Cursor NORM_CURSOR = new Cursor(Cursor.DEFAULT_CURSOR);
final static ImageIcon SYM_GIF = ResourceManager.loadImage("images/table.png");
final static ImageIcon REF_GIF = ResourceManager.loadImage("images/table_go.png");
private DockingAction viewSymTableAction;
private DockingAction viewRefTableAction;
private DockingAction openRefsAction;
private DockingAction deleteAction;
private DockingAction makeSelectionAction;
@ -113,10 +106,6 @@ public class SymbolTablePlugin extends Plugin implements DomainObjectListener {
symProvider = new SymbolProvider(this);
refProvider = new ReferenceProvider(this);
tool.addComponentProvider(symProvider, false);
tool.addComponentProvider(refProvider, false);
createActions();
createSymActions();
createRefActions();
@ -133,8 +122,6 @@ public class SymbolTablePlugin extends Plugin implements DomainObjectListener {
super.dispose();
swingMgr.dispose();
viewSymTableAction.dispose();
viewRefTableAction.dispose();
deleteAction.dispose();
makeSelectionAction.dispose();
@ -357,34 +344,6 @@ public class SymbolTablePlugin extends Plugin implements DomainObjectListener {
}
}
private void createActions() {
viewSymTableAction = new DockingAction("View Symbol Table", getName()) {
@Override
public void actionPerformed(ActionContext context) {
tool.showComponentProvider(symProvider, true);
}
};
viewSymTableAction.setToolBarData(
new ToolBarData(ResourceManager.loadImage("images/table.png"), "View"));
viewSymTableAction.setKeyBindingData(
new KeyBindingData(KeyEvent.VK_T, InputEvent.CTRL_DOWN_MASK));
viewSymTableAction.setDescription("Display Symbol Table");
tool.addAction(viewSymTableAction);
viewRefTableAction = new DockingAction("View Symbol References", getName()) {
@Override
public void actionPerformed(ActionContext context) {
tool.showComponentProvider(refProvider, true);
}
};
viewRefTableAction.setToolBarData(
new ToolBarData(ResourceManager.loadImage("images/table_go.png"), "View"));
viewRefTableAction.setDescription("Display Symbol References");
tool.addAction(viewRefTableAction);
}
private void createSymActions() {
String popupGroup = "1";

View file

@ -25,6 +25,7 @@ import javax.swing.*;
import org.junit.*;
import docking.action.DockingActionIf;
import docking.action.KeyBindingData;
import docking.actions.KeyEntryDialog;
import docking.tool.util.DockingToolConstants;
import ghidra.framework.options.ToolOptions;
@ -91,6 +92,59 @@ public class ComponentProviderActionsTest extends AbstractGhidraHeadedIntegratio
assertWindowMenuActionHasIcon(Icons.EMPTY_ICON);
}
@Test
public void testSetKeyBinding_DirectlyOnProvider() {
//
// This is how clients set key bindings on providers, as desired, when constructing them
//
KeyStroke defaultKs = CONTROL_T;
setDefaultKeyBinding(defaultKs);
showProvider();
assertProviderKeyStroke(defaultKs);
assertOptionsKeyStroke(defaultKs);
assertMenuItemHasKeyStroke(defaultKs);
}
@Test
public void testSetKeyBinding_DirectlyOnProvider_TransientProvider() {
//
// Transient providers cannot have key bindings
//
switchToTransientProvider();
setErrorsExpected(true);
setDefaultKeyBinding(CONTROL_T);
setErrorsExpected(false);
showProvider();
spyLogger.assertLogMessage("Transient", "cannot", "key", "binding");
}
@Test
public void testSetTransientAfterSettingKeyBinding() {
setDefaultKeyBinding(CONTROL_T);
setErrorsExpected(true);
switchToTransientProvider();
setErrorsExpected(false);
showProvider();
spyLogger.assertLogMessage("Transient", "not", "key", "binding");
}
@Test(expected = IllegalStateException.class)
public void testSetTransientAfterAddedProviderToTheTool() {
showProvider();
switchToTransientProvider(); // exception
}
@Test
public void testSetKeyBinding_ViaDialog_FromWindowMenu() {
@ -177,21 +231,6 @@ public class ComponentProviderActionsTest extends AbstractGhidraHeadedIntegratio
}
}
@Test
public void testChangeActionRelatedStateAfterConstruction_setTransient() {
setToolbarIcon(ICON);
showProvider(); // this creates the 'Show Provider' action
assertShowProviderActionIsInToolbar();
setErrorsExpected(true);
switchToTransientProvider();
setErrorsExpected(false);
assertShowProviderActionNotInToolbar();
spyLogger.assertLogMessage("Transient", "not", "toolbar");
}
//==================================================================================================
// Private Methods
//==================================================================================================
@ -215,6 +254,10 @@ public class ComponentProviderActionsTest extends AbstractGhidraHeadedIntegratio
waitForSwing();
}
private void setDefaultKeyBinding(KeyStroke defaultKs) {
runSwing(() -> provider.setDefaultKeyBinding(new KeyBindingData(defaultKs)));
}
private void setIcon(Icon icon) {
runSwing(() -> provider.setIcon(icon));
}

View file

@ -8,7 +8,7 @@
</head>
<body lang="EN-US">
<h1><a name="ByteViewerPlugin"></a><a name="Byte_Viewer"></a>The Byte Viewer </h1>
<h1><a name="ByteViewerPlugin"></a><a name="Bytes"></a>The Byte Viewer </h1>
<p>The Byte Viewer displays bytes in memory in various formats, e.g.,
Hex, Ascii, Octal, etc.&nbsp;The figure below shows the Byte Viewer
plugin in a separate window from the

View file

@ -19,9 +19,6 @@ import java.util.*;
import org.jdom.Element;
import docking.ActionContext;
import docking.action.DockingAction;
import docking.action.ToolBarData;
import ghidra.app.CorePluginPackage;
import ghidra.app.events.*;
import ghidra.app.plugin.PluginCategoryNames;
@ -35,7 +32,6 @@ import ghidra.program.model.listing.Program;
import ghidra.program.util.ProgramLocation;
import ghidra.program.util.ProgramSelection;
import ghidra.util.SystemUtilities;
import resources.ResourceManager;
import utility.function.Callback;
/**
@ -73,23 +69,6 @@ public class ByteViewerPlugin extends Plugin {
super(tool);
connectedProvider = new ProgramByteViewerComponentProvider(tool, this, true);
createActions();
}
private void createActions() {
DockingAction action = new DockingAction("Byte Viewer", getName()) {
@Override
public void actionPerformed(ActionContext context) {
showConnectedProvider();
}
};
action.setToolBarData(
new ToolBarData(ResourceManager.loadImage("images/binaryData.gif"), "View"));
action.setDescription("Display Bytes");
action.setEnabled(true);
tool.addAction(action);
}
protected void showConnectedProvider() {

View file

@ -71,8 +71,10 @@ public class ProgramByteViewerComponentProvider extends ByteViewerComponentProvi
boolean isConnected) {
super(tool, plugin, "Bytes", ByteViewerActionContext.class);
this.isConnected = isConnected;
decorationComponent = new DecoratorPanel(panel, isConnected);
setIcon(ResourceManager.loadImage("images/binaryData.gif"), true);
decorationComponent = new DecoratorPanel(panel, isConnected);
clipboardProvider = new ByteViewerClipboardProvider(this, tool);
addToTool();
@ -503,7 +505,8 @@ public class ProgramByteViewerComponentProvider extends ByteViewerComponentProvi
}
/**
* Gets the text of the current {@link ProgramSelection}.
* Gets the text of the current {@link ProgramSelection}
* @return the text
*/
String getCurrentTextSelection() {
return panel.getCurrentComponent().getTextForSelection();

View file

@ -15,14 +15,10 @@
*/
package ghidra.app.plugin.core.decompile;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.util.*;
import org.jdom.Element;
import docking.ActionContext;
import docking.action.*;
import ghidra.app.CorePluginPackage;
import ghidra.app.decompiler.component.DecompilerHighlightService;
import ghidra.app.decompiler.component.hover.DecompilerHoverService;
@ -37,9 +33,7 @@ import ghidra.program.model.address.Address;
import ghidra.program.model.listing.*;
import ghidra.program.util.ProgramLocation;
import ghidra.program.util.ProgramSelection;
import ghidra.util.HelpLocation;
import ghidra.util.task.SwingUpdateManager;
import resources.ResourceManager;
/**
* Plugin for producing a high-level C interpretation of assembly functions.
@ -72,8 +66,6 @@ public class DecompilePlugin extends Plugin {
private ProgramLocation currentLocation;
private ProgramSelection currentSelection;
private DockingAction decompileAction;
/**
* Delay location changes to allow location events to settle down.
* This happens when a readDataState occurs when a tool is restored
@ -92,8 +84,6 @@ public class DecompilePlugin extends Plugin {
disconnectedProviders = new ArrayList<>();
connectedProvider = new PrimaryDecompilerProvider(this);
createActions();
registerServices();
}
@ -112,22 +102,6 @@ public class DecompilePlugin extends Plugin {
}
}
private void createActions() {
decompileAction = new DockingAction("Display Decompiler", getName()) {
@Override
public void actionPerformed(ActionContext context) {
showProvider();
}
};
decompileAction.setToolBarData(
new ToolBarData(ResourceManager.loadImage("images/decompileFunction.gif"), "View"));
decompileAction.setKeyBindingData(
new KeyBindingData(KeyEvent.VK_E, InputEvent.CTRL_DOWN_MASK));
decompileAction.setHelpLocation(new HelpLocation(getName(), "Decompiler"));
tool.addAction(decompileAction);
}
/**
* Tells the Plugin to write any data-dependent state to the
* output stream.
@ -184,10 +158,6 @@ public class DecompilePlugin extends Plugin {
}
}
private void showProvider() {
connectedProvider.setVisible(true);
}
DecompilerProvider createNewDisconnectedProvider() {
DecompilerProvider decompilerProvider = new DecompilerProvider(this, false);
decompilerProvider.setClipboardService(tool.getService(ClipboardService.class));

View file

@ -15,6 +15,7 @@
*/
package ghidra.app.plugin.core.decompile;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.math.BigInteger;
import java.util.Arrays;
@ -22,8 +23,7 @@ import java.util.List;
import javax.swing.*;
import docking.ActionContext;
import docking.WindowPosition;
import docking.*;
import docking.action.*;
import docking.widgets.fieldpanel.LayoutModel;
import docking.widgets.fieldpanel.support.FieldLocation;
@ -125,6 +125,7 @@ public class DecompilerProvider extends NavigatableComponentProviderAdapter
public DecompilerProvider(DecompilePlugin plugin, boolean isConnected) {
super(plugin.getTool(), "Decompiler", plugin.getName(), DecompilerActionContext.class);
this.plugin = plugin;
clipboardProvider = new DecompilerClipboardProvider(plugin, this);
setConnected(isConnected);
@ -135,8 +136,11 @@ public class DecompilerProvider extends NavigatableComponentProviderAdapter
DecompilerPanel decompilerPanel = controller.getDecompilerPanel();
decompilerPanel.setHighlightController(highlightController);
decorationPanel = new DecoratorPanel(decompilerPanel, isConnected);
setTitle("Decompile");
setIcon(C_SOURCE_ICON);
setIcon(C_SOURCE_ICON, true);
setDefaultKeyBinding(
new KeyBindingData(KeyEvent.VK_E, DockingUtils.CONTROL_KEY_MODIFIER_MASK));
setWindowMenuGroup("Decompile");
setDefaultWindowPosition(WindowPosition.RIGHT);
createActions(isConnected);

View file

@ -109,8 +109,9 @@ public class FGProvider extends VisualGraphComponentProvider<FGVertex, FGEdge, F
setWindowMenuGroup(FunctionGraphPlugin.FUNCTION_GRAPH_NAME);
setWindowGroup(FunctionGraphPlugin.FUNCTION_GRAPH_NAME);
setDefaultWindowPosition(WindowPosition.WINDOW);
setIcon(FunctionGraphPlugin.ICON, true);
setHelpLocation(new HelpLocation("FunctionGraphPlugin", "FunctionGraphPlugin"));
setIcon(FunctionGraphPlugin.ICON);
addToTool();
addSatelliteFeature(); // must be after addToTool();

View file

@ -21,9 +21,6 @@ import javax.swing.ImageIcon;
import org.jdom.Element;
import docking.ActionContext;
import docking.action.DockingAction;
import docking.action.ToolBarData;
import ghidra.GhidraOptions;
import ghidra.app.CorePluginPackage;
import ghidra.app.events.*;
@ -43,7 +40,6 @@ import ghidra.graph.viewer.options.VisualGraphOptions;
import ghidra.program.model.listing.Program;
import ghidra.program.util.ProgramLocation;
import ghidra.program.util.ProgramSelection;
import ghidra.util.HelpLocation;
import resources.ResourceManager;
//@formatter:off
@ -75,8 +71,6 @@ public class FunctionGraphPlugin extends ProgramPlugin implements OptionsChangeL
private static final String PROGRAM_PATH_ID = "Program Path";
private static final String DISCONNECTED_COUNT_ID = "Disconnected Count";
private DockingAction showFunctionGraphAction;
private FGProvider connectedProvider;
private List<FGProvider> disconnectedProviders = new ArrayList<>();
private FormatManager userDefinedFormatManager;
@ -88,8 +82,6 @@ public class FunctionGraphPlugin extends ProgramPlugin implements OptionsChangeL
public FunctionGraphPlugin(PluginTool tool) {
super(tool, true, true, true);
createActions();
colorProvider = new IndependentColorProvider(tool);
}
@ -216,21 +208,6 @@ public class FunctionGraphPlugin extends ProgramPlugin implements OptionsChangeL
}
}
private void createActions() {
showFunctionGraphAction = new DockingAction("Display Function Graph", getName()) {
@Override
public void actionPerformed(ActionContext context) {
showProvider();
}
};
showFunctionGraphAction.setToolBarData(new ToolBarData(ICON, "View"));
showFunctionGraphAction.setHelpLocation(
new HelpLocation("FunctionGraphPlugin", "Function_Graph_Plugin"));
tool.addAction(showFunctionGraphAction);
}
void showProvider() {
connectedProvider.setVisible(true);
connectedProvider.setLocation(currentLocation);

View file

@ -76,6 +76,9 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
private static final String TRANSIENT_PROVIDER_TOOLBAR_WARNING_MESSAGE =
"Transient providers are not added to the toolbar";
private static final String TRANSIENT_PROVIDER_KEY_BINDING_WARNING_MESSAGE =
"Transient providers cannot have key bindings";
public static final String DEFAULT_WINDOW_GROUP = "Default";
private static final String TOOLBAR_GROUP = "View";
@ -95,20 +98,23 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
/** True if this provider's action should appear in the toolbar */
private boolean isToolbarAction;
private boolean isTransient;
private HelpLocation helpLocation;
private KeyBindingData defaultKeyBindingData;
private Icon icon;
private String windowMenuGroup;
private String group = DEFAULT_WINDOW_GROUP;
private WindowPosition defaultWindowPosition = WindowPosition.WINDOW;
private WindowPosition defaultIntraGroupPosition = WindowPosition.STACK;
private DockingAction showProviderAction;
private HelpLocation helpLocation;
private final Class<?> contextType;
private long instanceID = UniversalIdGenerator.nextID().getValue();
private boolean instanceIDHasBeenInitialized;
private String inceptionInformation;
/**
* Creates a new component provider with a default location of {@link WindowPosition#WINDOW}.
* @param tool The tool will manage and show this provider
@ -135,6 +141,8 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
this.owner = owner;
this.title = name;
this.contextType = contextType;
recordInception();
}
/**
@ -154,15 +162,6 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
showProviderAction = new ShowProviderAction();
}
private void removeShowProviderAction() {
if (showProviderAction == null) {
return; // not installed
}
dockingTool.removeAction(showProviderAction);
showProviderAction = null;
}
/**
* Returns the component to be displayed
* @return the component to be displayed
@ -493,6 +492,26 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
return tabText;
}
/**
* Sets the default key binding that will show this provider when pressed
* @param kbData the key binding
*/
public void setDefaultKeyBinding(KeyBindingData kbData) {
if (isInTool()) {
throw new IllegalStateException(
"Cannot set the default key binding after the provider is added to the tool");
}
this.defaultKeyBindingData = kbData;
if (isTransient) {
Msg.error(this, TRANSIENT_PROVIDER_KEY_BINDING_WARNING_MESSAGE,
ReflectionUtilities.createJavaFilteredThrowable());
this.defaultKeyBindingData = null;
}
}
/**
* Convenience method for setting the provider's icon.
* @param icon the icon to use for this provider.
@ -530,8 +549,8 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
4) Wire default 'close' action to keybinding
5) Add global action for (show last provider)
6) Remove plugin code that creates the 'show' actions
--Navigation menu?
Questions:
C) How to wire universal close action (it is focus-dependent)
@ -539,7 +558,8 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
Fix:
-Toolbar description for key doesn't match menu (goes away)
-Update key binding methods to use an enum for: no management / full management / shared management
-remove superfluous overrides of getIcon()
*/
@ -573,6 +593,12 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
protected void setTransient() {
isTransient = true;
if (isInTool()) {
throw new IllegalStateException(
"A component provider cannot be marked as 'transient' " +
"after it is added to the tool");
}
// avoid visually disturbing the user by adding/removing toolbar actions for temp providers
if (isToolbarAction) {
isToolbarAction = false;
@ -580,7 +606,11 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
ReflectionUtilities.createJavaFilteredThrowable());
}
removeShowProviderAction();
if (defaultKeyBindingData != null) {
defaultKeyBindingData = null;
Msg.error(this, TRANSIENT_PROVIDER_KEY_BINDING_WARNING_MESSAGE,
ReflectionUtilities.createJavaFilteredThrowable());
}
}
/**
@ -687,6 +717,22 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
return name + " - " + getTitle() + " - " + getSubTitle();
}
private void recordInception() {
if (!SystemUtilities.isInDevelopmentMode()) {
inceptionInformation = "";
return;
}
inceptionInformation = getInceptionFromTheFirstClassThatIsNotUs();
}
private String getInceptionFromTheFirstClassThatIsNotUs() {
Throwable t = ReflectionUtilities.createThrowableWithStackOlderThan(getClass());
StackTraceElement[] trace = t.getStackTrace();
String classInfo = trace[0].toString();
return classInfo;
}
/**
* Returns any registered new provider name for the oldName/oldOwner pair.
* @param oldOwner the old owner name
@ -737,6 +783,14 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
if (isToolbarAction) {
setToolBarData(new ToolBarData(icon, TOOLBAR_GROUP));
}
if (defaultKeyBindingData != null) {
// this action itself is not 'key binding managed', but the system *will* use
// any key binding value we set when connecting 'shared' actions
setKeyBindingData(defaultKeyBindingData);
}
setDescription("Display " + name);
}
@Override
@ -751,7 +805,14 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
@Override
public boolean usesSharedKeyBinding() {
// we do not allow transient providers to have key bindings
return !isTransient;
}
@Override
protected String getInceptionFromTheFirstClassThatIsNotUs() {
// overridden to show who created the provider, as that is what this action represents
return inceptionInformation;
}
}
}

View file

@ -143,13 +143,17 @@ class ShowComponentAction extends DockingAction implements Comparable<ShowCompon
public String getHelpInfo() {
StringBuilder buffy = new StringBuilder(super.getHelpInfo());
Class<? extends ComponentProvider> clazz = info.getProvider().getClass();
ComponentProvider provider = info.getProvider();
Class<? extends ComponentProvider> clazz = provider.getClass();
String className = clazz.getName();
String filename = className.substring(className.lastIndexOf('.') + 1);
String javaName = filename + ".java";
buffy.append(" ").append("PROVIDER: ").append(info.getName()).append(' ');
buffy.append('(').append(javaName).append(":1)");
DockingActionIf showAction = provider.getShowProviderAction();
String realInception = showAction.getInceptionInformation();
buffy.append(" ").append(realInception).append("\n ");
buffy.append(" ").append("PROVIDER: ").append(filename).append(' ');
buffy.append('(').append(provider.getOwner()).append(")");
buffy.append("\n ");
return buffy.toString();

View file

@ -489,7 +489,7 @@ public abstract class DockingAction implements DockingActionIf {
inceptionInformation = getInceptionFromTheFirstClassThatIsNotUs();
}
private String getInceptionFromTheFirstClassThatIsNotUs() {
protected String getInceptionFromTheFirstClassThatIsNotUs() {
Throwable t = ReflectionUtilities.createThrowableWithStackOlderThan(getClass());
StackTraceElement[] trace = t.getStackTrace();
String classInfo = trace[0].toString();

View file

@ -25,6 +25,7 @@ import org.apache.commons.lang3.StringUtils;
import docking.*;
import docking.action.*;
import ghidra.docking.util.DockingWindowsLookAndFeelUtils;
import ghidra.util.StringUtilities;
/**
@ -79,7 +80,7 @@ public class ToolBarItemManager implements PropertyChangeListener, ActionListene
}
private void setToolTipText(JButton button, DockingActionIf action, String toolTipText) {
String keyBindingText = getKeyBindingAcceleratorText(action.getKeyBinding());
String keyBindingText = getKeyBindingAcceleratorText(button, action.getKeyBinding());
if (keyBindingText != null) {
button.setToolTipText(combingToolTipTextWithKeyBinding(toolTipText, keyBindingText));
}
@ -121,7 +122,7 @@ public class ToolBarItemManager implements PropertyChangeListener, ActionListene
return action.getName();
}
private String getKeyBindingAcceleratorText(KeyStroke keyStroke) {
private String getKeyBindingAcceleratorText(JButton button, KeyStroke keyStroke) {
if (keyStroke == null) {
return null;
}
@ -130,8 +131,12 @@ public class ToolBarItemManager implements PropertyChangeListener, ActionListene
StringBuilder builder = new StringBuilder();
int modifiers = keyStroke.getModifiers();
if (modifiers > 0) {
builder.append(KeyEvent.getKeyModifiersText(modifiers));
builder.append('+');
builder.append(InputEvent.getModifiersExText(modifiers));
// The Aqua LaF does not use the '+' symbol between modifiers
if (!DockingWindowsLookAndFeelUtils.isUsingAquaUI(button.getUI())) {
builder.append('+');
}
}
int keyCode = keyStroke.getKeyCode();
if (keyCode != 0) {