GT-2855 - GhidraFileChooser code improvements

This commit is contained in:
dev747368 2019-05-08 17:40:57 -04:00
parent 131228a250
commit 463b74b60d
3 changed files with 83 additions and 41 deletions

View File

@ -25,6 +25,8 @@ import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import docking.event.mouse.GMouseListenerAdapter;
import docking.widgets.label.GDLabel;
@ -57,6 +59,23 @@ class DirectoryList extends GList<File> implements GhidraFileChooserDirectoryMod
setLayoutOrientation(JList.VERTICAL_WRAP);
setCellRenderer((cellRenderer = new FileListCellRenderer(getFont(), chooser)));
model.addListDataListener(new ListDataListener() {
@Override
public void contentsChanged(ListDataEvent e) {
// called when the list changes because a new file is inserted (ie. create new folder action)
recomputeListCellDimensions(null);
}
@Override
public void intervalAdded(ListDataEvent e) {
recomputeListCellDimensions(null);
}
@Override
public void intervalRemoved(ListDataEvent e) {
// don't care
}
});
addMouseListener(new MouseAdapter() {
@Override
@ -160,7 +179,15 @@ class DirectoryList extends GList<File> implements GhidraFileChooserDirectoryMod
e.consume();
}
else if (e.getKeyCode() == KeyEvent.VK_ENTER) {
stopListEdit();
String invalidFilenameMessage =
chooser.getInvalidFilenameMessage(listEditorField.getText());
if (invalidFilenameMessage != null) {
chooser.setStatusText(invalidFilenameMessage);
// keep the user in the field
}
else {
stopListEdit();
}
e.consume();
}
}
@ -324,6 +351,13 @@ class DirectoryList extends GList<File> implements GhidraFileChooserDirectoryMod
return;
}
String invalidFilenameMessage =
chooser.getInvalidFilenameMessage(listEditorField.getText());
if (invalidFilenameMessage != null) {
chooser.setStatusText("Rename aborted - " + invalidFilenameMessage);
return;
}
File editedFileCopy = editedFile;
int index = model.indexOfFile(editedFileCopy);
if (index < 0) {
@ -332,6 +366,7 @@ class DirectoryList extends GList<File> implements GhidraFileChooserDirectoryMod
File dest = new File(editedFileCopy.getParentFile(), listEditorField.getText());
cancelListEdit();
if (chooser.getModel().renameFile(editedFileCopy, dest)) {
chooser.setStatusText("");
model.set(index, dest);
//chooser.updateFiles(chooser.getCurrentDirectory(), true);
chooser.setSelectedFileAndUpdateDisplay(dest);
@ -350,26 +385,25 @@ class DirectoryList extends GList<File> implements GhidraFileChooserDirectoryMod
* @param files list of files to use to resize the list's fixed cell dimensions. If null, uses
* the model's current set of files.
*/
void recomputeListCellDimensions(List<File> files) {
private void recomputeListCellDimensions(List<File> files) {
files = (files != null) ? files : model.getAllFiles();
Dimension cellDims =
Dimension d =
cellRenderer.computePlainTextListCellDimensions(this, files, 0, DEFAULT_ICON_SIZE);
if (cellDims.width == 0 && getParent() != null) {
if (d.width == 0 && getParent() != null) {
// special case: if there were no files to measure, use the containing JScrollPane's
// width
if (getParent().getParent() instanceof JScrollPane) {
JScrollPane parent = (JScrollPane) getParent().getParent();
Dimension parentSize = parent.getSize();
Insets insets = parent.getInsets();
cellDims.width =
parentSize.width - (insets != null ? insets.right + insets.left : 0);
d.width = parentSize.width - (insets != null ? insets.right + insets.left : 0);
}
}
else {
cellDims.width += DEFAULT_ICON_SIZE + WIDTH_PADDING;
d.width += DEFAULT_ICON_SIZE + WIDTH_PADDING;
}
setFixedCellWidth(cellDims.width);
setFixedCellHeight(cellDims.height + HEIGHT_PADDING);
setFixedCellWidth(d.width);
setFixedCellHeight(d.height + HEIGHT_PADDING);
}
/*junit*/ JTextField getListEditorText() {

View File

@ -63,6 +63,14 @@ class FileEditor extends AbstractCellEditor implements TableCellEditor {
directoryTable.editingCanceled(new ChangeEvent(FileEditor.this));
e.consume();
}
else if (e.getKeyCode() == KeyEvent.VK_ENTER) {
String invalidFilenameMessage =
chooser.getInvalidFilenameMessage(nameField.getText());
if (invalidFilenameMessage != null) {
chooser.setStatusText(invalidFilenameMessage);
e.consume();
}
}
}
@Override
@ -72,7 +80,14 @@ class FileEditor extends AbstractCellEditor implements TableCellEditor {
e.consume();
}
else if (e.getKeyCode() == KeyEvent.VK_ENTER) {
directoryTable.editingStopped(new ChangeEvent(FileEditor.this));
String invalidFilenameMessage =
chooser.getInvalidFilenameMessage(nameField.getText());
if (invalidFilenameMessage != null) {
chooser.setStatusText(invalidFilenameMessage);
}
else {
directoryTable.editingStopped(new ChangeEvent(FileEditor.this));
}
e.consume();
}
}
@ -145,6 +160,11 @@ class FileEditor extends AbstractCellEditor implements TableCellEditor {
}
private File getNewFile() {
String invalidFilenameMessage = chooser.getInvalidFilenameMessage(nameField.getText());
if (invalidFilenameMessage != null) {
chooser.setStatusText("Rename aborted - " + invalidFilenameMessage);
return originalFile;
}
GhidraFileChooserModel fileChooserModel = chooser.getModel();
File newFile = new GhidraFile(originalFile.getParentFile(), nameField.getText(),
fileChooserModel.getSeparator());

View File

@ -22,22 +22,23 @@ import java.io.FileFilter;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.event.*;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.filechooser.FileSystemView;
import docking.*;
import docking.framework.DockingApplicationConfiguration;
import docking.widgets.*;
import docking.widgets.combobox.GComboBox;
import docking.widgets.label.GDLabel;
import docking.widgets.label.GLabel;
import docking.widgets.list.GListCellRenderer;
import ghidra.GhidraApplicationLayout;
import ghidra.framework.*;
import ghidra.framework.OperatingSystem;
import ghidra.framework.Platform;
import ghidra.framework.preferences.Preferences;
import ghidra.util.Msg;
import ghidra.util.SystemUtilities;
@ -86,6 +87,7 @@ public class GhidraFileChooser extends DialogComponentProvider
static final String DOT = ".";
static final String DOTDOT = "..";
static final String NEW_FOLDER = "New Folder";
static final Pattern INVALID_FILENAME_PATTERN = Pattern.compile("[/\\\\*?]");
private static final int PAD = 5;
@ -551,24 +553,6 @@ public class GhidraFileChooser extends DialogComponentProvider
private JScrollPane buildDirectoryList() {
directoryListModel = new DirectoryListModel();
directoryListModel.addListDataListener(new ListDataListener() {
@Override
public void contentsChanged(ListDataEvent e) {
// called when the list changes because a new file is inserted (ie. create new folder action)
directoryList.recomputeListCellDimensions(null);
}
@Override
public void intervalAdded(ListDataEvent e) {
// don't care
}
@Override
public void intervalRemoved(ListDataEvent e) {
// don't care
}
});
directoryList = new DirectoryList(this, directoryListModel);
directoryList.setName("LIST");
@ -863,7 +847,6 @@ public class GhidraFileChooser extends DialogComponentProvider
// if the visible listing is still the same directory as this incoming list of files
if (currentDirectory().equals(directory)) {
// recompute list cell dims before causing an update to the model
directoryList.recomputeListCellDimensions(files);
directoryTableModel.setFiles(files);
directoryTable.scrollRectToVisible(new Rectangle(0, 0, 0, 0));
directoryListModel.setFiles(files);
@ -2130,12 +2113,17 @@ public class GhidraFileChooser extends DialogComponentProvider
}
}
public static void main(String[] args) throws Exception {
GhidraApplicationLayout layout = new GhidraApplicationLayout();
Application.initializeApplication(layout, new DockingApplicationConfiguration());
GhidraFileChooser chooser = new GhidraFileChooser(null);
chooser.show();
System.exit(0);
String getInvalidFilenameMessage(String filename) {
switch (filename) {
case ".":
case "..":
return "Reserved name '" + filename + "'";
default:
Matcher m = GhidraFileChooser.INVALID_FILENAME_PATTERN.matcher(filename);
if (m.find()) {
return "Invalid characters: " + m.group();
}
}
return null;
}
}