I l@ve RuBoard |
![]() ![]() |
24.4 The Drag APIOnce you recognize a drag gesture, you can start an actual drag. The drag source receives many of the same types of events as the drop target. Like a drop target, a drag source has a native peer in the form of a DragSourceContext and receives events as the user drags his object over the source and finally drops it on a drop target. As shown in Figure 24-5, the class diagram for the Drag API is similar to that of the Drop API. Figure 24-5. Class diagram of DnD's drag side![]() 24.4.1 The DragSource ClassThe DragSource class, the flip side of DropTarget, provides support for creating draggable information. Recall from the beginning of this chapter that unlike the DropTarget class, a regular GUI component is not used as a base. Rather, the base component for starting a drag is encapsulated in the DragGestureRecognizer. The recognizer can in turn start a drag for the DragSource. The DragSource class encompasses the context of the drag and provides a focal point for maintaining the visual state of the drag. For example, several predefined cursors that you can use during the drag operation are built into this class. 24.4.1.1 PropertiesThe DragSource class has only three properties, two of which are static and apply to the overall DnD system. These properties are shown in Table 24-14.
The defaultDragSource property provides a "platform" drag source that can be retrieved from any other class. Since you do not really associate a component with a drag source, you can rely entirely on this default source during your drags. (This is not required; you can build your own.) The flavorMap property stores the flavor map for the source to help translate between native names and MIME types. The dragImageSupported property indicates whether your system can drag an Image along with the cursor during a drag operation. 24.4.1.2 ConstantsSeveral predefined cursors are at your disposal as constants in DragSource. These cursor constants can be used when starting a drag operation and are listed in Table 24-15. The sample images are merely representative of the types of cursors that appear. They may vary from system to system; with Java 2, you are certainly free to create your own.
24.4.1.3 EventsDragSource generates two types of events and includes the appropriate add and remove methods. The listeners and drag events are described later in this section.
24.4.1.4 ConstructorDragSource has one public constructor:
24.4.1.5 Helper creation methodsThe DragSource class has a few helper methods to create the other parts required for initiating a drag:
24.4.1.6 Start methodsAs you saw in the DragGestureEvent class, once a drag gesture has been recognized, you need to start the drag manually. You can use either the drag event versions, or if you need a bit more control, you can use any of the following methods as well:
24.4.2 The DragSourceContext ClassAs you may have gathered from the previous section, DragSource objects use a DragSourceContext to handle the necessary native windowing code in much the same way DropTarget objects do. You don't have to create an instance of this class on your own, but you can access the context from the DragSource class if you need any of the information provided by the context. 24.4.2.1 PropertiesThe properties for DragSourceContext are shown in Table 24-16. They are all read-only.
These properties give you access to the "way things look" during a drag operation. With the exception of the cursor property, which can tell you which cursor is currently displayed, these properties are similar to those in the DragGestureEvent class. 24.4.2.2 EventsThe DragSourceContext class is the source of DragSource events. By definition, the source of an event contains the appropriate add and remove methods for attaching listeners. While you can use these methods to attach (or detach) a listener, you typically pass in your listener when you call a startDrag( ) method. (The actual DragSourceEvent class is described in the next section.)
24.4.2.3 Protected constantsTable 24-17 defines four protected constants found in the DragSourceContext class.
These constants are used to identify cursor actions in the updateCurrentCursor( ) method, which is described later. 24.4.2.4 ConstructorsYou can create a DragSourceContext with its only constructor. However, you need a valid DragSourceContextPeer for your platform. Normally, you use the startDrag( ) methods, and a context is created for you. public DragSourceContext(DragSourceContextPeer dscp, DragGestureEvent trigger, Cursor dragCursor, Image dragImage, Point offset, Transferable t, DragSourceListener dsl) 24.4.2.5 Event methodsLike the DropTargetContext class, DragSourceContext implements the DragSourceList-ener interface itself.
24.4.2.6 Miscellaneous methodsTwo other methods round out the functionality of the DragSourceContext class:
24.4.3 The DragSourceListener InterfaceIf you care about events being sent to the drag source, you should implement the DragSourceListener interface. All drag events generated over the source object and the drop event (either an accepted drop over a valid drop target or a rejected drop) are sent here. 24.4.3.1 Event methodsThe types of events presented here mimic the types we saw with the DropTargetListener interface:
24.4.4 The DragSourceMotionListener InterfaceIf you care about events being sent while a drag is in motion, you should implement the DragSourceMotionListener interface. Introduced in 1.4, this interface allows you to listen in on the current position of a drag that is in progress. You might need this if you plan to respond to the location of the mouse cursor during a drag. While you probably won't use this interface, it is vital for any custom DnD support. 24.4.4.1 Event methodThe event presented here is similar to the types found in the MouseMotionListener interface:
24.4.5 The DragSourceAdapter ClassAs with the DropTargetAdapter from the previous section, the drag source listeners have a companion adapter: DragSourceAdapter. This class was introduced in 1.4 and implements both DragSourceListener and DragSourceMotionListener. It provides null bodies for each of the listener's methods. 24.4.6 Drag Source EventsNot surprisingly, we have drag source events similar to the drop target events. The DragSourceEvent class serves as the base of the event hierarchy and gives you access to the source context through its sole property, shown in Table 24-18.
24.4.6.1 Constructors
24.4.7 The DragSourceDragEvent ClassThe subclasses of DragSourceEvent distinguish between dragging events and drop events. DragSourceDragEvent is used in a majority of the events reported, with the exception of exit events and drop complete events. 24.4.7.1 PropertiesThe DragSourceDragEvent properties help you decide how the source of the drag should respond to various things the user does. Most of the properties deal with the types of actions the user can take and, of course, what the user is really doing. They are shown in Table 24-19.
dropAction represents the effective drop action found by combining the user's currently selected drop action (userAction) and the actions acceptable to the target (targetActions). Differences in the dropAction and userAction can be used to provide helpful feedback to the user during the drag operation. The gestureModifiers property describes the state of any input modifiers, such as holding down the Control key. 24.4.8 The DragSourceDropEvent ClassWhile it's not required, your source might care about the success (or failure) of a drop. This class encapsulates the drop event and its status. 24.4.8.1 PropertiesTable 24-20 shows the two properties available from a DragSourceDropEvent.
The dropAction property contains the final drop action taken by the user. If the drop target accepts the drop, dropSuccess is true (false otherwise). You may recall the dropComplete( ) method from the DropTargetDropEvent class. The dropSuccess property reflects the value passed to that method. 24.4.9 Completing the GestureNow we can go back to our GestureTest program and finish the job. We'll complete the DragSource object and add some listener methods so that we can see the different events as they are reported to the DragSourceListener. You should pay attention to what we do in the dragGestureRecognized( ) method, which is where we manually start the drag operation. (See Figure 24-6.) Figure 24-6. A drag operation started in a JList and dropped in a JTextArea![]() Here's the source for the complete DragTest application. (We used DropTest2 with the expanded drop( ) method for the receiving end.) /* * DragTest.java * A simple (?) test of the DragSource classes to * create a draggable object in a Java application. */ import java.awt.*; import java.awt.dnd.*; import java.awt.datatransfer.*; import java.awt.event.*; import java.io.*; import java.util.*; import javax.swing.*; public class DragTest extends JFrame implements DragSourceListener, DragGestureListener { DragSource ds; JList jl; StringSelection transferable; String[] items = {"Java", "C", "C++", "Lisp", "Perl", "Python"}; public DragTest( ) { super("Drag Test"); setSize(200,150); setDefaultCloseOperation(EXIT_ON_CLOSE); // Set up our JList and DragRecognizer as before. This time, the difference is // that we use the recognized drag to start a real drag process. jl = new JList(items); jl.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); getContentPane( ).add(new JScrollPane(jl), BorderLayout.CENTER); ds = new DragSource( ); DragGestureRecognizer dgr = ds.createDefaultDragGestureRecognizer( jl, DnDConstants.ACTION_COPY, this); setVisible(true); } // In addition to reporting a successful gesture, create a piece of transferable // data using java.awt.datatransfer.StringSelection. public void dragGestureRecognized(DragGestureEvent dge) { System.out.println("Drag Gesture Recognized!"); transferable = new StringSelection(jl.getSelectedValue( ).toString( )); ds.startDrag(dge, DragSource.DefaultCopyDrop, transferable, this); } public void dragEnter(DragSourceDragEvent dsde) { System.out.println("Drag Enter"); } public void dragExit(DragSourceEvent dse) { System.out.println("Drag Exit"); } public void dragOver(DragSourceDragEvent dsde) { System.out.println("Drag Over"); } public void dragDropEnd(DragSourceDropEvent dsde) { System.out.print("Drag Drop End: "); if (dsde.getDropSuccess( )) { System.out.println("Succeeded"); } else { System.out.println("Failed"); } } public void dropActionChanged(DragSourceDragEvent dsde) { System.out.println("Drop Action Changed"); } public static void main(String args[]) { new DragTest( ); } } With this version of the dragGestureRecognized( ) method, we create a real piece of draggable information. In our particular case, we create a String object with the StringSelection class. This object can be picked up by other Java applications as a String or as a serialized Java object—admittedly, not the ideal transfer medium if you are serious about dropping this text in a native application. Fortunately, the StringSelection class also supports the "plain-text" flavor, which is more useful for native applications. While we won't waste the paper needed to present it here, you can see the 1.4 version of this example in the online code. (It's also somewhat boring because it just works.) Check out DragTest14.java and DropTest14.java. Again, these examples work so cleanly because they don't require any customization. We hope that you'll be in the same position more often than not. |
I l@ve RuBoard |
![]() ![]() |