mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-02-16 07:30:16 +00:00
Merge remote-tracking branch
'origin/GP-3492-dragonmacher-file-chooser-editable-field--SQUASHED' (Closes #5291, Closes #7150)
This commit is contained in:
commit
ecb9bc2893
@ -402,7 +402,7 @@ public abstract class AbstractGhidraHeadedDebuggerTest
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Only use this to escape from pop-up menus. Otherwise, use
|
* Only use this to escape from pop-up menus. Otherwise, use
|
||||||
* {@link #triggerEscapeKey(Component)}.
|
* {@link #triggerEscape(Component)}.
|
||||||
*
|
*
|
||||||
* @throws AWTException
|
* @throws AWTException
|
||||||
*/
|
*/
|
||||||
|
@ -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.
|
||||||
@ -401,7 +401,7 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerTest
|
|||||||
waitForTasks();
|
waitForTasks();
|
||||||
|
|
||||||
modelProvider.pathField.setText("SomeNonsenseToBeCancelled");
|
modelProvider.pathField.setText("SomeNonsenseToBeCancelled");
|
||||||
triggerEscapeKey(modelProvider.pathField);
|
triggerEscape(modelProvider.pathField);
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
|
||||||
assertPathIsThreadsContainer();
|
assertPathIsThreadsContainer();
|
||||||
|
@ -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.
|
||||||
@ -195,14 +195,14 @@ public abstract class AbstractListingMergeManagerTest extends AbstractMergeTest
|
|||||||
KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow();
|
KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow();
|
||||||
assertNotNull(activeWindow);
|
assertNotNull(activeWindow);
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
triggerEscapeKey(activeWindow);
|
triggerEscape(activeWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
void escapeWindowWithTitleContaining(String partOfTitle) {
|
void escapeWindowWithTitleContaining(String partOfTitle) {
|
||||||
Window win = getWindowWithTitleContaining(partOfTitle);
|
Window win = getWindowWithTitleContaining(partOfTitle);
|
||||||
if (win != null) {
|
if (win != null) {
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
triggerEscapeKey(win);
|
triggerEscape(win);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.
|
||||||
@ -772,7 +772,7 @@ public class FrontEndPluginActionsTest extends AbstractGhidraHeadedIntegrationTe
|
|||||||
private void clearText(Component c, String text) {
|
private void clearText(Component c, String text) {
|
||||||
int n = text.length();
|
int n = text.length();
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
triggerBackspaceKey(c);
|
triggerBackspace(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,6 +56,8 @@ import utilities.util.reflection.ReflectionUtilities;
|
|||||||
* @since Tracker Id 329
|
* @since Tracker Id 329
|
||||||
*/
|
*/
|
||||||
public class KeyBindingUtils {
|
public class KeyBindingUtils {
|
||||||
|
private static final String NO_KEYBINDING_NAME = "none";
|
||||||
|
|
||||||
private static final String LAST_KEY_BINDING_EXPORT_DIRECTORY = "LastKeyBindingExportDirectory";
|
private static final String LAST_KEY_BINDING_EXPORT_DIRECTORY = "LastKeyBindingExportDirectory";
|
||||||
|
|
||||||
private static final String RELEASED = "released";
|
private static final String RELEASED = "released";
|
||||||
@ -338,7 +340,7 @@ public class KeyBindingUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Object keyText = im.get(keyStroke);
|
Object keyText = im.get(keyStroke);
|
||||||
if (keyText == null) {
|
if (keyText == null || keyText.equals(NO_KEYBINDING_NAME)) {
|
||||||
// no binding--just pick a name
|
// no binding--just pick a name
|
||||||
keyText = action.getValue(Action.NAME);
|
keyText = action.getValue(Action.NAME);
|
||||||
if (keyText == null) {
|
if (keyText == null) {
|
||||||
@ -404,7 +406,7 @@ public class KeyBindingUtils {
|
|||||||
int focusCondition) {
|
int focusCondition) {
|
||||||
InputMap inputMap = component.getInputMap(focusCondition);
|
InputMap inputMap = component.getInputMap(focusCondition);
|
||||||
if (inputMap != null) {
|
if (inputMap != null) {
|
||||||
inputMap.put(keyStroke, "none");
|
inputMap.put(keyStroke, NO_KEYBINDING_NAME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1503,7 +1503,7 @@ public abstract class AbstractDockingTest extends AbstractGuiTest {
|
|||||||
triggerKey(destination, modifiers, keyCode, keyChar);
|
triggerKey(destination, modifiers, keyCode, keyChar);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void triggerEscapeKey(Component c) {
|
public static void triggerEscape(Component c) {
|
||||||
// text components will not perform built-in actions if they are not focused
|
// text components will not perform built-in actions if they are not focused
|
||||||
if (c instanceof JTextComponent) {
|
if (c instanceof JTextComponent) {
|
||||||
triggerFocusGained(c);
|
triggerFocusGained(c);
|
||||||
@ -1511,7 +1511,7 @@ public abstract class AbstractDockingTest extends AbstractGuiTest {
|
|||||||
triggerText(c, "\033");
|
triggerText(c, "\033");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void triggerBackspaceKey(Component c) {
|
public static void triggerBackspace(Component c) {
|
||||||
triggerText(c, "\010");
|
triggerText(c, "\010");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,15 +29,19 @@ import javax.swing.*;
|
|||||||
import javax.swing.event.CellEditorListener;
|
import javax.swing.event.CellEditorListener;
|
||||||
import javax.swing.event.ChangeEvent;
|
import javax.swing.event.ChangeEvent;
|
||||||
import javax.swing.filechooser.FileSystemView;
|
import javax.swing.filechooser.FileSystemView;
|
||||||
|
import javax.swing.text.DefaultFormatter;
|
||||||
|
import javax.swing.text.DefaultFormatterFactory;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import docking.*;
|
import docking.*;
|
||||||
|
import docking.actions.KeyBindingUtils;
|
||||||
import docking.widgets.*;
|
import docking.widgets.*;
|
||||||
import docking.widgets.combobox.GComboBox;
|
import docking.widgets.combobox.GComboBox;
|
||||||
import docking.widgets.label.GDLabel;
|
import docking.widgets.label.GDLabel;
|
||||||
import docking.widgets.label.GLabel;
|
import docking.widgets.label.GLabel;
|
||||||
import docking.widgets.list.GListCellRenderer;
|
import docking.widgets.list.GListCellRenderer;
|
||||||
|
import docking.widgets.textfield.GFormattedTextField;
|
||||||
import generic.theme.GColor;
|
import generic.theme.GColor;
|
||||||
import generic.theme.GIcon;
|
import generic.theme.GIcon;
|
||||||
import ghidra.framework.preferences.Preferences;
|
import ghidra.framework.preferences.Preferences;
|
||||||
@ -171,7 +175,7 @@ public class GhidraFileChooser extends ReusableDialogComponentProvider implement
|
|||||||
private FileChooserToggleButton downloadsButton;
|
private FileChooserToggleButton downloadsButton;
|
||||||
private FileChooserToggleButton recentButton;
|
private FileChooserToggleButton recentButton;
|
||||||
|
|
||||||
private JTextField currentPathTextField;
|
private GFormattedTextField currentPathTextField;
|
||||||
private DropDownSelectionTextField<File> filenameTextField;
|
private DropDownSelectionTextField<File> filenameTextField;
|
||||||
private DirectoryTableModel directoryTableModel;
|
private DirectoryTableModel directoryTableModel;
|
||||||
private DirectoryTable directoryTable;
|
private DirectoryTable directoryTable;
|
||||||
@ -378,13 +382,13 @@ public class GhidraFileChooser extends ReusableDialogComponentProvider implement
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void editingStopped(ChangeEvent e) {
|
public void editingStopped(ChangeEvent e) {
|
||||||
// the user has cancelled editing in the text field (i.e., they pressed ESCAPE)
|
// the user has cancelled editing in the text field (i.e., they pressed ENTER)
|
||||||
enterCallback();
|
enterCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void editingCanceled(ChangeEvent e) {
|
public void editingCanceled(ChangeEvent e) {
|
||||||
// the user has committed editing from the text field (i.e, they pressed ENTER)
|
// the user has committed editing from the text field (i.e, they pressed ESCAPE)
|
||||||
escapeCallback();
|
escapeCallback();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -460,14 +464,106 @@ public class GhidraFileChooser extends ReusableDialogComponentProvider implement
|
|||||||
gbc.gridx = afterPathLabel;
|
gbc.gridx = afterPathLabel;
|
||||||
gbc.fill = GridBagConstraints.HORIZONTAL;
|
gbc.fill = GridBagConstraints.HORIZONTAL;
|
||||||
gbc.weightx = 1.0;
|
gbc.weightx = 1.0;
|
||||||
currentPathTextField = new JTextField();
|
currentPathTextField = buildPathTextField();
|
||||||
currentPathTextField.setName("Path");
|
|
||||||
currentPathTextField.setEditable(false);
|
|
||||||
headerPanel.add(currentPathTextField, gbc);
|
headerPanel.add(currentPathTextField, gbc);
|
||||||
|
|
||||||
return headerPanel;
|
return headerPanel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private GFormattedTextField buildPathTextField() {
|
||||||
|
DefaultFormatter formatter = new DefaultFormatter();
|
||||||
|
formatter.setOverwriteMode(false);
|
||||||
|
DefaultFormatterFactory factory = new DefaultFormatterFactory(formatter);
|
||||||
|
GFormattedTextField textField = new GFormattedTextField(factory, "") {
|
||||||
|
@Override
|
||||||
|
public void setText(String t) {
|
||||||
|
super.setText(t);
|
||||||
|
setDefaultValue(t);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
textField.setName("Path");
|
||||||
|
|
||||||
|
textField.addFocusListener(new FocusAdapter() {
|
||||||
|
@Override
|
||||||
|
public void focusGained(FocusEvent e) {
|
||||||
|
lastInputFocus = textField;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
DockingUtils.installUndoRedo(textField);
|
||||||
|
|
||||||
|
// have the Escape key clear any edits to the field
|
||||||
|
KeyStroke escapeKs = KeyBindingUtils.parseKeyStroke("Escape");
|
||||||
|
Action escapeAction = new AbstractAction("Reset Path") {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
|
||||||
|
if (textField.isChanged()) {
|
||||||
|
textField.reset();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// When not edited, pass the event up to the chooser so the behavior works as
|
||||||
|
// it does elsewhere in the dialog.
|
||||||
|
escapeCallback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// remove the table's escape key binding and then add our own
|
||||||
|
KeyBindingUtils.clearKeyBinding(textField, escapeKs);
|
||||||
|
KeyBindingUtils.registerAction(textField, escapeKs, escapeAction,
|
||||||
|
JComponent.WHEN_FOCUSED);
|
||||||
|
|
||||||
|
// update Enter to allow the user to pick the selected language
|
||||||
|
KeyStroke enterKs = KeyBindingUtils.parseKeyStroke("Enter");
|
||||||
|
Action enterAction = new AbstractAction("Choose File") {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
|
||||||
|
if (!textField.isChanged()) {
|
||||||
|
// When not edited, pass the event up to the chooser so the behavior works as
|
||||||
|
// it does elsewhere in the dialog.
|
||||||
|
enterCallback();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!textField.isValid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String text = textField.getText();
|
||||||
|
File f = new File(text);
|
||||||
|
if (f.isFile()) {
|
||||||
|
setSelectedFile(f);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
updateDirOnly(f, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// remove the table's enter key binding and then add our own
|
||||||
|
KeyBindingUtils.clearKeyBinding(textField, enterKs);
|
||||||
|
KeyBindingUtils.registerAction(textField, enterKs, enterAction,
|
||||||
|
JComponent.WHEN_FOCUSED);
|
||||||
|
|
||||||
|
// an input verifier that returns true if the path is an existing file or directory
|
||||||
|
InputVerifier inputVerifier = new InputVerifier() {
|
||||||
|
@Override
|
||||||
|
public boolean verify(JComponent input) {
|
||||||
|
String text = textField.getText();
|
||||||
|
File f = new File(text);
|
||||||
|
if (isSpecialDirectory(f)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return f.isFile() || f.isDirectory();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
textField.setInputVerifier(inputVerifier);
|
||||||
|
|
||||||
|
return textField;
|
||||||
|
}
|
||||||
|
|
||||||
private void buildWaitPanel() {
|
private void buildWaitPanel() {
|
||||||
waitPanel = new JPanel(new BorderLayout());
|
waitPanel = new JPanel(new BorderLayout());
|
||||||
waitPanel.setBorder(BorderFactory.createLoweredBevelBorder());
|
waitPanel.setBorder(BorderFactory.createLoweredBevelBorder());
|
||||||
@ -753,7 +849,8 @@ public class GhidraFileChooser extends ReusableDialogComponentProvider implement
|
|||||||
}
|
}
|
||||||
|
|
||||||
private File currentDirectory() {
|
private File currentDirectory() {
|
||||||
String path = currentPathTextField.getText();
|
// The default text should always be valid, regardless of user edits
|
||||||
|
String path = currentPathTextField.getDefaultText();
|
||||||
if (path.length() == 0) {
|
if (path.length() == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -97,6 +97,15 @@ public class GFormattedTextField extends JFormattedTextField {
|
|||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the default text. This is useful to know what the original text is after the user
|
||||||
|
* has edited the text.
|
||||||
|
* @return the default text
|
||||||
|
*/
|
||||||
|
public String getDefaultText() {
|
||||||
|
return defaultText;
|
||||||
|
}
|
||||||
|
|
||||||
public void disableFocusEventProcessing() {
|
public void disableFocusEventProcessing() {
|
||||||
ignoreFocusEditChanges = true;
|
ignoreFocusEditChanges = true;
|
||||||
}
|
}
|
||||||
@ -165,6 +174,30 @@ public class GFormattedTextField extends JFormattedTextField {
|
|||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restores this field to its default text.
|
||||||
|
*/
|
||||||
|
public void reset() {
|
||||||
|
setText(defaultText);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the contents of this field do not match the default.
|
||||||
|
* @return true if the contents of this field do not match the default.
|
||||||
|
*/
|
||||||
|
public boolean isChanged() {
|
||||||
|
return getTextEntryStatus() != Status.UNCHANGED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the contents of this field are invalid, as determined by the InputValidator.
|
||||||
|
* @return true if the contents of this field are invalid, as determined by the InputValidator.
|
||||||
|
*/
|
||||||
|
public boolean isInvalid() {
|
||||||
|
return getTextEntryStatus() == Status.INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
public void editingFinished() {
|
public void editingFinished() {
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
@ -196,7 +229,6 @@ public class GFormattedTextField extends JFormattedTextField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void update() {
|
private void update() {
|
||||||
|
|
||||||
updateStatus();
|
updateStatus();
|
||||||
if (isError) {
|
if (isError) {
|
||||||
setForeground(Colors.FOREGROUND);
|
setForeground(Colors.FOREGROUND);
|
||||||
@ -231,5 +263,4 @@ public class GFormattedTextField extends JFormattedTextField {
|
|||||||
textEntryStatusChanged(currentStatus);
|
textEntryStatusChanged(currentStatus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
@ -50,6 +50,8 @@ import docking.test.AbstractDockingTest;
|
|||||||
import docking.widgets.DropDownSelectionTextField;
|
import docking.widgets.DropDownSelectionTextField;
|
||||||
import docking.widgets.SpyDropDownWindowVisibilityListener;
|
import docking.widgets.SpyDropDownWindowVisibilityListener;
|
||||||
import docking.widgets.table.*;
|
import docking.widgets.table.*;
|
||||||
|
import docking.widgets.textfield.GFormattedTextField;
|
||||||
|
import docking.widgets.textfield.GFormattedTextField.Status;
|
||||||
import generic.concurrent.ConcurrentQ;
|
import generic.concurrent.ConcurrentQ;
|
||||||
import ghidra.framework.OperatingSystem;
|
import ghidra.framework.OperatingSystem;
|
||||||
import ghidra.framework.Platform;
|
import ghidra.framework.Platform;
|
||||||
@ -367,7 +369,7 @@ public class GhidraFileChooserTest extends AbstractDockingTest {
|
|||||||
|
|
||||||
// a string long enough to make the pick unique, in case there are similarly named files
|
// a string long enough to make the pick unique, in case there are similarly named files
|
||||||
String filenameText = prefix.substring(0, 13);
|
String filenameText = prefix.substring(0, 13);
|
||||||
typeTextForTextField(filenameText);
|
typeTextForFilenameTextField(filenameText);
|
||||||
triggerEnter(getFilenameTextField());
|
triggerEnter(getFilenameTextField());
|
||||||
|
|
||||||
// the following code should be put back if we move to the Enter key press simply closing the
|
// the following code should be put back if we move to the Enter key press simply closing the
|
||||||
@ -802,7 +804,7 @@ public class GhidraFileChooserTest extends AbstractDockingTest {
|
|||||||
|
|
||||||
setFilenameFieldText("");// clear any text so that we can trigger the matching window
|
setFilenameFieldText("");// clear any text so that we can trigger the matching window
|
||||||
String desktopText = "test";
|
String desktopText = "test";
|
||||||
typeTextForTextField(desktopText);
|
typeTextForFilenameTextField(desktopText);
|
||||||
|
|
||||||
assertDropDownWindowIsShowing(true);
|
assertDropDownWindowIsShowing(true);
|
||||||
|
|
||||||
@ -1976,6 +1978,70 @@ public class GhidraFileChooserTest extends AbstractDockingTest {
|
|||||||
assertChooserPreference(key, null);
|
assertChooserPreference(key, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEditPath_Directory() throws Exception {
|
||||||
|
|
||||||
|
TestFiles files = createMixedDirectory();
|
||||||
|
File dir = files.randomDir();
|
||||||
|
setPathFieldText(dir.getAbsolutePath());
|
||||||
|
|
||||||
|
triggerEnter(getPathTextField());
|
||||||
|
waitForChooser();
|
||||||
|
|
||||||
|
File currentDir = getCurrentDirectory();
|
||||||
|
assertEquals(dir, currentDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEditPath_File() throws Exception {
|
||||||
|
TestFiles files = createMixedDirectory();
|
||||||
|
File file = files.randomFile();
|
||||||
|
setPathFieldText(file.getAbsolutePath());
|
||||||
|
|
||||||
|
triggerEnter(getPathTextField());
|
||||||
|
waitForChooser();
|
||||||
|
|
||||||
|
File currentDir = getCurrentDirectory();
|
||||||
|
File parent = file.getParentFile();
|
||||||
|
assertEquals(parent, currentDir);
|
||||||
|
|
||||||
|
File selectedFile = getSelectedFile();
|
||||||
|
assertEquals(file, selectedFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEditPath_InvalidPath_Enter() throws Exception {
|
||||||
|
|
||||||
|
File startDir = getCurrentDirectory();
|
||||||
|
|
||||||
|
setPathFieldText("/some/fake/path");
|
||||||
|
triggerEnter(getPathTextField());
|
||||||
|
waitForChooser();
|
||||||
|
|
||||||
|
assertPathFieldIsInvalid();
|
||||||
|
|
||||||
|
// no change
|
||||||
|
File currentDir = getCurrentDirectory();
|
||||||
|
assertEquals(startDir, currentDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEditPath_InvalidPath_Escape() throws Exception {
|
||||||
|
|
||||||
|
File startDir = getCurrentDirectory();
|
||||||
|
|
||||||
|
setPathFieldText("/some/fake/path");
|
||||||
|
assertPathFieldIsInvalid();
|
||||||
|
|
||||||
|
triggerEscape(getPathTextField());
|
||||||
|
waitForChooser();
|
||||||
|
assertPathFieldIsUnchanged();
|
||||||
|
|
||||||
|
// no change
|
||||||
|
File currentDir = getCurrentDirectory();
|
||||||
|
assertEquals(startDir, currentDir);
|
||||||
|
}
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
// Private Methods
|
// Private Methods
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
@ -2348,7 +2414,7 @@ public class GhidraFileChooserTest extends AbstractDockingTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void typeTextForTextField(String text) {
|
private void typeTextForFilenameTextField(String text) {
|
||||||
JTextField textField = getFilenameTextField();
|
JTextField textField = getFilenameTextField();
|
||||||
triggerText(textField, text);
|
triggerText(textField, text);
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
@ -2375,11 +2441,20 @@ public class GhidraFileChooserTest extends AbstractDockingTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setFilenameFieldText(final String text) {
|
private void setFilenameFieldText(String text) {
|
||||||
final JTextField textField = getFilenameTextField();
|
JTextField textField = getFilenameTextField();
|
||||||
|
runSwing(() -> textField.requestFocusInWindow());
|
||||||
|
runSwing(() -> textField.setText(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setPathFieldText(String text) {
|
||||||
|
GFormattedTextField textField = getPathTextField();
|
||||||
runSwing(() -> textField.requestFocusInWindow());
|
runSwing(() -> textField.requestFocusInWindow());
|
||||||
|
|
||||||
runSwing(() -> textField.setText(text));
|
// note: we cannot call textField.setText() here, as that is overridden to make the new
|
||||||
|
// text the default value, which affects our test for textField.isChanged().
|
||||||
|
triggerText(textField, text);
|
||||||
|
waitForSwing();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getFilenameFieldText() {
|
private String getFilenameFieldText() {
|
||||||
@ -2393,6 +2468,10 @@ public class GhidraFileChooserTest extends AbstractDockingTest {
|
|||||||
return textField;
|
return textField;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private GFormattedTextField getPathTextField() {
|
||||||
|
return (GFormattedTextField) findComponentByName(chooser, "Path");
|
||||||
|
}
|
||||||
|
|
||||||
private void show() throws Exception {
|
private void show() throws Exception {
|
||||||
show(true);
|
show(true);
|
||||||
}
|
}
|
||||||
@ -2743,6 +2822,18 @@ public class GhidraFileChooserTest extends AbstractDockingTest {
|
|||||||
fail("File chooser does not in its list have file: " + expected);
|
fail("File chooser does not in its list have file: " + expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void assertPathFieldIsInvalid() {
|
||||||
|
GFormattedTextField textField = getPathTextField();
|
||||||
|
Status status = runSwing(() -> textField.getTextEntryStatus());
|
||||||
|
assertEquals(Status.INVALID, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertPathFieldIsUnchanged() {
|
||||||
|
GFormattedTextField textField = getPathTextField();
|
||||||
|
Status status = runSwing(() -> textField.getTextEntryStatus());
|
||||||
|
assertEquals(Status.UNCHANGED, status);
|
||||||
|
}
|
||||||
|
|
||||||
private void assertChooserHidden() {
|
private void assertChooserHidden() {
|
||||||
assertFalse("The chooser is showing; it should be closed",
|
assertFalse("The chooser is showing; it should be closed",
|
||||||
runSwing(() -> chooser.isShowing()));
|
runSwing(() -> chooser.isShowing()));
|
||||||
|
@ -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.
|
||||||
@ -99,7 +99,7 @@ public class IntegerTextFieldTest extends AbstractDockingTest {
|
|||||||
assertTrue(!field.isHexMode());
|
assertTrue(!field.isHexMode());
|
||||||
triggerText(textField, "x");
|
triggerText(textField, "x");
|
||||||
assertTrue(field.isHexMode());
|
assertTrue(field.isHexMode());
|
||||||
triggerBackspaceKey(textField);
|
triggerBackspace(textField);
|
||||||
assertTrue(!field.isHexMode());
|
assertTrue(!field.isHexMode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +200,7 @@ public class IntegerTextFieldTest extends AbstractDockingTest {
|
|||||||
assertEquals(12, listener.values.get(1));
|
assertEquals(12, listener.values.get(1));
|
||||||
assertEquals(123, listener.values.get(2));
|
assertEquals(123, listener.values.get(2));
|
||||||
|
|
||||||
triggerBackspaceKey(textField);
|
triggerBackspace(textField);
|
||||||
assertEquals(12, listener.values.get(3));
|
assertEquals(12, listener.values.get(3));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user