mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-01-08 21:47:59 -05:00
Updated the Column Filter Dialog to not lose focus when picking from the combo boxes
This commit is contained in:
@@ -469,18 +469,45 @@ public class ColumnFilterDialog<R> extends ReusableDialogComponentProvider
|
||||
// TableFilterDialogModelListener methods
|
||||
//==================================================================================================
|
||||
|
||||
void filterRemoved(ColumnBasedTableFilter<R> filter) {
|
||||
filterManager.updateSavedFilters(filter, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void editorValueChanged(ColumnConstraintEditor<?> editor) {
|
||||
updateStatus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void structureChanged() {
|
||||
loadFilterRows();
|
||||
updateStatus();
|
||||
private ColumnFilterGridLocation getFocusedGridLocation() {
|
||||
KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
|
||||
Component focusOwner = kfm.getFocusOwner();
|
||||
|
||||
for (int row = 0; row < filterPanels.size(); row++) {
|
||||
ColumnFilterPanel panel = filterPanels.get(row);
|
||||
if (SwingUtilities.isDescendingFrom(focusOwner, panel)) {
|
||||
return panel.getActiveGridLocation(focusOwner, row);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
void filterRemoved(ColumnBasedTableFilter<R> filter) {
|
||||
filterManager.updateSavedFilters(filter, false);
|
||||
@Override
|
||||
public void structureChanged() {
|
||||
|
||||
ColumnFilterGridLocation restoreLocation = getFocusedGridLocation();
|
||||
|
||||
loadFilterRows();
|
||||
updateStatus();
|
||||
|
||||
if (restoreLocation != null) {
|
||||
int dialogRow = restoreLocation.dialogRow();
|
||||
if (filterPanels.size() <= dialogRow) {
|
||||
return; // the UI was rebuilt in such a way that the old grid location is not valid
|
||||
}
|
||||
|
||||
ColumnFilterPanel panel = filterPanels.get(dialogRow);
|
||||
panel.restoreActiveGridLocation(restoreLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/* ###
|
||||
* 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.constraint.dialog;
|
||||
|
||||
/**
|
||||
* A simple object used to track a component's position in the filter dialog. This is used to
|
||||
* restore focus when the dialog is rebuilt.
|
||||
* <p>
|
||||
* This class models the filter dialog as grid. The dialog has a set of rows, each of which can
|
||||
* have sub-rows within the dialog's row. The columns values are the same for the dialog as they
|
||||
* are for sub-components.
|
||||
*
|
||||
* @param dialogRow the row number in the dialog's set of compound rows
|
||||
* @param subRow the row number within a given dialog row
|
||||
* @param col the column
|
||||
*/
|
||||
record ColumnFilterGridLocation(int dialogRow, int subRow, int col) {
|
||||
|
||||
}
|
||||
@@ -23,10 +23,11 @@ import javax.swing.*;
|
||||
import javax.swing.border.BevelBorder;
|
||||
|
||||
import docking.widgets.EmptyBorderButton;
|
||||
import docking.widgets.combobox.GhidraComboBox;
|
||||
import docking.widgets.combobox.GComboBox;
|
||||
import docking.widgets.label.GDLabel;
|
||||
import docking.widgets.list.GComboBoxCellRenderer;
|
||||
import generic.theme.GThemeDefaults.Colors.Messages;
|
||||
import ghidra.util.Swing;
|
||||
import ghidra.util.layout.VerticalLayout;
|
||||
import resources.Icons;
|
||||
import resources.ResourceManager;
|
||||
@@ -71,7 +72,8 @@ class ColumnFilterPanel extends JPanel {
|
||||
Vector<ColumnFilterData<?>> v = new Vector<>(filterEntry.getAllColumnData());
|
||||
|
||||
DefaultComboBoxModel<ColumnFilterData<?>> model = new DefaultComboBoxModel<>(v);
|
||||
columnFilterComboBox = new GhidraComboBox<>(model);
|
||||
columnFilterComboBox = new GComboBox<>(model);
|
||||
columnFilterComboBox.getAccessibleContext().setAccessibleName("Table Column");
|
||||
columnFilterComboBox.setRenderer(new GComboBoxCellRenderer<>() {
|
||||
@Override
|
||||
protected String getItemText(ColumnFilterData<?> value) {
|
||||
@@ -81,7 +83,6 @@ class ColumnFilterPanel extends JPanel {
|
||||
|
||||
columnFilterComboBox.setSelectedItem(filterEntry.getColumnFilterData());
|
||||
|
||||
columnFilterComboBox.addItemListener(e -> columnChanged());
|
||||
columnFilterComboBox.addActionListener(e -> columnChanged());
|
||||
return columnFilterComboBox;
|
||||
}
|
||||
@@ -127,4 +128,46 @@ class ColumnFilterPanel extends JPanel {
|
||||
DialogFilterRow getColumnFilterEntry() {
|
||||
return filterEntry;
|
||||
}
|
||||
|
||||
ColumnFilterGridLocation getActiveGridLocation(Component component, int dialogRow) {
|
||||
|
||||
if (columnFilterComboBox == component) {
|
||||
return new ColumnFilterGridLocation(dialogRow, 0, 0);
|
||||
}
|
||||
|
||||
for (int subRow = 0; subRow < filterPanels.size(); subRow++) {
|
||||
ConstraintFilterPanel panel = filterPanels.get(subRow);
|
||||
int col = panel.getActiveComponentColumn(component);
|
||||
if (col != -1) {
|
||||
return new ColumnFilterGridLocation(dialogRow, subRow, col);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
void restoreActiveGridLocation(ColumnFilterGridLocation location) {
|
||||
|
||||
Component component = getComponent(location);
|
||||
if (component != null) {
|
||||
Swing.runLater(() -> {
|
||||
component.requestFocusInWindow();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private Component getComponent(ColumnFilterGridLocation location) {
|
||||
int subRow = location.subRow();
|
||||
int col = location.col();
|
||||
if (subRow == 0 && col == 0) {
|
||||
return columnFilterComboBox;
|
||||
}
|
||||
|
||||
if (filterPanels.size() <= subRow) {
|
||||
return null; // the UI was rebuilt in such a way that the old grid location is not valid
|
||||
}
|
||||
|
||||
ConstraintFilterPanel panel = filterPanels.get(subRow);
|
||||
return panel.getActiveComponent(col);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,6 +84,7 @@ public class ConstraintFilterPanel extends JPanel {
|
||||
private Component buildConstraintCombo() {
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
constraintComboBox = new GComboBox<>();
|
||||
constraintComboBox.getAccessibleContext().setAccessibleName("Filter");
|
||||
constraintComboBox.setRenderer(new ConstraintComboBoxCellRenderer());
|
||||
constraintComboBox.addActionListener(constraintComboBoxListener);
|
||||
panel.add(constraintComboBox, BorderLayout.CENTER);
|
||||
@@ -119,6 +120,46 @@ public class ConstraintFilterPanel extends JPanel {
|
||||
constraintComboBox.addActionListener(constraintComboBoxListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the column value for the given component. The column value is relative to the dialog's
|
||||
* grid of components. This returns -1 if the given component is not inside the component
|
||||
* hierarchy of this filter panel.
|
||||
*
|
||||
* @param component the component
|
||||
* @return the column
|
||||
* @see #getActiveComponent(int)
|
||||
*/
|
||||
int getActiveComponentColumn(Component component) {
|
||||
|
||||
// Note: we provide a combo for choosing a condition and a field for entering a value.
|
||||
// The client of this class has a combo that is first in the row. We will allow that parent
|
||||
// widget to be column 0, so we will use column 1 and 2 for our widgets.
|
||||
if (constraintComboBox == component) {
|
||||
return 1;
|
||||
}
|
||||
else if (SwingUtilities.isDescendingFrom(component, inlineEditorPanel)) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the component for the given column value.
|
||||
* @param col the column value
|
||||
* @return the component
|
||||
* @see #getActiveComponentColumn(Component)
|
||||
*/
|
||||
Component getActiveComponent(int col) {
|
||||
if (col == 1) {
|
||||
return constraintComboBox;
|
||||
}
|
||||
else if (col == 2) {
|
||||
return inlineEditorPanel;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private class ConstraintComboBoxCellRenderer
|
||||
extends GComboBoxCellRenderer<ColumnConstraint<?>> {
|
||||
@Override
|
||||
@@ -126,4 +167,5 @@ public class ConstraintFilterPanel extends JPanel {
|
||||
return value.getName();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user