diff --git a/Ghidra/Features/Base/src/main/help/help/topics/Tool/ToolOptions_Dialog.htm b/Ghidra/Features/Base/src/main/help/help/topics/Tool/ToolOptions_Dialog.htm
index a486aea2a6..574d2d8fc1 100644
--- a/Ghidra/Features/Base/src/main/help/help/topics/Tool/ToolOptions_Dialog.htm
+++ b/Ghidra/Features/Base/src/main/help/help/topics/Tool/ToolOptions_Dialog.htm
@@ -150,12 +150,16 @@
Click in the text field for the key binding.
- Press the <Enter> or <Backspace> to clear it.
+ Press the
button to clear it.
Click on the OK or Apply
button.
-
+
+
+
+
+
Import Key Bindings
diff --git a/Ghidra/Features/Base/src/main/help/help/topics/Tool/images/KeyBindings.png b/Ghidra/Features/Base/src/main/help/help/topics/Tool/images/KeyBindings.png
index 224a6eb38d..c7f2c85ec2 100644
Binary files a/Ghidra/Features/Base/src/main/help/help/topics/Tool/images/KeyBindings.png and b/Ghidra/Features/Base/src/main/help/help/topics/Tool/images/KeyBindings.png differ
diff --git a/Ghidra/Features/Base/src/main/help/help/topics/Tool/images/SetKeyBindings.png b/Ghidra/Features/Base/src/main/help/help/topics/Tool/images/SetKeyBindings.png
index aea7d9ecb3..0322020868 100644
Binary files a/Ghidra/Features/Base/src/main/help/help/topics/Tool/images/SetKeyBindings.png and b/Ghidra/Features/Base/src/main/help/help/topics/Tool/images/SetKeyBindings.png differ
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/KeyBindingInputDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/KeyBindingInputDialog.java
index 422a3947bf..d7e3c90ac8 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/KeyBindingInputDialog.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/script/KeyBindingInputDialog.java
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -21,7 +21,6 @@ import java.awt.Component;
import javax.swing.*;
import docking.*;
-import docking.actions.KeyBindingUtils;
import docking.actions.ToolActions;
import docking.widgets.label.GLabel;
import ghidra.framework.plugintool.Plugin;
@@ -29,7 +28,7 @@ import ghidra.framework.plugintool.PluginTool;
import ghidra.util.HelpLocation;
class KeyBindingInputDialog extends DialogComponentProvider implements KeyEntryListener {
- private KeyEntryTextField kbField;
+ private KeyEntryPanel kbPanel;
private KeyStroke ks;
private boolean isCancelled;
private Plugin plugin;
@@ -39,15 +38,15 @@ class KeyBindingInputDialog extends DialogComponentProvider implements KeyEntryL
super("Assign Script Key Binding", true, true, true, false);
this.plugin = plugin;
- kbField = new KeyEntryTextField(20, this);
- kbField.setName("KEY_BINDING");
- kbField.setText(
- currentKeyStroke == null ? "" : KeyBindingUtils.parseKeyStroke(currentKeyStroke));
+ kbPanel = new KeyEntryPanel(20, this);
+ if (currentKeyStroke != null) {
+ kbPanel.setKeyStroke(currentKeyStroke);
+ }
JPanel panel = new JPanel(new BorderLayout(10, 10));
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
panel.add(new GLabel(scriptName), BorderLayout.NORTH);
- panel.add(kbField, BorderLayout.CENTER);
+ panel.add(kbPanel, BorderLayout.CENTER);
addWorkPanel(panel);
addOKButton();
@@ -91,6 +90,6 @@ class KeyBindingInputDialog extends DialogComponentProvider implements KeyEntryL
void setKeyStroke(KeyStroke ks) {
this.ks = ks;
- kbField.setKeyStroke(ks);
+ kbPanel.setKeyStroke(ks);
}
}
diff --git a/Ghidra/Features/Base/src/test.slow/java/docking/action/KeyEntryDialogTest.java b/Ghidra/Features/Base/src/test.slow/java/docking/action/KeyEntryDialogTest.java
index 40a644a351..f6d5bcbb78 100644
--- a/Ghidra/Features/Base/src/test.slow/java/docking/action/KeyEntryDialogTest.java
+++ b/Ghidra/Features/Base/src/test.slow/java/docking/action/KeyEntryDialogTest.java
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -40,6 +40,7 @@ public class KeyEntryDialogTest extends AbstractGhidraHeadedIntegrationTest {
private KeyEntryDialog keyEntryDialog;
private JTextPane collisionPane;
private KeyEntryTextField keyEntryField;
+ private JButton clearButton;
@Before
public void setUp() throws Exception {
@@ -71,7 +72,7 @@ public class KeyEntryDialogTest extends AbstractGhidraHeadedIntegrationTest {
// clear the action
showDialog(unboundAction);
- triggerBackspaceKey(keyEntryField);
+ pressButton(clearButton);
pressDialogOK();
acceleratorKey = unboundAction.getKeyBinding();
@@ -98,7 +99,7 @@ public class KeyEntryDialogTest extends AbstractGhidraHeadedIntegrationTest {
showDialog(boundAction);
assertEquals("OPEN_BRACKET", keyEntryField.getText());
- triggerBackspaceKey(keyEntryField);
+ pressButton(clearButton);
pressDialogOK();
KeyStroke ks = boundAction.getKeyBinding();
@@ -113,7 +114,7 @@ public class KeyEntryDialogTest extends AbstractGhidraHeadedIntegrationTest {
KeyStroke oldKs = boundAction.getKeyBinding();
assertEquals("OPEN_BRACKET", keyEntryField.getText());
- triggerBackspaceKey(keyEntryField);
+ pressButton(clearButton);
pressDialogOK();
KeyStroke ks = boundAction.getKeyBinding();
@@ -175,7 +176,7 @@ public class KeyEntryDialogTest extends AbstractGhidraHeadedIntegrationTest {
keyBindingKeyStroke.getKeyCode());
assertEquals(keyEntryDialog.getStatusText().trim(), "");
- triggerBackspaceKey(keyEntryField);
+ pressButton(clearButton);
triggerText(keyEntryField, "g");
pressDialogOK();
@@ -259,6 +260,8 @@ public class KeyEntryDialogTest extends AbstractGhidraHeadedIntegrationTest {
assertNotNull(keyEntryDialog);
collisionPane = (JTextPane) getInstanceField("collisionPane", keyEntryDialog);
- keyEntryField = (KeyEntryTextField) getInstanceField("keyEntryField", keyEntryDialog);
+ KeyEntryPanel keyPanel = (KeyEntryPanel) getInstanceField("keyEntryPanel", keyEntryDialog);
+ keyEntryField = (KeyEntryTextField) getInstanceField("keyEntryField", keyPanel);
+ clearButton = (JButton) getInstanceField("clearButton", keyPanel);
}
}
diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/script/GhidraScriptMgrPlugin3Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/script/GhidraScriptMgrPlugin3Test.java
index 677ac3a1c7..7dfd5322ba 100644
--- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/script/GhidraScriptMgrPlugin3Test.java
+++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/script/GhidraScriptMgrPlugin3Test.java
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -49,7 +49,7 @@ public class GhidraScriptMgrPlugin3Test extends AbstractGhidraScriptMgrPluginTes
KeyBindingInputDialog kbid = pressKeyBindingAction();
KeyEntryTextField keyField =
- (KeyEntryTextField) findComponentByName(kbid.getComponent(), "KEY_BINDING");
+ (KeyEntryTextField) findComponentByName(kbid.getComponent(), "Key Entry Text Field");
triggerActionKey(keyField, InputEvent.SHIFT_DOWN_MASK | InputEvent.ALT_DOWN_MASK,
KeyEvent.VK_H);
pressButtonByText(kbid, "OK");
@@ -292,7 +292,8 @@ public class GhidraScriptMgrPlugin3Test extends AbstractGhidraScriptMgrPluginTes
SaveDialog saveDialog = waitForDialogComponent(SaveDialog.class);
- final ListPanel listPanel = (ListPanel) findComponentByName(saveDialog.getComponent(), "PATH_LIST");
+ final ListPanel listPanel =
+ (ListPanel) findComponentByName(saveDialog.getComponent(), "PATH_LIST");
assertNotNull(listPanel);
assertTrue(listPanel.isVisible());
assertEquals(2, listPanel.getListModel().getSize());
diff --git a/Ghidra/Framework/Docking/src/main/java/docking/ActionBindingPanel.java b/Ghidra/Framework/Docking/src/main/java/docking/ActionBindingPanel.java
index 5a4e398620..4cc64eca82 100644
--- a/Ghidra/Framework/Docking/src/main/java/docking/ActionBindingPanel.java
+++ b/Ghidra/Framework/Docking/src/main/java/docking/ActionBindingPanel.java
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -30,7 +30,7 @@ public class ActionBindingPanel extends JPanel {
private static final String DISABLED_HINT = "Select an action";
- private KeyEntryTextField keyEntryField;
+ private KeyEntryPanel keyEntryPanel;
private JCheckBox useMouseBindingCheckBox;
private MouseEntryTextField mouseEntryField;
private JPanel textFieldPanel;
@@ -49,14 +49,14 @@ public class ActionBindingPanel extends JPanel {
textFieldPanel = new JPanel(new BorderLayout());
- keyEntryField = new KeyEntryTextField(20, ks -> listener.keyStrokeChanged(ks));
- keyEntryField.setDisabledHint(DISABLED_HINT);
- keyEntryField.setEnabled(false); // enabled on action selection
+ keyEntryPanel = new KeyEntryPanel(20, ks -> listener.keyStrokeChanged(ks));
+ keyEntryPanel.setDisabledHint(DISABLED_HINT);
+ keyEntryPanel.setEnabled(false); // enabled on action selection
mouseEntryField = new MouseEntryTextField(20, mb -> listener.mouseBindingChanged(mb));
mouseEntryField.setDisabledHint(DISABLED_HINT);
mouseEntryField.setEnabled(false); // enabled on action selection
- textFieldPanel.add(keyEntryField, BorderLayout.NORTH);
+ textFieldPanel.add(keyEntryPanel, BorderLayout.NORTH);
String checkBoxText = "Enter Mouse Binding";
useMouseBindingCheckBox = new GCheckBox(checkBoxText);
@@ -73,12 +73,12 @@ public class ActionBindingPanel extends JPanel {
private void updateTextField() {
if (useMouseBindingCheckBox.isSelected()) {
- textFieldPanel.remove(keyEntryField);
+ textFieldPanel.remove(keyEntryPanel);
textFieldPanel.add(mouseEntryField, BorderLayout.NORTH);
}
else {
textFieldPanel.remove(mouseEntryField);
- textFieldPanel.add(keyEntryField, BorderLayout.NORTH);
+ textFieldPanel.add(keyEntryPanel, BorderLayout.NORTH);
}
validate();
@@ -87,25 +87,25 @@ public class ActionBindingPanel extends JPanel {
public void setKeyBindingData(KeyStroke ks, MouseBinding mb) {
- keyEntryField.setKeyStroke(ks);
+ keyEntryPanel.setKeyStroke(ks);
mouseEntryField.setMouseBinding(mb);
}
@Override
public void setEnabled(boolean enabled) {
- keyEntryField.clearField();
+ keyEntryPanel.clearField();
mouseEntryField.clearField();
- keyEntryField.setEnabled(enabled);
+ keyEntryPanel.setEnabled(enabled);
mouseEntryField.setEnabled(enabled);
}
public void clearKeyStroke() {
- keyEntryField.clearField();
+ keyEntryPanel.clearField();
}
public KeyStroke getKeyStroke() {
- return keyEntryField.getKeyStroke();
+ return keyEntryPanel.getKeyStroke();
}
public MouseBinding getMouseBinding() {
diff --git a/Ghidra/Framework/Docking/src/main/java/docking/KeyEntryPanel.java b/Ghidra/Framework/Docking/src/main/java/docking/KeyEntryPanel.java
new file mode 100644
index 0000000000..e33fc5fdab
--- /dev/null
+++ b/Ghidra/Framework/Docking/src/main/java/docking/KeyEntryPanel.java
@@ -0,0 +1,85 @@
+/* ###
+ * IP: GHIDRA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package docking;
+
+import javax.swing.*;
+
+import docking.widgets.EmptyBorderButton;
+import resources.Icons;
+
+/**
+ * A panel that holds a {@link KeyEntryTextField} and a button for clearing the current key binding.
+ *
+ * This class is a drop-in replacement for clients that are currently using
+ * {@link KeyEntryTextField}.
+ */
+public class KeyEntryPanel extends JPanel {
+
+ private KeyEntryTextField keyEntryField;
+ private JButton clearButton;
+
+ /**
+ * Constructs this class with a text field based on the number of given columns.
+ * @param columns the number of columns for the text field
+ * @param listener the listener to be called as the user enters key strokes
+ */
+ public KeyEntryPanel(int columns, KeyEntryListener listener) {
+
+ setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
+
+ keyEntryField = new KeyEntryTextField(columns, listener);
+ clearButton = new EmptyBorderButton(Icons.DELETE_ICON);
+ clearButton.setToolTipText("Clear the current key binding");
+ clearButton.addActionListener(e -> keyEntryField.clearField());
+
+ add(keyEntryField);
+ add(Box.createHorizontalStrut(2));
+ add(clearButton);
+ }
+
+ /**
+ * Sets the key stroke on this panel
+ * @param ks the key stroke
+ */
+ public void setKeyStroke(KeyStroke ks) {
+ keyEntryField.setKeyStroke(ks);
+ }
+
+ /**
+ * Gets the key stroke being used by this panel
+ * @return the key stroke
+ */
+ public KeyStroke getKeyStroke() {
+ return keyEntryField.getKeyStroke();
+ }
+
+ /**
+ * Sets the text field hint for this panel.
+ *
+ * @param disabledHint the hint
+ * @see KeyEntryTextField#setDisabledHint(String)
+ */
+ public void setDisabledHint(String disabledHint) {
+ keyEntryField.setDisabledHint(disabledHint);
+ }
+
+ /**
+ * Clears the key stroke being used by this panel
+ */
+ public void clearField() {
+ keyEntryField.clearField();
+ }
+}
diff --git a/Ghidra/Framework/Docking/src/main/java/docking/KeyEntryTextField.java b/Ghidra/Framework/Docking/src/main/java/docking/KeyEntryTextField.java
index 6388a26a22..3ff2f824e0 100644
--- a/Ghidra/Framework/Docking/src/main/java/docking/KeyEntryTextField.java
+++ b/Ghidra/Framework/Docking/src/main/java/docking/KeyEntryTextField.java
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -82,9 +82,12 @@ public class KeyEntryTextField extends HintTextField {
}
public void clearField() {
- ksName = null;
+ if (currentKeyStroke == null) {
+ return;
+ }
+
setText("");
- currentKeyStroke = null;
+ processKeyStroke(null, true);
}
private void processKeyStroke(KeyStroke ks, boolean notify) {
@@ -128,17 +131,13 @@ public class KeyEntryTextField extends HintTextField {
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
KeyStroke keyStroke = null;
- if (!isClearKey(keyCode) && !isModifiersOnly(e)) {
+ if (!isModifiersOnly(e)) {
keyStroke = KeyStroke.getKeyStroke(keyCode, e.getModifiersEx());
}
processKeyStroke(keyStroke, true);
e.consume();
}
- private boolean isClearKey(int keyCode) {
- return keyCode == KeyEvent.VK_BACK_SPACE || keyCode == KeyEvent.VK_ENTER;
- }
-
private boolean isModifiersOnly(KeyEvent event) {
String keyText = KeyEvent.getKeyText(event.getKeyCode());
return keyText.equals(KeyEvent.getKeyText(KeyEvent.VK_CONTROL)) ||
diff --git a/Ghidra/Framework/Docking/src/main/java/docking/actions/KeyEntryDialog.java b/Ghidra/Framework/Docking/src/main/java/docking/actions/KeyEntryDialog.java
index 822996c993..61c6acd5ca 100644
--- a/Ghidra/Framework/Docking/src/main/java/docking/actions/KeyEntryDialog.java
+++ b/Ghidra/Framework/Docking/src/main/java/docking/actions/KeyEntryDialog.java
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -42,7 +42,7 @@ public class KeyEntryDialog extends DialogComponentProvider {
private DockingActionIf action;
private JPanel defaultPanel;
- private KeyEntryTextField keyEntryField;
+ private KeyEntryPanel keyEntryPanel;
private JTextPane collisionPane;
private StyledDocument doc;
@@ -83,8 +83,8 @@ public class KeyEntryDialog extends DialogComponentProvider {
StyledDocument document = pane.getStyledDocument();
try {
- document.insertString(0, "To add or change a key binding, type any key combination.\n" +
- "To remove a key binding, press or .", null);
+ document.insertString(0, "To add or change a key binding, type any key combination",
+ null);
}
catch (BadLocationException e1) {
// shouldn't be possible
@@ -100,7 +100,7 @@ public class KeyEntryDialog extends DialogComponentProvider {
labelPanel.add(pane);
labelPanel.add(Box.createHorizontalStrut(5));
- keyEntryField = new KeyEntryTextField(20, keyStroke -> {
+ keyEntryPanel = new KeyEntryPanel(20, keyStroke -> {
okButton.setEnabled(true);
updateCollisionPane(keyStroke);
});
@@ -109,12 +109,12 @@ public class KeyEntryDialog extends DialogComponentProvider {
defaultPanel.setBorder(BorderFactory.createLoweredBevelBorder());
JPanel p = new JPanel(new FlowLayout(FlowLayout.CENTER));
p.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0));
- p.add(keyEntryField);
+ p.add(keyEntryPanel);
KeyStroke keyBinding = action.getKeyBinding();
if (keyBinding != null) {
- keyEntryField.setText(KeyBindingUtils.parseKeyStroke(keyBinding));
+ keyEntryPanel.setKeyStroke(keyBinding);
}
- setFocusComponent(keyEntryField);
+ setFocusComponent(keyEntryPanel);
defaultPanel.add(p, BorderLayout.CENTER);
JPanel mainPanel = new JPanel(new BorderLayout());
@@ -144,7 +144,7 @@ public class KeyEntryDialog extends DialogComponentProvider {
* @param ks the keystroke to set
*/
public void setKeyStroke(KeyStroke ks) {
- keyEntryField.setKeyStroke(ks);
+ keyEntryPanel.setKeyStroke(ks);
updateCollisionPane(ks);
}
@@ -155,7 +155,7 @@ public class KeyEntryDialog extends DialogComponentProvider {
@Override
protected void okCallback() {
- KeyStroke newKs = keyEntryField.getKeyStroke();
+ KeyStroke newKs = keyEntryPanel.getKeyStroke();
String errorMessage = toolActions.validateActionKeyBinding(action, newKs);
if (errorMessage != null) {
setStatusText(errorMessage);
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/dialog/KeyBindingsPanel.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/dialog/KeyBindingsPanel.java
index 01ed0957f2..39632c098c 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/dialog/KeyBindingsPanel.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/dialog/KeyBindingsPanel.java
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -219,8 +219,7 @@ 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 \n" +
- "To remove a key binding, select an action and\n" + "press or ");
+ "and type any key combination.");
JPanel labelPanel = new JPanel();
labelPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 0));
BoxLayout bl = new BoxLayout(labelPanel, BoxLayout.X_AXIS);