diff options
author | Jeff Brown | 2001-06-18 23:30:38 +0000 |
---|---|---|
committer | Jeff Brown | 2001-06-18 23:30:38 +0000 |
commit | dc08cffb34cc4f10b1abd857e315c995abbb6fb1 (patch) | |
tree | d16955b04934753f36005ac8a1bbbd75ac59836c | |
parent | 53592b49b6487570611376efec7d6b9d59b5424b (diff) | |
download | eclipse.platform.swt-dc08cffb34cc4f10b1abd857e315c995abbb6fb1.tar.gz eclipse.platform.swt-dc08cffb34cc4f10b1abd857e315c995abbb6fb1.tar.xz eclipse.platform.swt-dc08cffb34cc4f10b1abd857e315c995abbb6fb1.zip |
*** empty log message ***
6 files changed, 40 insertions, 74 deletions
diff --git a/examples/org.eclipse.swt.examples/org/eclipse/swt/examples/fileviewer/FileViewer.java b/examples/org.eclipse.swt.examples/org/eclipse/swt/examples/fileviewer/FileViewer.java index c202ed7074..90eea668d1 100755 --- a/examples/org.eclipse.swt.examples/org/eclipse/swt/examples/fileviewer/FileViewer.java +++ b/examples/org.eclipse.swt.examples/org/eclipse/swt/examples/fileviewer/FileViewer.java @@ -390,38 +390,22 @@ public class FileViewer { }
/**
- * Validate a drop target event
+ * Validates a drop target as a candidate for a drop operation.
* <p>
- * Note event.detail is modified by this method
+ * Note event.detail is set to DND.DROP_NONE by this method if the target is not valid.
* </p>
* @param event the DropTargetEvent we are validating
* @param targetFile the File representing the drop target location
* under inspection, or null if none
- * @return an array of files to be operated on, or null on error
*/
- /* package */ File[] validateDrop(DropTargetEvent event, File targetFile) {
- final int dropMode = (event.detail != DND.DROP_NONE) ? event.detail : DND.DROP_MOVE;
- event.detail = DND.DROP_NONE; // simplify error reporting
-
// Validate the target
- if (targetFile == null) return null;
- if (! targetFile.isDirectory()) return null;
-
- // Get dropped data (an array of filenames)
- final String[] names = (String[]) event.data;
- final File[] files;
- if (names != null) {
- // Validate the source
- files = new File[names.length];
- for (int i = 0; i < names.length; ++i) {
- files[i] = new File(names[i]);
- if (files[i].equals(targetFile)) return null;
+ /* package */ void validateDropTarget(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 {
- // Files not available yet
- files = null;
+ event.detail = DND.DROP_NONE;
}
- event.detail = dropMode;
- return files;
}
/**
@@ -434,23 +418,22 @@ public class FileViewer { * under inspection, or null if none
*/
/* package */ void performDrop(DropTargetEvent event, File targetFile) {
- Vector /* of File */ dirtyFiles = new Vector();
- try {
- final File[] sourceFiles = validateDrop(event, targetFile);
- final int dropMode = event.detail;
+ validateDropTarget(event, targetFile);
- if (sourceFiles == null) {
- event.detail = DND.DROP_NONE;
- return;
- }
-
+ // Get dropped data (an array of filenames)
+ final String[] sourceNames = (String[]) event.data;
+ if (sourceNames == null) event.detail = DND.DROP_NONE;
+ if (event.detail == DND.DROP_NONE) return;
+
+ Vector /* of File */ dirtyFiles = new Vector();
+ try {
dirtyFiles.add(targetFile);
- for (int i = 0; i < sourceFiles.length; i++){
- final File source = sourceFiles[i];
+ for (int i = 0; i < sourceNames.length; i++){
+ final File source = new File(sourceNames[i]);
final File dest = new File(targetFile, source.getName());
// Perform action on each file
- switch (dropMode) {
+ switch (event.detail) {
default:
case DND.DROP_COPY:
if (! copyFileStructure(source, dest)) return;
diff --git a/examples/org.eclipse.swt.examples/org/eclipse/swt/examples/fileviewer/TableView.java b/examples/org.eclipse.swt.examples/org/eclipse/swt/examples/fileviewer/TableView.java index a1ed483d37..b0a8e1e4ed 100755 --- a/examples/org.eclipse.swt.examples/org/eclipse/swt/examples/fileviewer/TableView.java +++ b/examples/org.eclipse.swt.examples/org/eclipse/swt/examples/fileviewer/TableView.java @@ -1 +1 @@ -package org.eclipse.swt.examples.fileviewer;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved
*/
import org.eclipse.swt.*;
import org.eclipse.swt.dnd.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.program.*;
import org.eclipse.swt.widgets.*;
import java.io.*;
import java.text.*;
import java.util.*;
/**
* A detailed directory listing
*/
public class TableView {
private static final String TABLEITEMDATA_FILE = "TableItem.file";
// File: File associated with table row
private final Table table;
private final Label contentsOfLabel;
private final Shell shell;
private final Display display;
private final FileViewer viewer;
private File activeDir = null;
/* Worker thread control */
private UpdateWorker tableUpdateWorker = null;
final String[] titles = new String [] {
FileViewer.getResourceString("table.Name.title"),
FileViewer.getResourceString("table.Size.title"),
FileViewer.getResourceString("table.Type.title"),
FileViewer.getResourceString("table.Modified.title")
};
final int[] widths = new int[] {150, 60, 75, 150};
/**
* Creates the file details table.
*
* @param theViewer the viewer to attach to
* @param parent the parent control
* @param layoutData the layout data
*/
public TableView(FileViewer theViewer, Composite parent, Object layoutData) {
this.viewer = theViewer;
shell = parent.getShell();
display = shell.getDisplay();
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayoutData(layoutData);
GridLayout gridLayout = new GridLayout();
gridLayout.numColumns = 1;
gridLayout.marginHeight = gridLayout.marginWidth = 2;
gridLayout.horizontalSpacing = gridLayout.verticalSpacing = 0;
composite.setLayout(gridLayout);
contentsOfLabel = new Label(composite, SWT.BORDER);
contentsOfLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL));
table = new Table(composite, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI);
table.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL));
for (int i = 0; i < titles.length; i++) {
TableColumn column = new TableColumn(table, SWT.NONE);
column.setText(titles [i]);
column.setWidth(widths [i]);
}
table.setHeaderVisible(true);
table.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
viewer.notifySelectedFiles(getSelectedFiles());
}
public void widgetDefaultSelected(SelectionEvent event) {
viewer.doDefaultFileAction(getSelectedFiles());
}
private File[] getSelectedFiles() {
final TableItem[] items = table.getSelection();
final File[] files = new File[items.length];
for (int i = 0; i < items.length; ++i) {
files[i] = (File) items[i].getData(TABLEITEMDATA_FILE);
}
return files;
}
});
createTableDragSource(table);
createTableDropTarget(table);
tableUpdateWorker = new TableUpdateWorker();
}
/**
* Dispose of allocated resources and shut down.
*/
public void dispose() {
tableUpdateWorker.syncStop();
}
/**
* Updates the table with file information in the background.
* <p>
* It is designed such that it can be interrupted cleanly. Rather than put all the code
* to manage this here, the balance has been pushed out to UpdateWorker so it can be re-used.
* </p>
*/
private class TableUpdateWorker extends UpdateWorker {
private File currentDir = null;
private File[] currentFiles = null;
private File[] currentDirList = null;
public TableUpdateWorker() {
super(TableView.this.display);
}
/**
* Updates the table's contents
*
* @param data arguments in an Object[]
* <ul>
* <li>File data[0] dir the current directory, null does nothing
* <li>File[] data[1] the list of files to select, null does nothing
* <li>Boolean data[2] if true, forces a refresh
* </ul>
*/
protected void execute(Object data) {
// Get arguments
final Object[] args = (Object[]) data;
final File argDir = (File) args[0];
final File[] argFiles = (File[]) args[1];
final boolean argForce = ((Boolean) args[2]).booleanValue();
// Update current state
if (argDir != null) currentDir = argDir;
if (argFiles != null) currentFiles = argFiles;
else if (argDir != null) currentFiles = new File[0];
// Perform necessary refreshing
if (argDir != null) updateDirectoryListing();
else if (argFiles != null) updateFileSelection();
if (isCancelled()) {
currentFiles = null;
currentDir = null;
currentDirList = null;
}
}
/*
* Note the use of asyncExec() in some places to ensure that SWT Widgets are manipulated in the
* right thread. Exclusive use of syncExec() would be inappropriate as it would require a pair
* of context switches between each table update operation.
*/
/**
* Updates directory list
*/
private void updateDirectoryListing() {
// Clear existing information
TableView.this.display.syncExec(new Runnable() {
public void run() {
viewer.clearDetails();
contentsOfLabel.setText(FileViewer.getResourceString("details.ContentsOf.text",
new Object[] { currentDir.getPath() }));
table.removeAll();
table.setRedraw(false);
TableView.this.activeDir = currentDir; // synchronize this
}
});
currentDirList = FileViewer.getDirectoryList(currentDir);
updateDetails();
for (int i = 0; (! isCancelled()) && (i < currentDirList.length); i++) {
final File theFile = currentDirList[i];
addFileDetails(currentDirList[i]);
final boolean doIncrementalRefresh = ((i & 127) == 127);
if (doIncrementalRefresh) TableView.this.display.syncExec(new Runnable() {
public void run () {
table.setRedraw(true);
table.setRedraw(false);
}
});
}
// Allow the table to refresh itself
TableView.this.display.asyncExec(new Runnable() {
public void run() {
table.setRedraw(true);
}
});
}
/**
* Adds a file's detail information to the directory list
*/
private void addFileDetails(final File file) {
final FileDisplayInfo displayInfo = viewer.getFileDisplayInfo(file);
final String[] strings = new String[] {
displayInfo.nameString,
displayInfo.sizeString,
displayInfo.typeString,
displayInfo.dateString };
final Image image = displayInfo.iconImage;
TableView.this.display.asyncExec(new Runnable() {
public void run () {
TableItem tableItem = new TableItem(table, 0);
tableItem.setText(strings);
tableItem.setImage(image);
tableItem.setData(TABLEITEMDATA_FILE, file);
}
});
}
/**
* Updates the current file selection
*/
private void updateFileSelection() {
updateDetails();
}
/**
* Updates the detail information
*/
private void updateDetails() {
if (currentFiles.length == 0) {
if (currentDir == null) return;
final File folder = currentDir;
final File[] files = currentDirList;
// show directory information
TableView.this.display.asyncExec(new Runnable() {
public void run() {
viewer.setFolderDetails(folder, files);
}
});
} else if (currentFiles.length == 1) {
final File file = currentFiles[0];
// show individual file information
TableView.this.display.asyncExec(new Runnable() {
public void run() {
viewer.setFileDetails(file);
}
});
} else {
// show multi-selection file information
final File[] files = currentFiles;
TableView.this.display.asyncExec(new Runnable() {
public void run() {
viewer.setSelectionDetails(files);
}
});
}
}
}
/**
* Creates the Drag & Drop DropTarget for items being dropped onto the table.
*
* @return the DropTarget for the table
*/
private DropTarget createTableDropTarget(final Table table){
DropTarget dropTarget = new DropTarget(table, DND.DROP_MOVE | DND.DROP_COPY);
dropTarget.setTransfer(new Transfer[] { FileTransfer.getInstance() });
dropTarget.addDropListener(new DropTargetAdapter() {
public void dragOver(DropTargetEvent event) {
viewer.validateDrop(event, getTargetFile(event));
}
public void drop(DropTargetEvent event) {
viewer.performDrop(event, getTargetFile(event));
}
private File getTargetFile(DropTargetEvent event) {
// Determine the target File for the drop
final TableItem item = table.getItem(table.toControl(new Point(event.x, event.y)));
final File targetFile;
if (item == null) {
// We dropped on an unoccupied area of the table, use the table's root file
targetFile = activeDir;
} else {
// We dropped on a particular item in the table, use the item's file
targetFile = (File) item.getData(TABLEITEMDATA_FILE);
}
return targetFile;
}
});
return dropTarget;
}
/**
* Creates the Drag & Drop DragSource for items being dragged from the table.
*
* @return the DragSource for the table
*/
private DragSource createTableDragSource(final Table table) {
DragSource dragSource = new DragSource(table, DND.DROP_MOVE | DND.DROP_COPY);
dragSource.setTransfer(new Transfer[] { FileTransfer.getInstance() });
dragSource.addDragListener(new DragSourceListener() {
public void dragStart(DragSourceEvent e) {
e.doit = table.getSelectionCount() > 0;
}
public void dragSetData(DragSourceEvent event){
if (! FileTransfer.getInstance().isSupportedType(event.dataType)) return;
final TableItem[] tableDragItems = table.getSelection();
if (tableDragItems == null || tableDragItems.length == 0) return;
final String[] data = new String[tableDragItems.length];
for (int i = 0; i < tableDragItems.length; i++) {
File file = (File) tableDragItems[i].getData(TABLEITEMDATA_FILE);
data[i] = file.getAbsolutePath();
}
event.data = data;
}
public void dragFinished(DragSourceEvent event) {
}
});
return dragSource;
}
/**
* Listens to selectedDirectory events.
* <p>
* Displays the contents in the selected directory.
* </p>
*
* @param dir the directory that was selected, null is not permitted
*/
/* package */ void selectedDirectory(File dir) {
tableUpdateWorker.asyncUpdate(new Object[] { dir, null, new Boolean(false) });
}
/**
* Listens to selectedFiles events.
* <p>
* Updates the details to match the specified selection.
* </p>
*
* @param files the array of selected files, null is not permitted
*/
/* package */ void selectedFiles(File[] files) {
tableUpdateWorker.asyncUpdate(new Object[] { null, files, new Boolean(false) });
}
/**
* Listens to refreshFiles events.
* <p>
* Refreshes information about any files in the list and their children.
* </p>
*
* @param files the list of files to be refreshed, null refreshes everything
*/
/* package */ void refreshFiles(File[] files) {
tableUpdateWorker.asyncUpdate(new Object[] { null, null, new Boolean(true) });
}
}
\ No newline at end of file +package org.eclipse.swt.examples.fileviewer;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved
*/
import org.eclipse.swt.*;
import org.eclipse.swt.dnd.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.program.*;
import org.eclipse.swt.widgets.*;
import java.io.*;
import java.text.*;
import java.util.*;
/**
* A detailed directory listing
*/
public class TableView {
private static final String TABLEITEMDATA_FILE = "TableItem.file";
// File: File associated with table row
private final Table table;
private final Label contentsOfLabel;
private final Shell shell;
private final Display display;
private final FileViewer viewer;
private File activeDir = null;
private boolean inDrag = false;
/* Worker thread control */
private UpdateWorker tableUpdateWorker = null;
final String[] titles = new String [] {
FileViewer.getResourceString("table.Name.title"),
FileViewer.getResourceString("table.Size.title"),
FileViewer.getResourceString("table.Type.title"),
FileViewer.getResourceString("table.Modified.title")
};
final int[] widths = new int[] {150, 60, 75, 150};
/**
* Creates the file details table.
*
* @param theViewer the viewer to attach to
* @param parent the parent control
* @param layoutData the layout data
*/
public TableView(FileViewer theViewer, Composite parent, Object layoutData) {
this.viewer = theViewer;
shell = parent.getShell();
display = shell.getDisplay();
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayoutData(layoutData);
GridLayout gridLayout = new GridLayout();
gridLayout.numColumns = 1;
gridLayout.marginHeight = gridLayout.marginWidth = 2;
gridLayout.horizontalSpacing = gridLayout.verticalSpacing = 0;
composite.setLayout(gridLayout);
contentsOfLabel = new Label(composite, SWT.BORDER);
contentsOfLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL));
table = new Table(composite, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI);
table.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL));
for (int i = 0; i < titles.length; i++) {
TableColumn column = new TableColumn(table, SWT.NONE);
column.setText(titles [i]);
column.setWidth(widths [i]);
}
table.setHeaderVisible(true);
table.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
if (inDrag) return;
viewer.notifySelectedFiles(getSelectedFiles());
}
public void widgetDefaultSelected(SelectionEvent event) {
if (inDrag) return;
viewer.doDefaultFileAction(getSelectedFiles());
}
private File[] getSelectedFiles() {
final TableItem[] items = table.getSelection();
final File[] files = new File[items.length];
for (int i = 0; i < items.length; ++i) {
files[i] = (File) items[i].getData(TABLEITEMDATA_FILE);
}
return files;
}
});
createTableDragSource(table);
createTableDropTarget(table);
tableUpdateWorker = new TableUpdateWorker();
}
/**
* Dispose of allocated resources and shut down.
*/
public void dispose() {
tableUpdateWorker.syncStop();
}
/**
* Updates the table with file information in the background.
* <p>
* It is designed such that it can be interrupted cleanly. Rather than put all the code
* to manage this here, the balance has been pushed out to UpdateWorker so it can be re-used.
* </p>
*/
private class TableUpdateWorker extends UpdateWorker {
private File currentDir = null;
private File[] currentFiles = null;
private File[] currentDirList = null;
public TableUpdateWorker() {
super(TableView.this.display);
}
/**
* Updates the table's contents
*
* @param data arguments in an Object[]
* <ul>
* <li>File data[0] dir the current directory, null does nothing
* <li>File[] data[1] the list of files to select, null does nothing
* <li>Boolean data[2] if true, forces a refresh
* </ul>
*/
protected void execute(Object data) {
// Get arguments
final Object[] args = (Object[]) data;
final File argDir = (File) args[0];
final File[] argFiles = (File[]) args[1];
final boolean argForce = ((Boolean) args[2]).booleanValue();
// Update current state
if (argDir != null) currentDir = argDir;
if (argFiles != null) currentFiles = argFiles;
else if (argDir != null) currentFiles = new File[0];
// Perform necessary refreshing
if (argDir != null) updateDirectoryListing();
else if (argFiles != null) updateFileSelection();
if (isCancelled()) {
currentFiles = null;
currentDir = null;
currentDirList = null;
}
}
/*
* Note the use of asyncExec() in some places to ensure that SWT Widgets are manipulated in the
* right thread. Exclusive use of syncExec() would be inappropriate as it would require a pair
* of context switches between each table update operation.
*/
/**
* Updates directory list
*/
private void updateDirectoryListing() {
// Clear existing information
TableView.this.display.syncExec(new Runnable() {
public void run() {
viewer.clearDetails();
contentsOfLabel.setText(FileViewer.getResourceString("details.ContentsOf.text",
new Object[] { currentDir.getPath() }));
table.removeAll();
table.setRedraw(false);
TableView.this.activeDir = currentDir; // synchronize this
}
});
currentDirList = FileViewer.getDirectoryList(currentDir);
updateDetails();
for (int i = 0; (! isCancelled()) && (i < currentDirList.length); i++) {
final File theFile = currentDirList[i];
addFileDetails(currentDirList[i]);
final boolean doIncrementalRefresh = ((i & 127) == 127);
if (doIncrementalRefresh) TableView.this.display.syncExec(new Runnable() {
public void run () {
table.setRedraw(true);
table.setRedraw(false);
}
});
}
// Allow the table to refresh itself
TableView.this.display.asyncExec(new Runnable() {
public void run() {
table.setRedraw(true);
}
});
}
/**
* Adds a file's detail information to the directory list
*/
private void addFileDetails(final File file) {
final FileDisplayInfo displayInfo = viewer.getFileDisplayInfo(file);
final String[] strings = new String[] {
displayInfo.nameString,
displayInfo.sizeString,
displayInfo.typeString,
displayInfo.dateString };
final Image image = displayInfo.iconImage;
TableView.this.display.asyncExec(new Runnable() {
public void run () {
TableItem tableItem = new TableItem(table, 0);
tableItem.setText(strings);
tableItem.setImage(image);
tableItem.setData(TABLEITEMDATA_FILE, file);
}
});
}
/**
* Updates the current file selection
*/
private void updateFileSelection() {
updateDetails();
}
/**
* Updates the detail information
*/
private void updateDetails() {
if (currentFiles.length == 0) {
if (currentDir == null) return;
final File folder = currentDir;
final File[] files = currentDirList;
// show directory information
TableView.this.display.asyncExec(new Runnable() {
public void run() {
viewer.setFolderDetails(folder, files);
}
});
} else if (currentFiles.length == 1) {
final File file = currentFiles[0];
// show individual file information
TableView.this.display.asyncExec(new Runnable() {
public void run() {
viewer.setFileDetails(file);
}
});
} else {
// show multi-selection file information
final File[] files = currentFiles;
TableView.this.display.asyncExec(new Runnable() {
public void run() {
viewer.setSelectionDetails(files);
}
});
}
}
}
/**
* Creates the Drag & Drop DragSource for items being dragged from the table.
*
* @return the DragSource for the table
*/
private DragSource createTableDragSource(final Table table) {
DragSource dragSource = new DragSource(table, DND.DROP_MOVE | DND.DROP_COPY);
dragSource.setTransfer(new Transfer[] { FileTransfer.getInstance() });
dragSource.addDragListener(new DragSourceListener() {
TableItem[] dndSelection = null;
public void dragStart(DragSourceEvent event){
dndSelection = table.getSelection();
event.doit = dndSelection.length > 0;
}
public void dragFinished(DragSourceEvent event){
dndSelection = null;
}
public void dragSetData(DragSourceEvent event){
if (dndSelection == null || dndSelection.length == 0) return;
if (! FileTransfer.getInstance().isSupportedType(event.dataType)) return;
final String[] data = new String[dndSelection.length];
for (int i = 0; i < dndSelection.length; i++) {
File file = (File) dndSelection[i].getData(TABLEITEMDATA_FILE);
data[i] = file.getAbsolutePath();
}
event.data = data;
}
});
return dragSource;
}
/**
* Creates the Drag & Drop DropTarget for items being dropped onto the table.
*
* @return the DropTarget for the table
*/
private DropTarget createTableDropTarget(final Table table){
DropTarget dropTarget = new DropTarget(table, DND.DROP_MOVE | DND.DROP_COPY);
dropTarget.setTransfer(new Transfer[] { FileTransfer.getInstance() });
dropTarget.addDropListener(new DropTargetAdapter() {
public void dragEnter(DropTargetEvent event) {
inDrag = true;
}
public void dragLeave(DropTargetEvent event) {
inDrag = false;
}
public void dragOver(DropTargetEvent event) {
viewer.validateDropTarget(event, getTargetFile(event));
}
public void dropAccept(DropTargetEvent event) {
viewer.validateDropTarget(event, getTargetFile(event));
}
public void drop(DropTargetEvent event) {
viewer.performDrop(event, getTargetFile(event));
}
private File getTargetFile(DropTargetEvent event) {
// Determine the target File for the drop
final TableItem item = table.getItem(table.toControl(new Point(event.x, event.y)));
final File targetFile;
if (item == null) {
// We dropped on an unoccupied area of the table, use the table's root file
targetFile = activeDir;
} else {
// We dropped on a particular item in the table, use the item's file
targetFile = (File) item.getData(TABLEITEMDATA_FILE);
}
return targetFile;
}
});
return dropTarget;
}
/**
* Listens to selectedDirectory events.
* <p>
* Displays the contents in the selected directory.
* </p>
*
* @param dir the directory that was selected, null is not permitted
*/
/* package */ void selectedDirectory(File dir) {
tableUpdateWorker.asyncUpdate(new Object[] { dir, null, new Boolean(false) });
}
/**
* Listens to selectedFiles events.
* <p>
* Updates the details to match the specified selection.
* </p>
*
* @param files the array of selected files, null is not permitted
*/
/* package */ void selectedFiles(File[] files) {
tableUpdateWorker.asyncUpdate(new Object[] { null, files, new Boolean(false) });
}
/**
* Listens to refreshFiles events.
* <p>
* Refreshes information about any files in the list and their children.
* </p>
*
* @param files the list of files to be refreshed, null refreshes everything
*/
/* package */ void refreshFiles(File[] files) {
tableUpdateWorker.asyncUpdate(new Object[] { null, null, new Boolean(true) });
}
}
\ No newline at end of file diff --git a/examples/org.eclipse.swt.examples/org/eclipse/swt/examples/fileviewer/TreeView.java b/examples/org.eclipse.swt.examples/org/eclipse/swt/examples/fileviewer/TreeView.java index ee7a09ae91..2324a156bf 100755 --- a/examples/org.eclipse.swt.examples/org/eclipse/swt/examples/fileviewer/TreeView.java +++ b/examples/org.eclipse.swt.examples/org/eclipse/swt/examples/fileviewer/TreeView.java @@ -1 +1 @@ -package org.eclipse.swt.examples.fileviewer;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved
*/
import org.eclipse.swt.*;
import org.eclipse.swt.dnd.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
import java.io.*;
import java.util.*;
/**
* A directory tree
*/
class TreeView {
private static final String
TREEITEMDATA_FILE = "TreeItem.file",
// File: File associated with tree item
TREEITEMDATA_IMAGEEXPANDED = "TreeItem.imageExpanded",
// Image: shown when item is expanded
TREEITEMDATA_IMAGECOLLAPSED = "TreeItem.imageCollapsed",
// Image: shown when item is collapsed
TREEITEMDATA_STUB = "TreeItem.stub";
// Object: if not present or null then the item has not been populated
private final Tree tree;
private final Label scopeLabel;
private final Shell shell;
private final Display display;
private final FileViewer viewer;
/**
* Creates the file tree table.
*
* @param theViewer the viewer to attach to
* @param parent the parent control
* @param layoutData the layout data
*/
public TreeView(FileViewer theViewer, Composite parent, Object layoutData) {
this.viewer = theViewer;
shell = parent.getShell();
display = shell.getDisplay();
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayoutData(layoutData);
GridLayout gridLayout = new GridLayout();
gridLayout.numColumns = 1;
gridLayout.marginHeight = gridLayout.marginWidth = 2;
gridLayout.horizontalSpacing = gridLayout.verticalSpacing = 0;
composite.setLayout(gridLayout);
scopeLabel = new Label(composite, SWT.BORDER);
scopeLabel.setText(FileViewer.getResourceString("details.AllFolders.text"));
scopeLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL));
tree = new Tree(composite, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.SINGLE);
tree.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL));
tree.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent event) {
final TreeItem[] selection = tree.getSelection();
if (selection != null && selection.length != 0) {
TreeItem item = selection[0];
File file = (File) item.getData(TREEITEMDATA_FILE);
viewer.notifySelectedDirectory(file);
}
}
public void widgetDefaultSelected(SelectionEvent event) {
final TreeItem[] selection = tree.getSelection();
if (selection != null && selection.length != 0) {
TreeItem item = selection[0];
item.setExpanded(true);
expandTreeItem(item);
}
}
});
tree.addTreeListener(new TreeAdapter() {
public void treeExpanded(TreeEvent event) {
final TreeItem item = (TreeItem) event.item;
final Image image = (Image) item.getData(TREEITEMDATA_IMAGEEXPANDED);
if (image != null) item.setImage(image);
expandTreeItem(item);
}
public void treeCollapsed(TreeEvent event) {
final TreeItem item = (TreeItem) event.item;
final Image image = (Image) item.getData(TREEITEMDATA_IMAGECOLLAPSED);
if (image != null) item.setImage(image);
}
});
createTreeDragSource(tree);
createTreeDropTarget(tree);
}
/**
* Creates the Drag & Drop DragSource for items being dragged from the tree.
*
* @return the DragSource for the tree
*/
private DragSource createTreeDragSource(final Tree tree){
DragSource dragSource = new DragSource(tree, DND.DROP_MOVE | DND.DROP_COPY);
dragSource.setTransfer(new Transfer[] { FileTransfer.getInstance() });
dragSource.addDragListener(new DragSourceListener() {
public void dragStart(DragSourceEvent event){
event.doit = tree.getSelectionCount() > 0;
}
public void dragFinished(DragSourceEvent event){
}
public void dragSetData(DragSourceEvent event){
if (! FileTransfer.getInstance().isSupportedType(event.dataType)) return;
final TreeItem[] treeDragItems = tree.getSelection();
if (treeDragItems == null || treeDragItems.length == 0) return;
final String[] data = new String[treeDragItems.length];
for (int i = 0; i < treeDragItems.length; i++) {
File file = (File) treeDragItems[i].getData(TREEITEMDATA_FILE);
data[i] = file.getAbsolutePath();
}
event.data = data;
}
});
return dragSource;
}
/**
* Creates the Drag & Drop DropTarget for items being dropped onto the tree.
*
* @return the DropTarget for the tree
*/
private DropTarget createTreeDropTarget(final Tree tree) {
DropTarget dropTarget = new DropTarget(tree, DND.DROP_MOVE | DND.DROP_COPY);
dropTarget.setTransfer(new Transfer[] { FileTransfer.getInstance() });
dropTarget.addDropListener(new TreeScrollDropListener(tree));
dropTarget.addDropListener(new TreeExpandDropListener(tree));
dropTarget.addDropListener(new DropTargetAdapter() {
public void dragOver(DropTargetEvent event) {
viewer.validateDrop(event, getTargetFile(event));
}
public void drop(DropTargetEvent event) {
viewer.performDrop(event, getTargetFile(event));
}
private File getTargetFile(DropTargetEvent event) {
// Determine the target File for the drop
final TreeItem item = tree.getItem(tree.toControl(new Point(event.x, event.y)));
final File targetFile;
if (item == null) {
// We dropped on an unoccupied area of the tree, we have no recourse. Quit.
targetFile = null;
} else {
// We dropped on a particular item in the tree, use the item's file
targetFile = (File) item.getData(TREEITEMDATA_FILE);
}
return targetFile;
}
});
return dropTarget;
}
/**
* Handles expand events on a tree item.
*
* @param item the TreeItem to fill in
*/
private void expandTreeItem(TreeItem item) {
final File file = (File) item.getData(TREEITEMDATA_FILE);
final Object stub = item.getData(TREEITEMDATA_STUB);
if (stub == null) refreshTreeItem(item, file);
}
/**
* Populates an item in the tree with a complete directory listing.
*
* @param item the TreeItem to fill in
* @param file the directory to use
*/
private void refreshTreeItem(TreeItem item, File file) {
/* Get directory listing */
shell.setCursor(IconCache.stockCursors[IconCache.cursorWait]);
File[] subFiles = null;
if (file != null) {
subFiles = FileViewer.getDirectoryList(file);
}
/* Eliminate any existing (possibly placeholder) children */
final TreeItem[] oldChildren = item.getItems();
for (int i = 0; i < oldChildren.length; ++i) {
oldChildren[i].dispose();
}
if (subFiles != null && subFiles.length > 0) {
/* Add subdirectory entries */
for (int i = 0; i < subFiles.length; ++i) {
final File folder = subFiles[i];
if (! folder.isDirectory()) continue;
// add the directory to the tree
TreeItem newItem = new TreeItem(item, SWT.NULL);
initTreeItemFolder(newItem, folder);
// add a placeholder child item so we get the "expand" button
TreeItem placeholderItem = new TreeItem(newItem, SWT.NULL);
}
} else {
/* Error or nothing found -- collapse the item */
item.setExpanded(false);
}
// Clear stub flag
item.setData(TREEITEMDATA_STUB, this);
shell.setCursor(IconCache.stockCursors[IconCache.cursorDefault]);
}
/**
* Listens to selectedDirectory events.
* <p>
* If not already expanded, recursively expands the parents of the specified
* directory until it is visible.
* </p>
*
* @param dir the directory that was selected, null is not permitted
*/
/* package */ void selectedDirectory(File dir) {
Vector /* of File */ path = new Vector();
// Build a stack of paths from the root of the tree
while (dir != null) {
path.add(dir);
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);
TreeItem item = searchItems(items, pathElement);
if (item == null) break;
lastItem = item;
if (i != 0 && !item.getExpanded()) {
item.setExpanded(true);
expandTreeItem(item);
}
items = item.getItems();
}
tree.setSelection((lastItem != null) ? new TreeItem[] { lastItem } : new TreeItem[0]);
}
private TreeItem searchItems(TreeItem[] items, File element) {
// No guarantee that the items are sorted, so we'll just sequential scan
// shouldn't be more than a couple hundred entries, anyway.
for (int i = 0; i < items.length; ++i) {
final TreeItem item = items[i];
if (item.isDisposed()) continue;
final File itemFile = (File) item.getData(TREEITEMDATA_FILE);
if (itemFile != null && itemFile.equals(element)) return item;
}
return null;
}
/**
* Listens to refreshFiles events.
* <p>
* Refreshes information about any files in the list and their children.
* </p>
*
* @param files the list of files to be refreshed, null refreshes everything
*/
/* package */ void refreshFiles(File[] files) {
if (files == null) {
File[] roots = viewer.getRoots();
tree.removeAll();
for (int i = 0; i < roots.length; ++i) {
final File file = roots[i];
TreeItem item = new TreeItem(tree, SWT.NULL);
initTreeItemVolume(item, file);
// add a placeholder child item so we get the "expand" button
TreeItem placeholderItem = new TreeItem(item, SWT.NULL);
}
}
}
/**
* Initializes a volume item.
*
* @param item the TreeItem to initialize
* @param volume the File associated with this TreeItem
*/
private void initTreeItemVolume(TreeItem item, File volume) {
item.setText(volume.getPath());
item.setImage(IconCache.stockImages[IconCache.iconClosedDrive]);
item.setData(TREEITEMDATA_FILE, volume);
item.setData(TREEITEMDATA_IMAGEEXPANDED, IconCache.stockImages[IconCache.iconOpenDrive]);
item.setData(TREEITEMDATA_IMAGECOLLAPSED, IconCache.stockImages[IconCache.iconClosedDrive]);
}
/**
* Initializes a folder item.
*
* @param item the TreeItem to initialize
* @param folder the File associated with this TreeItem
*/
private void initTreeItemFolder(TreeItem item, File folder) {
item.setText(folder.getName());
item.setImage(IconCache.stockImages[IconCache.iconClosedFolder]);
item.setData(TREEITEMDATA_FILE, folder);
item.setData(TREEITEMDATA_IMAGEEXPANDED, IconCache.stockImages[IconCache.iconOpenFolder]);
item.setData(TREEITEMDATA_IMAGECOLLAPSED, IconCache.stockImages[IconCache.iconClosedFolder]);
}
}
\ No newline at end of file +package org.eclipse.swt.examples.fileviewer;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved
*/
import org.eclipse.swt.*;
import org.eclipse.swt.dnd.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
import java.io.*;
import java.util.*;
/**
* A directory tree
*/
class TreeView {
private static final String
TREEITEMDATA_FILE = "TreeItem.file",
// File: File associated with tree item
TREEITEMDATA_IMAGEEXPANDED = "TreeItem.imageExpanded",
// Image: shown when item is expanded
TREEITEMDATA_IMAGECOLLAPSED = "TreeItem.imageCollapsed",
// Image: shown when item is collapsed
TREEITEMDATA_STUB = "TreeItem.stub";
// Object: if not present or null then the item has not been populated
private final Tree tree;
private final Label scopeLabel;
private final Shell shell;
private final Display display;
private final FileViewer viewer;
private boolean inDrag = false;
/**
* Creates the file tree table.
*
* @param theViewer the viewer to attach to
* @param parent the parent control
* @param layoutData the layout data
*/
public TreeView(FileViewer theViewer, Composite parent, Object layoutData) {
this.viewer = theViewer;
shell = parent.getShell();
display = shell.getDisplay();
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayoutData(layoutData);
GridLayout gridLayout = new GridLayout();
gridLayout.numColumns = 1;
gridLayout.marginHeight = gridLayout.marginWidth = 2;
gridLayout.horizontalSpacing = gridLayout.verticalSpacing = 0;
composite.setLayout(gridLayout);
scopeLabel = new Label(composite, SWT.BORDER);
scopeLabel.setText(FileViewer.getResourceString("details.AllFolders.text"));
scopeLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL));
tree = new Tree(composite, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.SINGLE);
tree.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL));
tree.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent event) {
if (inDrag) return;
final TreeItem[] selection = tree.getSelection();
if (selection != null && selection.length != 0) {
TreeItem item = selection[0];
File file = (File) item.getData(TREEITEMDATA_FILE);
viewer.notifySelectedDirectory(file);
}
}
public void widgetDefaultSelected(SelectionEvent event) {
if (inDrag) return;
final TreeItem[] selection = tree.getSelection();
if (selection != null && selection.length != 0) {
TreeItem item = selection[0];
item.setExpanded(true);
expandTreeItem(item);
}
}
});
tree.addTreeListener(new TreeAdapter() {
public void treeExpanded(TreeEvent event) {
final TreeItem item = (TreeItem) event.item;
final Image image = (Image) item.getData(TREEITEMDATA_IMAGEEXPANDED);
if (image != null) item.setImage(image);
expandTreeItem(item);
}
public void treeCollapsed(TreeEvent event) {
final TreeItem item = (TreeItem) event.item;
final Image image = (Image) item.getData(TREEITEMDATA_IMAGECOLLAPSED);
if (image != null) item.setImage(image);
}
});
createTreeDragSource(tree);
createTreeDropTarget(tree);
}
/**
* Creates the Drag & Drop DragSource for items being dragged from the tree.
*
* @return the DragSource for the tree
*/
private DragSource createTreeDragSource(final Tree tree){
DragSource dragSource = new DragSource(tree, DND.DROP_MOVE | DND.DROP_COPY);
dragSource.setTransfer(new Transfer[] { FileTransfer.getInstance() });
dragSource.addDragListener(new DragSourceListener() {
TreeItem[] dndSelection = null;
public void dragStart(DragSourceEvent event){
dndSelection = tree.getSelection();
event.doit = dndSelection.length > 0;
}
public void dragFinished(DragSourceEvent event){
dndSelection = null;
}
public void dragSetData(DragSourceEvent event){
if (dndSelection == null || dndSelection.length == 0) return;
if (! FileTransfer.getInstance().isSupportedType(event.dataType)) return;
final String[] data = new String[dndSelection.length];
for (int i = 0; i < dndSelection.length; i++) {
File file = (File) dndSelection[i].getData(TREEITEMDATA_FILE);
data[i] = file.getAbsolutePath();
}
event.data = data;
}
});
return dragSource;
}
/**
* Creates the Drag & Drop DropTarget for items being dropped onto the tree.
*
* @return the DropTarget for the tree
*/
private DropTarget createTreeDropTarget(final Tree tree) {
DropTarget dropTarget = new DropTarget(tree, DND.DROP_MOVE | DND.DROP_COPY);
dropTarget.setTransfer(new Transfer[] { FileTransfer.getInstance() });
dropTarget.addDropListener(new TreeScrollDropListener(tree));
dropTarget.addDropListener(new TreeExpandDropListener(tree));
dropTarget.addDropListener(new DropTargetAdapter() {
public void dragEnter(DropTargetEvent event) {
inDrag = true;
}
public void dragLeave(DropTargetEvent event) {
inDrag = false;
}
public void dragOver(DropTargetEvent event) {
viewer.validateDropTarget(event, getTargetFile(event));
}
public void dropAccept(DropTargetEvent event) {
viewer.validateDropTarget(event, getTargetFile(event));
}
public void drop(DropTargetEvent event) {
viewer.performDrop(event, getTargetFile(event));
}
private File getTargetFile(DropTargetEvent event) {
// Determine the target File for the drop
final TreeItem item = tree.getItem(tree.toControl(new Point(event.x, event.y)));
final File targetFile;
if (item == null) {
// We dropped on an unoccupied area of the tree, we have no recourse. Quit.
targetFile = null;
} else {
// We dropped on a particular item in the tree, use the item's file
targetFile = (File) item.getData(TREEITEMDATA_FILE);
}
return targetFile;
}
});
return dropTarget;
}
/**
* Handles expand events on a tree item.
*
* @param item the TreeItem to fill in
*/
private void expandTreeItem(TreeItem item) {
final File file = (File) item.getData(TREEITEMDATA_FILE);
final Object stub = item.getData(TREEITEMDATA_STUB);
if (stub == null) refreshTreeItem(item, file);
}
/**
* Populates an item in the tree with a complete directory listing.
*
* @param item the TreeItem to fill in
* @param file the directory to use
*/
private void refreshTreeItem(TreeItem item, File file) {
/* Get directory listing */
shell.setCursor(IconCache.stockCursors[IconCache.cursorWait]);
File[] subFiles = null;
if (file != null) {
subFiles = FileViewer.getDirectoryList(file);
}
/* Eliminate any existing (possibly placeholder) children */
final TreeItem[] oldChildren = item.getItems();
for (int i = 0; i < oldChildren.length; ++i) {
oldChildren[i].dispose();
}
if (subFiles != null && subFiles.length > 0) {
/* Add subdirectory entries */
for (int i = 0; i < subFiles.length; ++i) {
final File folder = subFiles[i];
if (! folder.isDirectory()) continue;
// add the directory to the tree
TreeItem newItem = new TreeItem(item, SWT.NULL);
initTreeItemFolder(newItem, folder);
// add a placeholder child item so we get the "expand" button
TreeItem placeholderItem = new TreeItem(newItem, SWT.NULL);
}
} else {
/* Error or nothing found -- collapse the item */
item.setExpanded(false);
}
// Clear stub flag
item.setData(TREEITEMDATA_STUB, this);
shell.setCursor(IconCache.stockCursors[IconCache.cursorDefault]);
}
/**
* Listens to selectedDirectory events.
* <p>
* If not already expanded, recursively expands the parents of the specified
* directory until it is visible.
* </p>
*
* @param dir the directory that was selected, null is not permitted
*/
/* package */ void selectedDirectory(File dir) {
Vector /* of File */ path = new Vector();
// Build a stack of paths from the root of the tree
while (dir != null) {
path.add(dir);
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);
TreeItem item = searchItems(items, pathElement);
if (item == null) break;
lastItem = item;
if (i != 0 && !item.getExpanded()) {
expandTreeItem(item);
item.setExpanded(true);
}
items = item.getItems();
}
tree.setSelection((lastItem != null) ? new TreeItem[] { lastItem } : new TreeItem[0]);
}
private TreeItem searchItems(TreeItem[] items, File element) {
// No guarantee that the items are sorted, so we'll just sequential scan
// shouldn't be more than a couple hundred entries, anyway.
for (int i = 0; i < items.length; ++i) {
final TreeItem item = items[i];
if (item.isDisposed()) continue;
final File itemFile = (File) item.getData(TREEITEMDATA_FILE);
if (itemFile != null && itemFile.equals(element)) return item;
}
return null;
}
/**
* Listens to refreshFiles events.
* <p>
* Refreshes information about any files in the list and their children.
* </p>
*
* @param files the list of files to be refreshed, null refreshes everything
*/
/* package */ void refreshFiles(File[] files) {
if (files == null) {
File[] roots = viewer.getRoots();
tree.removeAll();
for (int i = 0; i < roots.length; ++i) {
final File file = roots[i];
TreeItem item = new TreeItem(tree, SWT.NULL);
initTreeItemVolume(item, file);
// add a placeholder child item so we get the "expand" button
TreeItem placeholderItem = new TreeItem(item, SWT.NULL);
}
}
}
/**
* Initializes a volume item.
*
* @param item the TreeItem to initialize
* @param volume the File associated with this TreeItem
*/
private void initTreeItemVolume(TreeItem item, File volume) {
item.setText(volume.getPath());
item.setImage(IconCache.stockImages[IconCache.iconClosedDrive]);
item.setData(TREEITEMDATA_FILE, volume);
item.setData(TREEITEMDATA_IMAGEEXPANDED, IconCache.stockImages[IconCache.iconOpenDrive]);
item.setData(TREEITEMDATA_IMAGECOLLAPSED, IconCache.stockImages[IconCache.iconClosedDrive]);
}
/**
* Initializes a folder item.
*
* @param item the TreeItem to initialize
* @param folder the File associated with this TreeItem
*/
private void initTreeItemFolder(TreeItem item, File folder) {
item.setText(folder.getName());
item.setImage(IconCache.stockImages[IconCache.iconClosedFolder]);
item.setData(TREEITEMDATA_FILE, folder);
item.setData(TREEITEMDATA_IMAGEEXPANDED, IconCache.stockImages[IconCache.iconOpenFolder]);
item.setData(TREEITEMDATA_IMAGECOLLAPSED, IconCache.stockImages[IconCache.iconClosedFolder]);
}
}
\ No newline at end of file diff --git a/examples/org.eclipse.swt.examples/src/org/eclipse/swt/examples/fileviewer/FileViewer.java b/examples/org.eclipse.swt.examples/src/org/eclipse/swt/examples/fileviewer/FileViewer.java index c202ed7074..90eea668d1 100755 --- a/examples/org.eclipse.swt.examples/src/org/eclipse/swt/examples/fileviewer/FileViewer.java +++ b/examples/org.eclipse.swt.examples/src/org/eclipse/swt/examples/fileviewer/FileViewer.java @@ -390,38 +390,22 @@ public class FileViewer { }
/**
- * Validate a drop target event
+ * Validates a drop target as a candidate for a drop operation.
* <p>
- * Note event.detail is modified by this method
+ * Note event.detail is set to DND.DROP_NONE by this method if the target is not valid.
* </p>
* @param event the DropTargetEvent we are validating
* @param targetFile the File representing the drop target location
* under inspection, or null if none
- * @return an array of files to be operated on, or null on error
*/
- /* package */ File[] validateDrop(DropTargetEvent event, File targetFile) {
- final int dropMode = (event.detail != DND.DROP_NONE) ? event.detail : DND.DROP_MOVE;
- event.detail = DND.DROP_NONE; // simplify error reporting
-
// Validate the target
- if (targetFile == null) return null;
- if (! targetFile.isDirectory()) return null;
-
- // Get dropped data (an array of filenames)
- final String[] names = (String[]) event.data;
- final File[] files;
- if (names != null) {
- // Validate the source
- files = new File[names.length];
- for (int i = 0; i < names.length; ++i) {
- files[i] = new File(names[i]);
- if (files[i].equals(targetFile)) return null;
+ /* package */ void validateDropTarget(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 {
- // Files not available yet
- files = null;
+ event.detail = DND.DROP_NONE;
}
- event.detail = dropMode;
- return files;
}
/**
@@ -434,23 +418,22 @@ public class FileViewer { * under inspection, or null if none
*/
/* package */ void performDrop(DropTargetEvent event, File targetFile) {
- Vector /* of File */ dirtyFiles = new Vector();
- try {
- final File[] sourceFiles = validateDrop(event, targetFile);
- final int dropMode = event.detail;
+ validateDropTarget(event, targetFile);
- if (sourceFiles == null) {
- event.detail = DND.DROP_NONE;
- return;
- }
-
+ // Get dropped data (an array of filenames)
+ final String[] sourceNames = (String[]) event.data;
+ if (sourceNames == null) event.detail = DND.DROP_NONE;
+ if (event.detail == DND.DROP_NONE) return;
+
+ Vector /* of File */ dirtyFiles = new Vector();
+ try {
dirtyFiles.add(targetFile);
- for (int i = 0; i < sourceFiles.length; i++){
- final File source = sourceFiles[i];
+ for (int i = 0; i < sourceNames.length; i++){
+ final File source = new File(sourceNames[i]);
final File dest = new File(targetFile, source.getName());
// Perform action on each file
- switch (dropMode) {
+ switch (event.detail) {
default:
case DND.DROP_COPY:
if (! copyFileStructure(source, dest)) return;
diff --git a/examples/org.eclipse.swt.examples/src/org/eclipse/swt/examples/fileviewer/TableView.java b/examples/org.eclipse.swt.examples/src/org/eclipse/swt/examples/fileviewer/TableView.java index a1ed483d37..b0a8e1e4ed 100755 --- a/examples/org.eclipse.swt.examples/src/org/eclipse/swt/examples/fileviewer/TableView.java +++ b/examples/org.eclipse.swt.examples/src/org/eclipse/swt/examples/fileviewer/TableView.java @@ -1 +1 @@ -package org.eclipse.swt.examples.fileviewer;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved
*/
import org.eclipse.swt.*;
import org.eclipse.swt.dnd.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.program.*;
import org.eclipse.swt.widgets.*;
import java.io.*;
import java.text.*;
import java.util.*;
/**
* A detailed directory listing
*/
public class TableView {
private static final String TABLEITEMDATA_FILE = "TableItem.file";
// File: File associated with table row
private final Table table;
private final Label contentsOfLabel;
private final Shell shell;
private final Display display;
private final FileViewer viewer;
private File activeDir = null;
/* Worker thread control */
private UpdateWorker tableUpdateWorker = null;
final String[] titles = new String [] {
FileViewer.getResourceString("table.Name.title"),
FileViewer.getResourceString("table.Size.title"),
FileViewer.getResourceString("table.Type.title"),
FileViewer.getResourceString("table.Modified.title")
};
final int[] widths = new int[] {150, 60, 75, 150};
/**
* Creates the file details table.
*
* @param theViewer the viewer to attach to
* @param parent the parent control
* @param layoutData the layout data
*/
public TableView(FileViewer theViewer, Composite parent, Object layoutData) {
this.viewer = theViewer;
shell = parent.getShell();
display = shell.getDisplay();
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayoutData(layoutData);
GridLayout gridLayout = new GridLayout();
gridLayout.numColumns = 1;
gridLayout.marginHeight = gridLayout.marginWidth = 2;
gridLayout.horizontalSpacing = gridLayout.verticalSpacing = 0;
composite.setLayout(gridLayout);
contentsOfLabel = new Label(composite, SWT.BORDER);
contentsOfLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL));
table = new Table(composite, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI);
table.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL));
for (int i = 0; i < titles.length; i++) {
TableColumn column = new TableColumn(table, SWT.NONE);
column.setText(titles [i]);
column.setWidth(widths [i]);
}
table.setHeaderVisible(true);
table.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
viewer.notifySelectedFiles(getSelectedFiles());
}
public void widgetDefaultSelected(SelectionEvent event) {
viewer.doDefaultFileAction(getSelectedFiles());
}
private File[] getSelectedFiles() {
final TableItem[] items = table.getSelection();
final File[] files = new File[items.length];
for (int i = 0; i < items.length; ++i) {
files[i] = (File) items[i].getData(TABLEITEMDATA_FILE);
}
return files;
}
});
createTableDragSource(table);
createTableDropTarget(table);
tableUpdateWorker = new TableUpdateWorker();
}
/**
* Dispose of allocated resources and shut down.
*/
public void dispose() {
tableUpdateWorker.syncStop();
}
/**
* Updates the table with file information in the background.
* <p>
* It is designed such that it can be interrupted cleanly. Rather than put all the code
* to manage this here, the balance has been pushed out to UpdateWorker so it can be re-used.
* </p>
*/
private class TableUpdateWorker extends UpdateWorker {
private File currentDir = null;
private File[] currentFiles = null;
private File[] currentDirList = null;
public TableUpdateWorker() {
super(TableView.this.display);
}
/**
* Updates the table's contents
*
* @param data arguments in an Object[]
* <ul>
* <li>File data[0] dir the current directory, null does nothing
* <li>File[] data[1] the list of files to select, null does nothing
* <li>Boolean data[2] if true, forces a refresh
* </ul>
*/
protected void execute(Object data) {
// Get arguments
final Object[] args = (Object[]) data;
final File argDir = (File) args[0];
final File[] argFiles = (File[]) args[1];
final boolean argForce = ((Boolean) args[2]).booleanValue();
// Update current state
if (argDir != null) currentDir = argDir;
if (argFiles != null) currentFiles = argFiles;
else if (argDir != null) currentFiles = new File[0];
// Perform necessary refreshing
if (argDir != null) updateDirectoryListing();
else if (argFiles != null) updateFileSelection();
if (isCancelled()) {
currentFiles = null;
currentDir = null;
currentDirList = null;
}
}
/*
* Note the use of asyncExec() in some places to ensure that SWT Widgets are manipulated in the
* right thread. Exclusive use of syncExec() would be inappropriate as it would require a pair
* of context switches between each table update operation.
*/
/**
* Updates directory list
*/
private void updateDirectoryListing() {
// Clear existing information
TableView.this.display.syncExec(new Runnable() {
public void run() {
viewer.clearDetails();
contentsOfLabel.setText(FileViewer.getResourceString("details.ContentsOf.text",
new Object[] { currentDir.getPath() }));
table.removeAll();
table.setRedraw(false);
TableView.this.activeDir = currentDir; // synchronize this
}
});
currentDirList = FileViewer.getDirectoryList(currentDir);
updateDetails();
for (int i = 0; (! isCancelled()) && (i < currentDirList.length); i++) {
final File theFile = currentDirList[i];
addFileDetails(currentDirList[i]);
final boolean doIncrementalRefresh = ((i & 127) == 127);
if (doIncrementalRefresh) TableView.this.display.syncExec(new Runnable() {
public void run () {
table.setRedraw(true);
table.setRedraw(false);
}
});
}
// Allow the table to refresh itself
TableView.this.display.asyncExec(new Runnable() {
public void run() {
table.setRedraw(true);
}
});
}
/**
* Adds a file's detail information to the directory list
*/
private void addFileDetails(final File file) {
final FileDisplayInfo displayInfo = viewer.getFileDisplayInfo(file);
final String[] strings = new String[] {
displayInfo.nameString,
displayInfo.sizeString,
displayInfo.typeString,
displayInfo.dateString };
final Image image = displayInfo.iconImage;
TableView.this.display.asyncExec(new Runnable() {
public void run () {
TableItem tableItem = new TableItem(table, 0);
tableItem.setText(strings);
tableItem.setImage(image);
tableItem.setData(TABLEITEMDATA_FILE, file);
}
});
}
/**
* Updates the current file selection
*/
private void updateFileSelection() {
updateDetails();
}
/**
* Updates the detail information
*/
private void updateDetails() {
if (currentFiles.length == 0) {
if (currentDir == null) return;
final File folder = currentDir;
final File[] files = currentDirList;
// show directory information
TableView.this.display.asyncExec(new Runnable() {
public void run() {
viewer.setFolderDetails(folder, files);
}
});
} else if (currentFiles.length == 1) {
final File file = currentFiles[0];
// show individual file information
TableView.this.display.asyncExec(new Runnable() {
public void run() {
viewer.setFileDetails(file);
}
});
} else {
// show multi-selection file information
final File[] files = currentFiles;
TableView.this.display.asyncExec(new Runnable() {
public void run() {
viewer.setSelectionDetails(files);
}
});
}
}
}
/**
* Creates the Drag & Drop DropTarget for items being dropped onto the table.
*
* @return the DropTarget for the table
*/
private DropTarget createTableDropTarget(final Table table){
DropTarget dropTarget = new DropTarget(table, DND.DROP_MOVE | DND.DROP_COPY);
dropTarget.setTransfer(new Transfer[] { FileTransfer.getInstance() });
dropTarget.addDropListener(new DropTargetAdapter() {
public void dragOver(DropTargetEvent event) {
viewer.validateDrop(event, getTargetFile(event));
}
public void drop(DropTargetEvent event) {
viewer.performDrop(event, getTargetFile(event));
}
private File getTargetFile(DropTargetEvent event) {
// Determine the target File for the drop
final TableItem item = table.getItem(table.toControl(new Point(event.x, event.y)));
final File targetFile;
if (item == null) {
// We dropped on an unoccupied area of the table, use the table's root file
targetFile = activeDir;
} else {
// We dropped on a particular item in the table, use the item's file
targetFile = (File) item.getData(TABLEITEMDATA_FILE);
}
return targetFile;
}
});
return dropTarget;
}
/**
* Creates the Drag & Drop DragSource for items being dragged from the table.
*
* @return the DragSource for the table
*/
private DragSource createTableDragSource(final Table table) {
DragSource dragSource = new DragSource(table, DND.DROP_MOVE | DND.DROP_COPY);
dragSource.setTransfer(new Transfer[] { FileTransfer.getInstance() });
dragSource.addDragListener(new DragSourceListener() {
public void dragStart(DragSourceEvent e) {
e.doit = table.getSelectionCount() > 0;
}
public void dragSetData(DragSourceEvent event){
if (! FileTransfer.getInstance().isSupportedType(event.dataType)) return;
final TableItem[] tableDragItems = table.getSelection();
if (tableDragItems == null || tableDragItems.length == 0) return;
final String[] data = new String[tableDragItems.length];
for (int i = 0; i < tableDragItems.length; i++) {
File file = (File) tableDragItems[i].getData(TABLEITEMDATA_FILE);
data[i] = file.getAbsolutePath();
}
event.data = data;
}
public void dragFinished(DragSourceEvent event) {
}
});
return dragSource;
}
/**
* Listens to selectedDirectory events.
* <p>
* Displays the contents in the selected directory.
* </p>
*
* @param dir the directory that was selected, null is not permitted
*/
/* package */ void selectedDirectory(File dir) {
tableUpdateWorker.asyncUpdate(new Object[] { dir, null, new Boolean(false) });
}
/**
* Listens to selectedFiles events.
* <p>
* Updates the details to match the specified selection.
* </p>
*
* @param files the array of selected files, null is not permitted
*/
/* package */ void selectedFiles(File[] files) {
tableUpdateWorker.asyncUpdate(new Object[] { null, files, new Boolean(false) });
}
/**
* Listens to refreshFiles events.
* <p>
* Refreshes information about any files in the list and their children.
* </p>
*
* @param files the list of files to be refreshed, null refreshes everything
*/
/* package */ void refreshFiles(File[] files) {
tableUpdateWorker.asyncUpdate(new Object[] { null, null, new Boolean(true) });
}
}
\ No newline at end of file +package org.eclipse.swt.examples.fileviewer;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved
*/
import org.eclipse.swt.*;
import org.eclipse.swt.dnd.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.program.*;
import org.eclipse.swt.widgets.*;
import java.io.*;
import java.text.*;
import java.util.*;
/**
* A detailed directory listing
*/
public class TableView {
private static final String TABLEITEMDATA_FILE = "TableItem.file";
// File: File associated with table row
private final Table table;
private final Label contentsOfLabel;
private final Shell shell;
private final Display display;
private final FileViewer viewer;
private File activeDir = null;
private boolean inDrag = false;
/* Worker thread control */
private UpdateWorker tableUpdateWorker = null;
final String[] titles = new String [] {
FileViewer.getResourceString("table.Name.title"),
FileViewer.getResourceString("table.Size.title"),
FileViewer.getResourceString("table.Type.title"),
FileViewer.getResourceString("table.Modified.title")
};
final int[] widths = new int[] {150, 60, 75, 150};
/**
* Creates the file details table.
*
* @param theViewer the viewer to attach to
* @param parent the parent control
* @param layoutData the layout data
*/
public TableView(FileViewer theViewer, Composite parent, Object layoutData) {
this.viewer = theViewer;
shell = parent.getShell();
display = shell.getDisplay();
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayoutData(layoutData);
GridLayout gridLayout = new GridLayout();
gridLayout.numColumns = 1;
gridLayout.marginHeight = gridLayout.marginWidth = 2;
gridLayout.horizontalSpacing = gridLayout.verticalSpacing = 0;
composite.setLayout(gridLayout);
contentsOfLabel = new Label(composite, SWT.BORDER);
contentsOfLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL));
table = new Table(composite, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI);
table.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL));
for (int i = 0; i < titles.length; i++) {
TableColumn column = new TableColumn(table, SWT.NONE);
column.setText(titles [i]);
column.setWidth(widths [i]);
}
table.setHeaderVisible(true);
table.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
if (inDrag) return;
viewer.notifySelectedFiles(getSelectedFiles());
}
public void widgetDefaultSelected(SelectionEvent event) {
if (inDrag) return;
viewer.doDefaultFileAction(getSelectedFiles());
}
private File[] getSelectedFiles() {
final TableItem[] items = table.getSelection();
final File[] files = new File[items.length];
for (int i = 0; i < items.length; ++i) {
files[i] = (File) items[i].getData(TABLEITEMDATA_FILE);
}
return files;
}
});
createTableDragSource(table);
createTableDropTarget(table);
tableUpdateWorker = new TableUpdateWorker();
}
/**
* Dispose of allocated resources and shut down.
*/
public void dispose() {
tableUpdateWorker.syncStop();
}
/**
* Updates the table with file information in the background.
* <p>
* It is designed such that it can be interrupted cleanly. Rather than put all the code
* to manage this here, the balance has been pushed out to UpdateWorker so it can be re-used.
* </p>
*/
private class TableUpdateWorker extends UpdateWorker {
private File currentDir = null;
private File[] currentFiles = null;
private File[] currentDirList = null;
public TableUpdateWorker() {
super(TableView.this.display);
}
/**
* Updates the table's contents
*
* @param data arguments in an Object[]
* <ul>
* <li>File data[0] dir the current directory, null does nothing
* <li>File[] data[1] the list of files to select, null does nothing
* <li>Boolean data[2] if true, forces a refresh
* </ul>
*/
protected void execute(Object data) {
// Get arguments
final Object[] args = (Object[]) data;
final File argDir = (File) args[0];
final File[] argFiles = (File[]) args[1];
final boolean argForce = ((Boolean) args[2]).booleanValue();
// Update current state
if (argDir != null) currentDir = argDir;
if (argFiles != null) currentFiles = argFiles;
else if (argDir != null) currentFiles = new File[0];
// Perform necessary refreshing
if (argDir != null) updateDirectoryListing();
else if (argFiles != null) updateFileSelection();
if (isCancelled()) {
currentFiles = null;
currentDir = null;
currentDirList = null;
}
}
/*
* Note the use of asyncExec() in some places to ensure that SWT Widgets are manipulated in the
* right thread. Exclusive use of syncExec() would be inappropriate as it would require a pair
* of context switches between each table update operation.
*/
/**
* Updates directory list
*/
private void updateDirectoryListing() {
// Clear existing information
TableView.this.display.syncExec(new Runnable() {
public void run() {
viewer.clearDetails();
contentsOfLabel.setText(FileViewer.getResourceString("details.ContentsOf.text",
new Object[] { currentDir.getPath() }));
table.removeAll();
table.setRedraw(false);
TableView.this.activeDir = currentDir; // synchronize this
}
});
currentDirList = FileViewer.getDirectoryList(currentDir);
updateDetails();
for (int i = 0; (! isCancelled()) && (i < currentDirList.length); i++) {
final File theFile = currentDirList[i];
addFileDetails(currentDirList[i]);
final boolean doIncrementalRefresh = ((i & 127) == 127);
if (doIncrementalRefresh) TableView.this.display.syncExec(new Runnable() {
public void run () {
table.setRedraw(true);
table.setRedraw(false);
}
});
}
// Allow the table to refresh itself
TableView.this.display.asyncExec(new Runnable() {
public void run() {
table.setRedraw(true);
}
});
}
/**
* Adds a file's detail information to the directory list
*/
private void addFileDetails(final File file) {
final FileDisplayInfo displayInfo = viewer.getFileDisplayInfo(file);
final String[] strings = new String[] {
displayInfo.nameString,
displayInfo.sizeString,
displayInfo.typeString,
displayInfo.dateString };
final Image image = displayInfo.iconImage;
TableView.this.display.asyncExec(new Runnable() {
public void run () {
TableItem tableItem = new TableItem(table, 0);
tableItem.setText(strings);
tableItem.setImage(image);
tableItem.setData(TABLEITEMDATA_FILE, file);
}
});
}
/**
* Updates the current file selection
*/
private void updateFileSelection() {
updateDetails();
}
/**
* Updates the detail information
*/
private void updateDetails() {
if (currentFiles.length == 0) {
if (currentDir == null) return;
final File folder = currentDir;
final File[] files = currentDirList;
// show directory information
TableView.this.display.asyncExec(new Runnable() {
public void run() {
viewer.setFolderDetails(folder, files);
}
});
} else if (currentFiles.length == 1) {
final File file = currentFiles[0];
// show individual file information
TableView.this.display.asyncExec(new Runnable() {
public void run() {
viewer.setFileDetails(file);
}
});
} else {
// show multi-selection file information
final File[] files = currentFiles;
TableView.this.display.asyncExec(new Runnable() {
public void run() {
viewer.setSelectionDetails(files);
}
});
}
}
}
/**
* Creates the Drag & Drop DragSource for items being dragged from the table.
*
* @return the DragSource for the table
*/
private DragSource createTableDragSource(final Table table) {
DragSource dragSource = new DragSource(table, DND.DROP_MOVE | DND.DROP_COPY);
dragSource.setTransfer(new Transfer[] { FileTransfer.getInstance() });
dragSource.addDragListener(new DragSourceListener() {
TableItem[] dndSelection = null;
public void dragStart(DragSourceEvent event){
dndSelection = table.getSelection();
event.doit = dndSelection.length > 0;
}
public void dragFinished(DragSourceEvent event){
dndSelection = null;
}
public void dragSetData(DragSourceEvent event){
if (dndSelection == null || dndSelection.length == 0) return;
if (! FileTransfer.getInstance().isSupportedType(event.dataType)) return;
final String[] data = new String[dndSelection.length];
for (int i = 0; i < dndSelection.length; i++) {
File file = (File) dndSelection[i].getData(TABLEITEMDATA_FILE);
data[i] = file.getAbsolutePath();
}
event.data = data;
}
});
return dragSource;
}
/**
* Creates the Drag & Drop DropTarget for items being dropped onto the table.
*
* @return the DropTarget for the table
*/
private DropTarget createTableDropTarget(final Table table){
DropTarget dropTarget = new DropTarget(table, DND.DROP_MOVE | DND.DROP_COPY);
dropTarget.setTransfer(new Transfer[] { FileTransfer.getInstance() });
dropTarget.addDropListener(new DropTargetAdapter() {
public void dragEnter(DropTargetEvent event) {
inDrag = true;
}
public void dragLeave(DropTargetEvent event) {
inDrag = false;
}
public void dragOver(DropTargetEvent event) {
viewer.validateDropTarget(event, getTargetFile(event));
}
public void dropAccept(DropTargetEvent event) {
viewer.validateDropTarget(event, getTargetFile(event));
}
public void drop(DropTargetEvent event) {
viewer.performDrop(event, getTargetFile(event));
}
private File getTargetFile(DropTargetEvent event) {
// Determine the target File for the drop
final TableItem item = table.getItem(table.toControl(new Point(event.x, event.y)));
final File targetFile;
if (item == null) {
// We dropped on an unoccupied area of the table, use the table's root file
targetFile = activeDir;
} else {
// We dropped on a particular item in the table, use the item's file
targetFile = (File) item.getData(TABLEITEMDATA_FILE);
}
return targetFile;
}
});
return dropTarget;
}
/**
* Listens to selectedDirectory events.
* <p>
* Displays the contents in the selected directory.
* </p>
*
* @param dir the directory that was selected, null is not permitted
*/
/* package */ void selectedDirectory(File dir) {
tableUpdateWorker.asyncUpdate(new Object[] { dir, null, new Boolean(false) });
}
/**
* Listens to selectedFiles events.
* <p>
* Updates the details to match the specified selection.
* </p>
*
* @param files the array of selected files, null is not permitted
*/
/* package */ void selectedFiles(File[] files) {
tableUpdateWorker.asyncUpdate(new Object[] { null, files, new Boolean(false) });
}
/**
* Listens to refreshFiles events.
* <p>
* Refreshes information about any files in the list and their children.
* </p>
*
* @param files the list of files to be refreshed, null refreshes everything
*/
/* package */ void refreshFiles(File[] files) {
tableUpdateWorker.asyncUpdate(new Object[] { null, null, new Boolean(true) });
}
}
\ No newline at end of file diff --git a/examples/org.eclipse.swt.examples/src/org/eclipse/swt/examples/fileviewer/TreeView.java b/examples/org.eclipse.swt.examples/src/org/eclipse/swt/examples/fileviewer/TreeView.java index ee7a09ae91..2324a156bf 100755 --- a/examples/org.eclipse.swt.examples/src/org/eclipse/swt/examples/fileviewer/TreeView.java +++ b/examples/org.eclipse.swt.examples/src/org/eclipse/swt/examples/fileviewer/TreeView.java @@ -1 +1 @@ -package org.eclipse.swt.examples.fileviewer;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved
*/
import org.eclipse.swt.*;
import org.eclipse.swt.dnd.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
import java.io.*;
import java.util.*;
/**
* A directory tree
*/
class TreeView {
private static final String
TREEITEMDATA_FILE = "TreeItem.file",
// File: File associated with tree item
TREEITEMDATA_IMAGEEXPANDED = "TreeItem.imageExpanded",
// Image: shown when item is expanded
TREEITEMDATA_IMAGECOLLAPSED = "TreeItem.imageCollapsed",
// Image: shown when item is collapsed
TREEITEMDATA_STUB = "TreeItem.stub";
// Object: if not present or null then the item has not been populated
private final Tree tree;
private final Label scopeLabel;
private final Shell shell;
private final Display display;
private final FileViewer viewer;
/**
* Creates the file tree table.
*
* @param theViewer the viewer to attach to
* @param parent the parent control
* @param layoutData the layout data
*/
public TreeView(FileViewer theViewer, Composite parent, Object layoutData) {
this.viewer = theViewer;
shell = parent.getShell();
display = shell.getDisplay();
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayoutData(layoutData);
GridLayout gridLayout = new GridLayout();
gridLayout.numColumns = 1;
gridLayout.marginHeight = gridLayout.marginWidth = 2;
gridLayout.horizontalSpacing = gridLayout.verticalSpacing = 0;
composite.setLayout(gridLayout);
scopeLabel = new Label(composite, SWT.BORDER);
scopeLabel.setText(FileViewer.getResourceString("details.AllFolders.text"));
scopeLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL));
tree = new Tree(composite, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.SINGLE);
tree.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL));
tree.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent event) {
final TreeItem[] selection = tree.getSelection();
if (selection != null && selection.length != 0) {
TreeItem item = selection[0];
File file = (File) item.getData(TREEITEMDATA_FILE);
viewer.notifySelectedDirectory(file);
}
}
public void widgetDefaultSelected(SelectionEvent event) {
final TreeItem[] selection = tree.getSelection();
if (selection != null && selection.length != 0) {
TreeItem item = selection[0];
item.setExpanded(true);
expandTreeItem(item);
}
}
});
tree.addTreeListener(new TreeAdapter() {
public void treeExpanded(TreeEvent event) {
final TreeItem item = (TreeItem) event.item;
final Image image = (Image) item.getData(TREEITEMDATA_IMAGEEXPANDED);
if (image != null) item.setImage(image);
expandTreeItem(item);
}
public void treeCollapsed(TreeEvent event) {
final TreeItem item = (TreeItem) event.item;
final Image image = (Image) item.getData(TREEITEMDATA_IMAGECOLLAPSED);
if (image != null) item.setImage(image);
}
});
createTreeDragSource(tree);
createTreeDropTarget(tree);
}
/**
* Creates the Drag & Drop DragSource for items being dragged from the tree.
*
* @return the DragSource for the tree
*/
private DragSource createTreeDragSource(final Tree tree){
DragSource dragSource = new DragSource(tree, DND.DROP_MOVE | DND.DROP_COPY);
dragSource.setTransfer(new Transfer[] { FileTransfer.getInstance() });
dragSource.addDragListener(new DragSourceListener() {
public void dragStart(DragSourceEvent event){
event.doit = tree.getSelectionCount() > 0;
}
public void dragFinished(DragSourceEvent event){
}
public void dragSetData(DragSourceEvent event){
if (! FileTransfer.getInstance().isSupportedType(event.dataType)) return;
final TreeItem[] treeDragItems = tree.getSelection();
if (treeDragItems == null || treeDragItems.length == 0) return;
final String[] data = new String[treeDragItems.length];
for (int i = 0; i < treeDragItems.length; i++) {
File file = (File) treeDragItems[i].getData(TREEITEMDATA_FILE);
data[i] = file.getAbsolutePath();
}
event.data = data;
}
});
return dragSource;
}
/**
* Creates the Drag & Drop DropTarget for items being dropped onto the tree.
*
* @return the DropTarget for the tree
*/
private DropTarget createTreeDropTarget(final Tree tree) {
DropTarget dropTarget = new DropTarget(tree, DND.DROP_MOVE | DND.DROP_COPY);
dropTarget.setTransfer(new Transfer[] { FileTransfer.getInstance() });
dropTarget.addDropListener(new TreeScrollDropListener(tree));
dropTarget.addDropListener(new TreeExpandDropListener(tree));
dropTarget.addDropListener(new DropTargetAdapter() {
public void dragOver(DropTargetEvent event) {
viewer.validateDrop(event, getTargetFile(event));
}
public void drop(DropTargetEvent event) {
viewer.performDrop(event, getTargetFile(event));
}
private File getTargetFile(DropTargetEvent event) {
// Determine the target File for the drop
final TreeItem item = tree.getItem(tree.toControl(new Point(event.x, event.y)));
final File targetFile;
if (item == null) {
// We dropped on an unoccupied area of the tree, we have no recourse. Quit.
targetFile = null;
} else {
// We dropped on a particular item in the tree, use the item's file
targetFile = (File) item.getData(TREEITEMDATA_FILE);
}
return targetFile;
}
});
return dropTarget;
}
/**
* Handles expand events on a tree item.
*
* @param item the TreeItem to fill in
*/
private void expandTreeItem(TreeItem item) {
final File file = (File) item.getData(TREEITEMDATA_FILE);
final Object stub = item.getData(TREEITEMDATA_STUB);
if (stub == null) refreshTreeItem(item, file);
}
/**
* Populates an item in the tree with a complete directory listing.
*
* @param item the TreeItem to fill in
* @param file the directory to use
*/
private void refreshTreeItem(TreeItem item, File file) {
/* Get directory listing */
shell.setCursor(IconCache.stockCursors[IconCache.cursorWait]);
File[] subFiles = null;
if (file != null) {
subFiles = FileViewer.getDirectoryList(file);
}
/* Eliminate any existing (possibly placeholder) children */
final TreeItem[] oldChildren = item.getItems();
for (int i = 0; i < oldChildren.length; ++i) {
oldChildren[i].dispose();
}
if (subFiles != null && subFiles.length > 0) {
/* Add subdirectory entries */
for (int i = 0; i < subFiles.length; ++i) {
final File folder = subFiles[i];
if (! folder.isDirectory()) continue;
// add the directory to the tree
TreeItem newItem = new TreeItem(item, SWT.NULL);
initTreeItemFolder(newItem, folder);
// add a placeholder child item so we get the "expand" button
TreeItem placeholderItem = new TreeItem(newItem, SWT.NULL);
}
} else {
/* Error or nothing found -- collapse the item */
item.setExpanded(false);
}
// Clear stub flag
item.setData(TREEITEMDATA_STUB, this);
shell.setCursor(IconCache.stockCursors[IconCache.cursorDefault]);
}
/**
* Listens to selectedDirectory events.
* <p>
* If not already expanded, recursively expands the parents of the specified
* directory until it is visible.
* </p>
*
* @param dir the directory that was selected, null is not permitted
*/
/* package */ void selectedDirectory(File dir) {
Vector /* of File */ path = new Vector();
// Build a stack of paths from the root of the tree
while (dir != null) {
path.add(dir);
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);
TreeItem item = searchItems(items, pathElement);
if (item == null) break;
lastItem = item;
if (i != 0 && !item.getExpanded()) {
item.setExpanded(true);
expandTreeItem(item);
}
items = item.getItems();
}
tree.setSelection((lastItem != null) ? new TreeItem[] { lastItem } : new TreeItem[0]);
}
private TreeItem searchItems(TreeItem[] items, File element) {
// No guarantee that the items are sorted, so we'll just sequential scan
// shouldn't be more than a couple hundred entries, anyway.
for (int i = 0; i < items.length; ++i) {
final TreeItem item = items[i];
if (item.isDisposed()) continue;
final File itemFile = (File) item.getData(TREEITEMDATA_FILE);
if (itemFile != null && itemFile.equals(element)) return item;
}
return null;
}
/**
* Listens to refreshFiles events.
* <p>
* Refreshes information about any files in the list and their children.
* </p>
*
* @param files the list of files to be refreshed, null refreshes everything
*/
/* package */ void refreshFiles(File[] files) {
if (files == null) {
File[] roots = viewer.getRoots();
tree.removeAll();
for (int i = 0; i < roots.length; ++i) {
final File file = roots[i];
TreeItem item = new TreeItem(tree, SWT.NULL);
initTreeItemVolume(item, file);
// add a placeholder child item so we get the "expand" button
TreeItem placeholderItem = new TreeItem(item, SWT.NULL);
}
}
}
/**
* Initializes a volume item.
*
* @param item the TreeItem to initialize
* @param volume the File associated with this TreeItem
*/
private void initTreeItemVolume(TreeItem item, File volume) {
item.setText(volume.getPath());
item.setImage(IconCache.stockImages[IconCache.iconClosedDrive]);
item.setData(TREEITEMDATA_FILE, volume);
item.setData(TREEITEMDATA_IMAGEEXPANDED, IconCache.stockImages[IconCache.iconOpenDrive]);
item.setData(TREEITEMDATA_IMAGECOLLAPSED, IconCache.stockImages[IconCache.iconClosedDrive]);
}
/**
* Initializes a folder item.
*
* @param item the TreeItem to initialize
* @param folder the File associated with this TreeItem
*/
private void initTreeItemFolder(TreeItem item, File folder) {
item.setText(folder.getName());
item.setImage(IconCache.stockImages[IconCache.iconClosedFolder]);
item.setData(TREEITEMDATA_FILE, folder);
item.setData(TREEITEMDATA_IMAGEEXPANDED, IconCache.stockImages[IconCache.iconOpenFolder]);
item.setData(TREEITEMDATA_IMAGECOLLAPSED, IconCache.stockImages[IconCache.iconClosedFolder]);
}
}
\ No newline at end of file +package org.eclipse.swt.examples.fileviewer;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved
*/
import org.eclipse.swt.*;
import org.eclipse.swt.dnd.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
import java.io.*;
import java.util.*;
/**
* A directory tree
*/
class TreeView {
private static final String
TREEITEMDATA_FILE = "TreeItem.file",
// File: File associated with tree item
TREEITEMDATA_IMAGEEXPANDED = "TreeItem.imageExpanded",
// Image: shown when item is expanded
TREEITEMDATA_IMAGECOLLAPSED = "TreeItem.imageCollapsed",
// Image: shown when item is collapsed
TREEITEMDATA_STUB = "TreeItem.stub";
// Object: if not present or null then the item has not been populated
private final Tree tree;
private final Label scopeLabel;
private final Shell shell;
private final Display display;
private final FileViewer viewer;
private boolean inDrag = false;
/**
* Creates the file tree table.
*
* @param theViewer the viewer to attach to
* @param parent the parent control
* @param layoutData the layout data
*/
public TreeView(FileViewer theViewer, Composite parent, Object layoutData) {
this.viewer = theViewer;
shell = parent.getShell();
display = shell.getDisplay();
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayoutData(layoutData);
GridLayout gridLayout = new GridLayout();
gridLayout.numColumns = 1;
gridLayout.marginHeight = gridLayout.marginWidth = 2;
gridLayout.horizontalSpacing = gridLayout.verticalSpacing = 0;
composite.setLayout(gridLayout);
scopeLabel = new Label(composite, SWT.BORDER);
scopeLabel.setText(FileViewer.getResourceString("details.AllFolders.text"));
scopeLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL));
tree = new Tree(composite, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.SINGLE);
tree.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL));
tree.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent event) {
if (inDrag) return;
final TreeItem[] selection = tree.getSelection();
if (selection != null && selection.length != 0) {
TreeItem item = selection[0];
File file = (File) item.getData(TREEITEMDATA_FILE);
viewer.notifySelectedDirectory(file);
}
}
public void widgetDefaultSelected(SelectionEvent event) {
if (inDrag) return;
final TreeItem[] selection = tree.getSelection();
if (selection != null && selection.length != 0) {
TreeItem item = selection[0];
item.setExpanded(true);
expandTreeItem(item);
}
}
});
tree.addTreeListener(new TreeAdapter() {
public void treeExpanded(TreeEvent event) {
final TreeItem item = (TreeItem) event.item;
final Image image = (Image) item.getData(TREEITEMDATA_IMAGEEXPANDED);
if (image != null) item.setImage(image);
expandTreeItem(item);
}
public void treeCollapsed(TreeEvent event) {
final TreeItem item = (TreeItem) event.item;
final Image image = (Image) item.getData(TREEITEMDATA_IMAGECOLLAPSED);
if (image != null) item.setImage(image);
}
});
createTreeDragSource(tree);
createTreeDropTarget(tree);
}
/**
* Creates the Drag & Drop DragSource for items being dragged from the tree.
*
* @return the DragSource for the tree
*/
private DragSource createTreeDragSource(final Tree tree){
DragSource dragSource = new DragSource(tree, DND.DROP_MOVE | DND.DROP_COPY);
dragSource.setTransfer(new Transfer[] { FileTransfer.getInstance() });
dragSource.addDragListener(new DragSourceListener() {
TreeItem[] dndSelection = null;
public void dragStart(DragSourceEvent event){
dndSelection = tree.getSelection();
event.doit = dndSelection.length > 0;
}
public void dragFinished(DragSourceEvent event){
dndSelection = null;
}
public void dragSetData(DragSourceEvent event){
if (dndSelection == null || dndSelection.length == 0) return;
if (! FileTransfer.getInstance().isSupportedType(event.dataType)) return;
final String[] data = new String[dndSelection.length];
for (int i = 0; i < dndSelection.length; i++) {
File file = (File) dndSelection[i].getData(TREEITEMDATA_FILE);
data[i] = file.getAbsolutePath();
}
event.data = data;
}
});
return dragSource;
}
/**
* Creates the Drag & Drop DropTarget for items being dropped onto the tree.
*
* @return the DropTarget for the tree
*/
private DropTarget createTreeDropTarget(final Tree tree) {
DropTarget dropTarget = new DropTarget(tree, DND.DROP_MOVE | DND.DROP_COPY);
dropTarget.setTransfer(new Transfer[] { FileTransfer.getInstance() });
dropTarget.addDropListener(new TreeScrollDropListener(tree));
dropTarget.addDropListener(new TreeExpandDropListener(tree));
dropTarget.addDropListener(new DropTargetAdapter() {
public void dragEnter(DropTargetEvent event) {
inDrag = true;
}
public void dragLeave(DropTargetEvent event) {
inDrag = false;
}
public void dragOver(DropTargetEvent event) {
viewer.validateDropTarget(event, getTargetFile(event));
}
public void dropAccept(DropTargetEvent event) {
viewer.validateDropTarget(event, getTargetFile(event));
}
public void drop(DropTargetEvent event) {
viewer.performDrop(event, getTargetFile(event));
}
private File getTargetFile(DropTargetEvent event) {
// Determine the target File for the drop
final TreeItem item = tree.getItem(tree.toControl(new Point(event.x, event.y)));
final File targetFile;
if (item == null) {
// We dropped on an unoccupied area of the tree, we have no recourse. Quit.
targetFile = null;
} else {
// We dropped on a particular item in the tree, use the item's file
targetFile = (File) item.getData(TREEITEMDATA_FILE);
}
return targetFile;
}
});
return dropTarget;
}
/**
* Handles expand events on a tree item.
*
* @param item the TreeItem to fill in
*/
private void expandTreeItem(TreeItem item) {
final File file = (File) item.getData(TREEITEMDATA_FILE);
final Object stub = item.getData(TREEITEMDATA_STUB);
if (stub == null) refreshTreeItem(item, file);
}
/**
* Populates an item in the tree with a complete directory listing.
*
* @param item the TreeItem to fill in
* @param file the directory to use
*/
private void refreshTreeItem(TreeItem item, File file) {
/* Get directory listing */
shell.setCursor(IconCache.stockCursors[IconCache.cursorWait]);
File[] subFiles = null;
if (file != null) {
subFiles = FileViewer.getDirectoryList(file);
}
/* Eliminate any existing (possibly placeholder) children */
final TreeItem[] oldChildren = item.getItems();
for (int i = 0; i < oldChildren.length; ++i) {
oldChildren[i].dispose();
}
if (subFiles != null && subFiles.length > 0) {
/* Add subdirectory entries */
for (int i = 0; i < subFiles.length; ++i) {
final File folder = subFiles[i];
if (! folder.isDirectory()) continue;
// add the directory to the tree
TreeItem newItem = new TreeItem(item, SWT.NULL);
initTreeItemFolder(newItem, folder);
// add a placeholder child item so we get the "expand" button
TreeItem placeholderItem = new TreeItem(newItem, SWT.NULL);
}
} else {
/* Error or nothing found -- collapse the item */
item.setExpanded(false);
}
// Clear stub flag
item.setData(TREEITEMDATA_STUB, this);
shell.setCursor(IconCache.stockCursors[IconCache.cursorDefault]);
}
/**
* Listens to selectedDirectory events.
* <p>
* If not already expanded, recursively expands the parents of the specified
* directory until it is visible.
* </p>
*
* @param dir the directory that was selected, null is not permitted
*/
/* package */ void selectedDirectory(File dir) {
Vector /* of File */ path = new Vector();
// Build a stack of paths from the root of the tree
while (dir != null) {
path.add(dir);
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);
TreeItem item = searchItems(items, pathElement);
if (item == null) break;
lastItem = item;
if (i != 0 && !item.getExpanded()) {
expandTreeItem(item);
item.setExpanded(true);
}
items = item.getItems();
}
tree.setSelection((lastItem != null) ? new TreeItem[] { lastItem } : new TreeItem[0]);
}
private TreeItem searchItems(TreeItem[] items, File element) {
// No guarantee that the items are sorted, so we'll just sequential scan
// shouldn't be more than a couple hundred entries, anyway.
for (int i = 0; i < items.length; ++i) {
final TreeItem item = items[i];
if (item.isDisposed()) continue;
final File itemFile = (File) item.getData(TREEITEMDATA_FILE);
if (itemFile != null && itemFile.equals(element)) return item;
}
return null;
}
/**
* Listens to refreshFiles events.
* <p>
* Refreshes information about any files in the list and their children.
* </p>
*
* @param files the list of files to be refreshed, null refreshes everything
*/
/* package */ void refreshFiles(File[] files) {
if (files == null) {
File[] roots = viewer.getRoots();
tree.removeAll();
for (int i = 0; i < roots.length; ++i) {
final File file = roots[i];
TreeItem item = new TreeItem(tree, SWT.NULL);
initTreeItemVolume(item, file);
// add a placeholder child item so we get the "expand" button
TreeItem placeholderItem = new TreeItem(item, SWT.NULL);
}
}
}
/**
* Initializes a volume item.
*
* @param item the TreeItem to initialize
* @param volume the File associated with this TreeItem
*/
private void initTreeItemVolume(TreeItem item, File volume) {
item.setText(volume.getPath());
item.setImage(IconCache.stockImages[IconCache.iconClosedDrive]);
item.setData(TREEITEMDATA_FILE, volume);
item.setData(TREEITEMDATA_IMAGEEXPANDED, IconCache.stockImages[IconCache.iconOpenDrive]);
item.setData(TREEITEMDATA_IMAGECOLLAPSED, IconCache.stockImages[IconCache.iconClosedDrive]);
}
/**
* Initializes a folder item.
*
* @param item the TreeItem to initialize
* @param folder the File associated with this TreeItem
*/
private void initTreeItemFolder(TreeItem item, File folder) {
item.setText(folder.getName());
item.setImage(IconCache.stockImages[IconCache.iconClosedFolder]);
item.setData(TREEITEMDATA_FILE, folder);
item.setData(TREEITEMDATA_IMAGEEXPANDED, IconCache.stockImages[IconCache.iconOpenFolder]);
item.setData(TREEITEMDATA_IMAGECOLLAPSED, IconCache.stockImages[IconCache.iconClosedFolder]);
}
}
\ No newline at end of file |