GP-4740 Added undo/redo support to composite editor. Switched actions to use isEnabledForContext. Transitioned VT FilterFormattedTestField to GFormattedTextField and use for editor text entry fields. Cleanup of old datatype tree actions no longer in use. Lots of changes to improve handling of data type dependency changes and restored original DTM.

This commit is contained in:
ghidra1 2024-08-20 13:06:03 -04:00
parent 6347d8bd94
commit 0ccb142e7e
98 changed files with 3898 additions and 3544 deletions

View file

@ -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.
@ -29,7 +29,9 @@ import docking.widgets.checkbox.GCheckBox;
import docking.widgets.combobox.GhidraComboBox;
import docking.widgets.label.GDLabel;
import docking.widgets.label.GHtmlLabel;
import docking.widgets.textfield.HexIntegerFormatter;
import docking.widgets.numberformat.HexIntegerFormatter;
import docking.widgets.numberformat.IntegerFormatterFactory;
import docking.widgets.textfield.*;
import generic.theme.GColor;
import ghidra.feature.vt.api.main.VTAssociation;
import ghidra.feature.vt.gui.provider.matchtable.NumberRangeProducer;
@ -59,8 +61,8 @@ public abstract class AbstractAddressRangeFilter<T> extends AncillaryFilter<T>
private static final Long MAX_ADDRESS_VALUE = Long.MAX_VALUE;
private JComponent component;
private FilterFormattedTextField lowerAddressRangeTextField;
private FilterFormattedTextField upperAddressRangeTextField;
private GFormattedTextField lowerAddressRangeTextField;
private GFormattedTextField upperAddressRangeTextField;
private JComboBox<String> lowerRangeComboBox;
private JComboBox<String> upperRangeComboBox;
@ -90,14 +92,14 @@ public abstract class AbstractAddressRangeFilter<T> extends AncillaryFilter<T>
enablePanel.add(enableCheckBox, BorderLayout.NORTH);
// begin address field (long input field with hex)
lowerAddressRangeTextField = new FilterFormattedTextField(
lowerAddressRangeTextField = new GFormattedTextField(
new IntegerFormatterFactory(new HexIntegerFormatter(), false), MIN_ADDRESS_VALUE);
lowerAddressRangeTextField.setName("Lower Address Range Text Field"); // for tracking state
lowerAddressRangeTextField.setColumns(15);
lowerAddressRangeTextField.setMinimumSize(lowerAddressRangeTextField.getPreferredSize());
// end address field (long input field with hex)
upperAddressRangeTextField = new FilterFormattedTextField(
upperAddressRangeTextField = new GFormattedTextField(
new IntegerFormatterFactory(new HexIntegerFormatter(), false), MAX_ADDRESS_VALUE);
upperAddressRangeTextField.setName("Upper Address Range Text Field"); // for tracking state
upperAddressRangeTextField.setColumns(15);
@ -169,17 +171,20 @@ public abstract class AbstractAddressRangeFilter<T> extends AncillaryFilter<T>
}
};
FilterStatusListener notificationListener = status -> fireStatusChanged(status);
TextEntryStatusListener notificationListener = s -> {
FilterEditingStatus status = FilterEditingStatus.getFilterStatus(s);
fireStatusChanged(status);
};
StatusLabel lowerScoreStatusLabel =
new StatusLabel(lowerAddressRangeTextField, MIN_ADDRESS_VALUE);
lowerAddressRangeTextField.addFilterStatusListener(lowerScoreStatusLabel);
lowerAddressRangeTextField.addFilterStatusListener(notificationListener);
lowerAddressRangeTextField.addTextEntryStatusListener(lowerScoreStatusLabel);
lowerAddressRangeTextField.addTextEntryStatusListener(notificationListener);
StatusLabel upperScoreStatusLabel =
new StatusLabel(upperAddressRangeTextField, MAX_ADDRESS_VALUE);
upperAddressRangeTextField.addFilterStatusListener(upperScoreStatusLabel);
upperAddressRangeTextField.addFilterStatusListener(notificationListener);
upperAddressRangeTextField.addTextEntryStatusListener(upperScoreStatusLabel);
upperAddressRangeTextField.addTextEntryStatusListener(notificationListener);
disabledScreen = createDisabledScreen(layeredPane);
@ -246,7 +251,7 @@ public abstract class AbstractAddressRangeFilter<T> extends AncillaryFilter<T>
component.validate();
}
private JComboBox<String> createComboBox(FilterFormattedTextField field, Long defaultValue,
private JComboBox<String> createComboBox(GFormattedTextField field, Long defaultValue,
String prototypeString) {
GhidraComboBox<String> comboBox = new GhidraComboBox<>(new LimitedHistoryComboBoxModel()) {
// overridden to paint seamlessly with out color changing text field
@ -287,14 +292,22 @@ public abstract class AbstractAddressRangeFilter<T> extends AncillaryFilter<T>
return component;
}
private FilterEditingStatus getLowerAddressRangeStatus() {
return FilterEditingStatus.getFilterStatus(lowerAddressRangeTextField);
}
private FilterEditingStatus getUpperAddressRangeStatus() {
return FilterEditingStatus.getFilterStatus(upperAddressRangeTextField);
}
@Override
public FilterEditingStatus getFilterStatus() {
if (!isEnabled) {
return FilterEditingStatus.NONE;
}
FilterEditingStatus lowerStatus = lowerAddressRangeTextField.getFilterStatus();
FilterEditingStatus upperStatus = upperAddressRangeTextField.getFilterStatus();
FilterEditingStatus lowerStatus = getLowerAddressRangeStatus();
FilterEditingStatus upperStatus = getUpperAddressRangeStatus();
if (lowerStatus == FilterEditingStatus.ERROR || upperStatus == FilterEditingStatus.ERROR) {
return FilterEditingStatus.ERROR;
@ -339,8 +352,8 @@ public abstract class AbstractAddressRangeFilter<T> extends AncillaryFilter<T>
return true;
}
if (lowerAddressRangeTextField.getFilterStatus() == FilterEditingStatus.ERROR ||
upperAddressRangeTextField.getFilterStatus() == FilterEditingStatus.ERROR) {
if (getLowerAddressRangeStatus() == FilterEditingStatus.ERROR ||
getUpperAddressRangeStatus() == FilterEditingStatus.ERROR) {
return true; // for an invalid filter state, we let all values through
}
@ -572,10 +585,10 @@ public abstract class AbstractAddressRangeFilter<T> extends AncillaryFilter<T>
private class FormattedFieldComboBoxEditor implements ComboBoxEditor {
private EventListenerList listeners = new EventListenerList();
private final FilterFormattedTextField textField;
private final GFormattedTextField textField;
private final Object defaultValue;
FormattedFieldComboBoxEditor(FilterFormattedTextField textField) {
FormattedFieldComboBoxEditor(GFormattedTextField textField) {
this.textField = textField;
defaultValue = textField.getValue();
}

View file

@ -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.
@ -22,6 +22,7 @@ import java.util.Set;
import javax.swing.Icon;
import javax.swing.JComponent;
import docking.widgets.textfield.GFormattedTextField;
import generic.theme.GIcon;
import ghidra.framework.options.SaveState;
import ghidra.util.exception.AssertException;
@ -72,8 +73,6 @@ public abstract class Filter<T> {
public enum FilterEditingStatus {
NONE("", null),
DIRTY("Filter contents have changed, but are not yet applied", new GIcon(
"icon.version.tracking.filter.status.changed")),
ERROR("Filter contents are not valid", new GIcon(
"icon.version.tracking.filter.status.invalid")),
APPLIED("Filter applied", new GIcon("icon.version.tracking.filter.status.applied"));
@ -93,6 +92,17 @@ public abstract class Filter<T> {
Icon getIcon() {
return icon;
}
public static FilterEditingStatus getFilterStatus(GFormattedTextField textEntryField) {
switch (textEntryField.getTextEntryStatus()) {
case INVALID:
return FilterEditingStatus.ERROR;
case CHANGED:
return FilterEditingStatus.APPLIED;
default:
return FilterEditingStatus.NONE;
}
}
}
/**

View file

@ -1,219 +0,0 @@
/* ###
* 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 ghidra.feature.vt.gui.filters;
import static ghidra.feature.vt.gui.filters.Filter.FilterEditingStatus.*;
import java.awt.Color;
import java.awt.event.FocusEvent;
import java.text.ParseException;
import java.util.HashSet;
import java.util.Set;
import javax.swing.InputVerifier;
import javax.swing.JFormattedTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import generic.theme.GColor;
import generic.theme.GThemeDefaults.Colors;
import ghidra.feature.vt.gui.filters.Filter.FilterEditingStatus;
import ghidra.util.SystemUtilities;
public class FilterFormattedTextField extends JFormattedTextField {
private static final Color ERROR_BACKGROUND_COLOR =
new GColor("color.bg.version.tracking.filter.formatted.field.error");
private static final Color EDITING_BACKGROUND_COLOR =
new GColor("color.bg.version.tracking.filter.formatted.field.editing");
private static final Color EDITING_FOREGROUND_COLOR =
new GColor("color.fg.version.tracking.filter.formatted.field.editing");
private Set<FilterStatusListener> listeners = new HashSet<>();
private FilterEditingStatus currentStatus = NONE;
private final Object defaultValue;
private final String defaultText;
private boolean isError;
private boolean ignoreFocusEditChanges;
/** A flag to let us know when we can ignore focus updates */
private boolean isProcessingFocusEvent;
public FilterFormattedTextField(AbstractFormatterFactory factory, Object defaultValue) {
super(factory);
setValue(defaultValue);
this.defaultValue = defaultValue;
this.defaultText = getText(); // get the formatted text
this.currentStatus = NONE;
getDocument().addDocumentListener(new DocumentListener() {
@Override
public void removeUpdate(DocumentEvent e) {
updateText();
}
@Override
public void insertUpdate(DocumentEvent e) {
updateText();
}
@Override
public void changedUpdate(DocumentEvent e) {
updateText();
}
});
addPropertyChangeListener("value", evt -> editingFinished());
update();
}
public void disableFocusEventProcessing() {
ignoreFocusEditChanges = true;
}
@Override
public int getFocusLostBehavior() {
if (ignoreFocusEditChanges) {
return -1; // force us to ignore the focus event
}
return super.getFocusLostBehavior();
}
@Override
protected void processFocusEvent(FocusEvent e) {
isProcessingFocusEvent = true;
super.processFocusEvent(e);
isProcessingFocusEvent = false;
}
public FilterEditingStatus getFilterStatus() {
return currentStatus;
}
public void addFilterStatusListener(FilterStatusListener listener) {
listeners.add(listener);
}
private void filterStatusChanged(FilterEditingStatus status) {
currentStatus = status;
if (listeners == null) {
return; // happens during construction
}
for (FilterStatusListener listener : listeners) {
listener.filterStatusChanged(status);
}
}
private void updateText() {
if (isProcessingFocusEvent) {
return; // ignore transient events
}
InputVerifier verifier = getInputVerifier();
if (verifier != null) {
setIsError(!verifier.verify(this));
}
update();
}
@Override
public void setText(String t) {
if (SystemUtilities.isEqual(getText(), t)) {
return;
}
super.setText(t);
update();
}
public void setIsError(boolean isError) {
// if ( isError && !this.isError ) {
// warn(); // only warn if we were not already in an error situation
// }
this.isError = isError;
update();
}
public void editingFinished() {
update();
}
private boolean hasNonDefaultValue() {
if (defaultText == null) {
return false; // not yet initialized
}
AbstractFormatter formatter = getFormatter();
if (formatter == null) {
return hasNonDefaultText(); // no formatter implies a text only field
}
try {
Object value = formatter.stringToValue(getText());
if (value == null) {
return true; // assume empty string or invalid text
}
return !value.equals(defaultValue);
}
catch (ParseException e) {
return true;
}
}
private boolean hasNonDefaultText() {
return !getText().equals(defaultText);
}
private void update() {
updateStatus();
if (isError) {
setForeground(Colors.FOREGROUND);
setBackground(ERROR_BACKGROUND_COLOR);
}
else if (hasNonDefaultValue()) {
setForeground(EDITING_FOREGROUND_COLOR);
setBackground(EDITING_BACKGROUND_COLOR);
}
else { // default
setForeground(Colors.FOREGROUND);
setBackground(Colors.BACKGROUND);
}
filterStatusChanged(currentStatus);
}
private void updateStatus() {
FilterEditingStatus oldStatus = currentStatus;
if (isError) {
currentStatus = FilterEditingStatus.ERROR;
}
else if (hasNonDefaultValue()) {
currentStatus = APPLIED;
}
else {
currentStatus = NONE;
}
if (oldStatus != currentStatus) {
filterStatusChanged(currentStatus);
}
}
}

View file

@ -1,45 +0,0 @@
/* ###
* 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.
* 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 ghidra.feature.vt.gui.filters;
import javax.swing.JFormattedTextField;
import javax.swing.JFormattedTextField.AbstractFormatter;
import javax.swing.text.DefaultFormatterFactory;
import docking.widgets.textfield.IntegerFormatter;
public class IntegerFormatterFactory extends DefaultFormatterFactory {
private AbstractFormatter formatter = new IntegerFormatter();
public IntegerFormatterFactory(boolean allowsNegativeInput) {
this(new IntegerFormatter(), allowsNegativeInput);
}
public IntegerFormatterFactory(IntegerFormatter formatter, boolean allowsNegativeInput) {
this.formatter = formatter;
if (allowsNegativeInput) {
formatter.setAllowsInvalid(true);
}
}
@Override
public AbstractFormatter getFormatter(JFormattedTextField tf) {
return formatter;
}
}

View file

@ -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,9 +21,11 @@ import java.awt.event.*;
import javax.swing.*;
import docking.widgets.label.GDLabel;
import docking.widgets.textfield.GFormattedTextField;
import docking.widgets.textfield.TextEntryStatusListener;
import ghidra.feature.vt.gui.filters.Filter.FilterEditingStatus;
public class StatusLabel extends GDLabel implements FilterStatusListener {
public class StatusLabel extends GDLabel implements TextEntryStatusListener {
private final JFormattedTextField textField;
@ -82,7 +84,8 @@ public class StatusLabel extends GDLabel implements FilterStatusListener {
}
@Override
public void filterStatusChanged(FilterEditingStatus status) {
public void statusChanged(GFormattedTextField textEntryField) {
FilterEditingStatus status = FilterEditingStatus.getFilterStatus(textEntryField);
resetBounds();
setIcon(status.getIcon());
setToolTipText(status.getDescription() + " (click to reset)");

View file

@ -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.
@ -26,6 +26,8 @@ import org.apache.commons.lang3.StringUtils;
import docking.widgets.label.GDLabel;
import docking.widgets.numberformat.BoundedRangeDecimalFormatterFactory;
import docking.widgets.textfield.GFormattedTextField;
import docking.widgets.textfield.TextEntryStatusListener;
import ghidra.feature.vt.gui.filters.*;
import ghidra.framework.options.SaveState;
import ghidra.util.layout.HorizontalLayout;
@ -41,8 +43,8 @@ public abstract class AbstractDoubleRangeFilter<T> extends Filter<T>
private final Double minValue;
private JComponent component;
private FilterFormattedTextField upperBoundField;
private FilterFormattedTextField lowerBoundField;
private GFormattedTextField upperBoundField;
private GFormattedTextField lowerBoundField;
private String filterName;
AbstractDoubleRangeFilter(String filterName, Double minValue, Double maxValue) {
@ -54,7 +56,7 @@ public abstract class AbstractDoubleRangeFilter<T> extends Filter<T>
}
private void createLowerBoundField() {
lowerBoundField = new FilterFormattedTextField(
lowerBoundField = new GFormattedTextField(
new BoundedRangeDecimalFormatterFactory(maxValue, minValue, FORMAT), minValue);
lowerBoundField.setName("Lower " + filterName + " Filter Field"); // for debugging
lowerBoundField.setColumns(4);
@ -63,7 +65,7 @@ public abstract class AbstractDoubleRangeFilter<T> extends Filter<T>
}
private void createUpperBoundField() {
upperBoundField = new FilterFormattedTextField(
upperBoundField = new GFormattedTextField(
new BoundedRangeDecimalFormatterFactory(maxValue, minValue, FORMAT), maxValue);
upperBoundField.setName("Upper " + filterName + " Filter Field"); // for debugging
upperBoundField.setColumns(4);
@ -93,15 +95,18 @@ public abstract class AbstractDoubleRangeFilter<T> extends Filter<T>
panel.add(middleLabel);
panel.add(upperBoundField);
FilterStatusListener notificationListener = status -> fireStatusChanged(status);
TextEntryStatusListener notificationListener = s -> {
FilterEditingStatus status = FilterEditingStatus.getFilterStatus(s);
fireStatusChanged(status);
};
StatusLabel lowerBoundStatusLabel = new StatusLabel(lowerBoundField, minValue);
lowerBoundField.addFilterStatusListener(lowerBoundStatusLabel);
lowerBoundField.addFilterStatusListener(notificationListener);
lowerBoundField.addTextEntryStatusListener(lowerBoundStatusLabel);
lowerBoundField.addTextEntryStatusListener(notificationListener);
StatusLabel upperBoundStatusLabel = new StatusLabel(upperBoundField, maxValue);
upperBoundField.addFilterStatusListener(upperBoundStatusLabel);
upperBoundField.addFilterStatusListener(notificationListener);
upperBoundField.addTextEntryStatusListener(upperBoundStatusLabel);
upperBoundField.addTextEntryStatusListener(notificationListener);
JLayeredPane layeredPane = new JLayeredPane();
layeredPane.add(panel, BASE_COMPONENT_LAYER);
@ -127,10 +132,18 @@ public abstract class AbstractDoubleRangeFilter<T> extends Filter<T>
return component;
}
private FilterEditingStatus getLowerBoundStatus() {
return FilterEditingStatus.getFilterStatus(lowerBoundField);
}
private FilterEditingStatus getUpperBoundStatus() {
return FilterEditingStatus.getFilterStatus(upperBoundField);
}
@Override
public FilterEditingStatus getFilterStatus() {
FilterEditingStatus lowerStatus = lowerBoundField.getFilterStatus();
FilterEditingStatus upperStatus = upperBoundField.getFilterStatus();
FilterEditingStatus lowerStatus = getLowerBoundStatus();
FilterEditingStatus upperStatus = getUpperBoundStatus();
if (lowerStatus == FilterEditingStatus.ERROR || upperStatus == FilterEditingStatus.ERROR) {
return FilterEditingStatus.ERROR;
@ -146,8 +159,8 @@ public abstract class AbstractDoubleRangeFilter<T> extends Filter<T>
@Override
public boolean passesFilter(T t) {
if (lowerBoundField.getFilterStatus() == FilterEditingStatus.ERROR ||
upperBoundField.getFilterStatus() == FilterEditingStatus.ERROR) {
if (getLowerBoundStatus() == FilterEditingStatus.ERROR ||
getUpperBoundStatus() == FilterEditingStatus.ERROR) {
return true; // for an invalid filter state, we let all values through
}

View file

@ -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.
@ -27,6 +27,8 @@ import javax.swing.border.Border;
import org.apache.commons.lang3.StringUtils;
import docking.widgets.label.GDLabel;
import docking.widgets.numberformat.IntegerFormatterFactory;
import docking.widgets.textfield.GFormattedTextField;
import ghidra.feature.vt.api.main.VTMatch;
import ghidra.feature.vt.gui.filters.*;
import ghidra.framework.options.SaveState;
@ -39,7 +41,7 @@ public class LengthFilter extends Filter<VTMatch> {
private static final Integer DEFAULT_FILTER_VALUE = 0;
private JComponent component;
private FilterFormattedTextField textField;
private GFormattedTextField textField;
public LengthFilter() {
component = createComponent();
@ -49,7 +51,7 @@ public class LengthFilter extends Filter<VTMatch> {
final JLabel label = new GDLabel("Length Filter: ");
Integer defaultValue = DEFAULT_FILTER_VALUE;
textField = new FilterFormattedTextField(new IntegerFormatterFactory(false), defaultValue);
textField = new GFormattedTextField(new IntegerFormatterFactory(false), defaultValue);
textField.setName("Length Filter Field"); // for debugging
textField.setInputVerifier(new IntegerInputVerifier());
textField.setHorizontalAlignment(SwingConstants.RIGHT);
@ -67,8 +69,11 @@ public class LengthFilter extends Filter<VTMatch> {
final JLayeredPane layeredPane = new JLayeredPane();
StatusLabel statusLabel = new StatusLabel(textField, defaultValue);
textField.addFilterStatusListener(statusLabel);
textField.addFilterStatusListener(status -> fireStatusChanged(status));
textField.addTextEntryStatusListener(statusLabel);
textField.addTextEntryStatusListener(s -> {
FilterEditingStatus status = FilterEditingStatus.getFilterStatus(s);
fireStatusChanged(status);
});
layeredPane.add(panel, BASE_COMPONENT_LAYER);
layeredPane.add(statusLabel, HOVER_COMPONENT_LAYER);
layeredPane.setPreferredSize(panel.getPreferredSize());
@ -91,7 +96,7 @@ public class LengthFilter extends Filter<VTMatch> {
@Override
public FilterEditingStatus getFilterStatus() {
return textField.getFilterStatus();
return FilterEditingStatus.getFilterStatus(textField);
}
@Override

View file

@ -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.
@ -28,9 +28,11 @@ import javax.swing.text.DefaultFormatterFactory;
import docking.widgets.label.GDLabel;
import docking.widgets.table.GTable;
import docking.widgets.textfield.GFormattedTextField;
import ghidra.feature.vt.api.main.VTAssociation;
import ghidra.feature.vt.api.main.VTSession;
import ghidra.feature.vt.gui.filters.*;
import ghidra.feature.vt.gui.filters.Filter;
import ghidra.feature.vt.gui.filters.StatusLabel;
import ghidra.feature.vt.gui.plugin.VTController;
import ghidra.framework.options.SaveState;
import ghidra.program.model.address.Address;
@ -44,7 +46,7 @@ public abstract class AbstractTextFilter<T> extends Filter<T> {
private static final Integer HOVER_COMPONENT_LAYER = 2;
private JComponent component;
private FilterFormattedTextField textField;
private GFormattedTextField textField;
private String defaultValue = "";
protected VTController controller;
protected final GTable table;
@ -62,7 +64,7 @@ public abstract class AbstractTextFilter<T> extends Filter<T> {
panel.setBorder(BorderFactory.createCompoundBorder(outsideBorder, paddingBorder));
DefaultFormatterFactory factory = new DefaultFormatterFactory(new DefaultFormatter());
textField = new FilterFormattedTextField(factory, defaultValue);
textField = new GFormattedTextField(factory, defaultValue);
textField.setName(filterName + " Field"); // for debugging
textField.setColumns(20);
textField.setMinimumSize(textField.getPreferredSize());
@ -76,8 +78,11 @@ public abstract class AbstractTextFilter<T> extends Filter<T> {
panel.add(textField, BorderLayout.CENTER);
StatusLabel nameFieldStatusLabel = new StatusLabel(textField, defaultValue);
textField.addFilterStatusListener(nameFieldStatusLabel);
textField.addFilterStatusListener(status -> fireStatusChanged(status));
textField.addTextEntryStatusListener(nameFieldStatusLabel);
textField.addTextEntryStatusListener(s -> {
FilterEditingStatus status = FilterEditingStatus.getFilterStatus(s);
fireStatusChanged(status);
});
final JLayeredPane layeredPane = new JLayeredPane();
layeredPane.add(panel, BASE_COMPONENT_LAYER);
@ -127,7 +132,7 @@ public abstract class AbstractTextFilter<T> extends Filter<T> {
@Override
public FilterEditingStatus getFilterStatus() {
return textField.getFilterStatus();
return FilterEditingStatus.getFilterStatus(textField);
}
protected String getTextFieldText() {