GP-5769 - Updated dialogs with combo boxes to have consistent behavior

when the Enter key is pressed
This commit is contained in:
dragonmacher 2025-08-27 19:47:35 -04:00
parent dc09c94c81
commit dc72238178
20 changed files with 46 additions and 137 deletions

View file

@ -154,7 +154,7 @@ public class FunctionStartRFParamsDialog extends ReusableDialogComponentProvider
private RandomForestTableModel tableModel;
private Program trainingSource;
private FunctionStartRFParams params;
private Vector<Long> moduli = new Vector<>(Arrays.asList(new Long[] { 4l, 8l, 16l, 32l }));
private List<Long> moduli = Arrays.asList(new Long[] { 4l, 8l, 16l, 32l });
private GComboBox<Long> modBox;
private JButton trainButton;
private JCheckBox includeBeforeAndAfterBox;

View file

@ -115,7 +115,6 @@ public class CreateBookmarkDialog extends DialogComponentProvider {
categoryComboBox = new GhidraComboBox<>(getModel());
categoryComboBox.setEditable(true);
categoryComboBox.setEnterKeyForwarding(true);
descriptionTextField = new JTextField(20);
panel.add(new JLabel("Address: ", SwingConstants.RIGHT));

View file

@ -235,7 +235,13 @@ public abstract class AbstractSettingsDialog extends DialogComponentProvider {
@Override
protected void okCallback() {
// prevent users from closing the dialog when pressing Enter to confirm an edit
if (settingsTable.isEditing()) {
settingsTable.editingStopped(null);
return;
}
apply();
close();
dispose();
@ -694,8 +700,6 @@ public abstract class AbstractSettingsDialog extends DialogComponentProvider {
private SettingsRowObject rowobject;
SettingsEditor() {
comboBox.setEnterKeyForwarding(false);
comboBox.addActionListener(e -> fireEditingStopped());
intTextField.addChangeListener(e -> updateHexMode());
}

View file

@ -16,8 +16,6 @@
package ghidra.app.plugin.core.datamgr.actions;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import javax.swing.JPanel;
@ -72,12 +70,6 @@ class AnnotationHandlerDialog extends DialogComponentProvider {
outerPanel.getAccessibleContext().setAccessibleName("Annotation Handler");
handlerComboBox = new GhidraComboBox<>(handlerList);
handlerComboBox.getAccessibleContext().setAccessibleName("Combo Box");
handlerComboBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
okCallback();
}
});
outerPanel.add(handlerComboBox, BorderLayout.NORTH);
return outerPanel;
}

View file

@ -63,7 +63,7 @@ public class OperandLabelDialog extends DialogComponentProvider {
myChoice = new GhidraComboBox<>();
myChoice.setName("MYCHOICE");
myChoice.setEditable(true);
myChoice.addActionListener(ev -> okCallback());
myChoice.getAccessibleContext().setAccessibleName("My Choice");
mainPanel.add(label);
mainPanel.add(myChoice);

View file

@ -192,12 +192,6 @@ class SearchTextDialog extends ReusableDialogComponentProvider {
valueComboBox = new GhidraComboBox<>();
valueComboBox.setEditable(true);
valueComboBox.setColumns(20);
valueComboBox.addActionListener(ev -> {
if (nextButton.isEnabled()) {
nextPrevious(true); // go forward
valueComboBox.requestFocus();
}
});
valueComboBox.addEditorKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {

View file

@ -16,7 +16,8 @@
package ghidra.app.plugin.core.strings;
import java.awt.*;
import java.awt.event.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;
import java.io.IOException;
import java.lang.Character.UnicodeScript;
@ -449,35 +450,6 @@ public class EncodedStringsDialog extends DialogComponentProvider {
EncodedStringsPlugin.CHARSET_DEFAULT_VALUE));
charsetComboBox.addItemListener(itemListener);
charsetComboBox.setToolTipText("Which character set to use to decode the raw bytes.");
charsetComboBox.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
// empty
}
@Override
public void keyReleased(KeyEvent e) {
// empty
}
@Override
public void keyPressed(KeyEvent e) {
// Note: we override the [ENTER] key handling to allow the user to invoke the
// dialog and just hit enter to create the string without having to do any
// clicking (otherwise the charset combobox consumes the keystroke)
if (e.getKeyChar() == '\n') {
e.consume();
if (charsetComboBox.isPopupVisible()) {
charsetComboBox.setPopupVisible(false);
}
else {
EncodedStringsDialog.this.createButton.doClick();
}
}
}
});
}
private void buildOptionsButtonComponents() {

View file

@ -563,7 +563,6 @@ public class AddEditDialog extends ReusableDialogComponentProvider {
labelNameChoices.setColumns(20);
labelNameChoices.setName("label.name.choices");
GhidraComboBox<NamespaceWrapper> comboBox = new GhidraComboBox<>();
comboBox.setEnterKeyForwarding(true);
namespaceChoices = comboBox;
primaryCheckBox = new GCheckBox("Primary");

View file

@ -199,7 +199,7 @@ public class GoToAddressLabelDialog extends ReusableDialogComponentProvider
comboBox = new GhidraComboBox<>();
comboBox.setEditable(true);
comboBox.addActionListener(evt -> okCallback());
String comboName = "Go To Address or Label Text Field / Combobox";
comboBox.setName(comboName);
comboBox.getAccessibleContext().setAccessibleName(comboName);
@ -243,9 +243,9 @@ public class GoToAddressLabelDialog extends ReusableDialogComponentProvider
private void readHistory(SaveState saveState) {
String[] strs = saveState.getStrings("GO_TO_HISTORY", null);
if (strs != null) {
for (int i = 0; i < strs.length; i++) {
if (!history.contains(strs[i])) {
history.add(strs[i]);
for (String str : strs) {
if (!history.contains(str)) {
history.add(str);
}
}
truncateHistoryAsNeeded();

View file

@ -266,7 +266,6 @@ public class ImporterDialog extends DialogComponentProvider {
Set<Loader> orderedLoaders = new LinkedHashSet<>(loaderMap.keySet()); // maintain order
loaderComboBox = new GhidraComboBox<>(orderedLoaders);
loaderComboBox.addItemListener(e -> selectedLoaderChanged());
loaderComboBox.setEnterKeyForwarding(true);
loaderComboBox.getAccessibleContext().setAccessibleName("Loader Choices");
loaderComboBox.setRenderer(
GComboBoxCellRenderer.createDefaultTextRenderer(loader -> loader.getName()));

View file

@ -157,7 +157,7 @@ public class DbViewer extends JFrame {
tables[i].getName() + " (" + Integer.toString(tables[i].getRecordCount()) + ")";
}
combo = new GComboBox<>(names);
combo.addActionListener(e -> updateTable());
combo.addItemListener(e -> updateTable());
subNorthPanel.add(combo);
northPanel.add(subNorthPanel);
mainPanel.add(northPanel, BorderLayout.NORTH);

View file

@ -77,7 +77,6 @@ public class DecompilerTextFinderDialog extends ReusableDialogComponentProvider
textCombo = new GhidraComboBox<>();
textCombo.setEditable(true);
textCombo.addActionListener(e -> doSearch());
textCombo.setColumns(20);
textCombo.addDocumentListener(new DocumentListener() {

View file

@ -257,7 +257,7 @@ public class PopulateFidDialog extends DialogComponentProvider {
List<FidFile> fidFileList = FidFileManager.getInstance().getUserAddedFiles();
FidFile[] files = fidFileList.toArray(new FidFile[fidFileList.size()]);
fidFileComboBox = new GComboBox<>(files);
fidFileComboBox.addActionListener(e -> updateLibraryChoices());
fidFileComboBox.addItemListener(e -> updateLibraryChoices());
fidFileComboBox.getAccessibleContext().setAccessibleName("Fid File");
return fidFileComboBox;
}

View file

@ -127,7 +127,6 @@ public class ChooseMatchTagAction extends DockingAction {
tagComboBox = new MatchTagComboBox(session, matches, component, selectedTag);
Dimension dim = new Dimension(50, tagComboBox.getPreferredSize().height);
tagComboBox.setMinimumSize(dim);
tagComboBox.addActionListener(e -> fieldEdited());
panel.add(tagComboBox, BorderLayout.CENTER);
return panel;
}
@ -148,12 +147,5 @@ public class ChooseMatchTagAction extends DockingAction {
VTMatchTag getSelectedTag() {
return selectedTag;
}
/**
* An address edit action occurred in the panel so handle it as if ok button were pressed.
*/
public void fieldEdited() {
okCallback();
}
}
}

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,10 +15,6 @@
*/
package ghidra.feature.vt.gui.editors;
import ghidra.feature.vt.api.main.*;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.util.SystemUtilities;
import java.awt.Component;
import java.awt.event.*;
import java.util.*;
@ -29,6 +24,9 @@ import javax.swing.table.TableCellEditor;
import javax.swing.table.TableModel;
import docking.widgets.table.RowObjectTableModel;
import ghidra.feature.vt.api.main.*;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.util.SystemUtilities;
public class MatchTagCellEditor extends AbstractCellEditor implements TableCellEditor {
@ -55,12 +53,6 @@ public class MatchTagCellEditor extends AbstractCellEditor implements TableCellE
VTSession session = controller.getSession();
tag = match.getTag();
matchTagChoices = new MatchTagComboBox(session, matches, theTable, tag);
matchTagChoices.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
stopCellEditing();
}
});
matchTagChoices.addItemListener(new ItemListener() {
@Override

View file

@ -831,7 +831,7 @@ public class ApplyMarkupPropertyEditor implements OptionsEditor {
Enum<?>[] enums = editor.getEnums();
final JComboBox<Enum<?>> applyComboBox = new GComboBox<>(enums);
applyComboBox.addActionListener(e -> changesMade(true));
applyComboBox.addItemListener(e -> changesMade(true));
return applyComboBox;
}

View file

@ -16,7 +16,7 @@
package docking.options.editor;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ItemListener;
import java.beans.PropertyEditorSupport;
import java.util.*;
import java.util.List;
@ -65,7 +65,7 @@ public class FontPropertyEditor extends PropertyEditorSupport {
private GComboBox<FontWrapper> fontCombo;
private GComboBox<Integer> sizeCombo;
private GComboBox<String> styleCombo;
private ActionListener actionListener = e -> fontChanged();
private ItemListener itemListener = e -> fontChanged();
private List<FontWrapper> systemFontNames;
public FontChooserPanel() {
@ -78,9 +78,9 @@ public class FontPropertyEditor extends PropertyEditorSupport {
}
updatePreviewLabel(font);
fontCombo.removeActionListener(actionListener);
sizeCombo.removeActionListener(actionListener);
styleCombo.removeActionListener(actionListener);
fontCombo.removeItemListener(itemListener);
sizeCombo.removeItemListener(itemListener);
styleCombo.removeItemListener(itemListener);
FontWrapper fontWrapper = new FontWrapper(font.getName());
updateComboBoxModeIfNeeded(fontWrapper);
@ -91,10 +91,9 @@ public class FontPropertyEditor extends PropertyEditorSupport {
sizeCombo.setSelectedItem(size);
styleCombo.setSelectedIndex(styleChoice);
fontCombo.addActionListener(actionListener);
sizeCombo.addActionListener(actionListener);
styleCombo.addActionListener(actionListener);
fontCombo.addItemListener(itemListener);
sizeCombo.addItemListener(itemListener);
styleCombo.addItemListener(itemListener);
}
private void updateComboBoxModeIfNeeded(FontWrapper fontWrapper) {
@ -144,7 +143,7 @@ public class FontPropertyEditor extends PropertyEditorSupport {
styleCombo =
new GComboBox<>(new String[] { "PLAIN", "BOLD", "ITALIC", "BOLD & ITALIC" });
styleCombo.setMaximumRowCount(9);
styleCombo.addActionListener(actionListener);
styleCombo.addItemListener(itemListener);
styleCombo.getAccessibleContext().setAccessibleName("Style");
panel.add(styleCombo);
panel.getAccessibleContext().setAccessibleName("Style");
@ -163,7 +162,7 @@ public class FontPropertyEditor extends PropertyEditorSupport {
sizeCombo =
new GComboBox<>(IntStream.rangeClosed(1, 72).boxed().toArray(Integer[]::new));
sizeCombo.setMaximumRowCount(9);
sizeCombo.addActionListener(actionListener);
sizeCombo.addItemListener(itemListener);
sizeCombo.getAccessibleContext().setAccessibleName("Size");
panel.add(sizeCombo);
panel.getAccessibleContext().setAccessibleName("Size");
@ -182,7 +181,7 @@ public class FontPropertyEditor extends PropertyEditorSupport {
systemFontNames = getSystemFontNames();
fontCombo = new GComboBox<>(systemFontNames.toArray(new FontWrapper[0]));
fontCombo.setMaximumRowCount(9);
fontCombo.addActionListener(actionListener);
fontCombo.addItemListener(itemListener);
fontCombo.getAccessibleContext().setAccessibleName("Font");
panel.add(fontCombo);
panel.getAccessibleContext().setAccessibleName("Font");

View file

@ -15,6 +15,7 @@
*/
package docking.widgets.combobox;
import java.util.Collection;
import java.util.Vector;
import javax.swing.*;
@ -71,8 +72,8 @@ public class GComboBox<E> extends JComboBox<E> implements GComponent {
*
* @param items a vector containing objects of generic type {@code E} to insert into the combo box
*/
public GComboBox(Vector<E> items) {
super(items);
public GComboBox(Collection<E> items) {
super(new Vector<>(items));
init();
}

View file

@ -64,8 +64,6 @@ public class GhidraComboBox<E> extends JComboBox<E> implements GComponent {
private List<KeyListener> keyListeners = new ArrayList<>();
private boolean setSelectedFlag = false;
private boolean forwardEnter;
private Action defaultSystemEnterForwardingAction;
private Document document;
private PassThroughActionListener passThroughActionListener;
private PassThroughKeyListener passThroughKeyListener;
@ -125,20 +123,6 @@ public class GhidraComboBox<E> extends JComboBox<E> implements GComponent {
setDocument(document);
}
// HACK ALERT: see setEnterKeyForwarding(boolean)
ActionMap am = getActionMap();
if (am != null) {
defaultSystemEnterForwardingAction = am.get("enterPressed");
am.put("enterPressed", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
if (forwardEnter) {
defaultSystemEnterForwardingAction.actionPerformed(e);
}
}
});
}
// As mentioned above, the default editor gets replaced. In that case, restore the columns
// if the client has set the value.
if (oldColumns > 0) {
@ -147,23 +131,6 @@ public class GhidraComboBox<E> extends JComboBox<E> implements GComponent {
}
}
/**
* HACK ALERT: By default, the JComboBoxUI forwards the &lt;Enter&gt; key actions to the root
* pane of the JComboBox's container (which is used primarily by any installed 'default
* button'). The problem is that the forwarding does not happen always. In the case that the
* &lt;Enter&gt; key will trigger a selection in the combo box, the action is NOT forwarded.
* <p>
* By default Ghidra disables the forwarding altogether, since most users of
* {@link GhidraComboBox} will add an action listener to handle &lt;Enter&gt; actions.
* <p>
* To re-enable the default behavior, set the <code>forwardEnter</code> value to true.
*
* @param forwardEnter true to enable default &lt;Enter&gt; key handling.
*/
public void setEnterKeyForwarding(boolean forwardEnter) {
this.forwardEnter = forwardEnter;
}
/**
* Returns the text in combobox's editor text component
* @return the text in combobox's editor text component

View file

@ -97,7 +97,7 @@ public interface SettingsDefinition {
public String getDescription();
/**
* Removes any values in the given settings object assocated with this settings definition
* Removes any values in the given settings object associated with this settings definition
* @param settings the settings object to be cleared.
*/
public void clear(Settings settings);