Test fixes

This commit is contained in:
dragonmacher 2025-03-20 14:25:03 -04:00
parent 22f36c2769
commit c02a321aef
5 changed files with 91 additions and 25 deletions

View file

@ -39,6 +39,7 @@ import ghidra.program.model.lang.Register;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.model.listing.ProgramContext; import ghidra.program.model.listing.ProgramContext;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.Swing;
class VarnodeLocationCellEditor extends AbstractCellEditor class VarnodeLocationCellEditor extends AbstractCellEditor
implements TableCellEditor, FocusableEditor { implements TableCellEditor, FocusableEditor {
@ -193,6 +194,9 @@ class VarnodeLocationCellEditor extends AbstractCellEditor
registerEntryTextField = new DropDownSelectionTextField<>(registerModel); registerEntryTextField = new DropDownSelectionTextField<>(registerModel);
registerEntryTextField.setBorder(null); registerEntryTextField.setBorder(null);
// this allows us to show the matching list when there is no text in the editor
registerEntryTextField.setShowMatchingListOnEmptyText(true);
AtomicReference<Register> currentReg = new AtomicReference<>(); AtomicReference<Register> currentReg = new AtomicReference<>();
Address address = varnode.getAddress(); Address address = varnode.getAddress();
@ -219,7 +223,12 @@ class VarnodeLocationCellEditor extends AbstractCellEditor
registerEntryTextField.addActionListener(e -> stopCellEditing()); registerEntryTextField.addActionListener(e -> stopCellEditing());
registerEntryTextField.showMatchingList(); // Note: need to do this later. At the time of construction, this text field is not yet
// showing. The text field has checks to avoid showing the list if it is not showing. By
// running later, this call will happen once the widget has been added to the table.
Swing.runLater(() -> {
registerEntryTextField.showMatchingList();
});
return registerEntryTextField; return registerEntryTextField;
} }

View file

@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -151,14 +151,8 @@ public class IconPropertyEditor extends PropertyEditorSupport {
private Component buildTopPanel() { private Component buildTopPanel() {
JPanel panel = new JPanel(new BorderLayout()); JPanel panel = new JPanel(new BorderLayout());
dataModel = new IconDropDownDataModel(); dataModel = new IconDropDownDataModel();
dropDown = new DropDownSelectionTextField<>(dataModel) { dropDown = new DropDownSelectionTextField<>(dataModel);
protected List<Icon> getMatchingData(String searchText) { dropDown.setShowMatchingListOnEmptyText(true);
if (searchText.isBlank()) {
return ((IconDropDownDataModel) dataModel).getData();
}
return super.getMatchingData(searchText);
}
};
dropDown.addDropDownSelectionChoiceListener(choiceListener); dropDown.addDropDownSelectionChoiceListener(choiceListener);
panel.add(dropDown, BorderLayout.CENTER); panel.add(dropDown, BorderLayout.CENTER);
JButton browseButton = new BrowseButton(); JButton browseButton = new BrowseButton();

View file

@ -91,6 +91,7 @@ public class DropDownTextField<T> extends JTextField implements GComponent {
private boolean consumeEnterKeyPress = true; // consume Enter presses by default private boolean consumeEnterKeyPress = true; // consume Enter presses by default
private boolean ignoreEnterKeyPress = false; // do not ignore enter by default private boolean ignoreEnterKeyPress = false; // do not ignore enter by default
private boolean ignoreCaretChanges; private boolean ignoreCaretChanges;
private boolean showMachingListOnEmptyText;
// We use an update manager to buffer requests to update the matches. This allows us to be // We use an update manager to buffer requests to update the matches. This allows us to be
// more responsive when the user is attempting to type multiple characters // more responsive when the user is attempting to type multiple characters
@ -354,6 +355,12 @@ public class DropDownTextField<T> extends JTextField implements GComponent {
return Collections.emptyList(); return Collections.emptyList();
} }
// By default we do not show the matches list is empty. This seems less noisy. Some
// clients would rather have empty text show all available choices.
if (searchText.isEmpty() && !showMachingListOnEmptyText) {
return Collections.emptyList();
}
// get the sublist of matches--this may take a while // get the sublist of matches--this may take a while
Cursor previousCursor = getCursor(); Cursor previousCursor = getCursor();
try { try {
@ -377,8 +384,22 @@ public class DropDownTextField<T> extends JTextField implements GComponent {
* text. * text.
*/ */
public void showMatchingList() { public void showMatchingList() {
String text = pendingTextUpdate != null ? pendingTextUpdate : getText();
updateDisplayContents(text); //
// We temporarily enable this list to show for empty text, even if the text is not empty.
// This handles the default setting, which has this feature off. We can refactor this class
// to allow us to make a direct call instead of using this temporary setting. This seems
// simple enough for now.
//
boolean restore = showMachingListOnEmptyText;
try {
showMachingListOnEmptyText = true;
pendingTextUpdate = pendingTextUpdate != null ? pendingTextUpdate : getText();
updateManager.updateNow();
}
finally {
showMachingListOnEmptyText = restore;
}
} }
/** /**
@ -414,6 +435,15 @@ public class DropDownTextField<T> extends JTextField implements GComponent {
this.ignoreEnterKeyPress = ignore; this.ignoreEnterKeyPress = ignore;
} }
/**
* Allows this text field to show all potential matches when the text of the field is empty.
* The default is false.
* @param show true to allow the list to be shown
*/
public void setShowMatchingListOnEmptyText(boolean show) {
this.showMachingListOnEmptyText = show;
}
/** /**
* Sets the height of the matching window. The default value is {@value #MIN_HEIGHT}. * Sets the height of the matching window. The default value is {@value #MIN_HEIGHT}.
* *

View file

@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -30,7 +30,6 @@ import org.junit.After;
import org.junit.Before; import org.junit.Before;
import docking.test.AbstractDockingTest; import docking.test.AbstractDockingTest;
import ghidra.util.Msg;
public abstract class AbstractDropDownTextFieldTest<T> extends AbstractDockingTest { public abstract class AbstractDropDownTextFieldTest<T> extends AbstractDockingTest {
@ -234,10 +233,10 @@ public abstract class AbstractDropDownTextFieldTest<T> extends AbstractDockingTe
protected void hideWindowPressKeyThenValidate(int keyCode) { protected void hideWindowPressKeyThenValidate(int keyCode) {
JWindow matchingWindow = textField.getActiveMatchingWindow(); JWindow matchingWindow = textField.getActiveMatchingWindow();
matchingWindow.setVisible(false); runSwing(() -> matchingWindow.setVisible(false));
waitForSwing(); waitForSwing();
assertTrue("The completion window is showing after a call to setVisible(false).", assertFalse("The completion window is showing after a call to setVisible(false).",
!matchingWindow.isShowing()); matchingWindow.isShowing());
tpyeActionKey(keyCode); tpyeActionKey(keyCode);
assertTrue("The completion window is not showing after being trigger by a navigation key.", assertTrue("The completion window is not showing after being trigger by a navigation key.",
matchingWindow.isShowing()); matchingWindow.isShowing());
@ -309,10 +308,6 @@ public abstract class AbstractDropDownTextFieldTest<T> extends AbstractDockingTe
return; return;
} }
if (!matchingWindow.isShowing()) {
Msg.debug(this, "");
}
assertTrue("Window is not showing when it should be", matchingWindow.isShowing()); assertTrue("Window is not showing when it should be", matchingWindow.isShowing());
} }

View file

@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -435,4 +435,42 @@ public class DropDownTextFieldTest extends AbstractDropDownTextFieldTest<String>
Dimension windowSize = matchingWindow.getSize(); Dimension windowSize = matchingWindow.getSize();
assertEquals(newSize, windowSize.height); assertEquals(newSize, windowSize.height);
} }
@Test
public void testShowMatchingListOnEmptyText() {
runSwing(() -> textField.setShowMatchingListOnEmptyText(false));
// insert some text and make sure the window is created
typeText("d", true);
assertMatchingWindowShowing();
// with this setting off, the list stays visible on empty text
clearText();
assertMatchingWindowHidden();
// even with this setting off, this method should always force the list to show
showMatchingList();
assertMatchingWindowShowing();
runSwing(() -> textField.setShowMatchingListOnEmptyText(true));
showMatchingList();
assertMatchingWindowShowing();
typeText("d", true);
assertMatchingWindowShowing();
// with this setting on, the list stays visible on empty text
clearText();
assertMatchingWindowShowing();
// with this setting on, this method should always force the list to show
showMatchingList();
assertMatchingWindowShowing();
}
private void showMatchingList() {
runSwing(() -> textField.showMatchingList());
}
} }