/*******************************************************************************
 * Copyright (c) 2000, 2017 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.dnd;

import java.util.*;

import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.cocoa.*;
import org.eclipse.swt.widgets.*;

/**
 *
 * Class <code>DropTarget</code> defines the target object for a drag and drop transfer.
 *
 * <p>IMPORTANT: This class is <em>not</em> intended to be subclassed.</p>
 *
 * <p>This class identifies the <code>Control</code> over which the user must position the cursor
 * in order to drop the data being transferred.  It also specifies what data types can be dropped on
 * this control and what operations can be performed.  You may have several DropTragets in an
 * application but there can only be a one to one mapping between a <code>Control</code> and a <code>DropTarget</code>.
 * The DropTarget can receive data from within the same application or from other applications
 * (such as text dragged from a text editor like Word).</p>
 *
 * <code><pre>
 *	int operations = DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK;
 *	Transfer[] types = new Transfer[] {TextTransfer.getInstance()};
 *	DropTarget target = new DropTarget(label, operations);
 *	target.setTransfer(types);
 * </code></pre>
 *
 * <p>The application is notified of data being dragged over this control and of when a drop occurs by
 * implementing the interface <code>DropTargetListener</code> which uses the class
 * <code>DropTargetEvent</code>.  The application can modify the type of drag being performed
 * on this Control at any stage of the drag by modifying the <code>event.detail</code> field or the
 * <code>event.currentDataType</code> field.  When the data is dropped, it is the responsibility of
 * the application to copy this data for its own purposes.
 *
 * <code><pre>
 *	target.addDropListener (new DropTargetListener() {
 *		public void dragEnter(DropTargetEvent event) {};
 *		public void dragOver(DropTargetEvent event) {};
 *		public void dragLeave(DropTargetEvent event) {};
 *		public void dragOperationChanged(DropTargetEvent event) {};
 *		public void dropAccept(DropTargetEvent event) {}
 *		public void drop(DropTargetEvent event) {
 *			// A drop has occurred, copy over the data
 *			if (event.data == null) { // no data to copy, indicate failure in event.detail
 *				event.detail = DND.DROP_NONE;
 *				return;
 *			}
 *			label.setText ((String) event.data); // data copied to label text
 *		}
 * 	});
 * </pre></code>
 *
 * <dl>
 *	<dt><b>Styles</b></dt> <dd>DND.DROP_NONE, DND.DROP_COPY, DND.DROP_MOVE, DND.DROP_LINK</dd>
 *	<dt><b>Events</b></dt> <dd>DND.DragEnter, DND.DragLeave, DND.DragOver, DND.DragOperationChanged,
 *                             DND.DropAccept, DND.Drop </dd>
 * </dl>
 *
 * @see <a href="http://www.eclipse.org/swt/snippets/#dnd">Drag and Drop snippets</a>
 * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: DNDExample</a>
 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
 * @noextend This class is not intended to be subclassed by clients.
 */
@SuppressWarnings({"rawtypes", "unchecked"})
public class DropTarget extends Widget {

	static Callback dropTarget2Args, dropTarget3Args, dropTarget6Args;
	static long /*int*/ proc2Args, proc3Args, proc6Args;
	static final String LOCK_CURSOR = "org.eclipse.swt.internal.lockCursor"; //$NON-NLS-1$

	static {
		Class clazz = DropTarget.class;

		dropTarget2Args = new Callback(clazz, "dropTargetProc", 2);
		proc2Args = dropTarget2Args.getAddress();
		if (proc2Args == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);

		dropTarget3Args = new Callback(clazz, "dropTargetProc", 3);
		proc3Args = dropTarget3Args.getAddress();
		if (proc3Args == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);

		dropTarget6Args = new Callback(clazz, "dropTargetProc", 6);
		proc6Args = dropTarget6Args.getAddress();
		if (proc6Args == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
	}

	static boolean dropNotAllowed = false;

	Control control;
	Listener controlListener;
	Transfer[] transferAgents = new Transfer[0];
	DropTargetEffect dropEffect;
	int feedback = DND.FEEDBACK_NONE;

	// Track application selections
	TransferData selectedDataType;
	int selectedOperation;

	// workaround - There is no event for "operation changed" so track operation based on key state
	int keyOperation = -1;

	static final String DEFAULT_DROP_TARGET_EFFECT = "DEFAULT_DROP_TARGET_EFFECT"; //$NON-NLS-1$
	static final String IS_ACTIVE = "org.eclipse.swt.internal.isActive"; //$NON-NLS-1$

void addDragHandlers() {
	// Our strategy here is to dynamically add methods to the control's class that are required
	// by NSDraggingDestination. Then, when setTransfer is called, we just register
	// the types with the Control's NSView and AppKit will call the methods in the protocol
	// when a drag goes over the view.

	long /*int*/ cls = OS.object_getClass(control.view.id);

	if (cls == 0) {
		DND.error(DND.ERROR_CANNOT_INIT_DROP);
	}

	// If we already added it, no need to do it again.
	long /*int*/ procPtr = OS.class_getMethodImplementation(cls, OS.sel_draggingEntered_);
	if (procPtr == proc3Args) return;
	addDragHandlers(cls);

	// If the content view can be image view, then add the dragging methods to image view too.
	// This is used by Label so that dragging can work even when the Label has an image set on it.
	long /*int*/ imageView = 0;
	if ((imageView = OS.objc_msgSend(control.view.id, OS.sel_getImageView)) != 0) {
		cls = OS.object_getClass(imageView);
		addDragHandlers(cls);
	}
}

void addDragHandlers (long /*int*/ cls) {
	// Add the NSDraggingDestination callbacks
	OS.class_addMethod(cls, OS.sel_draggingEntered_, proc3Args, "@:@");
	OS.class_addMethod(cls, OS.sel_draggingUpdated_, proc3Args, "@:@");
	OS.class_addMethod(cls, OS.sel_draggingExited_, proc3Args, "@:@");
	OS.class_addMethod(cls, OS.sel_performDragOperation_, proc3Args, "@:@");
	OS.class_addMethod(cls, OS.sel_wantsPeriodicDraggingUpdates, proc2Args, "@:");

	if (OS.class_getSuperclass(cls) == OS.class_NSOutlineView) {
		OS.class_addMethod(cls, OS.sel_outlineView_acceptDrop_item_childIndex_, proc6Args, "@:@@@i");
		OS.class_addMethod(cls, OS.sel_outlineView_validateDrop_proposedItem_proposedChildIndex_, proc6Args, "@:@@@i");
	} else if (OS.class_getSuperclass(cls) == OS.class_NSTableView) {
		OS.class_addMethod(cls, OS.sel_tableView_acceptDrop_row_dropOperation_, proc6Args, "@:@@@i");
		OS.class_addMethod(cls, OS.sel_tableView_validateDrop_proposedRow_proposedDropOperation_, proc6Args, "@:@@@i");
	}
}

/**
 * Adds the listener to the collection of listeners who will
 * be notified when a drag and drop operation is in progress, by sending
 * it one of the messages defined in the <code>DropTargetListener</code>
 * interface.
 *
 * <p><ul>
 * <li><code>dragEnter</code> is called when the cursor has entered the drop target boundaries
 * <li><code>dragLeave</code> is called when the cursor has left the drop target boundaries and just before
 * the drop occurs or is cancelled.
 * <li><code>dragOperationChanged</code> is called when the operation being performed has changed
 * (usually due to the user changing the selected modifier key(s) while dragging)
 * <li><code>dragOver</code> is called when the cursor is moving over the drop target
 * <li><code>dropAccept</code> is called just before the drop is performed.  The drop target is given
 * the chance to change the nature of the drop or veto the drop by setting the <code>event.detail</code> field
 * <li><code>drop</code> is called when the data is being dropped
 * </ul></p>
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see DropTargetListener
 * @see #getDropListeners
 * @see #removeDropListener
 * @see DropTargetEvent
 */
public void addDropListener(DropTargetListener listener) {
	if (listener == null) DND.error (SWT.ERROR_NULL_ARGUMENT);
	DNDListener typedListener = new DNDListener (listener);
	typedListener.dndWidget = this;
	addListener (DND.DragEnter, typedListener);
	addListener (DND.DragLeave, typedListener);
	addListener (DND.DragOver, typedListener);
	addListener (DND.DragOperationChanged, typedListener);
	addListener (DND.Drop, typedListener);
	addListener (DND.DropAccept, typedListener);
}

long /*int*/ dndCallSuper (long /*int*/ id, long /*int*/ sel, long /*int*/ arg0) {
	objc_super super_struct = new objc_super();
	super_struct.receiver = id;
	super_struct.super_class = OS.objc_msgSend(id, OS.sel_superclass);
	return OS.objc_msgSendSuper(super_struct, sel, arg0);
}

static int checkStyle (int style) {
	if (style == SWT.NONE) return DND.DROP_MOVE;
	return style;
}

@Override
protected void checkSubclass () {
	String name = getClass().getName ();
	String validName = DropTarget.class.getName();
	if (!validName.equals(name)) {
		DND.error (SWT.ERROR_INVALID_SUBCLASS);
	}
}

int draggingEntered(long /*int*/ id, long /*int*/ sel, NSObject sender) {
	if (sender == null) return OS.NSDragOperationNone;

	DNDEvent event = new DNDEvent();
	if (!setEventData(sender, event)) {
		keyOperation = -1;
		setDropNotAllowed();
		return OS.NSDragOperationNone;
	}

	int allowedOperations = event.operations;
	TransferData[] allowedDataTypes = new TransferData[event.dataTypes.length];
	System.arraycopy(event.dataTypes, 0, allowedDataTypes, 0, allowedDataTypes.length);

	selectedDataType = null;
	selectedOperation = DND.DROP_NONE;
	notifyListeners(DND.DragEnter, event);

	if (event.detail == DND.DROP_DEFAULT) {
		event.detail = (allowedOperations & DND.DROP_MOVE) != 0 ? DND.DROP_MOVE : DND.DROP_NONE;
	}

	if (event.dataType != null) {
		for (int i = 0; i < allowedDataTypes.length; i++) {
			if (allowedDataTypes[i].type == event.dataType.type) {
				selectedDataType = allowedDataTypes[i];
				break;
			}
		}
	}

	if (selectedDataType != null && (allowedOperations & event.detail) != 0) {
		selectedOperation = event.detail;
	}

	if (selectedOperation == DND.DROP_NONE) {
		setDropNotAllowed();
	} else {
		if(((Boolean)control.getData(IS_ACTIVE)).booleanValue() == false) {
			setDropNotAllowed();
		} else {
			clearDropNotAllowed();
		}
	}

	if (new NSObject(id).isKindOfClass(OS.class_NSTableView)) {
		return (int)/*64*/dndCallSuper(id, sel, sender.id);
	}
	return opToOsOp(selectedOperation);
}

void draggingExited(long /*int*/ id, long /*int*/ sel, NSObject sender) {
	clearDropNotAllowed();
	if (keyOperation == -1) return;
	keyOperation = -1;

	DNDEvent event = new DNDEvent();
	event.widget = this;
	event.time = (int)System.currentTimeMillis();
	event.detail = DND.DROP_NONE;
	notifyListeners(DND.DragLeave, event);

	if (new NSObject(id).isKindOfClass(OS.class_NSTableView)) {
		dndCallSuper(id, sel, sender.id);
	}
}

int draggingUpdated(long /*int*/ id, long /*int*/ sel, NSObject sender) {
	if (sender == null) return OS.NSDragOperationNone;
	int oldKeyOperation = keyOperation;

	DNDEvent event = new DNDEvent();
	if (!setEventData(sender, event)) {
		keyOperation = -1;
		setDropNotAllowed();
		return OS.NSDragOperationNone;
	}

	int allowedOperations = event.operations;
	TransferData[] allowedDataTypes = new TransferData[event.dataTypes.length];
	System.arraycopy(event.dataTypes, 0, allowedDataTypes, 0, allowedDataTypes.length);

	if (keyOperation == oldKeyOperation) {
		event.type = DND.DragOver;
		event.dataType = selectedDataType;
		event.detail = selectedOperation;
	} else {
		event.type = DND.DragOperationChanged;
		event.dataType = selectedDataType;
	}

	selectedDataType = null;
	selectedOperation = DND.DROP_NONE;
	notifyListeners(event.type, event);
	if (event.detail == DND.DROP_DEFAULT) {
		event.detail = (allowedOperations & DND.DROP_MOVE) != 0 ? DND.DROP_MOVE : DND.DROP_NONE;
	}

	if (event.dataType != null) {
		for (int i = 0; i < allowedDataTypes.length; i++) {
			if (allowedDataTypes[i].type == event.dataType.type) {
				selectedDataType = allowedDataTypes[i];
				break;
			}
		}
	}

	if (selectedDataType != null && (event.detail & allowedOperations) != 0) {
		selectedOperation = event.detail;
	}

	if (selectedOperation == DND.DROP_NONE) {
		setDropNotAllowed();
	} else {
		if(((Boolean)control.getData(IS_ACTIVE)).booleanValue() == false) {
			setDropNotAllowed();
		} else {
			clearDropNotAllowed();
		}
	}

	if (new NSObject(id).isKindOfClass(OS.class_NSTableView)) {
		return (int)/*64*/dndCallSuper(id, sel, sender.id);
	}

	return opToOsOp(selectedOperation);
}

/**
 * Creates a new <code>DropTarget</code> to allow data to be dropped on the specified
 * <code>Control</code>.
 * Creating an instance of a DropTarget may cause system resources to be allocated
 * depending on the platform.  It is therefore mandatory that the DropTarget instance
 * be disposed when no longer required.
 *
 * @param control the <code>Control</code> over which the user positions the cursor to drop the data
 * @param style the bitwise OR'ing of allowed operations; this may be a combination of any of
 *		   DND.DROP_NONE, DND.DROP_COPY, DND.DROP_MOVE, DND.DROP_LINK
 *
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
 *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
 * </ul>
 * @exception SWTError <ul>
 *    <li>ERROR_CANNOT_INIT_DROP - unable to initiate drop target; this will occur if more than one
 *        drop target is created for a control or if the operating system will not allow the creation
 *        of the drop target</li>
 * </ul>
 *
 * <p>NOTE: ERROR_CANNOT_INIT_DROP should be an SWTException, since it is a
 * recoverable error, but can not be changed due to backward compatibility.</p>
 *
 * @see Widget#dispose
 * @see DropTarget#checkSubclass
 * @see DND#DROP_NONE
 * @see DND#DROP_COPY
 * @see DND#DROP_MOVE
 * @see DND#DROP_LINK
 */
public DropTarget(Control control, int style) {
	super(control, checkStyle(style));
	this.control = control;

	if (control.getData(DND.DROP_TARGET_KEY) != null) {
		DND.error(DND.ERROR_CANNOT_INIT_DROP);
	}

	control.setData(DND.DROP_TARGET_KEY, this);

	controlListener = event -> {
		if (!DropTarget.this.isDisposed()) {
			DropTarget.this.dispose();
		}
	};
	control.addListener (SWT.Dispose, controlListener);

	this.addListener(SWT.Dispose, event -> onDispose());

	Object effect = control.getData(DEFAULT_DROP_TARGET_EFFECT);
	if (effect instanceof DropTargetEffect) {
		dropEffect = (DropTargetEffect) effect;
	} else if (control instanceof Table) {
		dropEffect = new TableDropTargetEffect((Table) control);
	} else if (control instanceof Tree) {
		dropEffect = new TreeDropTargetEffect((Tree) control);
	}

	addDragHandlers();
}

static long /*int*/ dropTargetProc(long /*int*/ id, long /*int*/ sel) {
	Display display = Display.findDisplay(Thread.currentThread());
	if (display == null || display.isDisposed()) return 0;
	Widget widget = display.findWidget(id);
	if (widget == null) return 0;
	DropTarget dt = (DropTarget)widget.getData(DND.DROP_TARGET_KEY);
	if (dt == null) return 0;

	if (sel == OS.sel_wantsPeriodicDraggingUpdates) {
		return dt.wantsPeriodicDraggingUpdates(id, sel) ? 1 : 0;
	}

	return 0;
}

static long /*int*/ dropTargetProc(long /*int*/ id, long /*int*/ sel, long /*int*/ arg0) {
	Display display = Display.findDisplay(Thread.currentThread());
	if (display == null || display.isDisposed()) return 0;
	Widget widget = display.findWidget(id);
	if (widget == null) return 0;
	DropTarget dt = (DropTarget)widget.getData(DND.DROP_TARGET_KEY);
	if (dt == null) return 0;

	// arg0 is _always_ the sender, and implements NSDraggingInfo.
	// Looks like an NSObject for our purposes, though.
	NSObject sender = new NSObject(arg0);

	if (sel == OS.sel_draggingEntered_) {
		return dt.draggingEntered(id, sel, sender);
	} else if (sel == OS.sel_draggingUpdated_) {
		return dt.draggingUpdated(id, sel, sender);
	} else if (sel == OS.sel_draggingExited_) {
		dt.draggingExited(id, sel, sender);
	} else if (sel == OS.sel_performDragOperation_) {
		return dt.performDragOperation(id, sel, sender) ? 1 : 0;
	}

	return 0;
}

static long /*int*/ dropTargetProc(long /*int*/ id, long /*int*/ sel, long /*int*/ arg0, long /*int*/ arg1, long /*int*/ arg2, long /*int*/ arg3) {
	Display display = Display.findDisplay(Thread.currentThread());
	if (display == null || display.isDisposed()) return 0;
	Widget widget = display.findWidget(id);
	if (widget == null) return 0;
	DropTarget dt = (DropTarget)widget.getData(DND.DROP_TARGET_KEY);
	if (dt == null) return 0;

	if (sel == OS.sel_outlineView_acceptDrop_item_childIndex_) {
		return dt.outlineView_acceptDrop_item_childIndex(id, sel, arg0, arg1, arg2, arg3) ? 1 : 0;
	} else if (sel == OS.sel_outlineView_validateDrop_proposedItem_proposedChildIndex_) {
		return dt.outlineView_validateDrop_proposedItem_proposedChildIndex(id, sel, arg0, arg1, arg2, arg3);
	} else if (sel == OS.sel_tableView_acceptDrop_row_dropOperation_) {
		return dt.tableView_acceptDrop_row_dropOperation(id, sel, arg0, arg1, arg2, arg3) ? 1 : 0;
	} else if (sel == OS.sel_tableView_validateDrop_proposedRow_proposedDropOperation_) {
		return dt.tableView_validateDrop_proposedRow_proposedDropOperation(id, sel, arg0, arg1, arg2, arg3);
	}

	return 0;
}

/**
 * Returns the Control which is registered for this DropTarget.  This is the control over which the
 * user positions the cursor to drop the data.
 *
 * @return the Control which is registered for this DropTarget
 */
public Control getControl () {
	return control;
}

/**
 * Returns an array of listeners who will be notified when a drag and drop
 * operation is in progress, by sending it one of the messages defined in
 * the <code>DropTargetListener</code> interface.
 *
 * @return the listeners who will be notified when a drag and drop
 * operation is in progress
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see DropTargetListener
 * @see #addDropListener
 * @see #removeDropListener
 * @see DropTargetEvent
 *
 * @since 3.4
 */
public DropTargetListener[] getDropListeners() {
	Listener[] listeners = getListeners(DND.DragEnter);
	int length = listeners.length;
	DropTargetListener[] dropListeners = new DropTargetListener[length];
	int count = 0;
	for (int i = 0; i < length; i++) {
		Listener listener = listeners[i];
		if (listener instanceof DNDListener) {
			dropListeners[count] = (DropTargetListener) ((DNDListener) listener).getEventListener();
			count++;
		}
	}
	if (count == length) return dropListeners;
	DropTargetListener[] result = new DropTargetListener[count];
	System.arraycopy(dropListeners, 0, result, 0, count);
	return result;
}

/**
 * Returns the drop effect for this DropTarget.  This drop effect will be
 * used during a drag and drop to display the drag under effect on the
 * target widget.
 *
 * @return the drop effect that is registered for this DropTarget
 *
 * @since 3.3
 */
public DropTargetEffect getDropTargetEffect() {
	return dropEffect;
}

int getOperationFromKeyState() {
	// The NSDraggingInfo object already combined the modifier keys with the
	// drag source's allowed events. This might be better accomplished by diffing
	// the base drag source mask with the active drag state mask instead of snarfing
	// the current event.

	// See documentation on [NSDraggingInfo draggingSourceOperationMask] for the
	// correct Cocoa behavior.  Control + Option or Command is NSDragOperationGeneric,
	// or DND.DROP_DEFAULT in the SWT.
	NSEvent currEvent = NSApplication.sharedApplication().currentEvent();
	long /*int*/ modifiers = currEvent.modifierFlags();
	boolean option = (modifiers & OS.NSAlternateKeyMask) == OS.NSAlternateKeyMask;
	boolean control = (modifiers & OS.NSControlKeyMask) == OS.NSControlKeyMask;
	if (control && option) return DND.DROP_DEFAULT;
	if (control) return DND.DROP_LINK;
	if (option) return DND.DROP_COPY;
	return DND.DROP_DEFAULT;
}

/**
 * Returns a list of the data types that can be transferred to this DropTarget.
 *
 * @return a list of the data types that can be transferred to this DropTarget
 */
public Transfer[] getTransfer() {
	return transferAgents;
}

void onDispose () {
	if (control == null)
		return;
	if (controlListener != null)
		control.removeListener(SWT.Dispose, controlListener);
	controlListener = null;
	control.setData(DND.DROP_TARGET_KEY, null);
	transferAgents = null;

	// Unregister the control as a drop target.
	control.view.unregisterDraggedTypes();
	control = null;
}

int opToOsOp(int operation) {
	int osOperation = 0;
	if ((operation & DND.DROP_COPY) != 0){
		osOperation |= OS.NSDragOperationCopy;
	}
	if ((operation & DND.DROP_LINK) != 0) {
		osOperation |= OS.NSDragOperationLink;
	}
	if ((operation & DND.DROP_MOVE) != 0) {
		osOperation |= OS.NSDragOperationMove;
	}
	if ((operation & DND.DROP_TARGET_MOVE) != 0) {
		osOperation |= OS.NSDragOperationDelete;
	}
	return osOperation;
}

int osOpToOp(long /*int*/ osOperation){
	int operation = 0;
	if ((osOperation & OS.NSDragOperationCopy) != 0){
		operation |= DND.DROP_COPY;
	}
	if ((osOperation & OS.NSDragOperationLink) != 0) {
		operation |= DND.DROP_LINK;
	}
	if ((osOperation & OS.NSDragOperationDelete) != 0) {
		operation |= DND.DROP_TARGET_MOVE;
	}
	if ((osOperation & OS.NSDragOperationMove) != 0) {
		operation |= DND.DROP_MOVE;
	}
	if (osOperation == OS.NSDragOperationEvery) {
		operation = DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_LINK;
	}
	return operation;
}

boolean drop(NSObject sender) {
	clearDropNotAllowed();
	DNDEvent event = new DNDEvent();
	event.widget = this;
	event.time = (int)System.currentTimeMillis();

	if (dropEffect != null) {
		NSPoint mouseLocation = sender.draggingLocation();
		NSPoint globalLoc = sender.draggingDestinationWindow().convertBaseToScreen(mouseLocation);
		event.item = dropEffect.getItem((int)globalLoc.x, (int)globalLoc.y);
	}

	event.detail = DND.DROP_NONE;
	notifyListeners(DND.DragLeave, event);

	event = new DNDEvent();
	if (!setEventData(sender, event) || (((Boolean)control.getData(IS_ACTIVE)).booleanValue() == false)) {
		return false;
	}

	keyOperation = -1;
	int allowedOperations = event.operations;
	TransferData[] allowedDataTypes = new TransferData[event.dataTypes.length];
	System.arraycopy(event.dataTypes, 0, allowedDataTypes, 0, event.dataTypes.length);
	event.dataType = selectedDataType;
	event.detail = selectedOperation;
	notifyListeners(DND.DropAccept, event);

	selectedDataType = null;
	if (event.dataType != null) {
		for (int i = 0; i < allowedDataTypes.length; i++) {
			if (allowedDataTypes[i].type == event.dataType.type) {
				selectedDataType = allowedDataTypes[i];
				break;
			}
		}
	}

	selectedOperation = DND.DROP_NONE;
	if (selectedDataType != null && (event.detail & allowedOperations) != 0) {
		selectedOperation = event.detail;
	}

	if (selectedOperation == DND.DROP_NONE) {
		return false;
	}

	// ask drag source for dropped data
	NSPasteboard pasteboard = sender.draggingPasteboard();
	NSObject data = null;
	NSMutableArray types = NSMutableArray.arrayWithCapacity(10);

	for (int i = 0; i < transferAgents.length; i++){
		Transfer transfer = transferAgents[i];
		String[] typeNames = transfer.getTypeNames();
		int[] typeIds = transfer.getTypeIds();

		for (int j = 0; j < typeNames.length; j++) {
			if (selectedDataType.type == typeIds[j]) {
				types.addObject(NSString.stringWith(typeNames[j]));
				break;
			}
		}
	}

	NSString type = pasteboard.availableTypeFromArray(types);
	TransferData tdata = new TransferData();

	if (type != null) {
		tdata.type = Transfer.registerType(type.getString());
		if (type.isEqual(OS.NSPasteboardTypeString) ||
				type.isEqual(OS.NSPasteboardTypeHTML) ||
				type.isEqual(OS.NSPasteboardTypeRTF)) {
			tdata.data = pasteboard.stringForType(type);
		} else if (type.isEqual(OS.NSURLPboardType) || type.isEqual(OS.kUTTypeURL)) {
			tdata.data = NSURL.URLFromPasteboard(pasteboard);
		} else if (type.isEqual(OS.NSFilenamesPboardType) || type.isEqual(OS.kUTTypeFileURL)) {
			tdata.data = new NSArray(pasteboard.propertyListForType(OS.NSFilenamesPboardType).id);
		} else {
			tdata.data = pasteboard.dataForType(type);
		}
	}

	if (tdata.data != null) {
		data = tdata.data;
	}

	// Get Data in a Java format
	Object object = null;
	for (int i = 0; i < transferAgents.length; i++) {
		Transfer transfer = transferAgents[i];
		if (transfer != null && transfer.isSupportedType(selectedDataType)) {
			selectedDataType.data = data;
			object = transfer.nativeToJava(selectedDataType);
			break;
		}
	}

	if (object == null) {
		selectedOperation = DND.DROP_NONE;
	}

	event.dataType = selectedDataType;
	event.detail = selectedOperation;
	event.data = object;
	notifyListeners(DND.Drop, event);
	selectedOperation = DND.DROP_NONE;
	if ((allowedOperations & event.detail) == event.detail) {
		selectedOperation = event.detail;
	}
	//notify source of action taken
	return (selectedOperation != DND.DROP_NONE);
}

boolean performDragOperation(long /*int*/ id, long /*int*/ sel, NSObject sender) {
	if (new NSObject(id).isKindOfClass(OS.class_NSTableView)) {
		return dndCallSuper(id, sel, sender.id) != 0;
	}

	return drop (sender);
}

boolean outlineView_acceptDrop_item_childIndex(long /*int*/ id, long /*int*/ sel, long /*int*/ outlineView, long /*int*/ info, long /*int*/ item, long /*int*/ index) {
	return drop(new NSObject(info));
}

long /*int*/ outlineView_validateDrop_proposedItem_proposedChildIndex(long /*int*/ id, long /*int*/ sel, long /*int*/ outlineView, long /*int*/ info, long /*int*/ item, long /*int*/ index) {
	//TODO expansion animation and auto collapse not working because of outlineView:shouldExpandItem:
	NSOutlineView widget = new NSOutlineView(outlineView);
	NSObject sender = new NSObject(info);
	NSPoint pt = sender.draggingLocation();
	pt = widget.convertPoint_fromView_(pt, null);
	Tree tree = (Tree)getControl();
	TreeItem childItem = tree.getItem(new Point((int)pt.x, (int)pt.y));
	if (feedback == 0 || childItem == null) {
		widget.setDropItem(null, -1);
	} else {
		if ((feedback & DND.FEEDBACK_SELECT) != 0) {
			widget.setDropItem(childItem.handle, -1);
		} else {
			TreeItem parentItem = childItem.getParentItem();
			int childIndex;
			id parentID = null;
			if (parentItem != null) {
				parentID = parentItem.handle;
				childIndex = parentItem.indexOf(childItem);
			} else {
				childIndex = ((Tree)getControl()).indexOf(childItem);
			}
			if ((feedback & DND.FEEDBACK_INSERT_AFTER) != 0) {
				widget.setDropItem(parentID, childIndex + 1);
			}
			if ((feedback & DND.FEEDBACK_INSERT_BEFORE) != 0) {
				widget.setDropItem(parentID, childIndex);
			}
		}
	}

	return opToOsOp(selectedOperation);
}

/**
 * Removes the listener from the collection of listeners who will
 * be notified when a drag and drop operation is in progress.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see DropTargetListener
 * @see #addDropListener
 * @see #getDropListeners
 */
public void removeDropListener(DropTargetListener listener) {
	if (listener == null) DND.error (SWT.ERROR_NULL_ARGUMENT);
	removeListener (DND.DragEnter, listener);
	removeListener (DND.DragLeave, listener);
	removeListener (DND.DragOver, listener);
	removeListener (DND.DragOperationChanged, listener);
	removeListener (DND.Drop, listener);
	removeListener (DND.DropAccept, listener);
}

/**
 * Specifies the drop effect for this DropTarget.  This drop effect will be
 * used during a drag and drop to display the drag under effect on the
 * target widget.
 *
 * @param effect the drop effect that is registered for this DropTarget
 *
 * @since 3.3
 */
public void setDropTargetEffect(DropTargetEffect effect) {
	dropEffect = effect;
}

boolean setEventData(NSObject draggingState, DNDEvent event) {
	if (draggingState == null) return false;

	// get allowed operations
	int style = getStyle();
	long /*int*/ allowedActions = draggingState.draggingSourceOperationMask();
	int operations = osOpToOp(allowedActions) & style;
	if (operations == DND.DROP_NONE) return false;

	// get current operation
	int operation = getOperationFromKeyState();
	keyOperation = operation;
	if (operation == DND.DROP_DEFAULT) {
		 if ((style & DND.DROP_DEFAULT) == 0) {
			operation = (operations & DND.DROP_MOVE) != 0 ? DND.DROP_MOVE : DND.DROP_NONE;
		 }
	} else {
		if ((operation & operations) == 0) operation = DND.DROP_NONE;
	}


	// get allowed transfer types
	NSPasteboard dragPBoard = draggingState.draggingPasteboard();
	NSArray draggedTypes = dragPBoard.types();
	if (draggedTypes == null) return false;

	long /*int*/ draggedTypeCount = draggedTypes.count();

	TransferData[] dataTypes = new TransferData[(int)draggedTypeCount];
	int index = -1;
	for (int i = 0; i < draggedTypeCount; i++) {
		id draggedType = draggedTypes.objectAtIndex(i);
		NSString nativeDataType = new NSString(draggedType);
		TransferData data = new TransferData();
		data.type = Transfer.registerType(nativeDataType.getString());

		for (int j = 0; j < transferAgents.length; j++) {
			Transfer transfer = transferAgents[j];
			if (transfer != null && transfer.isSupportedType(data)) {
				dataTypes[++index] = data;
				break;
			}
		}
	}
	if (index == -1) return false;

	if (index < dataTypes.length - 1) {
		TransferData[] temp = new TransferData[index + 1];
		System.arraycopy(dataTypes, 0, temp, 0, index + 1);
		dataTypes = temp;
	}

	// Convert from window-relative to global coordinates, and flip it.
	NSPoint mouse = draggingState.draggingLocation();
	NSPoint globalMouse = draggingState.draggingDestinationWindow().convertBaseToScreen(mouse);
	NSArray screens = NSScreen.screens();
	NSRect screenRect = new NSScreen(screens.objectAtIndex(0)).frame();
	globalMouse.y = screenRect.height - globalMouse.y;

	event.widget = this;
	event.x = (int)globalMouse.x;
	event.y = (int)globalMouse.y;
	event.time = (int)System.currentTimeMillis();
	event.feedback = DND.FEEDBACK_SELECT;
	event.dataTypes = dataTypes;
	event.dataType = dataTypes[0];
	event.operations = operations;
	event.detail = operation;
	if (dropEffect != null) {
		event.item = dropEffect.getItem(event.x, event.y);
	}

	return true;
}

/**
 * Specifies the data types that can be transferred to this DropTarget.  If data is
 * being dragged that does not match one of these types, the drop target will be notified of
 * the drag and drop operation but the currentDataType will be null and the operation
 * will be DND.NONE.
 *
 * @param transferAgents a list of Transfer objects which define the types of data that can be
 *						 dropped on this target
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if transferAgents is null</li>
 * </ul>
 */
public void setTransfer(Transfer... transferAgents){
	if (transferAgents == null) DND.error(SWT.ERROR_NULL_ARGUMENT);
	this.transferAgents = transferAgents;


	// Register the types as valid drop types in Cocoa.
	// Accumulate all of the transfer types into a list.
	ArrayList typeStrings = new ArrayList();

	for (int i = 0; i < this.transferAgents.length; i++) {
		String[] types = transferAgents[i].getTypeNames();

		for (int j = 0; j < types.length; j++) {
			typeStrings.add(types[j]);
		}
	}

	// Convert to an NSArray of NSStrings so we can register with the Control.
	int typeStringCount = typeStrings.size();
	NSMutableArray nsTypeStrings = NSMutableArray.arrayWithCapacity(typeStringCount);

	for (int i = 0; i < typeStringCount; i++) {
		nsTypeStrings.addObject(NSString.stringWith((String)typeStrings.get(i)));
	}

	control.view.registerForDraggedTypes(nsTypeStrings);

}

void setDropNotAllowed() {
	if (!dropNotAllowed) {
		NSCursor.currentCursor().push();
		Display display = getDisplay();
		display.setData (LOCK_CURSOR, Boolean.FALSE);
		NSCursor.operationNotAllowedCursor().push();
		display.setData (LOCK_CURSOR, Boolean.TRUE);
		dropNotAllowed = true;
	}
}

void clearDropNotAllowed() {
	if (dropNotAllowed) {
		Display display = getDisplay();
		display.setData (LOCK_CURSOR, Boolean.FALSE);
		NSCursor.pop();
		display.setData (LOCK_CURSOR, Boolean.TRUE);
		NSCursor.pop();
		dropNotAllowed = false;
	}
}

boolean tableView_acceptDrop_row_dropOperation(long /*int*/ id, long /*int*/ sel, long /*int*/ tableView, long /*int*/ info, long /*int*/ row, long /*int*/ operation) {
	return drop(new NSObject(info));
}

int tableView_validateDrop_proposedRow_proposedDropOperation(long /*int*/ id, long /*int*/ sel, long /*int*/ tableView, long /*int*/ info, long /*int*/ row, long /*int*/ operation) {
	NSTableView widget = new NSTableView(tableView);
	NSObject sender = new NSObject(info);
	NSPoint pt = sender.draggingLocation();
	pt = widget.convertPoint_fromView_(pt, null);
	long /*int*/ hitRow = widget.rowAtPoint(pt);
	if (0 <= hitRow && hitRow < widget.numberOfRows()) {
		if (feedback == 0) {
			widget.setDropRow(-1, OS.NSTableViewDropOn);
		} else {
			if ((feedback & DND.FEEDBACK_SELECT) != 0) {
				widget.setDropRow(hitRow, OS.NSTableViewDropOn);
			} else {
				if ((feedback & DND.FEEDBACK_INSERT_AFTER) != 0) {
					widget.setDropRow(hitRow + 1, OS.NSTableViewDropAbove);
				}
				if ((feedback & DND.FEEDBACK_INSERT_BEFORE) != 0) {
					widget.setDropRow(hitRow, OS.NSTableViewDropAbove);
				}
			}
		}
	}
	return opToOsOp(selectedOperation);
}

// By returning true we get draggingUpdated messages even when the mouse isn't moving.
boolean wantsPeriodicDraggingUpdates(long /*int*/ id, long /*int*/ sel) {
	return true;
}

}
