mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-27 19:45:37 +08:00
GT-2855 - GhidraFileChooser code improvements
This commit is contained in:
+43
-9
@@ -25,6 +25,8 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.ListDataEvent;
|
||||||
|
import javax.swing.event.ListDataListener;
|
||||||
|
|
||||||
import docking.event.mouse.GMouseListenerAdapter;
|
import docking.event.mouse.GMouseListenerAdapter;
|
||||||
import docking.widgets.label.GDLabel;
|
import docking.widgets.label.GDLabel;
|
||||||
@@ -57,6 +59,23 @@ class DirectoryList extends GList<File> implements GhidraFileChooserDirectoryMod
|
|||||||
|
|
||||||
setLayoutOrientation(JList.VERTICAL_WRAP);
|
setLayoutOrientation(JList.VERTICAL_WRAP);
|
||||||
setCellRenderer((cellRenderer = new FileListCellRenderer(getFont(), chooser)));
|
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() {
|
addMouseListener(new MouseAdapter() {
|
||||||
@Override
|
@Override
|
||||||
@@ -160,7 +179,15 @@ class DirectoryList extends GList<File> implements GhidraFileChooserDirectoryMod
|
|||||||
e.consume();
|
e.consume();
|
||||||
}
|
}
|
||||||
else if (e.getKeyCode() == KeyEvent.VK_ENTER) {
|
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();
|
e.consume();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -324,6 +351,13 @@ class DirectoryList extends GList<File> implements GhidraFileChooserDirectoryMod
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String invalidFilenameMessage =
|
||||||
|
chooser.getInvalidFilenameMessage(listEditorField.getText());
|
||||||
|
if (invalidFilenameMessage != null) {
|
||||||
|
chooser.setStatusText("Rename aborted - " + invalidFilenameMessage);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
File editedFileCopy = editedFile;
|
File editedFileCopy = editedFile;
|
||||||
int index = model.indexOfFile(editedFileCopy);
|
int index = model.indexOfFile(editedFileCopy);
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
@@ -332,6 +366,7 @@ class DirectoryList extends GList<File> implements GhidraFileChooserDirectoryMod
|
|||||||
File dest = new File(editedFileCopy.getParentFile(), listEditorField.getText());
|
File dest = new File(editedFileCopy.getParentFile(), listEditorField.getText());
|
||||||
cancelListEdit();
|
cancelListEdit();
|
||||||
if (chooser.getModel().renameFile(editedFileCopy, dest)) {
|
if (chooser.getModel().renameFile(editedFileCopy, dest)) {
|
||||||
|
chooser.setStatusText("");
|
||||||
model.set(index, dest);
|
model.set(index, dest);
|
||||||
//chooser.updateFiles(chooser.getCurrentDirectory(), true);
|
//chooser.updateFiles(chooser.getCurrentDirectory(), true);
|
||||||
chooser.setSelectedFileAndUpdateDisplay(dest);
|
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
|
* @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.
|
* the model's current set of files.
|
||||||
*/
|
*/
|
||||||
void recomputeListCellDimensions(List<File> files) {
|
private void recomputeListCellDimensions(List<File> files) {
|
||||||
files = (files != null) ? files : model.getAllFiles();
|
files = (files != null) ? files : model.getAllFiles();
|
||||||
Dimension cellDims =
|
Dimension d =
|
||||||
cellRenderer.computePlainTextListCellDimensions(this, files, 0, DEFAULT_ICON_SIZE);
|
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
|
// special case: if there were no files to measure, use the containing JScrollPane's
|
||||||
// width
|
// width
|
||||||
if (getParent().getParent() instanceof JScrollPane) {
|
if (getParent().getParent() instanceof JScrollPane) {
|
||||||
JScrollPane parent = (JScrollPane) getParent().getParent();
|
JScrollPane parent = (JScrollPane) getParent().getParent();
|
||||||
Dimension parentSize = parent.getSize();
|
Dimension parentSize = parent.getSize();
|
||||||
Insets insets = parent.getInsets();
|
Insets insets = parent.getInsets();
|
||||||
cellDims.width =
|
d.width = parentSize.width - (insets != null ? insets.right + insets.left : 0);
|
||||||
parentSize.width - (insets != null ? insets.right + insets.left : 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
cellDims.width += DEFAULT_ICON_SIZE + WIDTH_PADDING;
|
d.width += DEFAULT_ICON_SIZE + WIDTH_PADDING;
|
||||||
}
|
}
|
||||||
setFixedCellWidth(cellDims.width);
|
setFixedCellWidth(d.width);
|
||||||
setFixedCellHeight(cellDims.height + HEIGHT_PADDING);
|
setFixedCellHeight(d.height + HEIGHT_PADDING);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*junit*/ JTextField getListEditorText() {
|
/*junit*/ JTextField getListEditorText() {
|
||||||
|
|||||||
@@ -63,6 +63,14 @@ class FileEditor extends AbstractCellEditor implements TableCellEditor {
|
|||||||
directoryTable.editingCanceled(new ChangeEvent(FileEditor.this));
|
directoryTable.editingCanceled(new ChangeEvent(FileEditor.this));
|
||||||
e.consume();
|
e.consume();
|
||||||
}
|
}
|
||||||
|
else if (e.getKeyCode() == KeyEvent.VK_ENTER) {
|
||||||
|
String invalidFilenameMessage =
|
||||||
|
chooser.getInvalidFilenameMessage(nameField.getText());
|
||||||
|
if (invalidFilenameMessage != null) {
|
||||||
|
chooser.setStatusText(invalidFilenameMessage);
|
||||||
|
e.consume();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -72,7 +80,14 @@ class FileEditor extends AbstractCellEditor implements TableCellEditor {
|
|||||||
e.consume();
|
e.consume();
|
||||||
}
|
}
|
||||||
else if (e.getKeyCode() == KeyEvent.VK_ENTER) {
|
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();
|
e.consume();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -145,6 +160,11 @@ class FileEditor extends AbstractCellEditor implements TableCellEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private File getNewFile() {
|
private File getNewFile() {
|
||||||
|
String invalidFilenameMessage = chooser.getInvalidFilenameMessage(nameField.getText());
|
||||||
|
if (invalidFilenameMessage != null) {
|
||||||
|
chooser.setStatusText("Rename aborted - " + invalidFilenameMessage);
|
||||||
|
return originalFile;
|
||||||
|
}
|
||||||
GhidraFileChooserModel fileChooserModel = chooser.getModel();
|
GhidraFileChooserModel fileChooserModel = chooser.getModel();
|
||||||
File newFile = new GhidraFile(originalFile.getParentFile(), nameField.getText(),
|
File newFile = new GhidraFile(originalFile.getParentFile(), nameField.getText(),
|
||||||
fileChooserModel.getSeparator());
|
fileChooserModel.getSeparator());
|
||||||
|
|||||||
+19
-31
@@ -22,22 +22,23 @@ import java.io.FileFilter;
|
|||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.border.Border;
|
import javax.swing.event.CellEditorListener;
|
||||||
import javax.swing.event.*;
|
import javax.swing.event.ChangeEvent;
|
||||||
import javax.swing.filechooser.FileSystemView;
|
import javax.swing.filechooser.FileSystemView;
|
||||||
|
|
||||||
import docking.*;
|
import docking.*;
|
||||||
import docking.framework.DockingApplicationConfiguration;
|
|
||||||
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 ghidra.GhidraApplicationLayout;
|
import ghidra.framework.OperatingSystem;
|
||||||
import ghidra.framework.*;
|
import ghidra.framework.Platform;
|
||||||
import ghidra.framework.preferences.Preferences;
|
import ghidra.framework.preferences.Preferences;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.SystemUtilities;
|
import ghidra.util.SystemUtilities;
|
||||||
@@ -86,6 +87,7 @@ public class GhidraFileChooser extends DialogComponentProvider
|
|||||||
static final String DOT = ".";
|
static final String DOT = ".";
|
||||||
static final String DOTDOT = "..";
|
static final String DOTDOT = "..";
|
||||||
static final String NEW_FOLDER = "New Folder";
|
static final String NEW_FOLDER = "New Folder";
|
||||||
|
static final Pattern INVALID_FILENAME_PATTERN = Pattern.compile("[/\\\\*?]");
|
||||||
|
|
||||||
private static final int PAD = 5;
|
private static final int PAD = 5;
|
||||||
|
|
||||||
@@ -551,24 +553,6 @@ public class GhidraFileChooser extends DialogComponentProvider
|
|||||||
|
|
||||||
private JScrollPane buildDirectoryList() {
|
private JScrollPane buildDirectoryList() {
|
||||||
directoryListModel = new DirectoryListModel();
|
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 = new DirectoryList(this, directoryListModel);
|
||||||
directoryList.setName("LIST");
|
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 the visible listing is still the same directory as this incoming list of files
|
||||||
if (currentDirectory().equals(directory)) {
|
if (currentDirectory().equals(directory)) {
|
||||||
// recompute list cell dims before causing an update to the model
|
// recompute list cell dims before causing an update to the model
|
||||||
directoryList.recomputeListCellDimensions(files);
|
|
||||||
directoryTableModel.setFiles(files);
|
directoryTableModel.setFiles(files);
|
||||||
directoryTable.scrollRectToVisible(new Rectangle(0, 0, 0, 0));
|
directoryTable.scrollRectToVisible(new Rectangle(0, 0, 0, 0));
|
||||||
directoryListModel.setFiles(files);
|
directoryListModel.setFiles(files);
|
||||||
@@ -2130,12 +2113,17 @@ public class GhidraFileChooser extends DialogComponentProvider
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
String getInvalidFilenameMessage(String filename) {
|
||||||
|
switch (filename) {
|
||||||
GhidraApplicationLayout layout = new GhidraApplicationLayout();
|
case ".":
|
||||||
Application.initializeApplication(layout, new DockingApplicationConfiguration());
|
case "..":
|
||||||
GhidraFileChooser chooser = new GhidraFileChooser(null);
|
return "Reserved name '" + filename + "'";
|
||||||
chooser.show();
|
default:
|
||||||
System.exit(0);
|
Matcher m = GhidraFileChooser.INVALID_FILENAME_PATTERN.matcher(filename);
|
||||||
|
if (m.find()) {
|
||||||
|
return "Invalid characters: " + m.group();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user