diff --git a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/base/widgets/table/DataTypeTableCellEditor.java b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/base/widgets/table/DataTypeTableCellEditor.java index 19a2ed8fb0..07692bfc61 100644 --- a/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/base/widgets/table/DataTypeTableCellEditor.java +++ b/Ghidra/Debug/ProposedUtils/src/main/java/ghidra/base/widgets/table/DataTypeTableCellEditor.java @@ -26,6 +26,7 @@ import javax.swing.table.TableCellEditor; import docking.widgets.DropDownSelectionTextField; import docking.widgets.table.CellEditorUtils; +import docking.widgets.table.FocusableEditor; import ghidra.app.services.DataTypeManagerService; import ghidra.app.util.datatype.DataTypeSelectionEditor; import ghidra.framework.plugintool.PluginTool; @@ -34,13 +35,14 @@ import ghidra.util.Swing; import ghidra.util.data.DataTypeParser.AllowedDataTypes; public class DataTypeTableCellEditor extends AbstractCellEditor - implements TableCellEditor { + implements TableCellEditor, FocusableEditor { private final PluginTool tool; private DataTypeManagerService service; private JTable table; private JPanel editorPanel; private DataTypeSelectionEditor editor; + private DropDownSelectionTextField textField; private DataType dt; @@ -119,6 +121,11 @@ public class DataTypeTableCellEditor extends AbstractCellEditor return editorPanel; } + @Override + public void focusEditor() { + textField.requestFocusInWindow(); + } + protected void init(int row, int column) { updateService(); editor = new DataTypeSelectionEditor(service, getAllowed(row, column)); @@ -126,17 +133,12 @@ public class DataTypeTableCellEditor extends AbstractCellEditor editor.setTabCommitsEdit(true); editor.setConsumeEnterKeyPress(false); - final DropDownSelectionTextField textField = editor.getDropDownTextField(); + textField = editor.getDropDownTextField(); textField.setBorder(UIManager.getBorder("Table.focusCellHighlightBorder")); CellEditorUtils.onOneFocus(textField, () -> textField.selectAll()); editor.addCellEditorListener(cellEditorListener); - editorPanel = new JPanel(new BorderLayout()) { - @Override - public void requestFocus() { - textField.requestFocus(); - } - }; + editorPanel = new JPanel(new BorderLayout()); editorPanel.add(textField, BorderLayout.CENTER); editorPanel.add(dataTypeChooserButton, BorderLayout.EAST); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompositeEditorPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompositeEditorPanel.java index 49e101d625..e31dd83199 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompositeEditorPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/compositeeditor/CompositeEditorPanel.java @@ -1235,9 +1235,10 @@ public abstract class CompositeEditorPanel extends JPanel } private class ComponentDataTypeCellEditor extends AbstractCellEditor - implements TableCellEditor { + implements TableCellEditor, FocusableEditor { private DataTypeSelectionEditor editor; + private DropDownSelectionTextField textField; private DataType dt; private int maxLength; private boolean bitfieldAllowed; @@ -1277,7 +1278,7 @@ public abstract class CompositeEditorPanel extends JPanel editor.setPreferredDataTypeManager(originalDataTypeManager); editor.setConsumeEnterKeyPress(false); // we want the table to handle Enter key presses - final DropDownSelectionTextField textField = editor.getDropDownTextField(); + textField = editor.getDropDownTextField(); textField.setBorder(UIManager.getBorder("Table.focusCellHighlightBorder")); editor.addCellEditorListener(new CellEditorListener() { @Override @@ -1311,12 +1312,7 @@ public abstract class CompositeEditorPanel extends JPanel } }); - editorPanel = new JPanel() { - @Override - public void requestFocus() { - textField.requestFocus(); - } - }; + editorPanel = new JPanel(); editorPanel.setLayout(new BorderLayout()); editorPanel.add(textField, BorderLayout.CENTER); editorPanel.add(dataTypeChooserButton, BorderLayout.EAST); @@ -1334,6 +1330,11 @@ public abstract class CompositeEditorPanel extends JPanel } } + @Override + public void focusEditor() { + textField.requestFocusInWindow(); + } + @Override public Object getCellEditorValue() { return dt; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/ParameterDataTypeCellEditor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/ParameterDataTypeCellEditor.java index 0be0367f99..1ba2d23476 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/ParameterDataTypeCellEditor.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/ParameterDataTypeCellEditor.java @@ -26,13 +26,15 @@ import javax.swing.table.TableCellEditor; import docking.DialogComponentProvider; import docking.widgets.DropDownSelectionTextField; +import docking.widgets.table.FocusableEditor; import ghidra.app.services.DataTypeManagerService; import ghidra.app.util.datatype.DataTypeSelectionEditor; import ghidra.program.model.data.DataType; import ghidra.util.MessageType; import ghidra.util.data.DataTypeParser; -class ParameterDataTypeCellEditor extends AbstractCellEditor implements TableCellEditor { +class ParameterDataTypeCellEditor extends AbstractCellEditor + implements TableCellEditor, FocusableEditor { private DataTypeSelectionEditor editor; private DropDownSelectionTextField textField; private JButton dataTypeChooserButton; @@ -113,6 +115,11 @@ class ParameterDataTypeCellEditor extends AbstractCellEditor implements TableCel editorPanel.add(dataTypeChooserButton, BorderLayout.EAST); } + @Override + public void focusEditor() { + textField.requestFocusInWindow(); + } + /** * @return text field associated with the generated component. Null will * be returned if getTableCellEditorComponent method has not yet been invoked. diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/VarnodeLocationCellEditor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/VarnodeLocationCellEditor.java index a93be40e57..fcd29e0255 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/VarnodeLocationCellEditor.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/function/editor/VarnodeLocationCellEditor.java @@ -16,7 +16,7 @@ package ghidra.app.plugin.core.function.editor; import java.awt.Component; -import java.awt.event.*; +import java.awt.event.MouseEvent; import java.math.BigInteger; import java.util.*; @@ -26,6 +26,7 @@ import javax.swing.event.PopupMenuListener; import javax.swing.table.TableCellEditor; import docking.widgets.combobox.GhidraComboBox; +import docking.widgets.table.FocusableEditor; import docking.widgets.textfield.IntegerTextField; import generic.theme.GThemeDefaults.Colors.Palette; import ghidra.app.util.AddressInput; @@ -36,7 +37,8 @@ import ghidra.program.model.listing.Program; import ghidra.program.model.listing.ProgramContext; import ghidra.util.Msg; -class VarnodeLocationCellEditor extends AbstractCellEditor implements TableCellEditor { +class VarnodeLocationCellEditor extends AbstractCellEditor + implements TableCellEditor, FocusableEditor { private Program program; private VarnodeType type; private Component editorComponent; @@ -44,7 +46,8 @@ class VarnodeLocationCellEditor extends AbstractCellEditor implements TableCellE private AddressInput addressInput; private IntegerTextField offsetInput; - private Comparator registerWrapperComparator = (r1, r2) -> r1.toString().compareToIgnoreCase(r2.toString()); + private Comparator registerWrapperComparator = + (r1, r2) -> r1.toString().compareToIgnoreCase(r2.toString()); private VarnodeInfo currentVarnode; private int maxRegisterSize; @@ -134,6 +137,16 @@ class VarnodeLocationCellEditor extends AbstractCellEditor implements TableCellE return editorComponent; } + @Override + public void focusEditor() { + if (editorComponent instanceof AddressInput input) { + input.focusEditor(); + } + else { + editorComponent.requestFocusInWindow(); + } + } + private Component createAddressEditor(VarnodeInfo varnode) { addressInput = new AddressInput(BorderFactory.createEmptyBorder()); addressInput.setAddressFactory(program.getAddressFactory()); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/AddressInput.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/AddressInput.java index 53b278a575..4e6d8febf7 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/AddressInput.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/AddressInput.java @@ -17,7 +17,6 @@ package ghidra.app.util; import java.awt.BorderLayout; import java.awt.FontMetrics; -import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Arrays; import java.util.Comparator; @@ -27,13 +26,14 @@ import javax.swing.border.Border; import javax.swing.event.*; import docking.widgets.combobox.GComboBox; +import docking.widgets.table.FocusableEditor; import ghidra.program.model.address.*; /** * Panel for user input of addresses. Handles case with multiple address * spaces. */ -public class AddressInput extends JPanel { +public class AddressInput extends JPanel implements FocusableEditor { private JTextField textField; private JComboBox combo; private boolean comboAdded; @@ -45,19 +45,16 @@ public class AddressInput extends JPanel { private JTextField spaceField; private static final Comparator ADDRESS_SPACE_SORT_COMPARATOR = - new Comparator<>() { - @Override - public int compare(AddressSpace s1, AddressSpace s2) { - if (s1.isOverlaySpace()) { - if (!s2.isOverlaySpace()) { - return 1; - } + (s1, s2) -> { + if (s1.isOverlaySpace()) { + if (!s2.isOverlaySpace()) { + return 1; } - else if (s2.isOverlaySpace()) { - return -1; - } - return s1.getName().compareTo(s2.getName()); } + else if (s2.isOverlaySpace()) { + return -1; + } + return s1.getName().compareTo(s2.getName()); }; /** @@ -101,12 +98,7 @@ public class AddressInput extends JPanel { } }); - combo.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent ev) { - stateChanged(); - } - }); + combo.addActionListener(ev -> stateChanged()); } /** @@ -353,6 +345,16 @@ public class AddressInput extends JPanel { return textField.isEditable(); } + @Override + public void focusEditor() { + if (comboAdded) { + combo.requestFocusInWindow(); + } + else { + textField.requestFocusInWindow(); + } + } + private void stateChanged() { if (changeListener != null && !updatingAddress && !stateChanging) { stateChanging = true; diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/FocusableEditor.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/FocusableEditor.java new file mode 100644 index 0000000000..eb20ec4419 --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/FocusableEditor.java @@ -0,0 +1,28 @@ +/* ### + * 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.widgets.table; + +/** + * Signals that the implementing cell editor desires to be notified when editing begins so that the + * editor can request focus on the right widget. + */ +public interface FocusableEditor { + + /** + * Called with the editor should take focus. + */ + public void focusEditor(); +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTable.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTable.java index 254e56a3d1..f882c42701 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTable.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTable.java @@ -940,9 +940,16 @@ public class GTable extends JTable { public boolean editCellAt(int row, int column, EventObject e) { boolean editAtCell = super.editCellAt(row, column, e); if (editAtCell) { - Component editor = getEditorComponent(); - editor.requestFocusInWindow(); - if (editor instanceof JTextComponent textComponent) { + TableCellEditor currentEditor = getCellEditor(); + Component editorComponent = getEditorComponent(); + if (currentEditor instanceof FocusableEditor focusable) { + focusable.focusEditor(); + } + else { + editorComponent.requestFocusInWindow(); + } + + if (editorComponent instanceof JTextComponent textComponent) { textComponent.selectAll(); } }