Java 1.2 adds drag-and-drop support to Java. Drag-and-drop requires quite a bit more infrastructure than cut-and-paste, and this infrastructure is added in a package of its own, java.awt.dnd. Despite the complexity of the infrastructure, drag-and-drop is built upon the same data transfer architecture as cut-and-paste. The key classes are still DataFlavor and Transferable.
Here's the general outline of a drag-and-drop transaction from the standpoint of the initiating or dragging application or component:
If a component within an application wants to allow data to be dragged from it, it first obtains a DragSource object and then uses this DragSource to create a DragGestureRecognizer. This DragGestureRecognizer pays attention to mouse events that occur over the component, looking for the platform-dependent gesture that indicates that the user wants to drag something.
When the DragGestureRecognizer sees a drag gesture, it invokes the dragGestureRecognized() of a specified DragGestureListener object.
The dragGestureRecognized() method determines if there is data available for dragging, and, if so, it encapsulates the data in a Transferable object. dragGestureRecognized is passed a DragGestureEvent object. Unlike most other event objects, many of the event objects in the java.awt.dnd package define important methods that are used during a drag-and-drop transaction. In this case, the dragGestureRecognized() method activates the native drag-and-drop system by calling the startDrag() method of its DragGestureEvent object and passing it the Transferable object. In the call to startDrag(), you also specify a cursor that is displayed during the drag and a DragSourceListener object that keeps the data source notified about how the drag is progressing. You can also specify an optional Image that is dragged along with the cursor, on systems that support it. (Call the static DragSource.isDragImageSupported() to see if image dragging is supported on the system.)
As the user drags the data, various methods of the DragSourceListener are invoked to notify the initiating application of the status of the drag. These methods can be used to update the cursor being displayed or the image being dragged along with the cursor. The methods provide a way to implement specialized drag-over animation effects, for example. The native drag-and-drop system typically supplies basic drag-over effects, by changing the cursor when it is over a receptive drop target.
The most commonly used DragSourceListener method is dragDropEnd(). This method is invoked when the user drops the data. The initiating application can use this method to determine whether the drop was successful. If the user were moving data instead of copying data, the initiating application should delete its copy of the data once it has been successfully transferred to the recipient. dragDropEnd() is passed a DragSourceDropEvent object. The getDropSuccess() and getDropAction() methods of this event help the initiating application decide on the appropriate action to take.
A drag-and-drop transaction looks somewhat different from the standpoint of a receiving application or component:
A component that wants to allow data to be dropped on it must create a DropTarget object to act as an intermediary between itself and the native drag-and-drop system. When creating a DropTarget, you must specify the component on which data can be dropped and also a DropTargetListener object that can be notified when data is dragged over the component.
When the user drags data over the component, the dragEnter() method of the DropTargetListener is invoked. This method is passed a DropTargetDragEvent that it can query to determine the supported data flavors of the data being dragged. If the component is willing to accept a drop of that type of data, it should call the acceptDrop() method of the event object to signal its willingness. This in turn causes the dragEnter() method of the DragSourceListener in the initiating application to be invoked. The dragEnter() method of the DropTargetListener may also want to display some visual cue to the user of its willingness to accept a drop. For example, it might change colors or change its border. This kind of visual change is known as a "drag-under effect."
The dragOver() method is called repeatedly as the user continues to drag the data over the component. If the user drags the data out of the component, the dragExit() method is called. If dragEnter() displayed a visual cue, dragExit() should undo it.
If the user drops the data while over the component, the drop() method of the DropTargetListener is invoked. It is this method that performs the actual data transfer. drop() is passed a DropTargetDropEvent. The getTransferable() method of this event returns the Transferable object that was dropped. If the Transferable object supports a DataFlavor that the component can accept, the component calls the acceptDrop() method of the event to tell the native drag-and-drop system that the drop is valid. If it cannot work with any of the available data flavors, it should call rejectDrop(). After accepting the drop, the receiving component uses the getTransferData() method of the Transferable object to actually transfer the data. This phase of the data transfer is done exactly as it is in cut-and-paste. Finally, the component calls the dropComplete() method of the DropTargetDropEvent, passing true if the transfer was successful or false if something went wrong and the transfer did not succeed.
Copyright © 2001 O'Reilly & Associates. All rights reserved.