📄 fileviewer.java
字号:
dir = dir.getParentFile();
}
// Recursively expand the tree to get to the specified directory
TreeItem[] items = tree.getItems();
TreeItem lastItem = null;
for (int i = path.size() - 1; i >= 0; --i) {
final File pathElement = (File) path.elementAt(i);
// Search for a particular File in the array of tree items
// No guarantee that the items are sorted in any recognizable fashion, so we'll
// just sequential scan. There shouldn't be more than a few thousand entries.
TreeItem item = null;
for (int k = 0; k < items.length; ++k) {
item = items[k];
if (item.isDisposed()) continue;
final File itemFile = (File) item.getData(TREEITEMDATA_FILE);
if (itemFile != null && itemFile.equals(pathElement)) break;
}
if (item == null) break;
lastItem = item;
if (i != 0 && !item.getExpanded()) {
treeExpandItem(item);
item.setExpanded(true);
}
items = item.getItems();
}
tree.setSelection((lastItem != null) ? new TreeItem[] { lastItem } : new TreeItem[0]);
}
/**
* Notifies the application components that files have been selected
*
* @param files the files that were selected, null or empty array indicates no active selection
*/
void notifySelectedFiles(File[] files) {
/* Details:
* Update the details that are visible on screen.
*/
if ((files != null) && (files.length != 0)) {
numObjectsLabel.setText(getResourceString("details.NumberOfSelectedFiles.text",
new Object[] { new Integer(files.length) }));
long fileSize = 0L;
for (int i = 0; i < files.length; ++i) {
fileSize += files[i].length();
}
diskSpaceLabel.setText(getResourceString("details.FileSize.text",
new Object[] { new Long(fileSize) }));
} else {
// No files selected
diskSpaceLabel.setText("");
if (currentDirectory != null) {
int numObjects = getDirectoryList(currentDirectory).length;
numObjectsLabel.setText(getResourceString("details.DirNumberOfObjects.text",
new Object[] { new Integer(numObjects) }));
} else {
numObjectsLabel.setText("");
}
}
}
/**
* Notifies the application components that files must be refreshed
*
* @param files the files that need refreshing, empty array is a no-op, null refreshes all
*/
void notifyRefreshFiles(File[] files) {
if (files != null && files.length == 0) return;
if ((deferredRefreshRequested) && (deferredRefreshFiles != null) && (files != null)) {
// merge requests
File[] newRequest = new File[deferredRefreshFiles.length + files.length];
System.arraycopy(deferredRefreshFiles, 0, newRequest, 0, deferredRefreshFiles.length);
System.arraycopy(files, 0, newRequest, deferredRefreshFiles.length, files.length);
deferredRefreshFiles = newRequest;
} else {
deferredRefreshFiles = files;
deferredRefreshRequested = true;
}
handleDeferredRefresh();
}
/**
* Handles deferred Refresh notifications (due to Drag & Drop)
*/
void handleDeferredRefresh() {
if (isDragging || isDropping || ! deferredRefreshRequested) return;
if (progressDialog != null) {
progressDialog.close();
progressDialog = null;
}
deferredRefreshRequested = false;
File[] files = deferredRefreshFiles;
deferredRefreshFiles = null;
shell.setCursor(iconCache.stockCursors[iconCache.cursorWait]);
/* Table view:
* Refreshes information about any files in the list and their children.
*/
boolean refreshTable = false;
if (files != null) {
for (int i = 0; i < files.length; ++i) {
final File file = files[i];
if (file.equals(currentDirectory)) {
refreshTable = true;
break;
}
File parentFile = file.getParentFile();
if ((parentFile != null) && (parentFile.equals(currentDirectory))) {
refreshTable = true;
break;
}
}
} else refreshTable = true;
if (refreshTable) workerUpdate(currentDirectory, true);
/* Combo view:
* Refreshes the list of roots
*/
final File[] roots = getRoots();
if (files == null) {
boolean refreshCombo = false;
final File[] comboRoots = (File[]) combo.getData(COMBODATA_ROOTS);
if ((comboRoots != null) && (comboRoots.length == roots.length)) {
for (int i = 0; i < roots.length; ++i) {
if (! roots[i].equals(comboRoots[i])) {
refreshCombo = true;
break;
}
}
} else refreshCombo = true;
if (refreshCombo) {
combo.removeAll();
combo.setData(COMBODATA_ROOTS, roots);
for (int i = 0; i < roots.length; ++i) {
final File file = roots[i];
combo.add(file.getPath());
}
}
}
/* Tree view:
* Refreshes information about any files in the list and their children.
*/
treeRefresh(roots);
// Remind everyone where we are in the filesystem
final File dir = currentDirectory;
currentDirectory = null;
notifySelectedDirectory(dir);
shell.setCursor(iconCache.stockCursors[iconCache.cursorDefault]);
}
/**
* Performs the default action on a set of files.
*
* @param files the array of files to process
*/
void doDefaultFileAction(File[] files) {
// only uses the 1st file (for now)
if (files.length == 0) return;
final File file = files[0];
if (file.isDirectory()) {
notifySelectedDirectory(file);
} else {
final String fileName = file.getAbsolutePath();
if (! Program.launch(fileName)) {
MessageBox dialog = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK);
dialog.setMessage(getResourceString("error.FailedLaunch.message", new Object[] { fileName }));
dialog.setText(shell.getText ());
dialog.open();
}
}
}
/**
* Navigates to the parent directory
*/
void doParent() {
if (currentDirectory == null) return;
File parentDirectory = currentDirectory.getParentFile();
notifySelectedDirectory(parentDirectory);
}
/**
* Performs a refresh
*/
void doRefresh() {
notifyRefreshFiles(null);
}
/**
* Validates a drop target as a candidate for a drop operation.
* <p>
* Used in dragOver() and dropAccept().<br>
* Note event.detail is set to DND.DROP_NONE by this method if the target is not valid.
* </p>
* @param event the DropTargetEvent to validate
* @param targetFile the File representing the drop target location
* under inspection, or null if none
*/
private boolean dropTargetValidate(DropTargetEvent event, File targetFile) {
if (targetFile != null && targetFile.isDirectory()) {
if (event.detail != DND.DROP_COPY && event.detail != DND.DROP_MOVE) {
event.detail = DND.DROP_MOVE;
}
} else {
event.detail = DND.DROP_NONE;
}
return event.detail != DND.DROP_NONE;
}
/**
* Handles a drop on a dropTarget.
* <p>
* Used in drop().<br>
* Note event.detail is modified by this method.
* </p>
* @param event the DropTargetEvent passed as parameter to the drop() method
* @param targetFile the File representing the drop target location
* under inspection, or null if none
*/
private void dropTargetHandleDrop(DropTargetEvent event, File targetFile) {
// Get dropped data (an array of filenames)
if (! dropTargetValidate(event, targetFile)) return;
final String[] sourceNames = (String[]) event.data;
if (sourceNames == null) event.detail = DND.DROP_NONE;
if (event.detail == DND.DROP_NONE) return;
// Open progress dialog
progressDialog = new ProgressDialog(shell,
(event.detail == DND.DROP_MOVE) ? ProgressDialog.MOVE : ProgressDialog.COPY);
progressDialog.setTotalWorkUnits(sourceNames.length);
progressDialog.open();
// Copy each file
Vector /* of File */ processedFiles = new Vector();
for (int i = 0; (i < sourceNames.length) && (! progressDialog.isCancelled()); i++){
final File source = new File(sourceNames[i]);
final File dest = new File(targetFile, source.getName());
if (source.equals(dest)) continue; // ignore if in same location
progressDialog.setDetailFile(source, ProgressDialog.COPY);
while (! progressDialog.isCancelled()) {
if (copyFileStructure(source, dest)) {
processedFiles.add(source);
break;
} else if (! progressDialog.isCancelled()) {
if (event.detail == DND.DROP_MOVE && (!isDragging)) {
// It is not possible to notify an external drag source that a drop
// operation was only partially successful. This is particularly a
// problem for DROP_MOVE operations since unless the source gets
// DROP_NONE, it will delete the original data including bits that
// may not have been transferred successfully.
MessageBox box = new MessageBox(shell, SWT.ICON_ERROR | SWT.RETRY | SWT.CANCEL);
box.setText(getResourceString("dialog.FailedCopy.title"));
box.setMessage(getResourceString("dialog.FailedCopy.description",
new Object[] { source, dest }));
int button = box.open();
if (button == SWT.CANCEL) {
i = sourceNames.length;
event.detail = DND.DROP_NONE;
break;
}
} else {
// We can recover gracefully from errors if the drag source belongs
// to this application since it will look at processedDropFiles.
MessageBox box = new MessageBox(shell, SWT.ICON_ERROR | SWT.ABORT | SWT.RETRY | SWT.IGNORE);
box.setText(getResourceString("dialog.FailedCopy.title"));
box.setMessage(getResourceString("dialog.FailedCopy.description",
new Object[] { source, dest }));
int button = box.open();
if (button == SWT.ABORT) i = sourceNames.length;
if (button != SWT.RETRY) break;
}
}
progressDialog.addProgress(1);
}
}
if (isDragging) {
// Remember exactly which files we processed
processedDropFiles = ((File[]) processedFiles.toArray(new File[processedFiles.size()]));
} else {
progressDialog.close();
progressDialog = null;
}
notifyRefreshFiles(new File[] { targetFile });
}
/**
* Handles the completion of a drag on a dragSource.
* <p>
* Used in dragFinished().<br>
* </p>
* @param event the DragSourceEvent passed as parameter to the dragFinished() method
* @param sourceNames the names of the files that were dragged (event.data is invalid)
*/
private void dragSourceHandleDragFinished(DragSourceEvent event, String[] sourceNames) {
if (sourceNames == null) return;
if (event.detail != DND.DROP_MOVE) return;
// Get array of files that were actually transferred
final File[] sourceFiles;
if (processedDropFiles != null) {
sourceFiles = processedDropFiles;
} else {
sourceFiles = new File[sourceNames.length];
for (int i = 0; i < sourceNames.length; ++i)
sourceFiles[i] = new File(sourceNames[i]);
}
if (progressDialog == null)
progressDialog = new ProgressDialog(shell, ProgressDialog.MOVE);
progressDialog.setTotalWorkUnits(sourceFiles.length);
progressDialog.setProgress(0);
progressDialog.open();
// Delete each file
for (int i = 0; (i < sourceFiles.length) && (! progressDialog.isCancelled()); i++){
final File source = sourceFiles[i];
progressDialog.setDetailFile(source, ProgressDialog.DELETE);
while (! progressDialog.isCancelled()) {
if (deleteFileStructure(source)) {
break;
} else if (! progressDialog.isCancelled()) {
MessageBox box = new MessageBox(shell, SWT.ICON_ERROR | SWT.ABORT | SWT.RETRY | SWT.IGNORE);
box.setText(getResourceString("dialog.FailedDelete.title"));
box.setMessage(getResourceString("dialog.FailedDelete.description",
new Object[] { source }));
int button = box.open();
if (button == SWT.ABORT) i = sourceNames.length;
if (button == SWT.RETRY) break;
}
}
progressDialog.addProgress(1);
}
notifyRefreshFiles(sourceFiles);
progressDialog.close();
progressDialog = null;
}
/**
* Gets filesystem root entries
*
* @return an array of Files corresponding to the root directories on the platform,
* may be empty but not null
*/
File[] getRoots() {
/*
* On JDK 1.22 only...
*/
// return File.listRoots();
/*
* On JDK 1.1.7 and beyond...
* -- PORTABILITY ISSUES HERE --
*/
if (System.getProperty ("os.name").indexOf ("Windows") != -1) {
Vector /* of File */ list = new Vector();
list.add(new File(DRIVE_A));
list.add(new File(DRIVE_B));
for (char i = 'c'; i <= 'z'; ++i) {
File drive = new File(i + ":" + File.separator);
if (drive.isDirectory() && drive.exists()) {
list.add(drive);
if (initial && i == 'c') {
currentDirectory = drive;
initial = false;
}
}
}
File[] roots = (File[]) list.toArray(new File[list.size()]);
sortFiles(roots);
return roots;
} else {
File root = new File(File.separator);
if (initial) {
currentDirectory = root;
}
return new File[] { root };
}
}
/**
* Gets a directory listing
*
* @param file the directory to be listed
* @return an array of files this directory contains, may be empty but not null
*/
static File[] getDirectoryList(File file) {
File[] list = file.listFiles();
if (list == null) return new File[0];
sortFiles(list);
return list;
}
/**
* Copies a file or entire directory structure.
*
* @param oldFile the location of the old file or directory
* @param newFile the location of the new file or directory
* @return true iff the operation succeeds without errors
*/
boolean copyFileStructure(File oldFile, File newFile) {
if (oldFile == null || newFile == null) return false;
// ensure that newFile is not a child of oldFile or a dupe
File searchFile = newFile;
do {
if (oldFile.equals(searchFile)) return false;
searchFile = searchFile.getParentFile();
} while (searchFile != null);
if (oldFile.isDirectory()) {
/*
* Copy a directory
*/
if (progressDialog != null) {
progressDialog.setDetailFile(oldFile, ProgressDialog.COPY);
}
if (simulateOnly) {
//System.out.println(getResourceString("simulate.DirectoriesCreated.text",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -