GT-3430 - Key Bindings - Updated the Function Call Trees Plugin's

actions key bindings so users can set the bindings separately
This commit is contained in:
dragonmacher 2019-12-30 12:02:28 -05:00
parent cbe5b9e9ca
commit 74b67be5ed
11 changed files with 78 additions and 23 deletions

View File

@ -1049,7 +1049,6 @@ src/main/resources/images/functions.gif||GHIDRA||||END|
src/main/resources/images/go-down.tango.16.png||Tango Icons - Public Domain|||tango icon set|END|
src/main/resources/images/go-home.png||Tango Icons - Public Domain|||Tango|END|
src/main/resources/images/go-up.tango.16.png||Tango Icons - Public Domain|||tango icon set|END|
src/main/resources/images/help-browser.png||Tango Icons - Public Domain|||tango icon set|END|
src/main/resources/images/help-hint.png||Oxygen Icons - LGPL 3.0|||renamed from help-hing.png|END|
src/main/resources/images/hexData.png||GHIDRA||||END|
src/main/resources/images/house.png||FAMFAMFAM Icons - CC 2.5|||famfamfam silk icon set|END|

View File

@ -374,7 +374,7 @@
</BLOCKQUOTE>
</BLOCKQUOTE>
<H2><A name="View_Check_Outs"></A>View Checkouts</H2>
<H2><A name="View_Checkouts"></A>View Checkouts</H2>
<BLOCKQUOTE>
<P>To view a list of who has a file checked out, right mouse click on the file in the Ghidra

View File

@ -21,7 +21,8 @@ import java.util.List;
import javax.swing.Icon;
import docking.ActionContext;
import docking.action.*;
import docking.action.DockingAction;
import docking.action.MenuData;
import ghidra.app.CorePluginPackage;
import ghidra.app.context.ListingActionContext;
import ghidra.app.plugin.PluginCategoryNames;
@ -125,9 +126,9 @@ public class CallTreePlugin extends ProgramPlugin {
private void createActions() {
// use the name of the provider so that the shared key binding data will get used
String actionName = CallTreeProvider.TITLE;
String actionName = "Static Function Call Trees";
showCallTreeFromMenuAction =
new DockingAction(actionName, getName(), KeyBindingType.SHARED) {
new DockingAction(actionName, getName()) {
@Override
public void actionPerformed(ActionContext context) {
showOrCreateNewCallTree(currentLocation);
@ -143,6 +144,8 @@ public class CallTreePlugin extends ProgramPlugin {
new String[] { "References", "Show Call Trees" }, PROVIDER_ICON, "ShowReferencesTo"));
showCallTreeFromMenuAction.setHelpLocation(
new HelpLocation("CallTreePlugin", "Call_Tree_Plugin"));
showCallTreeFromMenuAction.setDescription("Shows the Function Call Trees window for the " +
"item under the cursor. The new window will not change along with the Listing cursor.");
tool.addAction(showCallTreeFromMenuAction);
}

View File

@ -604,7 +604,7 @@ public class CallTreeProvider extends ComponentProviderAdapter implements Domain
// Show new call tree action
//
DockingAction newCallTree =
new DockingAction("Show Call Tree For Function", plugin.getName()) {
new DockingAction("Show Call Trees For Function", plugin.getName()) {
@Override
public void actionPerformed(ActionContext context) {
GTree gTree = (GTree) context.getContextObject();
@ -671,6 +671,8 @@ public class CallTreeProvider extends ComponentProviderAdapter implements Domain
"Call_Tree_Context_Action_Show_Call_Tree_For_Function"));
newCallTree.setPopupMenuData(new MenuData(new String[] { "Show Call Tree For Function" },
CallTreePlugin.PROVIDER_ICON, newTreeMenu));
newCallTree.setDescription("Show the Function Call Tree window for the function " +
"selected in the call tree");
tool.addLocalAction(this, newCallTree);
}

View File

@ -18,7 +18,6 @@ package ghidra.app.plugin.core.decompile.actions;
import docking.action.MenuData;
import ghidra.app.decompiler.component.*;
import ghidra.app.plugin.core.decompile.DecompilerActionContext;
import ghidra.app.util.HelpTopics;
import ghidra.util.HelpLocation;
/**
@ -35,7 +34,7 @@ public class RemoveAllSecondaryHighlightsAction extends AbstractDecompilerAction
setPopupMenuData(new MenuData(
new String[] { "Secondary Highlight", "Remove All Highlights" }, "Decompile"));
setHelpLocation(new HelpLocation(HelpTopics.SELECTION, getName()));
setHelpLocation(new HelpLocation("DecompilePlugin", getName()));
}
@Override

View File

@ -19,7 +19,6 @@ import docking.action.MenuData;
import ghidra.app.decompiler.ClangToken;
import ghidra.app.decompiler.component.*;
import ghidra.app.plugin.core.decompile.DecompilerActionContext;
import ghidra.app.util.HelpTopics;
import ghidra.util.HelpLocation;
/**
@ -36,7 +35,7 @@ public class RemoveSecondaryHighlightAction extends AbstractDecompilerAction {
setPopupMenuData(
new MenuData(new String[] { "Secondary Highlight", "Remove Highlight" }, "Decompile"));
setHelpLocation(new HelpLocation(HelpTopics.SELECTION, getName()));
setHelpLocation(new HelpLocation("DecompilePlugin", getName()));
}
@Override

View File

@ -145,6 +145,20 @@ public class SharedStubKeyBindingAction extends DockingAction implements Options
return StringUtils.join(owners, ", ");
}
@Override
public String getDescription() {
Set<DockingActionIf> actions = clientActions.keySet();
for (DockingActionIf action : actions) {
String description = action.getDescription();
if (!StringUtils.isBlank(description)) {
return description;
}
}
return super.getDescription();
}
private KeyStroke validateActionsHaveTheSameDefaultKeyStroke(DockingActionIf newAction) {
// this value may be null

View File

@ -49,6 +49,7 @@ src/main/resources/images/face-monkey16.png||Tango Icons - Public Domain|||origi
src/main/resources/images/flag.png||Oxygen Icons - LGPL 3.0|||Oxygen icon theme (dual license; LGPL or CC-SA-3.0)|END|
src/main/resources/images/greenDragon16.png||GHIDRA||||END|
src/main/resources/images/greenDragon24.png||GHIDRA||||END|
src/main/resources/images/help-browser.png||Tango Icons - Public Domain|||tango icon set|END|
src/main/resources/images/internet-web-browser16.png||Tango Icons - Public Domain|||originally internet-web-browser.png from tango|END|
src/main/resources/images/kgpg.png||Nuvola Icons - LGPL 2.1|||Nuvola icon set|END|
src/main/resources/images/mergemgr16.gif||GHIDRA||||END|

View File

@ -35,6 +35,9 @@ public class Icons {
public static final ImageIcon EMPTY_ICON = ResourceManager.loadImage("images/EmptyIcon16.gif");
public static final ImageIcon HELP_ICON =
ResourceManager.loadImage("images/help-browser.png");
public static final ImageIcon ADD_ICON = ResourceManager.loadImage("images/Plus2.png");
public static final ImageIcon COLLAPSE_ALL_ICON =
@ -82,7 +85,7 @@ public class Icons {
new DotDotDotIcon(ResourceManager.loadImage("images/Disk.png")));
public static final ImageIcon MAKE_SELECTION_ICON =
ResourceManager.getImageIcon(ResourceManager.loadImage("images/text_align_justify.png"));
ResourceManager.loadImage("images/text_align_justify.png");
// Not necessarily re-usable, but this is needed for the help system; these should
// probably be moved to the client that uses them, while updating the

View File

Before

Width:  |  Height:  |  Size: 932 B

After

Width:  |  Height:  |  Size: 932 B

View File

@ -32,9 +32,10 @@ import docking.KeyEntryTextField;
import docking.action.DockingActionIf;
import docking.action.KeyBindingData;
import docking.actions.KeyBindingUtils;
import docking.help.Help;
import docking.help.HelpService;
import docking.tool.util.DockingToolConstants;
import docking.widgets.MultiLineLabel;
import docking.widgets.OptionDialog;
import docking.widgets.*;
import docking.widgets.label.GIconLabel;
import docking.widgets.table.*;
import ghidra.framework.options.Options;
@ -44,6 +45,7 @@ import ghidra.util.*;
import ghidra.util.exception.AssertException;
import ghidra.util.layout.PairLayout;
import ghidra.util.layout.VerticalLayout;
import resources.Icons;
import resources.ResourceManager;
/**
@ -56,6 +58,7 @@ public class KeyBindingsPanel extends JPanel {
private final static int ACTION_NAME = 0;
private final static int KEY_BINDING = 1;
private final static int PLUGIN_NAME = 2;
private static final int FONT_SIZE = 11;
private JTextPane statusLabel;
@ -79,6 +82,7 @@ public class KeyBindingsPanel extends JPanel {
private boolean firingTableDataChanged;
private PropertyChangeListener propertyChangeListener;
private GTableFilterPanel<DockingActionIf> tableFilterPanel;
private EmptyBorderButton helpButton;
public KeyBindingsPanel(PluginTool tool, Options options) {
this.tool = tool;
@ -203,6 +207,7 @@ public class KeyBindingsPanel extends JPanel {
JScrollPane sp = new JScrollPane(actionTable);
actionTable.setPreferredScrollableViewportSize(new Dimension(400, 100));
actionTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
actionTable.setHTMLRenderingEnabled(true);
adjustTableColumns();
@ -231,7 +236,7 @@ public class KeyBindingsPanel extends JPanel {
statusLabel = new JTextPane();
statusLabel.setEnabled(false);
DockingUtils.setTransparent(statusLabel);
statusLabel.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
statusLabel.setBorder(BorderFactory.createEmptyBorder(5, 10, 0, 5));
statusLabel.setContentType("text/html"); // render any HTML we find in descriptions
// make sure the label gets enough space
@ -240,9 +245,27 @@ public class KeyBindingsPanel extends JPanel {
Font f = new Font("SansSerif", Font.PLAIN, FONT_SIZE);
statusLabel.setFont(f);
helpButton = new EmptyBorderButton(Icons.HELP_ICON);
helpButton.setEnabled(false);
helpButton.addActionListener(e -> {
DockingActionIf action = getSelectedAction();
HelpService hs = Help.getHelpService();
hs.showHelp(action, false, KeyBindingsPanel.this);
});
JPanel helpButtonPanel = new JPanel();
helpButtonPanel.setLayout(new BoxLayout(helpButtonPanel, BoxLayout.PAGE_AXIS));
helpButtonPanel.add(helpButton);
helpButtonPanel.add(Box.createVerticalGlue());
JPanel lowerStatusPanel = new JPanel();
lowerStatusPanel.setLayout(new BoxLayout(lowerStatusPanel, BoxLayout.X_AXIS));
lowerStatusPanel.add(helpButtonPanel);
lowerStatusPanel.add(statusLabel);
JPanel panel = new JPanel(new VerticalLayout(5));
panel.add(keyPanel);
panel.add(statusLabel);
panel.add(lowerStatusPanel);
return panel;
}
@ -260,9 +283,9 @@ public class KeyBindingsPanel extends JPanel {
// the content of the left-hand side label
MultiLineLabel mlabel =
new MultiLineLabel("To add or change a key binding, select an action\n" +
" and type any key combination.\n" +
"and type any key combination\n \n" +
"To remove a key binding, select an action and\n" +
"press <Enter> or <Backspace>.");
"press <Enter> or <Backspace>");
JPanel labelPanel = new JPanel();
labelPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 0));
BoxLayout bl = new BoxLayout(labelPanel, BoxLayout.X_AXIS);
@ -451,13 +474,21 @@ public class KeyBindingsPanel extends JPanel {
unappliedChanges = changes;
}
private String getSelectedAction() {
private DockingActionIf getSelectedAction() {
if (selectionModel.isSelectionEmpty()) {
return null;
}
int selectedRow = actionTable.getSelectedRow();
int modelRow = tableFilterPanel.getModelRow(selectedRow);
return tableActions.get(modelRow).getFullName();
return tableActions.get(modelRow);
}
private String getSelectedActionName() {
DockingActionIf action = getSelectedAction();
if (action == null) {
return null;
}
return action.getFullName();
}
private void addToKeyMap(KeyStroke ks, String actionName) {
@ -580,7 +611,7 @@ public class KeyBindingsPanel extends JPanel {
return;
}
String selectedActionName = getSelectedAction();
String selectedActionName = getSelectedActionName();
if (selectedActionName != null) {
if (processKeyStroke(selectedActionName, ks)) {
String keyStrokeText = KeyEntryTextField.parseKeyStroke(ks);
@ -645,11 +676,14 @@ public class KeyBindingsPanel extends JPanel {
return;
}
String fullActionName = getSelectedAction();
helpButton.setEnabled(false);
String fullActionName = getSelectedActionName();
if (fullActionName == null) {
statusLabel.setText("");
return;
}
helpButton.setEnabled(true);
KeyStroke ks = keyStrokesByFullName.get(fullActionName);
String ksName = "";
clearInfoPanel();
@ -672,12 +706,14 @@ public class KeyBindingsPanel extends JPanel {
if (description == null || description.trim().isEmpty()) {
description = action.getName();
}
statusLabel.setText("<html>" + HTMLUtilities.escapeHTML(description));
}
}
private class KeyBindingsTableModel extends AbstractSortedTableModel<DockingActionIf> {
private final String[] columnNames = { "Action Name", "KeyBinding", "Plugin Name" };
private final String[] columnNames =
{ "Action Name", "KeyBinding", "Plugin Name" };
KeyBindingsTableModel() {
super(0);
@ -694,7 +730,6 @@ public class KeyBindingsPanel extends JPanel {
switch (columnIndex) {
case ACTION_NAME:
return action.getName();
case KEY_BINDING:
KeyStroke ks = keyStrokesByFullName.get(action.getFullName());
if (ks != null) {