sourceBounds);
}
// Create a tracker. This is just an XOR rect on the screen.
// As it moves we notify the drag listeners.
final Tracker tracker = new Tracker(display, SWT.NULL);
tracker.setStippled(true);
tracker.addListener(SWT.Move, new Listener() {
public void handleEvent(final Event event) {
display.syncExec(new Runnable() {
public void run() {
// Get the curslor location as a point
Point location = new Point(event.x, event.y);
// Select a drop target; use the global one by default
IDropTarget target = null;
Control targetControl = display.getCursorControl();
// Get the drop target for this location
target = getDropTarget(targetControl,
draggedItem, location,
tracker.getRectangles()[0]);
// Set up the tracker feedback based on the target
Rectangle snapTarget = null;
if (target != null) {
snapTarget = target.getSnapRectangle();
tracker.setCursor(target.getCursor());
} else {
tracker.setCursor(DragCursors
.getCursor(DragCursors.INVALID));
}
// If snapping then reset the tracker's rectangle based on the current drop target
if (allowSnapping) {
if (snapTarget == null) {
snapTarget = new Rectangle(sourceBounds.x
+ location.x - initialLocation.x,
sourceBounds.y + location.y
- initialLocation.y,
sourceBounds.width, sourceBounds.height);
}
// Try to prevent flicker: don't change the rectangles if they're already in
// the right location
Rectangle[] currentRectangles = tracker.getRectangles();
if (!(currentRectangles.length == 1 && currentRectangles[0]
.equals(snapTarget))) {
tracker.setRectangles(new Rectangle[] { snapTarget });
}
}
}
});
}
});
// Setup...when the drag starts we might already be over a valid target, check this...
// If there is a 'global' target then skip the check
IDropTarget target = null;
Control startControl = display.getCursorControl();
if (startControl != null && allowSnapping) {
target = getDropTarget(startControl,
draggedItem, initialLocation,
sourceBounds);
}
// Set up an initial tracker rectangle
Rectangle startRect = sourceBounds;
if (target != null) {
Rectangle rect = target.getSnapRectangle();
if (rect != null) {
startRect = rect;
}
tracker.setCursor(target.getCursor());
}
if (startRect != null) {
tracker.setRectangles(new Rectangle[] { Geometry.copy(startRect)});
}
// Tracking Loop...tracking is preformed on the 'SWT.Move' listener registered
// against the tracker.
// HACK:
// Some control needs to capture the mouse during the drag or other
// controls will interfere with the cursor
Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
if (shell != null) {
shell.setCapture(true);
}
// Run tracker until mouse up occurs or escape key pressed.
boolean trackingOk = tracker.open();
// HACK:
// Release the mouse now
if (shell != null) {
shell.setCapture(false);
}
// Done tracking...
// Get the current drop target
IDropTarget dropTarget = null;
Point finalLocation = display.getCursorLocation();
Control targetControl = display.getCursorControl();
dropTarget = getDropTarget(targetControl, draggedItem,
finalLocation, tracker.getRectangles()[0]);
// Cleanup...
tracker.dispose();
// if we're going to perform a 'drop' then delay the issuing of the 'finished'
// callback until after it's done...
if (trackingOk) {
return dropTarget;