/*******************************************************************************
 * Copyright (c) 2000, 2016 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
 *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 497807
 *******************************************************************************/
package org.eclipse.swt.dnd;


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.*;
/**
 *
 * <code>DragSource</code> defines the source object for a drag and drop transfer.
 *
 * <p>IMPORTANT: This class is <em>not</em> intended to be subclassed.</p>
 *
 * <p>A drag source is the object which originates a drag and drop operation. For the specified widget,
 * it defines the type of data that is available for dragging and the set of operations that can
 * be performed on that data.  The operations can be any bit-wise combination of DND.MOVE, DND.COPY or
 * DND.LINK.  The type of data that can be transferred is specified by subclasses of Transfer such as
 * TextTransfer or FileTransfer.  The type of data transferred can be a predefined system type or it
 * can be a type defined by the application.  For instructions on how to define your own transfer type,
 * refer to <code>ByteArrayTransfer</code>.</p>
 *
 * <p>You may have several DragSources in an application but you can only have one DragSource
 * per Control.  Data dragged from this DragSource can be dropped on a site within this application
 * or it can be dropped on another application such as an external Text editor.</p>
 *
 * <p>The application supplies the content of the data being transferred by implementing the
 * <code>DragSourceListener</code> and associating it with the DragSource via DragSource#addDragListener.</p>
 *
 * <p>When a successful move operation occurs, the application is required to take the appropriate
 * action to remove the data from its display and remove any associated operating system resources or
 * internal references.  Typically in a move operation, the drop target makes a copy of the data
 * and the drag source deletes the original.  However, sometimes copying the data can take a long
 * time (such as copying a large file).  Therefore, on some platforms, the drop target may actually
 * move the data in the operating system rather than make a copy.  This is usually only done in
 * file transfers.  In this case, the drag source is informed in the DragEnd event that a
 * DROP_TARGET_MOVE was performed.  It is the responsibility of the drag source at this point to clean
 * up its displayed information.  No action needs to be taken on the operating system resources.</p>
 *
 * <p> The following example shows a Label widget that allows text to be dragged from it.</p>
 *
 * <code><pre>
 *	// Enable a label as a Drag Source
 *	Label label = new Label(shell, SWT.NONE);
 *	// This example will allow text to be dragged
 *	Transfer[] types = new Transfer[] {TextTransfer.getInstance()};
 *	// This example will allow the text to be copied or moved to the drop target
 *	int operations = DND.DROP_MOVE | DND.DROP_COPY;
 *
 *	DragSource source = new DragSource(label, operations);
 *	source.setTransfer(types);
 *	source.addDragListener(new DragSourceListener() {
 *		public void dragStart(DragSourceEvent e) {
 *			// Only start the drag if there is actually text in the
 *			// label - this text will be what is dropped on the target.
 *			if (label.getText().length() == 0) {
 *				event.doit = false;
 *			}
 *		};
 *		public void dragSetData(DragSourceEvent event) {
 *			// A drop has been performed, so provide the data of the
 *			// requested type.
 *			// (Checking the type of the requested data is only
 *			// necessary if the drag source supports more than
 *			// one data type but is shown here as an example).
 *			if (TextTransfer.getInstance().isSupportedType(event.dataType)){
 *				event.data = label.getText();
 *			}
 *		}
 *		public void dragFinished(DragSourceEvent event) {
 *			// A Move operation has been performed so remove the data
 *			// from the source
 *			if (event.detail == DND.DROP_MOVE)
 *				label.setText("");
 *		}
 *	});
 * </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.DragStart, DND.DragSetData, DND.DragEnd</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"})
public class DragSource extends Widget {

	// TODO: These should either move out of Display or be accessible to this class.
	static byte[] types = {'*','\0'};
	static int size = C.PTR_SIZEOF, align = C.PTR_SIZEOF == 4 ? 2 : 3;

	static Callback dragSource2Args, dragSource3Args, dragSource4Args, dragSource5Args, dragSource6Args;
	static final byte[] SWT_OBJECT = {'S', 'W', 'T', '_', 'O', 'B', 'J', 'E', 'C', 'T', '\0'};
	static long /*int*/ proc2 = 0, proc3 = 0, proc4 = 0, proc5 = 0, proc6 = 0;

	String paths[];
	boolean exist[];

	static {
		String className = "SWTDragSourceDelegate";

		Class clazz = DragSource.class;

		dragSource2Args = new Callback(clazz, "dragSourceProc", 2);
		proc2 = dragSource2Args.getAddress();
		if (proc2 == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);

		dragSource3Args = new Callback(clazz, "dragSourceProc", 3);
		proc3 = dragSource3Args.getAddress();
		if (proc3 == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);

		dragSource4Args = new Callback(clazz, "dragSourceProc", 4);
		proc4 = dragSource4Args.getAddress();
		if (proc4 == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);

		dragSource5Args = new Callback(clazz, "dragSourceProc", 5);
		proc5 = dragSource5Args.getAddress();
		if (proc5 == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);

		dragSource6Args = new Callback(clazz, "dragSourceProc", 6);
		proc6 = dragSource6Args.getAddress();
		if (proc6 == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);

		long /*int*/ cls = OS.objc_allocateClassPair(OS.class_NSObject, className, 0);
		OS.class_addIvar(cls, SWT_OBJECT, size, (byte)align, types);

		long /*int*/ draggedImage_endedAt_operationProc = OS.CALLBACK_draggedImage_endedAt_operation_(proc5);

		// Add the NSDraggingSource callbacks
		OS.class_addMethod(cls, OS.sel_draggingSourceOperationMaskForLocal_, proc3, "@:I");
		OS.class_addMethod(cls, OS.sel_draggedImage_beganAt_, proc4, "@:@{NSPoint=ff}");
		OS.class_addMethod(cls, OS.sel_draggedImage_endedAt_operation_, draggedImage_endedAt_operationProc, "@:@{NSPoint=ff}I");
		OS.class_addMethod(cls, OS.sel_ignoreModifierKeysWhileDragging, proc3, "@:");

		// Add the NSPasteboard delegate callback
		OS.class_addMethod(cls, OS.sel_pasteboard_provideDataForType_, proc4, "@:@@");

		OS.objc_registerClassPair(cls);
	}

	// info for registering as a drag source
	Control control;
	Listener controlListener;
	Transfer[] transferAgents = new Transfer[0];
	DragSourceEffect dragEffect;
	Image dragImageFromListener;
	private int dragOperations;
	SWTDragSourceDelegate dragSourceDelegate;

	static final String DEFAULT_DRAG_SOURCE_EFFECT = "DEFAULT_DRAG_SOURCE_EFFECT"; //$NON-NLS-1$

	private long /*int*/ delegateJniRef;
	private Point dragOffset;

/**
 * Creates a new <code>DragSource</code> to handle dragging from the specified <code>Control</code>.
 * Creating an instance of a DragSource may cause system resources to be allocated depending on the platform.
 * It is therefore mandatory that the DragSource instance be disposed when no longer required.
 *
 * @param control the <code>Control</code> that the user clicks on to initiate the drag
 * @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_DRAG - unable to initiate drag source; this will occur if more than one
 *        drag source is created for a control or if the operating system will not allow the creation
 *        of the drag source</li>
 * </ul>
 *
 * <p>NOTE: ERROR_CANNOT_INIT_DRAG should be an SWTException, since it is a
 * recoverable error, but can not be changed due to backward compatibility.</p>
 *
 * @see Widget#dispose
 * @see DragSource#checkSubclass
 * @see DND#DROP_NONE
 * @see DND#DROP_COPY
 * @see DND#DROP_MOVE
 * @see DND#DROP_LINK
 */
public DragSource(Control control, int style) {
	super (control, checkStyle(style));
	this.control = control;
	if (control.getData(DND.DRAG_SOURCE_KEY) != null) {
		DND.error(DND.ERROR_CANNOT_INIT_DRAG);
	}
	control.setData(DND.DRAG_SOURCE_KEY, this);

	controlListener = event -> {
		if (event.type == SWT.Dispose) {
			if (!DragSource.this.isDisposed()) {
				DragSource.this.dispose();
			}
		}
		if (event.type == SWT.DragDetect) {
			if (!DragSource.this.isDisposed()) {
				if (event.widget instanceof Table || event.widget instanceof Tree) {
					DragSource.this.dragOutlineViewStart(event);
				} else {
					DragSource.this.drag(event);
				}
			}
		}
	};
	control.addListener (SWT.Dispose, controlListener);
	control.addListener (SWT.DragDetect, controlListener);

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

	Object effect = control.getData(DEFAULT_DRAG_SOURCE_EFFECT);
	if (effect instanceof DragSourceEffect) {
		dragEffect = (DragSourceEffect) effect;
	} else if (control instanceof Tree) {
		dragEffect = new TreeDragSourceEffect((Tree) control);
	} else if (control instanceof Table) {
		dragEffect = new TableDragSourceEffect((Table) control);
	}

	delegateJniRef = OS.NewGlobalRef(this);
	if (delegateJniRef == 0) SWT.error(SWT.ERROR_NO_HANDLES);

	// The dragSourceDelegate implements the pasteboard callback to provide the dragged data, so we always need
	// to create it. NSDraggingSource methods are ignored in the table and tree case.
	dragSourceDelegate = (SWTDragSourceDelegate)new SWTDragSourceDelegate().alloc().init();
	OS.object_setInstanceVariable(dragSourceDelegate.id, SWT_OBJECT, delegateJniRef);

	// Tables and trees already implement dragging, so we need to override their drag methods instead of creating a dragging source.
	if (control instanceof Tree || control instanceof Table) {
		long /*int*/ cls = OS.object_getClass(control.view.id);

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

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

		long /*int*/ draggedImage_endedAt_operationProc = OS.CALLBACK_draggedImage_endedAt_operation_(proc5);

		// Add the NSDraggingSource overrides.
		OS.class_addMethod(cls, OS.sel_draggingSourceOperationMaskForLocal_, proc3, "@:I");
		OS.class_addMethod(cls, OS.sel_draggedImage_beganAt_, proc4, "@:@{NSPoint=ff}");
		OS.class_addMethod(cls, OS.sel_draggedImage_endedAt_operation_, draggedImage_endedAt_operationProc, "@:@{NSPoint=ff}I");
		OS.class_addMethod(cls, OS.sel_ignoreModifierKeysWhileDragging, proc3, "@:");

		// Override to return the drag effect's image.
		OS.class_addMethod(cls, OS.sel_dragImageForRowsWithIndexes_tableColumns_event_offset_, proc6, "@:@@@^NSPoint");
	}

}

/**
 * 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>DragSourceListener</code>
 * interface.
 *
 * <p><ul>
 * <li><code>dragStart</code> is called when the user has begun the actions required to drag the widget.
 * This event gives the application the chance to decide if a drag should be started.
 * <li><code>dragSetData</code> is called when the data is required from the drag source.
 * <li><code>dragFinished</code> is called when the drop has successfully completed (mouse up
 * over a valid target) or has been terminated (such as hitting the ESC key). Perform cleanup
 * such as removing data from the source side on a successful move operation.
 * </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 DragSourceListener
 * @see #getDragListeners
 * @see #removeDragListener
 * @see DragSourceEvent
 */
public void addDragListener(DragSourceListener listener) {
	if (listener == null) DND.error (SWT.ERROR_NULL_ARGUMENT);
	DNDListener typedListener = new DNDListener (listener);
	typedListener.dndWidget = this;
	addListener (DND.DragStart, typedListener);
	addListener (DND.DragSetData, typedListener);
	addListener (DND.DragEnd, typedListener);
}

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

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

long /*int*/ dndCallSuperObject(long /*int*/ id, long /*int*/ sel, long /*int*/ arg0, long /*int*/ arg1, long /*int*/ arg2, long /*int*/ arg3) {
	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, arg1, arg2, arg3);
}

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

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

void drag(Event dragDetectEvent) {

	DNDEvent event = startDrag(dragDetectEvent);
	if (event == null) return;

	// Start the drag here from the Control's view.
	NSEvent currEvent = NSApplication.sharedApplication().currentEvent();
	NSPoint pt = currEvent.locationInWindow();
	NSPoint viewPt = control.view.convertPoint_fromView_(pt, null);

	// Get the image for the drag. The drag should happen from the middle of the image.
	NSImage dragImage = null;
	Image defaultDragImage = null;
	try {
		Image image = event.image;

		// If no image was provided, just create a trivial image. dragImage requires a non-null image.
		if (image == null) {
			int width = 20, height = 20;
			Image newDragImage = new Image(Display.getCurrent(), width, height);
			GC imageGC = new GC(newDragImage);
			Color grayColor = new Color(Display.getCurrent(), 50, 50, 50);
			imageGC.setForeground(grayColor);
			imageGC.drawRectangle(0, 0, 19, 19);
			imageGC.dispose();
			ImageData newImageData = newDragImage.getImageData();
			newImageData.alpha = (int)(255 * .4);
			defaultDragImage = new Image(Display.getCurrent(), newImageData);
			newDragImage.dispose();
			grayColor.dispose();
			image = defaultDragImage;
			event.offsetX = width / 2;
			event.offsetY = height / 2;
		}

		dragImage = image.handle;

		NSSize imageSize = dragImage.size();
		viewPt.x -= event.offsetX;

		if (control.view.isFlipped())
			viewPt.y += imageSize.height - event.offsetY;
		else
			viewPt.y -= event.offsetY;

		// The third argument to dragImage is ignored as of 10.4.
		NSSize ignored = new NSSize();

		control.view.dragImage(dragImage, viewPt, ignored, NSApplication.sharedApplication().currentEvent(), NSPasteboard.pasteboardWithName(OS.NSDragPboard), dragSourceDelegate, true);

	} finally {
		if (defaultDragImage != null) defaultDragImage.dispose();
	}
}

void dragOutlineViewStart(Event dragDetectEvent) {
	DNDEvent event = startDrag(dragDetectEvent);
	if (event == null) return;

	// Save off the custom image, if any.
	dragImageFromListener = event.image;

	// Save the computed offset for the image.  This needs to be passed back in dragImageForRowsWithIndexes
	// so the proxy image originates from the selection and not centered under the mouse.
	dragOffset = new Point(event.offsetX, event.offsetY);
}

void draggedImage_beganAt(long /*int*/ id, long /*int*/ sel, long /*int*/ arg0, long /*int*/ arg1) {
	if (new NSObject(id).isKindOfClass(OS.class_NSTableView)) {
		dndCallSuper(id, sel, arg0, arg1);
	}
}

void draggedImage_endedAt_operation(long /*int*/ id, long /*int*/ sel, long /*int*/ arg0, NSPoint arg1, long /*int*/ arg2) {
	int swtOperation = osOpToOp(arg2);
	if (paths != null) {
		NSFileManager fileManager = NSFileManager.defaultManager();
		for (int i = 0; i < paths.length; i++) {
			if (paths[i] != null && exist[i]) {
				if (!fileManager.fileExistsAtPath(NSString.stringWith(paths[i]))) {
					swtOperation &= ~DND.DROP_MOVE;
					swtOperation |= DND.DROP_TARGET_MOVE;
				}
			}
		}
		paths = null;
		exist = null;
	}
	OS.objc_msgSend(id, OS.sel_retain);
	try {
		Event event = new DNDEvent();
		event.widget = this;
		event.time = (int)System.currentTimeMillis();
		event.doit = swtOperation != DND.DROP_NONE;
		event.detail = swtOperation;
		notifyListeners(DND.DragEnd, event);
		dragImageFromListener = null;

		if (new NSObject(id).isKindOfClass(OS.class_NSTableView)) {
			dndCallSuper(id, sel, arg0, arg1, arg2);
		}
	} finally {
		OS.objc_msgSend(id, OS.sel_release);
	}
}

long /*int*/ dragImageForRowsWithIndexes_tableColumns_event_offset(long /*int*/ id, long /*int*/ sel, long /*int*/ arg0, long /*int*/ arg1, long /*int*/ arg2, long /*int*/ arg3) {
	if (dragImageFromListener != null) {
		NSPoint point = new NSPoint();
		point.x = dragOffset.x;
		point.y = dragOffset.y;
		OS.memmove(arg3, point, NSPoint.sizeof);
		return dragImageFromListener.handle.id;
	} else {
		return dndCallSuperObject(id, sel, arg0, arg1, arg2, arg3);
	}
}

/**
 * Cocoa NSDraggingSource implementations
 */
long /*int*/ draggingSourceOperationMaskForLocal(long /*int*/ id, long /*int*/ sel, long /*int*/ arg0) {
	// Drag operations are same for local or remote drags.
	return dragOperations;
}

static long /*int*/ dragSourceProc(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;
	DragSource ds = null;

	if (widget instanceof DragSource) {
		ds = (DragSource)widget;
	} else {
		ds = (DragSource)widget.getData(DND.DRAG_SOURCE_KEY);
	}

	if (ds == null) return 0;

	if (sel == OS.sel_ignoreModifierKeysWhileDragging) {
		return (ds.ignoreModifierKeysWhileDragging(id, sel) ? 1 : 0);
	}

	return 0;
}

static long /*int*/ dragSourceProc(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;
	DragSource ds = null;

	if (widget instanceof DragSource) {
		ds = (DragSource)widget;
	} else {
		ds = (DragSource)widget.getData(DND.DRAG_SOURCE_KEY);
	}

	if (ds == null) return 0;

	if (sel == OS.sel_draggingSourceOperationMaskForLocal_) {
		return ds.draggingSourceOperationMaskForLocal(id, sel, arg0);
	}

	return 0;
}

static long /*int*/ dragSourceProc(long /*int*/ id, long /*int*/ sel, long /*int*/ arg0, long /*int*/ arg1) {
	Display display = Display.findDisplay(Thread.currentThread());
	if (display == null || display.isDisposed()) return 0;
	Widget widget = display.findWidget(id);
	if (widget == null) return 0;
	DragSource ds = null;

	if (widget instanceof DragSource) {
		ds = (DragSource)widget;
	} else {
		ds = (DragSource)widget.getData(DND.DRAG_SOURCE_KEY);
	}

	if (ds == null) return 0;

	if (sel == OS.sel_draggedImage_beganAt_) {
		ds.draggedImage_beganAt(id, sel, arg0, arg1);
	} else if (sel == OS.sel_pasteboard_provideDataForType_) {
		ds.pasteboard_provideDataForType(id, sel, arg0, arg1);
	}

	return 0;
}

static long /*int*/ dragSourceProc(long /*int*/ id, long /*int*/ sel, long /*int*/ arg0, long /*int*/ arg1, long /*int*/ arg2) {
	Display display = Display.findDisplay(Thread.currentThread());
	if (display == null || display.isDisposed()) return 0;
	Widget widget = display.findWidget(id);
	if (widget == null) return 0;
	DragSource ds = null;

	if (widget instanceof DragSource) {
		ds = (DragSource)widget;
	} else {
		ds = (DragSource)widget.getData(DND.DRAG_SOURCE_KEY);
	}

	if (ds == null) return 0;

	if (sel == OS.sel_draggedImage_endedAt_operation_) {
		NSPoint point = new NSPoint();
		OS.memmove(point, arg1, NSPoint.sizeof);
		ds.draggedImage_endedAt_operation(id, sel, arg0, point, arg2);
	}

	return 0;
}

static long /*int*/ dragSourceProc(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;
	DragSource ds = null;

	if (widget instanceof DragSource) {
		ds = (DragSource)widget;
	} else {
		ds = (DragSource)widget.getData(DND.DRAG_SOURCE_KEY);
	}

	if (ds == null) return 0;

	if (sel == OS.sel_dragImageForRowsWithIndexes_tableColumns_event_offset_) {
		return ds.dragImageForRowsWithIndexes_tableColumns_event_offset(id, sel, arg0, arg1, arg2, arg3);
	}

	return 0;
}

/**
 * Returns the Control which is registered for this DragSource.  This is the control that the
 * user clicks in to initiate dragging.
 *
 * @return the Control which is registered for this DragSource
 */
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>DragSourceListener</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 DragSourceListener
 * @see #addDragListener
 * @see #removeDragListener
 * @see DragSourceEvent
 *
 * @since 3.4
 */
public DragSourceListener[] getDragListeners() {
	Listener[] listeners = getListeners(DND.DragStart);
	int length = listeners.length;
	DragSourceListener[] dragListeners = new DragSourceListener[length];
	int count = 0;
	for (int i = 0; i < length; i++) {
		Listener listener = listeners[i];
		if (listener instanceof DNDListener) {
			dragListeners[count] = (DragSourceListener) ((DNDListener) listener).getEventListener();
			count++;
		}
	}
	if (count == length) return dragListeners;
	DragSourceListener[] result = new DragSourceListener[count];
	System.arraycopy(dragListeners, 0, result, 0, count);
	return result;
}

/**
 * Returns the drag effect that is registered for this DragSource.  This drag
 * effect will be used during a drag and drop operation.
 *
 * @return the drag effect that is registered for this DragSource
 *
 * @since 3.3
 */
public DragSourceEffect getDragSourceEffect() {
	return dragEffect;
}

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

/**
 * We always want the modifier keys to potentially update the drag.
 */
boolean ignoreModifierKeysWhileDragging(long /*int*/ id, long /*int*/ sel) {
	return false;
}

void onDispose() {
	if (control == null)
		return;

	if (controlListener != null) {
		control.removeListener(SWT.Dispose, controlListener);
		control.removeListener(SWT.DragDetect, controlListener);
	}
	controlListener = null;
	control.setData(DND.DRAG_SOURCE_KEY, null);
	control = null;
	transferAgents = null;

	if (delegateJniRef != 0) OS.DeleteGlobalRef(delegateJniRef);
	delegateJniRef = 0;

	if (dragSourceDelegate != null) {
		OS.object_setInstanceVariable(dragSourceDelegate.id, SWT_OBJECT, 0);
		dragSourceDelegate.release();
	}
}

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;
}

void pasteboard_provideDataForType(long /*int*/ id, long /*int*/ sel, long /*int*/ arg0, long /*int*/ arg1) {
	NSPasteboard pasteboard = new NSPasteboard(arg0);
	NSString dataType = new NSString(arg1);
	if (pasteboard == null || dataType == null) return;
	TransferData transferData = new TransferData();
	transferData.type = Transfer.registerType(dataType.getString());
	DNDEvent event = new DNDEvent();
	event.widget = this;
	event.time = (int)System.currentTimeMillis();
	event.dataType = transferData;
	notifyListeners(DND.DragSetData, event);
	if (!event.doit) return;
	Transfer transfer = null;
	for (int i = 0; i < transferAgents.length; i++) {
		Transfer transferAgent = transferAgents[i];
		if (transferAgent != null && transferAgent.isSupportedType(transferData)) {
			transfer = transferAgent;
			break;
		}
	}
	if (transfer == null) return;
	transfer.javaToNative(event.data, transferData);
	if (transferData.data == null) return;

	NSObject tdata = transferData.data;

	if (dataType.isEqual(OS.NSStringPboardType) ||
			dataType.isEqual(OS.NSHTMLPboardType) ||
			dataType.isEqual(OS.NSRTFPboardType)) {
		pasteboard.setString((NSString) tdata, dataType);
	} else if (dataType.isEqual(OS.NSURLPboardType) || dataType.isEqual(OS.kUTTypeURL)) {
		NSURL url = (NSURL) tdata;
		url.writeToPasteboard(pasteboard);
	} else if (dataType.isEqual(OS.NSFilenamesPboardType) || dataType.isEqual(OS.kUTTypeFileURL)) {
		NSArray array = (NSArray) transferData.data;
		int count = (int) /*64*/ array.count();
		paths = new String[count];
		exist = new boolean[count];
		NSFileManager fileManager = NSFileManager.defaultManager();
		for (int i = 0; i < count; i++) {
			NSString filePath = new NSString(array.objectAtIndex(i));
			paths[i] = filePath.getString();
			exist[i] = fileManager.fileExistsAtPath(filePath);
		}
		pasteboard.setPropertyList((NSArray) tdata, OS.NSFilenamesPboardType);
	} else {
		pasteboard.setData((NSData) tdata, dataType);
	}
}

/**
 * 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 DragSourceListener
 * @see #addDragListener
 * @see #getDragListeners
 */
public void removeDragListener(DragSourceListener listener) {
	if (listener == null) DND.error (SWT.ERROR_NULL_ARGUMENT);
	removeListener (DND.DragStart, listener);
	removeListener (DND.DragSetData, listener);
	removeListener (DND.DragEnd, listener);
}

/**
 * Specifies the drag effect for this DragSource.  This drag effect will be
 * used during a drag and drop operation.
 *
 * @param effect the drag effect that is registered for this DragSource
 *
 * @since 3.3
 */
public void setDragSourceEffect(DragSourceEffect effect) {
	dragEffect = effect;
}
/**
 * Specifies the list of data types that can be transferred by this DragSource.
 * The application must be able to provide data to match each of these types when
 * a successful drop has occurred.
 *
 * @param transferAgents a list of Transfer objects which define the types of data that can be
 * dragged from this source
 */
public void setTransfer(Transfer... transferAgents){
	this.transferAgents = transferAgents;
}

DNDEvent startDrag(Event dragEvent) {
	DNDEvent event = new DNDEvent();
	event.widget = this;
	event.x = dragEvent.x;
	event.y = dragEvent.y;
	event.time = dragEvent.time;
	event.doit = true;
	notifyListeners(DND.DragStart, event);
	if (!event.doit || transferAgents == null || transferAgents.length == 0) return null;

	NSPasteboard dragBoard = NSPasteboard.pasteboardWithName(OS.NSDragPboard);
	NSMutableArray nativeTypeArray = NSMutableArray.arrayWithCapacity(10);

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

			for (int j = 0; j < typeNames.length; j++) {
				nativeTypeArray.addObject(NSString.stringWith(typeNames[j]));
			}
		}
	}
	dragBoard.declareTypes(nativeTypeArray, dragSourceDelegate);

	// Save off the drag operations -- AppKit will call back to us to request them during the drag.
	dragOperations = opToOsOp(getStyle());

	return event;
}
}
