CONTENTS | PREV | NEXT Drag and Drop


2.2 Drag Source

The DragSource is the entity responsible for the initiation of the Drag and Drop operation:


2.2.1 The DragSource definition

The DragSource and associated constant interfaces are defined as follows:

The DnDConstants class defines the operations that may be applied to the subject of the transfer:

public class java.awt.dnd.DnDConstants {
	public static int ACTION_NONE					= 	0x0;
	public static int ACTION_COPY					=	 0x1;
	public static int ACTION_MOVE					=	 0x2;
	public static int ACTION_COPY_OR_MOVE					= ACTION_COPY | 
					                   ACTION_MOVE;
	public static int ACTION_REFERENCE = 0x40000000;
}

public class java.awt.dnd.DragSource {

     public static Cursor     getDefaultCopyDropCursor();
     public static Cursor     getDefaultMoveDropCursor();
     public static Cursor     getDefaultLinkDropCursor();

     public static Cursor     getDefaultCopyNoDropCursor();
     public static Cursor     getDefaultMoveNoDropCursor();
     public static Cursor     getDefaultLinkNoDropCursor();

	public static DragSource getDefaultDragSource();

	public void
		  startDrag(Component      				    c,
				  AWTEvent       			 trigger,
				  int 		    	 actions,
				  Cursor			 dragCursor,
				  Image			 dragImage,
				  Point			 dragImageOffset,
				  Transferable 			 transferable,
			 	  DragSourceListener			 dsl)
		  throws InvalidDnDOperationException;

	protected DragSourceContext
		createDragSourceContext(
			DragSourceContextPeer dscp,
			Component             c,
			int                   actions,
			Cursor                dragCursor,
			Image                 dragImage,
  			Point                 dragImageOffset,
			Transferable          transferable,
			DragSourceListener    dsl
		);

	public FlavorMap getFlavorMap();
}


The DragSource may be used in a number of scenarios:

A controlling object, the Drag Initiator, shall obtain a DragSource instance either prior to, or at the time a users gesture, effecting an associated Component, in order to process the operation.

The initial interpretation of the users gesture, and the subsequent starting of the Drag operation are the responsibility of the implementing Component, or associated controlling entity.

When a gesture occurs, the DragSource's startDrag() method shall be invoked in order to cause processing of the users navigational gestures and delivery of Drag and Drop protocol notifications.

In order to start a drag operation the caller of the startDrag() method shall provide the following parameters:

On platforms that can support this feature, a "Drag" image may be associated with the operation to enhance the fidelity of the "Drag Over" feedback. This image would typically be a small "iconic" representation of the object, or objects being dragged, and would be rendered by the underlying system, tracking the movement of, and coincident with, but typically in addition to the Cursor animation.

Where this facility is not available, or where the image is not of a suitable type to be rendered by the underlying system, this parameter is ignored and only Cursor "Drag Over" animation results, so applications should not depend upon this feature.

The Transferable instance associated with the DragSource at the start of the Drag operation, represent the object(s) or data that are the operand(s), or the subject(s), of the Drag and Drop operation, that is the information that will subsequently be passed from the DragSource to the DropTarget as a result of a successful Drop on the Component associated with that DropTarget.

Note that multiple (collections) of either homogeneous, or heterogeneous, objects may be subject of a Drag and Drop operation, by creating a container object, that is the subject of the transfer, and implements Transferable. However it should be noted that since none of the targeted native platforms systems support a standard mechanism for describing and thus transferring such collections it is not possible to implement such transfers in a transparent, or platform portable fashion.

As stated above, the primary role of the startDrag() method is to initiate a Drag on behalf of the user. In order to accomplish this, the startDrag() method must create a DragSourceContext instance to track the operation itself, and more importantly it must initiate the operation itself in the underlying platform implementation. In order to accomplish this, the DragSource must first obtain a DragSourceContextPeer from the underlying system (usually via an invocation of java.awt.Toolkit.createDragSourceContextPeer() method) and subsequently associate this newly created DragSourceContextPeer (which provides a platform independent interface to the underlying systems capabilities) with a DragSourceContext.The startDrag() method invokes the createDragSourceContext() method to instantiate an appropriate DragSourceContext and associate the DragSourceContextPeer.

If the Drag and Drop System is unable to initiate a Drag operation for some reason the startDrag() method shall throw a java.awt.dnd.InvalidDnDOperationException to signal such a condition. Typically this exception is thrown when the underlying platform system is either not in a state to initiate a Drag, or the parameters specified are invalid.

Note that during the Drag neither the set of operations the source, nor the set of DataFlavors exposed by the Transferable at the start of the Drag operation may change for the duration of the operation, in other words the operation(s) and data are constant for the duration of the operation with respect to the DragSource.

For security reasons the caller of the startDrag() method is required to have the AWTPermission "startDrag", invoking this method without such permission shall result in a SecurityException being thrown.

The getFlavorMap() method is used by the underlying system to obtain a FlavorMap object in order to map the DataFlavors exposed by the Transferable to data type names of the underlying DnD platform. [see later for details of the FlavorMap]


2.2.2 The DragSourceContext Definition

As a result of a DragSource's startDrag() method being successfully invoked an instance of the DragSourceContext class is created. This instance is responsible for tracking the state of the operation on behalf of the DragSource and dispatching state changes to the DragSourceListener.

The DragSourceContext class is defined as follows:

public class DragSourceContext implements DragSourceListener 
{

	protected DragSourceContext(
				DragSource					ds,
				DragSourceContextPeer	dscp,
				int		actions,
				Cursor			dragCursor,
				Image			dragImage,
				Point			dragOffset,
				Transferable		transferable,
				DragSourceListener		dsl		
	);

	public DragSource				getDragSource();

	public Component				getComponent();

	public AWTEvent				getTrigger();

	public Image				getDragImage();

	public Point				getDragImageOffset();


	public int  				getSourceActions();

	Cursor getCursor();
	void   setCursor(Cursor Cursor) 
				throws InvalidDnDOperationException;

	void cancelDrag() throws InvalidDnDOperationException;

	void addDragSourceListener(DragSourceListener dsl)
		throws TooManyListenersException;

	void removeDragSourceListener(DragSourceListener dsl);
}


Note that the DragSourceContext itself implements DragSourceListener, this is to allow the platform peer, the DragSourceContextPeer instance, created by the DragSource, to notify the DragSourceContext of changes in state in the ongoing operation, and thus allows the DragSourceContext to interpose itself between the platform and the DragSourceListener provided by the initiator of the operation.

The state machine the platform exposes, with respect to the source, or initiator of the Drag and Drop operation is detailed below:

Notifications of changes in state with respect to the initiator during a Drag and Drop operation, as illustrated above, are delivered from the DragSourceContextPeer, to the appropriate DragSourceContext, which delegates notifications, via a unicast JavaBeans compliant EventListener subinterface, to an arbitrary object that implements DragSourceListener registered with the DragSource via startDrag().

The primary responsibility of the DragSourceListener is to monitor the progress of the users navigation during the Drag and Drop operation and provide the "Drag-Over" effects feedback to the user. Typically this is accomplished via changes to the "Drag Cursor".

Every DragSource object has 2 logical cursor states associated with it:

The state of the Cursor may be modified by calling the setCursor() method of the DragSourceContext.


2.2.3 The DragSourceListener Definition

The DragSourceListener interface is defined as follows:

public interface java.awt.dnd.DragSourceListener
	extends java.util.EventListener {
	void dragEnter					(DragSourceDragEvent dsde);
	void dragOver					(DragSourceDragEvent dsde);
	void dragGestureChanged(DragSourceDragEvent dsde);
	void dragExit					(DragSourceEvent     dse);
	void dragDropEnd					(DragSourceDropEvent dsde);
}

As the drag operation progresses, the DragSourceListener's dragEnter(), dragOver(), and dragExit() methods shall be invoked as a result of the users navigation of the logical "Drag" cursor's location intersecting the geometry of GUI Component(s) with associated DropTarget(s). [See below for details of the DropTarget's protocol interactions].

The DragSourceListener's dragEnter() method is invoked when the following conditions are true:

The DragSourceListener's dragOver() method is invoked when the following conditions are true:

The DragSourceListener's dragExit() method is invoked when one of the following conditions is true:

Or:

Or:

The DragSourceListener's dragGestureChanged() method is invoked when the state of the input device(s), typically the mouse buttons or keyboard modifiers, that the user is interacting with in order to preform the Drag operation, changes.

The dragDropEnd() method is invoked to signify that the operation is completed. The isDropAborted() and isDropSuccessful() methods of the DragSourceDropEvent can be used to determine the termination state. The getDropAction() method returns the operation that the DropTarget selected (via the DropTargetDropEvent acceptDrop() parameter) to apply to the Drop operation.1

Once this method is complete the DragSourceContext and the associated resources are invalid.


2.2.4 The DragSourceEvent Definition

The DragSourceEvent class is the root Event class for all events pertaining to the DragSource, and is defined as follows:

public class   java.awt.dnd.DragSourceEvent
	  extends java.util.EventObject {
	public DragSourceEvent(DragSourceContext dsc);

	public DragSourceContext getDragSourceContext();
};


An instance of this event is passed to the DragSourceListener dragExit() method.


2.2.5 The DragSourceDragEvent Definition

The DragSourceDragEvent class is defined as follows:


public class java.awt.dnd.DragSourceDragEvent 
	  extends DragSourceEvent {
	public int getTargetActions();

	public int getGestureModifiers();

	public boolean isDropTargetLocal();
}


An instance of the above class is passed to a DragSourceListener's dragEnter(), dragOver(), and dragGestureChanged() methods.

The getDragSourceContext() method returns the DragSourceContext associated with the current Drag and Drop operation.

The getTargetActions() method returns the drop actions, supported by, and returned from the current DropTarget (if any in the case of dragGestureChanged()).

The getGestureModifiers() returns the current state of the input device modifiers, usually the mouse buttons and keyboard modifiers, associated with the users gesture.

The isDropTargetLocal() method returns true if the current DropTarget is contained within the same JVM as the DragSource, and false otherwise. This information can be useful to the implementor of the DragSource's Transferable in order to implement certain local optimizations.


2.2.6 The DragSourceDropEvent Definition

The DragSourceDropEvent class is defined as follows:


public public class java.awt.dnd.DragSourceDropEvent
	  extends java.util.EventObject {

	public DragSourceDropEvent(DragSourceContext dsc);
	public DragSourceDropEvent(DragSourceContext dsc,
						      int                action, 
						      boolean            success);

	public boolean isDropAborted();
	public boolean isDropSuccessful();

	public int getDropAction();
}

An instance of the above class is passed to a DragSourceListener's dragDropEnd() method. This event encapsulates the termination state of the Drag and Drop operation for the DragSource.

If the Drop occurs, then the participating DropTarget will signal the success or failure of the data transfer via the DropTargetContext's dropComplete() method, this status is made availlable to the initiator via the isDropSuccessful() method. The operation that the destination DropTarget selected to perform on the subject of the Drag (passed by the DropTarget's acceptDrop() method) is returned via the getDropAction() method.

If the Drag operation was aborted for any reason prior to a Drop occurring, for example if the users ends the gesture outwith a DropTarget, or if the DropTarget invokes rejectDrop() , the isDropAborted() method will return false, otherwise true.



CONTENTS | PREV | NEXT
Copyright © 1997 Sun Microsystems, Inc. All Rights Reserved.