diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/bookmark/BookmarkPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/bookmark/BookmarkPlugin.java index 63e6f8fb2e..cf8ae6c1db 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/bookmark/BookmarkPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/bookmark/BookmarkPlugin.java @@ -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; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/bookmark/BookmarkProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/bookmark/BookmarkProvider.java index 05dc2b0159..df694141a4 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/bookmark/BookmarkProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/bookmark/BookmarkProvider.java @@ -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); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/calltree/CallTreePlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/calltree/CallTreePlugin.java index 4f4050153d..b7a43a0d55 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/calltree/CallTreePlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/calltree/CallTreePlugin.java @@ -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 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); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/calltree/CallTreeProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/calltree/CallTreeProvider.java index 39fd756f18..f61684e6e8 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/calltree/CallTreeProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/calltree/CallTreeProvider.java @@ -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() { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/console/ConsoleComponentProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/console/ConsoleComponentProvider.java index d7e74e29b9..ec21bf1e82 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/console/ConsoleComponentProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/console/ConsoleComponentProvider.java @@ -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")); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeManagerPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeManagerPlugin.java index 7c3478d4bb..2932a3e30b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeManagerPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeManagerPlugin.java @@ -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(); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesProvider.java index 225ef050f0..c0fe79acb8 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesProvider.java @@ -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 diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/equate/EquateTablePlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/equate/EquateTablePlugin.java index bf74f06bce..5449bcc647 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/equate/EquateTablePlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/equate/EquateTablePlugin.java @@ -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 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; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/InterpreterComponentProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/InterpreterComponentProvider.java index c41690114c..a51652fc3a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/InterpreterComponentProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/interpreter/InterpreterComponentProvider.java @@ -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 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(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapPlugin.java index 65fa8f6a8a..784bdc3bdc 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapPlugin.java @@ -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; - /** * MemoryMapPlugin 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); - } - } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapProvider.java index 8edc51298d..0f80af9006 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/memory/MemoryMapProvider.java @@ -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(); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/RegisterManagerProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/RegisterManagerProvider.java index 25435f96f2..0ea506490b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/RegisterManagerProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/RegisterManagerProvider.java @@ -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()); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/RegisterPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/RegisterPlugin.java index c9bbe6f1b0..495d71ccaf 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/RegisterPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/register/RegisterPlugin.java @@ -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 list = new ArrayList(); + ArrayList 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 }; } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptComponentProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptComponentProvider.java index 5618f802f9..5613dd0d22 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptComponentProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptComponentProvider.java @@ -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(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptMgrPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptMgrPlugin.java index 97d542a34b..498772040a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptMgrPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/GhidraScriptMgrPlugin.java @@ -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(); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symboltree/SymbolTreePlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symboltree/SymbolTreePlugin.java index 8202778be5..52cb02c549 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symboltree/SymbolTreePlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symboltree/SymbolTreePlugin.java @@ -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; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symboltree/SymbolTreeProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symboltree/SymbolTreeProvider.java index 7e9e74d317..d55419243d 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symboltree/SymbolTreeProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symboltree/SymbolTreeProvider.java @@ -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 //================================================================================================== diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symtable/ReferenceProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symtable/ReferenceProvider.java index 5c215d91b6..0d7f861661 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symtable/ReferenceProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symtable/ReferenceProvider.java @@ -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); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symtable/SymbolProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symtable/SymbolProvider.java index 2db72d136a..3f170249a6 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symtable/SymbolProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symtable/SymbolProvider.java @@ -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); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symtable/SymbolTablePlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symtable/SymbolTablePlugin.java index e11de4db46..41be28e348 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symtable/SymbolTablePlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/symtable/SymbolTablePlugin.java @@ -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"; diff --git a/Ghidra/Features/Base/src/test.slow/java/docking/ComponentProviderActionsTest.java b/Ghidra/Features/Base/src/test.slow/java/docking/ComponentProviderActionsTest.java index 19dd9c493d..8501ba3685 100644 --- a/Ghidra/Features/Base/src/test.slow/java/docking/ComponentProviderActionsTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/docking/ComponentProviderActionsTest.java @@ -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)); } diff --git a/Ghidra/Features/ByteViewer/src/main/help/help/topics/ByteViewerPlugin/The_Byte_Viewer.htm b/Ghidra/Features/ByteViewer/src/main/help/help/topics/ByteViewerPlugin/The_Byte_Viewer.htm index 61866121be..c325e89c3a 100644 --- a/Ghidra/Features/ByteViewer/src/main/help/help/topics/ByteViewerPlugin/The_Byte_Viewer.htm +++ b/Ghidra/Features/ByteViewer/src/main/help/help/topics/ByteViewerPlugin/The_Byte_Viewer.htm @@ -8,7 +8,7 @@ -

The Byte Viewer

+

The Byte Viewer

The Byte Viewer displays bytes in memory in various formats, e.g., Hex, Ascii, Octal, etc. The figure below shows the Byte Viewer plugin in a separate window from the diff --git a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerPlugin.java b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerPlugin.java index b68d8d30c6..57cf9009a3 100644 --- a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerPlugin.java +++ b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ByteViewerPlugin.java @@ -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() { diff --git a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ProgramByteViewerComponentProvider.java b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ProgramByteViewerComponentProvider.java index 83ea31b888..5bf2b527cc 100644 --- a/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ProgramByteViewerComponentProvider.java +++ b/Ghidra/Features/ByteViewer/src/main/java/ghidra/app/plugin/core/byteviewer/ProgramByteViewerComponentProvider.java @@ -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(); diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/DecompilePlugin.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/DecompilePlugin.java index 8939c16d59..9c063f51a3 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/DecompilePlugin.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/DecompilePlugin.java @@ -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)); diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/DecompilerProvider.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/DecompilerProvider.java index 8f048c2fb9..cd5ebc1a6b 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/DecompilerProvider.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/decompile/DecompilerProvider.java @@ -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); diff --git a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/FGProvider.java b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/FGProvider.java index f469c92895..e0f3fd4d5a 100644 --- a/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/FGProvider.java +++ b/Ghidra/Features/FunctionGraph/src/main/java/ghidra/app/plugin/core/functiongraph/FGProvider.java @@ -109,8 +109,9 @@ public class FGProvider extends VisualGraphComponentProvider 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); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/ComponentProvider.java b/Ghidra/Framework/Docking/src/main/java/docking/ComponentProvider.java index 9a1e4f851f..55b6e2dd35 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/ComponentProvider.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/ComponentProvider.java @@ -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; + } } } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/ShowComponentAction.java b/Ghidra/Framework/Docking/src/main/java/docking/ShowComponentAction.java index 4db4c5aede..734dc77ed6 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/ShowComponentAction.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/ShowComponentAction.java @@ -143,13 +143,17 @@ class ShowComponentAction extends DockingAction implements Comparable clazz = info.getProvider().getClass(); + ComponentProvider provider = info.getProvider(); + Class 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(); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/action/DockingAction.java b/Ghidra/Framework/Docking/src/main/java/docking/action/DockingAction.java index 63fecf7ea9..9c7dcdb5f2 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/action/DockingAction.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/action/DockingAction.java @@ -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(); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/menu/ToolBarItemManager.java b/Ghidra/Framework/Docking/src/main/java/docking/menu/ToolBarItemManager.java index b0388559fd..c1fd4bff3a 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/menu/ToolBarItemManager.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/menu/ToolBarItemManager.java @@ -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) {