Merge remote-tracking branch

'origin/GP-3173-dragonmacher-function-editor-focus-issue' (Closes #3561)
This commit is contained in:
Ryan Kurtz
2023-03-10 11:44:02 -05:00
7 changed files with 102 additions and 42 deletions
@@ -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<DataType> 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<DataType> 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);
}
@@ -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<DataType> 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<DataType> 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;
@@ -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<DataType> 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.
@@ -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<Register> registerWrapperComparator = (r1, r2) -> r1.toString().compareToIgnoreCase(r2.toString());
private Comparator<Register> 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());
@@ -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<AddressSpace> combo;
private boolean comboAdded;
@@ -45,19 +45,16 @@ public class AddressInput extends JPanel {
private JTextField spaceField;
private static final Comparator<AddressSpace> 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;
@@ -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();
}
@@ -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();
}
}