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 javax.swing.SwingUtilities;
import docking.ActionContext; import docking.ActionContext;
import docking.DockingUtils;
import docking.action.*; import docking.action.*;
import docking.widgets.table.GTable; import docking.widgets.table.GTable;
import ghidra.app.CorePluginPackage; import ghidra.app.CorePluginPackage;
@ -72,7 +71,6 @@ public class BookmarkPlugin extends ProgramPlugin
private BookmarkProvider provider; private BookmarkProvider provider;
private DockingAction addAction; private DockingAction addAction;
private DockingAction showAction;
private DockingAction deleteAction; private DockingAction deleteAction;
private CreateBookmarkDialog createDialog; private CreateBookmarkDialog createDialog;
private GoToService goToService; private GoToService goToService;
@ -113,19 +111,6 @@ public class BookmarkPlugin extends ProgramPlugin
addAction.setEnabled(true); addAction.setEnabled(true);
tool.addAction(addAction); 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); MultiIconBuilder builder = new MultiIconBuilder(Icons.CONFIGURE_FILTER_ICON);
builder.addLowerRightIcon(ResourceManager.loadImage("images/check.png")); builder.addLowerRightIcon(ResourceManager.loadImage("images/check.png"));
Icon filterTypesChanged = builder.build(); Icon filterTypesChanged = builder.build();
@ -213,10 +198,6 @@ public class BookmarkPlugin extends ProgramPlugin
addAction.dispose(); addAction.dispose();
addAction = null; addAction = null;
} }
if (showAction != null) {
showAction.dispose();
showAction = null;
}
if (provider != null) { if (provider != null) {
provider.dispose(); provider.dispose();
provider = null; provider = null;

View file

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

View file

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

View file

@ -57,7 +57,7 @@ import resources.ResourceManager;
public class CallTreeProvider extends ComponentProviderAdapter implements DomainObjectListener { public class CallTreeProvider extends ComponentProviderAdapter implements DomainObjectListener {
static final String EXPAND_ACTION_NAME = "Fully Expand Selected Nodes"; 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 EMPTY_ICON = ResourceManager.loadImage("images/EmptyIcon16.gif");
private static final Icon EXPAND_ICON = Icons.EXPAND_ALL_ICON; private static final Icon EXPAND_ICON = Icons.EXPAND_ALL_ICON;
private static final Icon COLLAPSE_ICON = Icons.COLLAPSE_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 JSplitPane splitPane;
private GTree incomingTree; private GTree incomingTree;
private GTree outgoingTree; private GTree outgoingTree;
private boolean isPrimary;
private SwingUpdateManager reloadUpdateManager = new SwingUpdateManager(500, () -> doUpdate()); private SwingUpdateManager reloadUpdateManager = new SwingUpdateManager(500, () -> doUpdate());
@ -93,20 +94,20 @@ public class CallTreeProvider extends ComponentProviderAdapter implements Domain
private AtomicInteger recurseDepth = new AtomicInteger(); private AtomicInteger recurseDepth = new AtomicInteger();
private NumberIcon recurseIcon; private NumberIcon recurseIcon;
public CallTreeProvider(CallTreePlugin plugin) { public CallTreeProvider(CallTreePlugin plugin, boolean isPrimary) {
super(plugin.getTool(), TITLE, plugin.getName()); super(plugin.getTool(), TITLE, plugin.getName());
this.plugin = plugin; this.plugin = plugin;
this.isPrimary = isPrimary;
component = buildComponent(); component = buildComponent();
// try to give the trees a suitable amount of space by default // try to give the trees a suitable amount of space by default
component.setPreferredSize(new Dimension(800, 400)); component.setPreferredSize(new Dimension(800, 400));
setTransient();
setWindowMenuGroup(TITLE); setWindowMenuGroup(TITLE);
setDefaultWindowPosition(WindowPosition.BOTTOM); setDefaultWindowPosition(WindowPosition.BOTTOM);
setIcon(CallTreePlugin.PROVIDER_ICON); setIcon(CallTreePlugin.PROVIDER_ICON, true);
setHelpLocation(new HelpLocation(plugin.getName(), "Call_Tree_Plugin")); setHelpLocation(new HelpLocation(plugin.getName(), "Call_Tree_Plugin"));
addToTool(); 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( navigateIncomingToggleAction.setToolBarData(new ToolBarData(
Icons.NAVIGATE_ON_INCOMING_EVENT_ICON, navigationOptionsToolbarGroup, "2")); Icons.NAVIGATE_ON_INCOMING_EVENT_ICON, navigationOptionsToolbarGroup, "2"));
navigateIncomingToggleAction.setDescription(HTMLUtilities.toHTML("Incoming Navigation" + navigateIncomingToggleAction.setDescription(HTMLUtilities.toHTML("Incoming Navigation" +
@ -818,7 +823,9 @@ public class CallTreeProvider extends ComponentProviderAdapter implements Domain
@Override @Override
public void componentHidden() { public void componentHidden() {
plugin.removeProvider(this); if (!isPrimary) {
plugin.removeProvider(this);
}
} }
private void reload() { private void reload() {

View file

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

View file

@ -23,7 +23,6 @@ import java.io.IOException;
import java.util.*; import java.util.*;
import java.util.Map.Entry; import java.util.Map.Entry;
import javax.swing.ImageIcon;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import javax.swing.tree.TreePath; import javax.swing.tree.TreePath;
@ -60,7 +59,6 @@ import ghidra.util.HelpLocation;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.datastruct.LRUMap; import ghidra.util.datastruct.LRUMap;
import ghidra.util.task.TaskLauncher; import ghidra.util.task.TaskLauncher;
import resources.ResourceManager;
/** /**
* Plugin to pop up the dialog to manage data types in the program * 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 public class DataTypeManagerPlugin extends ProgramPlugin
implements DomainObjectListener, DataTypeManagerService, PopupListener { 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 String SEACH_PROVIDER_NAME = "Search DataTypes Provider";
private static final int RECENTLY_USED_CACHE_SIZE = 10; private static final int RECENTLY_USED_CACHE_SIZE = 10;
private static final String STANDARD_ARCHIVE_MENU = "Standard Archive"; private static final String STANDARD_ARCHIVE_MENU = "Standard Archive";
private static final String RECENTLY_OPENED_MENU = "Recently Opened Archive"; private static final String RECENTLY_OPENED_MENU = "Recently Opened Archive";
private DockingAction manageDataAction;
private DataTypeManagerHandler dataTypeManagerHandler; private DataTypeManagerHandler dataTypeManagerHandler;
private DataTypesProvider provider; private DataTypesProvider provider;
private OpenVersionedFileDialog openDialog; private OpenVersionedFileDialog openDialog;
@ -126,12 +122,10 @@ public class DataTypeManagerPlugin extends ProgramPlugin
@Override @Override
public void archiveClosed(Archive archive) { public void archiveClosed(Archive archive) {
if (archive instanceof ProjectArchive) { if (archive instanceof ProjectArchive) {
// Program is handled by deactivation event
((ProjectArchive) archive).getDomainObject().removeListener( ((ProjectArchive) archive).getDomainObject().removeListener(
DataTypeManagerPlugin.this); DataTypeManagerPlugin.this);
} }
// Program is handled by deactivation.
// Otherwise, don't care.
} }
@Override @Override
@ -467,21 +461,6 @@ public class DataTypeManagerPlugin extends ProgramPlugin
* Create the actions for the menu on the tool. * Create the actions for the menu on the tool.
*/ */
private void createActions() { 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(); createStandardArchivesMenu();
} }

View file

@ -57,6 +57,8 @@ import resources.ResourceManager;
import util.HistoryList; import util.HistoryList;
public class DataTypesProvider extends ComponentProviderAdapter { 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 TITLE = "Data Type Manager";
private static final String POINTER_FILTER_STATE = "PointerFilterState"; private static final String POINTER_FILTER_STATE = "PointerFilterState";
private static final String ARRAY_FILTER_STATE = "ArrayFilterState"; private static final String ARRAY_FILTER_STATE = "ArrayFilterState";
@ -95,9 +97,11 @@ public class DataTypesProvider extends ComponentProviderAdapter {
public DataTypesProvider(DataTypeManagerPlugin plugin, String providerName) { public DataTypesProvider(DataTypeManagerPlugin plugin, String providerName) {
super(plugin.getTool(), providerName, plugin.getName(), DataTypesActionContext.class); super(plugin.getTool(), providerName, plugin.getName(), DataTypesActionContext.class);
setTitle(TITLE);
this.plugin = plugin; this.plugin = plugin;
setTitle(TITLE);
setIcon(ResourceManager.loadImage(DATA_TYPES_ICON), true);
navigationHistory.setAllowDuplicates(true); navigationHistory.setAllowDuplicates(true);
buildComponent(); buildComponent();
@ -106,11 +110,6 @@ public class DataTypesProvider extends ComponentProviderAdapter {
createLocalActions(); createLocalActions();
} }
@Override
public ImageIcon getIcon() {
return ResourceManager.loadImage(DataTypeManagerPlugin.DATA_TYPES_ICON);
}
/** /**
* This creates all the actions for opening/creating data type archives. * This creates all the actions for opening/creating data type archives.
* It also creates the action for refreshing the built-in data types * 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) { public EquateTablePlugin(PluginTool tool) {
super(tool, true, false); super(tool, true, false);
updateMgr = new SwingUpdateManager(1000, 3000, new Runnable() { updateMgr = new SwingUpdateManager(1000, 3000, () -> provider.updateEquates());
@Override
public void run() {
provider.updateEquates();
}
});
provider = new EquateTableProvider(this); 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_ADDED) ||
ev.containsEvent(ChangeManager.DOCR_CODE_MOVED) || 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)) { ev.containsEvent(ChangeManager.DOCR_DATA_TYPE_CHANGED)) {
updateMgr.update(); updateMgr.update();
} }
@ -154,9 +149,6 @@ public class EquateTablePlugin extends ProgramPlugin implements DomainObjectList
provider.programClosed(); provider.programClosed();
} }
/**
* Delete the list of equates.
*/
void deleteEquates(List<Equate> equates) { void deleteEquates(List<Equate> equates) {
if (equates.isEmpty()) { if (equates.isEmpty()) {
return; return;
@ -173,13 +165,11 @@ public class EquateTablePlugin extends ProgramPlugin implements DomainObjectList
} }
} }
String title = "Delete Equate" + (equates.size() > 1 ? "s" : "") + "?"; String title = "Delete Equate" + (equates.size() > 1 ? "s" : "") + "?";
String msg = String msg = "Do you really want to delete the equate" + (equates.size() > 1 ? "s" : "") +
"Do you really want to delete the equate" + (equates.size() > 1 ? "s" : "") + ": " + ": " + equates + " ?" + "\n\n NOTE: All references will be removed.";
equates + " ?" + "\n\n NOTE: All references will be removed.";
int option = int option = OptionDialog.showOptionDialog(provider.getComponent(), title, msg, "Delete",
OptionDialog.showOptionDialog(provider.getComponent(), title, msg, "Delete", OptionDialog.QUESTION_MESSAGE);
OptionDialog.QUESTION_MESSAGE);
if (option != OptionDialog.CANCEL_OPTION) { if (option != OptionDialog.CANCEL_OPTION) {
tool.execute(new RemoveEquateCmd(equateNames, getTool()), currentProgram); 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 * If the equate exists, checks to make sure the value matches the current scalar value
* current scalar value.
* *
* @param dialog the dialog whose status area should be set with any error messages. * @param equate the equate to check
* @param equateStr the candidate equate name for the set or rename operation. * @param equateStr the candidate equate name for the set or rename operation
* @return true if valid
*/ */
boolean isValid(Equate equate, String equateStr) { 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) { if (equateStr == null || equateStr.length() <= 0) {
return false; return false;
} }
// look up the new equate string
EquateTable equateTable = currentProgram.getEquateTable(); EquateTable equateTable = currentProgram.getEquateTable();
Equate newEquate = equateTable.getEquate(equateStr); Equate newEquate = equateTable.getEquate(equateStr);
if (newEquate != null && !newEquate.equals(equate)) { if (newEquate != null && !newEquate.equals(equate)) {
Msg.showInfo(getClass(), provider.getComponent(), "Rename Equate Failed!", "Equate " + Msg.showInfo(getClass(), provider.getComponent(), "Rename Equate Failed!",
equateStr + " exists with value 0x" + Long.toHexString(newEquate.getValue()) + "Equate " + equateStr + " exists with value 0x" +
" (" + newEquate.getValue() + ")"); Long.toHexString(newEquate.getValue()) + " (" + newEquate.getValue() + ")");
return false; return false;
} }
return true; return true;

View file

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

View file

@ -15,6 +15,8 @@
*/ */
package ghidra.app.plugin.core.memory; package ghidra.app.plugin.core.memory;
import java.awt.Cursor;
import ghidra.app.CorePluginPackage; import ghidra.app.CorePluginPackage;
import ghidra.app.events.ProgramLocationPluginEvent; import ghidra.app.events.ProgramLocationPluginEvent;
import ghidra.app.plugin.PluginCategoryNames; import ghidra.app.plugin.PluginCategoryNames;
@ -31,15 +33,6 @@ import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.util.ChangeManager; import ghidra.program.util.ChangeManager;
import ghidra.program.util.ProgramLocation; 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 * <CODE>MemoryMapPlugin</CODE> displays a memory map of all blocks in
* the current program's memory. Options for Adding, Editing, and Deleting * 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 WAIT_CURSOR = new Cursor(Cursor.WAIT_CURSOR);
final static Cursor NORM_CURSOR = new Cursor(Cursor.DEFAULT_CURSOR); final static Cursor NORM_CURSOR = new Cursor(Cursor.DEFAULT_CURSOR);
private DockingAction memViewAction;
private MemoryMapProvider provider; private MemoryMapProvider provider;
private GoToService goToService; private GoToService goToService;
private MemoryMapManager memManager; private MemoryMapManager memManager;
/**
* Constructor
*/
public MemoryMapPlugin(PluginTool tool) { public MemoryMapPlugin(PluginTool tool) {
super(tool, true, false); super(tool, true, false);
memManager = new MemoryMapManager(this); memManager = new MemoryMapManager(this);
provider = new MemoryMapProvider(this); provider = new MemoryMapProvider(this);
createActions();
} }
/** /**
@ -83,9 +71,6 @@ public class MemoryMapPlugin extends ProgramPlugin implements DomainObjectListen
*/ */
@Override @Override
public void dispose() { public void dispose() {
if (memViewAction != null) {
memViewAction.dispose();
}
if (provider != null) { if (provider != null) {
provider.dispose(); provider.dispose();
provider = null; provider = null;
@ -122,8 +107,9 @@ public class MemoryMapPlugin extends ProgramPlugin implements DomainObjectListen
@Override @Override
protected void init() { protected void init() {
goToService = tool.getService(GoToService.class); goToService = tool.getService(GoToService.class);
if (currentProgram != null) if (currentProgram != null) {
programActivated(currentProgram); programActivated(currentProgram);
}
} }
/** /**
@ -168,29 +154,4 @@ public class MemoryMapPlugin extends ProgramPlugin implements DomainObjectListen
ProgramLocation loc = new ProgramLocation(currentProgram, addr); ProgramLocation loc = new ProgramLocation(currentProgram, addr);
goToService.goTo(loc); 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) { MemoryMapProvider(MemoryMapPlugin plugin) {
super(plugin.getTool(), "Memory Map", plugin.getName(), ProgramActionContext.class); super(plugin.getTool(), "Memory Map", plugin.getName(), ProgramActionContext.class);
this.plugin = plugin; this.plugin = plugin;
setHelpLocation(new HelpLocation(plugin.getName(), getName())); setHelpLocation(new HelpLocation(plugin.getName(), getName()));
memManager = plugin.getMemoryMapManager(); memManager = plugin.getMemoryMapManager();
setIcon(ResourceManager.loadImage(MEMORY_IMAGE)); setIcon(ResourceManager.loadImage(MEMORY_IMAGE), true);
mainPanel = buildMainPanel(); mainPanel = buildMainPanel();
addToTool(); addToTool();
addLocalActions(); addLocalActions();
@ -107,9 +108,6 @@ class MemoryMapProvider extends ComponentProviderAdapter {
return new ProgramActionContext(this, program); return new ProgramActionContext(this, program);
} }
/**
* Set the status text on this dialog.
*/
void setStatusText(String msg) { void setStatusText(String msg) {
tool.setStatusInfo(msg); tool.setStatusInfo(msg);
} }
@ -367,9 +365,6 @@ class MemoryMapProvider extends ComponentProviderAdapter {
} }
} }
/**
* @return
*/
JTable getTable() { JTable getTable() {
return memTable; return memTable;
} }
@ -462,7 +457,8 @@ class MemoryMapProvider extends ComponentProviderAdapter {
public void mousePressed(MouseEvent e) { public void mousePressed(MouseEvent e) {
setStatusText(""); setStatusText("");
if (!e.isPopupTrigger()) { 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(); selectAddress();
} }
} }

View file

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

View file

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

View file

@ -19,9 +19,6 @@ import java.io.IOException;
import java.io.PrintStream; import java.io.PrintStream;
import java.net.Socket; import java.net.Socket;
import docking.ActionContext;
import docking.action.DockingAction;
import docking.action.ToolBarData;
import generic.jar.ResourceFile; import generic.jar.ResourceFile;
import ghidra.app.CorePluginPackage; import ghidra.app.CorePluginPackage;
import ghidra.app.plugin.PluginCategoryNames; import ghidra.app.plugin.PluginCategoryNames;
@ -36,9 +33,7 @@ import ghidra.framework.plugintool.PluginInfo;
import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.util.PluginStatus; import ghidra.framework.plugintool.util.PluginStatus;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.util.HelpLocation;
import ghidra.util.task.TaskListener; import ghidra.util.task.TaskListener;
import resources.ResourceManager;
//@formatter:off //@formatter:off
@PluginInfo( @PluginInfo(
@ -54,7 +49,6 @@ import resources.ResourceManager;
public class GhidraScriptMgrPlugin extends ProgramPlugin implements GhidraScriptService { public class GhidraScriptMgrPlugin extends ProgramPlugin implements GhidraScriptService {
private GhidraScriptComponentProvider provider; private GhidraScriptComponentProvider provider;
private DockingAction action;
public GhidraScriptMgrPlugin(PluginTool tool) { public GhidraScriptMgrPlugin(PluginTool tool) {
super(tool, true, true, true); super(tool, true, true, true);
@ -62,31 +56,9 @@ public class GhidraScriptMgrPlugin extends ProgramPlugin implements GhidraScript
provider = new GhidraScriptComponentProvider(this); 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 @Override
protected void dispose() { protected void dispose() {
super.dispose(); super.dispose();
action.dispose();
provider.dispose(); provider.dispose();
} }

View file

@ -15,11 +15,6 @@
*/ */
package ghidra.app.plugin.core.symboltree; 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.CorePluginPackage;
import ghidra.app.events.*; import ghidra.app.events.*;
import ghidra.app.plugin.PluginCategoryNames; 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.listing.Program;
import ghidra.program.model.symbol.*; import ghidra.program.model.symbol.*;
import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramLocation;
import ghidra.util.HelpLocation;
import resources.ResourceManager;
//@formatter:off //@formatter:off
@PluginInfo( @PluginInfo(
@ -50,17 +43,13 @@ public class SymbolTreePlugin extends Plugin {
public static final String PLUGIN_NAME = "SymbolTreePlugin"; public static final String PLUGIN_NAME = "SymbolTreePlugin";
private DockingAction symTreeAction;
private SymbolTreeProvider provider; private SymbolTreeProvider provider;
private Program program; private Program program;
private GoToService goToService; private GoToService goToService;
private boolean processingGoTo; private boolean processingGoTo;
final static ImageIcon SYMBOL_TREE_ICON = ResourceManager.loadImage("images/sitemap_color.png");
public SymbolTreePlugin(PluginTool tool) { public SymbolTreePlugin(PluginTool tool) {
super(tool); super(tool);
createAction();
provider = new SymbolTreeProvider(tool, this); provider = new SymbolTreeProvider(tool, this);
} }
@ -151,26 +140,6 @@ public class SymbolTreePlugin extends Plugin {
goToService.goToExternalLocation(extLoc, false); 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() { public Program getProgram() {
return program; return program;
} }

View file

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

View file

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

View file

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

View file

@ -16,7 +16,6 @@
package ghidra.app.plugin.core.symtable; package ghidra.app.plugin.core.symtable;
import java.awt.Cursor; import java.awt.Cursor;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import javax.swing.ImageIcon; 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 WAIT_CURSOR = new Cursor(Cursor.WAIT_CURSOR);
final static Cursor NORM_CURSOR = new Cursor(Cursor.DEFAULT_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 openRefsAction;
private DockingAction deleteAction; private DockingAction deleteAction;
private DockingAction makeSelectionAction; private DockingAction makeSelectionAction;
@ -113,10 +106,6 @@ public class SymbolTablePlugin extends Plugin implements DomainObjectListener {
symProvider = new SymbolProvider(this); symProvider = new SymbolProvider(this);
refProvider = new ReferenceProvider(this); refProvider = new ReferenceProvider(this);
tool.addComponentProvider(symProvider, false);
tool.addComponentProvider(refProvider, false);
createActions();
createSymActions(); createSymActions();
createRefActions(); createRefActions();
@ -133,8 +122,6 @@ public class SymbolTablePlugin extends Plugin implements DomainObjectListener {
super.dispose(); super.dispose();
swingMgr.dispose(); swingMgr.dispose();
viewSymTableAction.dispose();
viewRefTableAction.dispose();
deleteAction.dispose(); deleteAction.dispose();
makeSelectionAction.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() { private void createSymActions() {
String popupGroup = "1"; String popupGroup = "1";

View file

@ -25,6 +25,7 @@ import javax.swing.*;
import org.junit.*; import org.junit.*;
import docking.action.DockingActionIf; import docking.action.DockingActionIf;
import docking.action.KeyBindingData;
import docking.actions.KeyEntryDialog; import docking.actions.KeyEntryDialog;
import docking.tool.util.DockingToolConstants; import docking.tool.util.DockingToolConstants;
import ghidra.framework.options.ToolOptions; import ghidra.framework.options.ToolOptions;
@ -91,6 +92,59 @@ public class ComponentProviderActionsTest extends AbstractGhidraHeadedIntegratio
assertWindowMenuActionHasIcon(Icons.EMPTY_ICON); 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 @Test
public void testSetKeyBinding_ViaDialog_FromWindowMenu() { 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 // Private Methods
//================================================================================================== //==================================================================================================
@ -215,6 +254,10 @@ public class ComponentProviderActionsTest extends AbstractGhidraHeadedIntegratio
waitForSwing(); waitForSwing();
} }
private void setDefaultKeyBinding(KeyStroke defaultKs) {
runSwing(() -> provider.setDefaultKeyBinding(new KeyBindingData(defaultKs)));
}
private void setIcon(Icon icon) { private void setIcon(Icon icon) {
runSwing(() -> provider.setIcon(icon)); runSwing(() -> provider.setIcon(icon));
} }

View file

@ -8,7 +8,7 @@
</head> </head>
<body lang="EN-US"> <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., <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 Hex, Ascii, Octal, etc.&nbsp;The figure below shows the Byte Viewer
plugin in a separate window from the plugin in a separate window from the

View file

@ -19,9 +19,6 @@ import java.util.*;
import org.jdom.Element; import org.jdom.Element;
import docking.ActionContext;
import docking.action.DockingAction;
import docking.action.ToolBarData;
import ghidra.app.CorePluginPackage; import ghidra.app.CorePluginPackage;
import ghidra.app.events.*; import ghidra.app.events.*;
import ghidra.app.plugin.PluginCategoryNames; import ghidra.app.plugin.PluginCategoryNames;
@ -35,7 +32,6 @@ 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 ghidra.util.SystemUtilities; import ghidra.util.SystemUtilities;
import resources.ResourceManager;
import utility.function.Callback; import utility.function.Callback;
/** /**
@ -73,23 +69,6 @@ public class ByteViewerPlugin extends Plugin {
super(tool); super(tool);
connectedProvider = new ProgramByteViewerComponentProvider(tool, this, true); 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() { protected void showConnectedProvider() {

View file

@ -71,8 +71,10 @@ public class ProgramByteViewerComponentProvider extends ByteViewerComponentProvi
boolean isConnected) { boolean isConnected) {
super(tool, plugin, "Bytes", ByteViewerActionContext.class); super(tool, plugin, "Bytes", ByteViewerActionContext.class);
this.isConnected = isConnected; 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); clipboardProvider = new ByteViewerClipboardProvider(this, tool);
addToTool(); 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() { String getCurrentTextSelection() {
return panel.getCurrentComponent().getTextForSelection(); return panel.getCurrentComponent().getTextForSelection();

View file

@ -15,14 +15,10 @@
*/ */
package ghidra.app.plugin.core.decompile; package ghidra.app.plugin.core.decompile;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.util.*; import java.util.*;
import org.jdom.Element; import org.jdom.Element;
import docking.ActionContext;
import docking.action.*;
import ghidra.app.CorePluginPackage; import ghidra.app.CorePluginPackage;
import ghidra.app.decompiler.component.DecompilerHighlightService; import ghidra.app.decompiler.component.DecompilerHighlightService;
import ghidra.app.decompiler.component.hover.DecompilerHoverService; 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.model.listing.*;
import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramLocation;
import ghidra.program.util.ProgramSelection; import ghidra.program.util.ProgramSelection;
import ghidra.util.HelpLocation;
import ghidra.util.task.SwingUpdateManager; import ghidra.util.task.SwingUpdateManager;
import resources.ResourceManager;
/** /**
* Plugin for producing a high-level C interpretation of assembly functions. * Plugin for producing a high-level C interpretation of assembly functions.
@ -72,8 +66,6 @@ public class DecompilePlugin extends Plugin {
private ProgramLocation currentLocation; private ProgramLocation currentLocation;
private ProgramSelection currentSelection; private ProgramSelection currentSelection;
private DockingAction decompileAction;
/** /**
* Delay location changes to allow location events to settle down. * Delay location changes to allow location events to settle down.
* This happens when a readDataState occurs when a tool is restored * This happens when a readDataState occurs when a tool is restored
@ -92,8 +84,6 @@ public class DecompilePlugin extends Plugin {
disconnectedProviders = new ArrayList<>(); disconnectedProviders = new ArrayList<>();
connectedProvider = new PrimaryDecompilerProvider(this); connectedProvider = new PrimaryDecompilerProvider(this);
createActions();
registerServices(); 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 * Tells the Plugin to write any data-dependent state to the
* output stream. * output stream.
@ -184,10 +158,6 @@ public class DecompilePlugin extends Plugin {
} }
} }
private void showProvider() {
connectedProvider.setVisible(true);
}
DecompilerProvider createNewDisconnectedProvider() { DecompilerProvider createNewDisconnectedProvider() {
DecompilerProvider decompilerProvider = new DecompilerProvider(this, false); DecompilerProvider decompilerProvider = new DecompilerProvider(this, false);
decompilerProvider.setClipboardService(tool.getService(ClipboardService.class)); decompilerProvider.setClipboardService(tool.getService(ClipboardService.class));

View file

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

View file

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

View file

@ -21,9 +21,6 @@ import javax.swing.ImageIcon;
import org.jdom.Element; import org.jdom.Element;
import docking.ActionContext;
import docking.action.DockingAction;
import docking.action.ToolBarData;
import ghidra.GhidraOptions; import ghidra.GhidraOptions;
import ghidra.app.CorePluginPackage; import ghidra.app.CorePluginPackage;
import ghidra.app.events.*; import ghidra.app.events.*;
@ -43,7 +40,6 @@ import ghidra.graph.viewer.options.VisualGraphOptions;
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 ghidra.util.HelpLocation;
import resources.ResourceManager; import resources.ResourceManager;
//@formatter:off //@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 PROGRAM_PATH_ID = "Program Path";
private static final String DISCONNECTED_COUNT_ID = "Disconnected Count"; private static final String DISCONNECTED_COUNT_ID = "Disconnected Count";
private DockingAction showFunctionGraphAction;
private FGProvider connectedProvider; private FGProvider connectedProvider;
private List<FGProvider> disconnectedProviders = new ArrayList<>(); private List<FGProvider> disconnectedProviders = new ArrayList<>();
private FormatManager userDefinedFormatManager; private FormatManager userDefinedFormatManager;
@ -88,8 +82,6 @@ public class FunctionGraphPlugin extends ProgramPlugin implements OptionsChangeL
public FunctionGraphPlugin(PluginTool tool) { public FunctionGraphPlugin(PluginTool tool) {
super(tool, true, true, true); super(tool, true, true, true);
createActions();
colorProvider = new IndependentColorProvider(tool); 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() { void showProvider() {
connectedProvider.setVisible(true); connectedProvider.setVisible(true);
connectedProvider.setLocation(currentLocation); 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 = private static final String TRANSIENT_PROVIDER_TOOLBAR_WARNING_MESSAGE =
"Transient providers are not added to the toolbar"; "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"; public static final String DEFAULT_WINDOW_GROUP = "Default";
private static final String TOOLBAR_GROUP = "View"; 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 */ /** True if this provider's action should appear in the toolbar */
private boolean isToolbarAction; private boolean isToolbarAction;
private boolean isTransient; private boolean isTransient;
private HelpLocation helpLocation; private KeyBindingData defaultKeyBindingData;
private Icon icon; private Icon icon;
private String windowMenuGroup; private String windowMenuGroup;
private String group = DEFAULT_WINDOW_GROUP; private String group = DEFAULT_WINDOW_GROUP;
private WindowPosition defaultWindowPosition = WindowPosition.WINDOW; private WindowPosition defaultWindowPosition = WindowPosition.WINDOW;
private WindowPosition defaultIntraGroupPosition = WindowPosition.STACK; private WindowPosition defaultIntraGroupPosition = WindowPosition.STACK;
private DockingAction showProviderAction; private DockingAction showProviderAction;
private HelpLocation helpLocation;
private final Class<?> contextType; private final Class<?> contextType;
private long instanceID = UniversalIdGenerator.nextID().getValue(); private long instanceID = UniversalIdGenerator.nextID().getValue();
private boolean instanceIDHasBeenInitialized; private boolean instanceIDHasBeenInitialized;
private String inceptionInformation;
/** /**
* Creates a new component provider with a default location of {@link WindowPosition#WINDOW}. * Creates a new component provider with a default location of {@link WindowPosition#WINDOW}.
* @param tool The tool will manage and show this provider * @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.owner = owner;
this.title = name; this.title = name;
this.contextType = contextType; this.contextType = contextType;
recordInception();
} }
/** /**
@ -154,15 +162,6 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
showProviderAction = new ShowProviderAction(); showProviderAction = new ShowProviderAction();
} }
private void removeShowProviderAction() {
if (showProviderAction == null) {
return; // not installed
}
dockingTool.removeAction(showProviderAction);
showProviderAction = null;
}
/** /**
* Returns the component to be displayed * Returns the component to be displayed
* @return the component to be displayed * @return the component to be displayed
@ -493,6 +492,26 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
return tabText; 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. * Convenience method for setting the provider's icon.
* @param icon the icon to use for this provider. * @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 4) Wire default 'close' action to keybinding
5) Add global action for (show last provider) 5) Add global action for (show last provider)
6) Remove plugin code that creates the 'show' actions --Navigation menu?
Questions: Questions:
C) How to wire universal close action (it is focus-dependent) C) How to wire universal close action (it is focus-dependent)
@ -539,7 +558,8 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
Fix: 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() { protected void setTransient() {
isTransient = true; 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 // avoid visually disturbing the user by adding/removing toolbar actions for temp providers
if (isToolbarAction) { if (isToolbarAction) {
isToolbarAction = false; isToolbarAction = false;
@ -580,7 +606,11 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
ReflectionUtilities.createJavaFilteredThrowable()); 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(); 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. * Returns any registered new provider name for the oldName/oldOwner pair.
* @param oldOwner the old owner name * @param oldOwner the old owner name
@ -737,6 +783,14 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
if (isToolbarAction) { if (isToolbarAction) {
setToolBarData(new ToolBarData(icon, TOOLBAR_GROUP)); 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 @Override
@ -751,7 +805,14 @@ public abstract class ComponentProvider implements HelpDescriptor, ActionContext
@Override @Override
public boolean usesSharedKeyBinding() { public boolean usesSharedKeyBinding() {
// we do not allow transient providers to have key bindings
return !isTransient; 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() { public String getHelpInfo() {
StringBuilder buffy = new StringBuilder(super.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 className = clazz.getName();
String filename = className.substring(className.lastIndexOf('.') + 1); String filename = className.substring(className.lastIndexOf('.') + 1);
String javaName = filename + ".java";
buffy.append(" ").append("PROVIDER: ").append(info.getName()).append(' '); DockingActionIf showAction = provider.getShowProviderAction();
buffy.append('(').append(javaName).append(":1)"); 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 "); buffy.append("\n ");
return buffy.toString(); return buffy.toString();

View file

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

View file

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