diff options
author | Jeff Brown | 2001-06-27 23:45:29 +0000 |
---|---|---|
committer | Jeff Brown | 2001-06-27 23:45:29 +0000 |
commit | e19f3ee2e5f1fa5577672314ef96ca3ab839cf03 (patch) | |
tree | 65e64fadf8fe98af88838977f6335a3f7bd1365d /examples/org.eclipse.swt.examples | |
parent | f49332c775fa13aa2d8bdf58dbda00cc4dbee67f (diff) | |
download | eclipse.platform.swt-e19f3ee2e5f1fa5577672314ef96ca3ab839cf03.tar.gz eclipse.platform.swt-e19f3ee2e5f1fa5577672314ef96ca3ab839cf03.tar.xz eclipse.platform.swt-e19f3ee2e5f1fa5577672314ef96ca3ab839cf03.zip |
*** empty log message ***
Diffstat (limited to 'examples/org.eclipse.swt.examples')
5 files changed, 143 insertions, 64 deletions
diff --git a/examples/org.eclipse.swt.examples/examples_fileviewer.properties b/examples/org.eclipse.swt.examples/examples_fileviewer.properties index e3073b7d84..7df80bcb1b 100755 --- a/examples/org.eclipse.swt.examples/examples_fileviewer.properties +++ b/examples/org.eclipse.swt.examples/examples_fileviewer.properties @@ -46,7 +46,6 @@ dialog.FailedDelete.description = An error occured while trying to delete "{0}". simulate.CopyFromTo.text = Simulated copy from "{0}" to "{1}". simulate.DirectoriesCreated.text = Simulated directories created for "{0}". -simulate.UnknownResource.text = Ignoring unknown resource "{0}". -simulate.Delete.text = Deleting "{0}". +simulate.Delete.text = Simulated delete of "{0}". error.FailedLaunch.message = Could not launch "{0}" 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 20bc41d0da..a2243b5748 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 @@ -33,6 +33,12 @@ public class FileViewer { private Label diskSpaceLabel;
private File currentDirectory = null;
+
+ /* Drag and drop optimizations -- avoid redundant updates */
+ private File[] deferredRefreshFiles = null;
+ private boolean deferredRefreshRequested = false;
+ private boolean isDragging = false; // don't refresh during drag and drop
+ private boolean isDropping = false; // don't refresh during drag and drop
/* Combo view */
private static final String COMBODATA_ROOTS = "Combo.roots";
@@ -424,11 +430,14 @@ public class FileViewer { dndSelection = tree.getSelection();
sourceNames = null;
event.doit = dndSelection.length > 0;
+ isDragging = true;
}
public void dragFinished(DragSourceEvent event){
dragSourceHandleDragFinished(event, sourceNames);
dndSelection = null;
sourceNames = null;
+ isDragging = false;
+ handleDeferredRefresh();
}
public void dragSetData(DragSourceEvent event){
if (dndSelection == null || dndSelection.length == 0) return;
@@ -455,6 +464,13 @@ public class FileViewer { dropTarget.setTransfer(new Transfer[] { FileTransfer.getInstance() });
dropTarget.addDropListener(new TreeDropFeedbackListener(tree));
dropTarget.addDropListener(new DropTargetAdapter() {
+ public void dragEnter(DropTargetEvent event) {
+ isDropping = true;
+ }
+ public void dragLeave(DropTargetEvent event) {
+ isDropping = false;
+ handleDeferredRefresh();
+ }
public void dragOver(DropTargetEvent event) {
dropTargetValidate(event, getTargetFile(event));
}
@@ -625,11 +641,14 @@ public class FileViewer { dndSelection = table.getSelection();
sourceNames = null;
event.doit = dndSelection.length > 0;
+ isDragging = true;
}
public void dragFinished(DragSourceEvent event){
dragSourceHandleDragFinished(event, sourceNames);
dndSelection = null;
sourceNames = null;
+ isDragging = false;
+ handleDeferredRefresh();
}
public void dragSetData(DragSourceEvent event){
if (dndSelection == null || dndSelection.length == 0) return;
@@ -655,6 +674,13 @@ public class FileViewer { 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) {
+ isDropping = true;
+ }
+ public void dragLeave(DropTargetEvent event) {
+ isDropping = false;
+ handleDeferredRefresh();
+ }
public void dragOver(DropTargetEvent event) {
dropTargetValidate(event, getTargetFile(event));
}
@@ -794,6 +820,30 @@ public class FileViewer { 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;
+ deferredRefreshRequested = false;
+ File[] files = deferredRefreshFiles;
+ deferredRefreshFiles = null;
+
+ // Does not refresh very intelligently at the moment.
+
/* Table view:
* Refreshes information about any files in the list and their children.
*/
@@ -1019,7 +1069,25 @@ public class FileViewer { searchFile = searchFile.getParentFile();
} while (searchFile != null);
- if (oldFile.isFile()) {
+ if (oldFile.isDirectory()) {
+ /*
+ * Copy a directory
+ */
+ if (simulateOnly) {
+ System.out.println(getResourceString("simulate.DirectoriesCreated.text",
+ new Object[] { newFile.getPath() }));
+ } else {
+ if (! newFile.mkdirs()) return false;
+ }
+ File[] subFiles = oldFile.listFiles();
+ if (subFiles != null) {
+ for (int i = 0; i < subFiles.length; i++) {
+ File oldSubFile = subFiles[i];
+ File newSubFile = new File(newFile, oldSubFile.getName());
+ if (! copyFileStructure(oldSubFile, newSubFile)) return false;
+ }
+ }
+ } else {
/*
* Copy a file
*/
@@ -1048,36 +1116,8 @@ public class FileViewer { }
}
}
- return true;
- } else if (oldFile.isDirectory()) {
- /*
- * Copy a directory
- */
- if (simulateOnly) {
- System.out.println(getResourceString("simulate.DirectoriesCreated.text",
- new Object[] { newFile.getPath() }));
- } else {
- if (! newFile.mkdirs()) return false;
- }
- File[] subFiles = oldFile.listFiles();
- if (subFiles != null) {
- for (int i = 0; i < subFiles.length; i++) {
- File oldSubFile = subFiles[i];
- File newSubFile = new File(newFile, oldSubFile.getName());
- if (! copyFileStructure(oldSubFile, newSubFile)) return false;
- }
- }
- return true;
- } else {
- /*
- * Unknown type
- */
- if (simulateOnly) {
- System.out.println(getResourceString("simulate.UnknownResource.text",
- new Object[] { oldFile.getPath() }));
- }
- return false; // error we don't know how to copy this
}
+ return true;
}
/**
diff --git a/examples/org.eclipse.swt.examples/org/eclipse/swt/examples/fileviewer/TreeDropFeedbackListener.java b/examples/org.eclipse.swt.examples/org/eclipse/swt/examples/fileviewer/TreeDropFeedbackListener.java index c40fa9b5ba..262eff01b4 100644 --- a/examples/org.eclipse.swt.examples/org/eclipse/swt/examples/fileviewer/TreeDropFeedbackListener.java +++ b/examples/org.eclipse.swt.examples/org/eclipse/swt/examples/fileviewer/TreeDropFeedbackListener.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.graphics.*;
import org.eclipse.swt.widgets.*;
/**
* TreeDropFeedbackListener provides the following feedback mechanisms for Trees
* during drag and drop operations:
* <ul>
* <li>Automatic Tree scrolling.
* <p>If the pointer drags over an item in the Tree near its upper or
* lower edges, the Tree will scroll so as to make previous or successive items visible
* onscreen. This behaviour is consistent with that of popular GUI systems.
* </p>
* <li>Automatic TreeItem expansion.
* <p>If the pointer hovers for a time over an item in the Tree that has not yet been
* expanded, the item is expanded automatically. This behaviour is consistent with
* that of popular GUI systems.
* </p>
* </ul>
* <p>
* To use it send addDropListener(new TreeDropFeedbackListener(tree)) to the DropTarget
* object attached to the Tree.
* </p>
*/
public class TreeDropFeedbackListener extends DropTargetAdapter {
public static final long DEFAULT_EXPAND_DELAY = 1000; // millis
private Tree tree;
private long hoverThreshhold = DEFAULT_EXPAND_DELAY;
private long hoverBegin = 0;
private TreeItem hoverItem = null;
/**
* Constructs a Tree scrolling Drop Listener
*
* @param tree the Tree that the DropTarget is attached to
*/
public TreeDropFeedbackListener(Tree tree) {
this.tree = tree;
}
/**
* Handles dragEnter events.
*/
public void dragEnter(DropTargetEvent event) {
hoverItem = null;
}
/**
* Handles dragExit events.
*/
public void dragExit(DropTargetEvent event) {
hoverItem = null;
}
/**
* Handles dragOver events.
*/
public void dragOver(DropTargetEvent event) {
Point point = tree.toControl(new Point(event.x, event.y));
// Get the item directly under the point
TreeItem item = tree.getItem(point);
if (item == null) return;
// Expand the item if we've been hovering over it for some time
if (item != hoverItem) {
// We just started hovering, remember this item
if ((item != null) && (! item.getExpanded())) {
hoverBegin = System.currentTimeMillis();
hoverItem = item;
} else {
hoverItem = null;
}
} else if (hoverItem != null) {
// We've been hovering for a while, expand if our timer elapsed
long hoverCurrent = System.currentTimeMillis();
if (hoverCurrent - hoverBegin >= hoverThreshhold) {
// Fake as if the user expanded the item manually
Event hoverEvent = new Event();
hoverEvent.x = event.x;
hoverEvent.y = event.y;
hoverEvent.item = hoverItem;
hoverEvent.time = (int) hoverCurrent;
hoverItem.setExpanded(true);
hoverItem = null;
tree.notifyListeners(SWT.Expand, hoverEvent);
return;
}
}
// Determine scroll direction according to whether we're nearer the top, middle, or bottom
Rectangle clientArea = tree.getClientArea();
int scrollRegionSize = Math.min(clientArea.height / 3, 24); // cut region into 3 parts
if (scrollRegionSize < 8) return; // don't scroll if the control is too small to make sense
TreeItem showItem = item;
for(;;) {
if (point.y < clientArea.y + scrollRegionSize) {
// in upper region
showItem = getPreviousVisibleItem(tree, showItem);
} else if (point.y > clientArea.height + clientArea.y - scrollRegionSize) {
// in lower region
showItem = getNextVisibleItem(tree, showItem, false);
} else {
// in middle region
break;
}
// Show the item (causes a scroll if it is outside of the visible region)
if (showItem == null) break;
tree.showItem(showItem);
// Test that we actually scrolled, if we didn't try again with the next item
if (item != tree.getItem(point)) break;
}
}
/**
* Given a TreeItem, locates the previous (above the specified item) visible TreeItem in a tree.
* <p>
* Note that the item may not be actually rendered onscreen though it would be
* visible were the control scrolled appropriately.
* </p>
*
* @param tree the Tree containing the items
* @param item the TreeItem whose previous visible neighbour is to be found
* @return the previous visible item, or null if none.
*/
private TreeItem getPreviousVisibleItem(Tree tree, TreeItem item) {
TreeItem parent = item.getParentItem();
TreeItem[] items = (parent != null) ? parent.getItems() : tree.getItems();
if (items != null) {
for (int i = items.length - 1; i > 0; --i) {
if (items[i] == item) return getLastVisibleChild(items[i - 1]);
}
}
return parent;
}
/**
* Given a TreeItem, locates the following (below the specified item) visible TreeItem in a tree.
* <p>
* Note that the item may not be actually rendered onscreen though it would be
* visible were the control scrolled appropriately.
* </p>
*
* @param tree the Tree containing the items
* @param item the TreeItem whose next visible neighbour is to be found
* @return the next visible item, or null if none.
*/
private TreeItem getNextVisibleItem(Tree tree, TreeItem item, boolean ignoreChildren) {
TreeItem parent = item.getParentItem();
TreeItem[] items = (parent != null) ? parent.getItems() : tree.getItems();
if (items != null) {
for (int i = 0; i < items.length; ++i) {
if (items[i] == item) {
if (! ignoreChildren && items[i].getExpanded()) {
items = items[i].getItems();
if (items != null && items.length > 0) return items[0];
}
if (i + 1 < items.length) return items[i + 1];
break;
}
}
if (parent != null) return getNextVisibleItem(tree, parent, true);
}
return null;
}
/**
* Given a TreeItem, locates its last (lowest) visible item
* <p>
* Note that the item may not be actually rendered onscreen though it would be
* visible were the control scrolled appropriately.
* </p>
*
* @param item the TreeItem whose last visible child is to be found
* @return the last visible child, or <code>item</code> if no visible children.
*/
private TreeItem getLastVisibleChild(TreeItem item) {
if (! item.getExpanded()) return item;
TreeItem[] items = item.getItems();
if (items == null || items.length == 0) return item;
return getLastVisibleChild(items[items.length - 1]);
}
}
\ 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.graphics.*;
import org.eclipse.swt.widgets.*;
/**
* TreeDropFeedbackListener provides the following feedback mechanisms for Trees
* during drag and drop operations:
* <ul>
* <li>Automatic Tree scrolling.
* <p>If the pointer drags over an item in the Tree near its upper or
* lower edges, the Tree will scroll so as to make previous or successive items visible
* onscreen. This behaviour is consistent with that of popular GUI systems.
* </p>
* <li>Automatic TreeItem expansion.
* <p>If the pointer hovers for a time over an item in the Tree that has not yet been
* expanded, the item is expanded automatically. This behaviour is consistent with
* that of popular GUI systems.
* </p>
* </ul>
* <p>
* To use it send addDropListener(new TreeDropFeedbackListener(tree)) to the DropTarget
* object attached to the Tree.
* </p>
*/
public class TreeDropFeedbackListener extends DropTargetAdapter {
protected static final int EXPAND_DELAY = 750; // millis
protected static final int SCROLL_DELAY = 50; // millis
protected static final int MAX_SCROLL_TRIES = 3;
protected Tree tree;
protected TreeItem hoverItem = null;
protected Point hoverPoint = null;
protected Runnable hoverRunnable = null;
protected long hoverResumeTime = 0;
/**
* Constructs a Tree scrolling Drop Listener
*
* @param tree the Tree that the DropTarget is attached to
*/
public TreeDropFeedbackListener(Tree tree) {
this.tree = tree;
}
/**
* Handles dragEnter events.
*/
public void dragEnter(DropTargetEvent event) {
hoverItem = null;
hoverRunnable = null;
}
/**
* Handles dragExit events.
*/
public void dragExit(DropTargetEvent event) {
hoverItem = null;
hoverRunnable = null;
}
/**
* Handles dragOver events.
* <p>
* On Windows, we receive multiple dragOver()'s even if the mouse has not moved.
* But we can't get timerExec()'s.<br>
* <br>
* On Motif, we only get dragOver()'s when the mouse has actually moved.
* But timerExec()'s are processed as usual.<br>
* <br>
* So to ensure cross-platform UI consistency we must handle both cases!
* </p>
*/
public void dragOver(DropTargetEvent event) {
Point point = tree.toControl(new Point(event.x, event.y));
// Fetch the item we're hovering over
TreeItem item = tree.getItem(point);
if ((hoverRunnable != null) && (item == hoverItem)) {
if (System.currentTimeMillis() >= hoverResumeTime) hoverRunnable.run();
return;
}
hoverItem = item;
hoverPoint = point;
/*
* Determine the candidate action for this position: nothing, scroll or expand
*/
hoverRunnable = null;
if (hoverItem == null) return; // Nothing to do
// Consider scrolling
Rectangle clientArea = tree.getClientArea();
int scrollRegionSize = Math.min(clientArea.height / 3, 24); // cut region into 3 parts
if (scrollRegionSize >= 8) {
// Decide scroll direction according to whether we're nearer the top, middle, or bottom
if (point.y < clientArea.y + scrollRegionSize) {
// in upper region
setTimer(SCROLL_DELAY, new ScrollRunnable(true));
return;
} else if (point.y > clientArea.height + clientArea.y - scrollRegionSize) {
// in lower region
setTimer(SCROLL_DELAY, new ScrollRunnable(false));
return;
}
// else we are in middle region
}
// else the region is too small for scrolling
tryExpand(0);
}
private void tryExpand(int recoverTime) {
// Expand the item if it hasn't already been expanded
if (! hoverItem.getExpanded()) {
setTimer(EXPAND_DELAY - recoverTime, new ExpandRunnable());
}
}
private void setTimer(int delay, Runnable runnable) {
hoverRunnable = runnable;
hoverResumeTime = System.currentTimeMillis() + delay;
tree.getDisplay().timerExec(delay, hoverRunnable);
}
/**
* Implements scrolling on a timer
*/
private class ScrollRunnable implements Runnable {
boolean isScrollUp;
public ScrollRunnable(boolean isScrollUp) {
this.isScrollUp = isScrollUp;
}
public void run() {
if (hoverRunnable != this) return;
hoverRunnable = null;
if (hoverItem.isDisposed()) return; // this can happen due to other events
System.out.println("Scroll");
// Loop until we see a different item (abort after a few tries, just in case)
TreeItem showItem = hoverItem;
for (int i = MAX_SCROLL_TRIES; i > 0; --i) {
showItem = (isScrollUp) ? getPreviousVisibleItem(tree, showItem) :
getNextVisibleItem(tree, showItem, false);
// Show the item (causes a scroll if it is outside of the visible region)
if (showItem == null) break;
tree.showItem(showItem);
if (hoverItem != tree.getItem(hoverPoint)) return; // stop if we actually scrolled
}
// We get here if we failed to scroll
tryExpand(SCROLL_DELAY); // try auto-expand if auto-scroll failed
}
}
/**
* Implements expanding on a timer
*/
private class ExpandRunnable implements Runnable {
public void run() {
if (hoverRunnable != this) return;
hoverRunnable = null;
if (hoverItem.isDisposed()) return; // this can happen due to other events
System.out.println("Expand");
// Fake as if the user expanded the item manually
Event hoverEvent = new Event();
hoverEvent.x = hoverPoint.x;
hoverEvent.y = hoverPoint.y;
hoverEvent.item = hoverItem;
hoverEvent.time = (int) System.currentTimeMillis();
hoverItem.setExpanded(true);
tree.notifyListeners(SWT.Expand, hoverEvent);
}
}
/**
* Given a TreeItem, locates the previous (above the specified item) visible TreeItem in a tree.
* <p>
* Note that the item may not be actually rendered onscreen though it would be
* visible were the control scrolled appropriately.
* </p>
*
* @param tree the Tree containing the items
* @param item the TreeItem whose previous visible neighbour is to be found
* @return the previous visible item, or null if none.
*/
private TreeItem getPreviousVisibleItem(Tree tree, TreeItem item) {
TreeItem parent = item.getParentItem();
TreeItem[] items = (parent != null) ? parent.getItems() : tree.getItems();
if (items != null) {
for (int i = items.length - 1; i > 0; --i) {
if (items[i] == item) return getLastVisibleChild(items[i - 1]);
}
}
return parent;
}
/**
* Given a TreeItem, locates the following (below the specified item) visible TreeItem in a tree.
* <p>
* Note that the item may not be actually rendered onscreen though it would be
* visible were the control scrolled appropriately.
* </p>
*
* @param tree the Tree containing the items
* @param item the TreeItem whose next visible neighbour is to be found
* @return the next visible item, or null if none.
*/
private TreeItem getNextVisibleItem(Tree tree, TreeItem item, boolean ignoreChildren) {
TreeItem parent = item.getParentItem();
TreeItem[] items = (parent != null) ? parent.getItems() : tree.getItems();
if (items != null) {
for (int i = 0; i < items.length; ++i) {
if (items[i] == item) {
if (! ignoreChildren && items[i].getExpanded()) {
items = items[i].getItems();
if (items != null && items.length > 0) return items[0];
}
if (i + 1 < items.length) return items[i + 1];
break;
}
}
if (parent != null) return getNextVisibleItem(tree, parent, true);
}
return null;
}
/**
* Given a TreeItem, locates its last (lowest) visible item
* <p>
* Note that the item may not be actually rendered onscreen though it would be
* visible were the control scrolled appropriately.
* </p>
*
* @param item the TreeItem whose last visible child is to be found
* @return the last visible child, or <code>item</code> if no visible children.
*/
private TreeItem getLastVisibleChild(TreeItem item) {
if (! item.getExpanded()) return item;
TreeItem[] items = item.getItems();
if (items == null || items.length == 0) return item;
return getLastVisibleChild(items[items.length - 1]);
}
}
\ 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 20bc41d0da..a2243b5748 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 @@ -33,6 +33,12 @@ public class FileViewer { private Label diskSpaceLabel;
private File currentDirectory = null;
+
+ /* Drag and drop optimizations -- avoid redundant updates */
+ private File[] deferredRefreshFiles = null;
+ private boolean deferredRefreshRequested = false;
+ private boolean isDragging = false; // don't refresh during drag and drop
+ private boolean isDropping = false; // don't refresh during drag and drop
/* Combo view */
private static final String COMBODATA_ROOTS = "Combo.roots";
@@ -424,11 +430,14 @@ public class FileViewer { dndSelection = tree.getSelection();
sourceNames = null;
event.doit = dndSelection.length > 0;
+ isDragging = true;
}
public void dragFinished(DragSourceEvent event){
dragSourceHandleDragFinished(event, sourceNames);
dndSelection = null;
sourceNames = null;
+ isDragging = false;
+ handleDeferredRefresh();
}
public void dragSetData(DragSourceEvent event){
if (dndSelection == null || dndSelection.length == 0) return;
@@ -455,6 +464,13 @@ public class FileViewer { dropTarget.setTransfer(new Transfer[] { FileTransfer.getInstance() });
dropTarget.addDropListener(new TreeDropFeedbackListener(tree));
dropTarget.addDropListener(new DropTargetAdapter() {
+ public void dragEnter(DropTargetEvent event) {
+ isDropping = true;
+ }
+ public void dragLeave(DropTargetEvent event) {
+ isDropping = false;
+ handleDeferredRefresh();
+ }
public void dragOver(DropTargetEvent event) {
dropTargetValidate(event, getTargetFile(event));
}
@@ -625,11 +641,14 @@ public class FileViewer { dndSelection = table.getSelection();
sourceNames = null;
event.doit = dndSelection.length > 0;
+ isDragging = true;
}
public void dragFinished(DragSourceEvent event){
dragSourceHandleDragFinished(event, sourceNames);
dndSelection = null;
sourceNames = null;
+ isDragging = false;
+ handleDeferredRefresh();
}
public void dragSetData(DragSourceEvent event){
if (dndSelection == null || dndSelection.length == 0) return;
@@ -655,6 +674,13 @@ public class FileViewer { 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) {
+ isDropping = true;
+ }
+ public void dragLeave(DropTargetEvent event) {
+ isDropping = false;
+ handleDeferredRefresh();
+ }
public void dragOver(DropTargetEvent event) {
dropTargetValidate(event, getTargetFile(event));
}
@@ -794,6 +820,30 @@ public class FileViewer { 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;
+ deferredRefreshRequested = false;
+ File[] files = deferredRefreshFiles;
+ deferredRefreshFiles = null;
+
+ // Does not refresh very intelligently at the moment.
+
/* Table view:
* Refreshes information about any files in the list and their children.
*/
@@ -1019,7 +1069,25 @@ public class FileViewer { searchFile = searchFile.getParentFile();
} while (searchFile != null);
- if (oldFile.isFile()) {
+ if (oldFile.isDirectory()) {
+ /*
+ * Copy a directory
+ */
+ if (simulateOnly) {
+ System.out.println(getResourceString("simulate.DirectoriesCreated.text",
+ new Object[] { newFile.getPath() }));
+ } else {
+ if (! newFile.mkdirs()) return false;
+ }
+ File[] subFiles = oldFile.listFiles();
+ if (subFiles != null) {
+ for (int i = 0; i < subFiles.length; i++) {
+ File oldSubFile = subFiles[i];
+ File newSubFile = new File(newFile, oldSubFile.getName());
+ if (! copyFileStructure(oldSubFile, newSubFile)) return false;
+ }
+ }
+ } else {
/*
* Copy a file
*/
@@ -1048,36 +1116,8 @@ public class FileViewer { }
}
}
- return true;
- } else if (oldFile.isDirectory()) {
- /*
- * Copy a directory
- */
- if (simulateOnly) {
- System.out.println(getResourceString("simulate.DirectoriesCreated.text",
- new Object[] { newFile.getPath() }));
- } else {
- if (! newFile.mkdirs()) return false;
- }
- File[] subFiles = oldFile.listFiles();
- if (subFiles != null) {
- for (int i = 0; i < subFiles.length; i++) {
- File oldSubFile = subFiles[i];
- File newSubFile = new File(newFile, oldSubFile.getName());
- if (! copyFileStructure(oldSubFile, newSubFile)) return false;
- }
- }
- return true;
- } else {
- /*
- * Unknown type
- */
- if (simulateOnly) {
- System.out.println(getResourceString("simulate.UnknownResource.text",
- new Object[] { oldFile.getPath() }));
- }
- return false; // error we don't know how to copy this
}
+ return true;
}
/**
diff --git a/examples/org.eclipse.swt.examples/src/org/eclipse/swt/examples/fileviewer/TreeDropFeedbackListener.java b/examples/org.eclipse.swt.examples/src/org/eclipse/swt/examples/fileviewer/TreeDropFeedbackListener.java index c40fa9b5ba..262eff01b4 100644 --- a/examples/org.eclipse.swt.examples/src/org/eclipse/swt/examples/fileviewer/TreeDropFeedbackListener.java +++ b/examples/org.eclipse.swt.examples/src/org/eclipse/swt/examples/fileviewer/TreeDropFeedbackListener.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.graphics.*;
import org.eclipse.swt.widgets.*;
/**
* TreeDropFeedbackListener provides the following feedback mechanisms for Trees
* during drag and drop operations:
* <ul>
* <li>Automatic Tree scrolling.
* <p>If the pointer drags over an item in the Tree near its upper or
* lower edges, the Tree will scroll so as to make previous or successive items visible
* onscreen. This behaviour is consistent with that of popular GUI systems.
* </p>
* <li>Automatic TreeItem expansion.
* <p>If the pointer hovers for a time over an item in the Tree that has not yet been
* expanded, the item is expanded automatically. This behaviour is consistent with
* that of popular GUI systems.
* </p>
* </ul>
* <p>
* To use it send addDropListener(new TreeDropFeedbackListener(tree)) to the DropTarget
* object attached to the Tree.
* </p>
*/
public class TreeDropFeedbackListener extends DropTargetAdapter {
public static final long DEFAULT_EXPAND_DELAY = 1000; // millis
private Tree tree;
private long hoverThreshhold = DEFAULT_EXPAND_DELAY;
private long hoverBegin = 0;
private TreeItem hoverItem = null;
/**
* Constructs a Tree scrolling Drop Listener
*
* @param tree the Tree that the DropTarget is attached to
*/
public TreeDropFeedbackListener(Tree tree) {
this.tree = tree;
}
/**
* Handles dragEnter events.
*/
public void dragEnter(DropTargetEvent event) {
hoverItem = null;
}
/**
* Handles dragExit events.
*/
public void dragExit(DropTargetEvent event) {
hoverItem = null;
}
/**
* Handles dragOver events.
*/
public void dragOver(DropTargetEvent event) {
Point point = tree.toControl(new Point(event.x, event.y));
// Get the item directly under the point
TreeItem item = tree.getItem(point);
if (item == null) return;
// Expand the item if we've been hovering over it for some time
if (item != hoverItem) {
// We just started hovering, remember this item
if ((item != null) && (! item.getExpanded())) {
hoverBegin = System.currentTimeMillis();
hoverItem = item;
} else {
hoverItem = null;
}
} else if (hoverItem != null) {
// We've been hovering for a while, expand if our timer elapsed
long hoverCurrent = System.currentTimeMillis();
if (hoverCurrent - hoverBegin >= hoverThreshhold) {
// Fake as if the user expanded the item manually
Event hoverEvent = new Event();
hoverEvent.x = event.x;
hoverEvent.y = event.y;
hoverEvent.item = hoverItem;
hoverEvent.time = (int) hoverCurrent;
hoverItem.setExpanded(true);
hoverItem = null;
tree.notifyListeners(SWT.Expand, hoverEvent);
return;
}
}
// Determine scroll direction according to whether we're nearer the top, middle, or bottom
Rectangle clientArea = tree.getClientArea();
int scrollRegionSize = Math.min(clientArea.height / 3, 24); // cut region into 3 parts
if (scrollRegionSize < 8) return; // don't scroll if the control is too small to make sense
TreeItem showItem = item;
for(;;) {
if (point.y < clientArea.y + scrollRegionSize) {
// in upper region
showItem = getPreviousVisibleItem(tree, showItem);
} else if (point.y > clientArea.height + clientArea.y - scrollRegionSize) {
// in lower region
showItem = getNextVisibleItem(tree, showItem, false);
} else {
// in middle region
break;
}
// Show the item (causes a scroll if it is outside of the visible region)
if (showItem == null) break;
tree.showItem(showItem);
// Test that we actually scrolled, if we didn't try again with the next item
if (item != tree.getItem(point)) break;
}
}
/**
* Given a TreeItem, locates the previous (above the specified item) visible TreeItem in a tree.
* <p>
* Note that the item may not be actually rendered onscreen though it would be
* visible were the control scrolled appropriately.
* </p>
*
* @param tree the Tree containing the items
* @param item the TreeItem whose previous visible neighbour is to be found
* @return the previous visible item, or null if none.
*/
private TreeItem getPreviousVisibleItem(Tree tree, TreeItem item) {
TreeItem parent = item.getParentItem();
TreeItem[] items = (parent != null) ? parent.getItems() : tree.getItems();
if (items != null) {
for (int i = items.length - 1; i > 0; --i) {
if (items[i] == item) return getLastVisibleChild(items[i - 1]);
}
}
return parent;
}
/**
* Given a TreeItem, locates the following (below the specified item) visible TreeItem in a tree.
* <p>
* Note that the item may not be actually rendered onscreen though it would be
* visible were the control scrolled appropriately.
* </p>
*
* @param tree the Tree containing the items
* @param item the TreeItem whose next visible neighbour is to be found
* @return the next visible item, or null if none.
*/
private TreeItem getNextVisibleItem(Tree tree, TreeItem item, boolean ignoreChildren) {
TreeItem parent = item.getParentItem();
TreeItem[] items = (parent != null) ? parent.getItems() : tree.getItems();
if (items != null) {
for (int i = 0; i < items.length; ++i) {
if (items[i] == item) {
if (! ignoreChildren && items[i].getExpanded()) {
items = items[i].getItems();
if (items != null && items.length > 0) return items[0];
}
if (i + 1 < items.length) return items[i + 1];
break;
}
}
if (parent != null) return getNextVisibleItem(tree, parent, true);
}
return null;
}
/**
* Given a TreeItem, locates its last (lowest) visible item
* <p>
* Note that the item may not be actually rendered onscreen though it would be
* visible were the control scrolled appropriately.
* </p>
*
* @param item the TreeItem whose last visible child is to be found
* @return the last visible child, or <code>item</code> if no visible children.
*/
private TreeItem getLastVisibleChild(TreeItem item) {
if (! item.getExpanded()) return item;
TreeItem[] items = item.getItems();
if (items == null || items.length == 0) return item;
return getLastVisibleChild(items[items.length - 1]);
}
}
\ 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.graphics.*;
import org.eclipse.swt.widgets.*;
/**
* TreeDropFeedbackListener provides the following feedback mechanisms for Trees
* during drag and drop operations:
* <ul>
* <li>Automatic Tree scrolling.
* <p>If the pointer drags over an item in the Tree near its upper or
* lower edges, the Tree will scroll so as to make previous or successive items visible
* onscreen. This behaviour is consistent with that of popular GUI systems.
* </p>
* <li>Automatic TreeItem expansion.
* <p>If the pointer hovers for a time over an item in the Tree that has not yet been
* expanded, the item is expanded automatically. This behaviour is consistent with
* that of popular GUI systems.
* </p>
* </ul>
* <p>
* To use it send addDropListener(new TreeDropFeedbackListener(tree)) to the DropTarget
* object attached to the Tree.
* </p>
*/
public class TreeDropFeedbackListener extends DropTargetAdapter {
protected static final int EXPAND_DELAY = 750; // millis
protected static final int SCROLL_DELAY = 50; // millis
protected static final int MAX_SCROLL_TRIES = 3;
protected Tree tree;
protected TreeItem hoverItem = null;
protected Point hoverPoint = null;
protected Runnable hoverRunnable = null;
protected long hoverResumeTime = 0;
/**
* Constructs a Tree scrolling Drop Listener
*
* @param tree the Tree that the DropTarget is attached to
*/
public TreeDropFeedbackListener(Tree tree) {
this.tree = tree;
}
/**
* Handles dragEnter events.
*/
public void dragEnter(DropTargetEvent event) {
hoverItem = null;
hoverRunnable = null;
}
/**
* Handles dragExit events.
*/
public void dragExit(DropTargetEvent event) {
hoverItem = null;
hoverRunnable = null;
}
/**
* Handles dragOver events.
* <p>
* On Windows, we receive multiple dragOver()'s even if the mouse has not moved.
* But we can't get timerExec()'s.<br>
* <br>
* On Motif, we only get dragOver()'s when the mouse has actually moved.
* But timerExec()'s are processed as usual.<br>
* <br>
* So to ensure cross-platform UI consistency we must handle both cases!
* </p>
*/
public void dragOver(DropTargetEvent event) {
Point point = tree.toControl(new Point(event.x, event.y));
// Fetch the item we're hovering over
TreeItem item = tree.getItem(point);
if ((hoverRunnable != null) && (item == hoverItem)) {
if (System.currentTimeMillis() >= hoverResumeTime) hoverRunnable.run();
return;
}
hoverItem = item;
hoverPoint = point;
/*
* Determine the candidate action for this position: nothing, scroll or expand
*/
hoverRunnable = null;
if (hoverItem == null) return; // Nothing to do
// Consider scrolling
Rectangle clientArea = tree.getClientArea();
int scrollRegionSize = Math.min(clientArea.height / 3, 24); // cut region into 3 parts
if (scrollRegionSize >= 8) {
// Decide scroll direction according to whether we're nearer the top, middle, or bottom
if (point.y < clientArea.y + scrollRegionSize) {
// in upper region
setTimer(SCROLL_DELAY, new ScrollRunnable(true));
return;
} else if (point.y > clientArea.height + clientArea.y - scrollRegionSize) {
// in lower region
setTimer(SCROLL_DELAY, new ScrollRunnable(false));
return;
}
// else we are in middle region
}
// else the region is too small for scrolling
tryExpand(0);
}
private void tryExpand(int recoverTime) {
// Expand the item if it hasn't already been expanded
if (! hoverItem.getExpanded()) {
setTimer(EXPAND_DELAY - recoverTime, new ExpandRunnable());
}
}
private void setTimer(int delay, Runnable runnable) {
hoverRunnable = runnable;
hoverResumeTime = System.currentTimeMillis() + delay;
tree.getDisplay().timerExec(delay, hoverRunnable);
}
/**
* Implements scrolling on a timer
*/
private class ScrollRunnable implements Runnable {
boolean isScrollUp;
public ScrollRunnable(boolean isScrollUp) {
this.isScrollUp = isScrollUp;
}
public void run() {
if (hoverRunnable != this) return;
hoverRunnable = null;
if (hoverItem.isDisposed()) return; // this can happen due to other events
System.out.println("Scroll");
// Loop until we see a different item (abort after a few tries, just in case)
TreeItem showItem = hoverItem;
for (int i = MAX_SCROLL_TRIES; i > 0; --i) {
showItem = (isScrollUp) ? getPreviousVisibleItem(tree, showItem) :
getNextVisibleItem(tree, showItem, false);
// Show the item (causes a scroll if it is outside of the visible region)
if (showItem == null) break;
tree.showItem(showItem);
if (hoverItem != tree.getItem(hoverPoint)) return; // stop if we actually scrolled
}
// We get here if we failed to scroll
tryExpand(SCROLL_DELAY); // try auto-expand if auto-scroll failed
}
}
/**
* Implements expanding on a timer
*/
private class ExpandRunnable implements Runnable {
public void run() {
if (hoverRunnable != this) return;
hoverRunnable = null;
if (hoverItem.isDisposed()) return; // this can happen due to other events
System.out.println("Expand");
// Fake as if the user expanded the item manually
Event hoverEvent = new Event();
hoverEvent.x = hoverPoint.x;
hoverEvent.y = hoverPoint.y;
hoverEvent.item = hoverItem;
hoverEvent.time = (int) System.currentTimeMillis();
hoverItem.setExpanded(true);
tree.notifyListeners(SWT.Expand, hoverEvent);
}
}
/**
* Given a TreeItem, locates the previous (above the specified item) visible TreeItem in a tree.
* <p>
* Note that the item may not be actually rendered onscreen though it would be
* visible were the control scrolled appropriately.
* </p>
*
* @param tree the Tree containing the items
* @param item the TreeItem whose previous visible neighbour is to be found
* @return the previous visible item, or null if none.
*/
private TreeItem getPreviousVisibleItem(Tree tree, TreeItem item) {
TreeItem parent = item.getParentItem();
TreeItem[] items = (parent != null) ? parent.getItems() : tree.getItems();
if (items != null) {
for (int i = items.length - 1; i > 0; --i) {
if (items[i] == item) return getLastVisibleChild(items[i - 1]);
}
}
return parent;
}
/**
* Given a TreeItem, locates the following (below the specified item) visible TreeItem in a tree.
* <p>
* Note that the item may not be actually rendered onscreen though it would be
* visible were the control scrolled appropriately.
* </p>
*
* @param tree the Tree containing the items
* @param item the TreeItem whose next visible neighbour is to be found
* @return the next visible item, or null if none.
*/
private TreeItem getNextVisibleItem(Tree tree, TreeItem item, boolean ignoreChildren) {
TreeItem parent = item.getParentItem();
TreeItem[] items = (parent != null) ? parent.getItems() : tree.getItems();
if (items != null) {
for (int i = 0; i < items.length; ++i) {
if (items[i] == item) {
if (! ignoreChildren && items[i].getExpanded()) {
items = items[i].getItems();
if (items != null && items.length > 0) return items[0];
}
if (i + 1 < items.length) return items[i + 1];
break;
}
}
if (parent != null) return getNextVisibleItem(tree, parent, true);
}
return null;
}
/**
* Given a TreeItem, locates its last (lowest) visible item
* <p>
* Note that the item may not be actually rendered onscreen though it would be
* visible were the control scrolled appropriately.
* </p>
*
* @param item the TreeItem whose last visible child is to be found
* @return the last visible child, or <code>item</code> if no visible children.
*/
private TreeItem getLastVisibleChild(TreeItem item) {
if (! item.getExpanded()) return item;
TreeItem[] items = item.getItems();
if (items == null || items.length == 0) return item;
return getLastVisibleChild(items[items.length - 1]);
}
}
\ No newline at end of file |