24.4 The Drag API


Once 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
figs/swng2.2405.gif

24.4.1 The DragSource Class

The 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 Properties

The 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.

Table 24-14. DragSource properties

Property

Data type

get

is

set

Default value

defaultDragSources

DragSource

·

     

dragImageSupporteds

boolean

 

·

   

dragSourceListeners1.4

DragSourceListener[]

·

   

Empty array

dragSourceMotionListeners1.4

DragSourceMotionListener[]

·

   

Empty array

flavorMap

FlavorMap

·

     

sstatic, 1.4since 1.4

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 Constants

Several 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.

Table 24-15. DragSource constants

Constant

Data type

Illustration

DefaultCopyDrop

Cursor

figs/copy.cursor.gif

DefaultCopyNoDrop

Cursor

figs/nodrop.cursor.gif

DefaultLinkDrop

Cursor

figs/link.cursor.gif

DefaultLinkNoDrop

Cursor

figs/nodrop.cursor.gif

DefaultMoveDrop

Cursor

figs/move.cursor.gif

DefaultMoveNoDrop

Cursor

figs/nodrop.cursor.gif

24.4.1.3 Events

DragSource generates two types of events and includes the appropriate add and remove methods. The listeners and drag events are described later in this section.

public void addDragSourceListener( )
public void removeDragSourceListener( )

Manage listeners for source events such as reporting when a successful drop occurrs on the drop side.

public void addDragSourceMotionListener( )
public void removeDragSourceMotionListener( )

Manage listeners for source motion events. You might listen to motion events if you support any custom functionality based on the location of the mouse. (For example, if you still want to notice when a user passes into a particular part of the screen that is not a drop target.)

24.4.1.4 Constructor

DragSource has one public constructor:

public DragSource( )

This constructor creates a new DragSource.

24.4.1.5 Helper creation methods

The DragSource class has a few helper methods to create the other parts required for initiating a drag:

public DragGestureRecognizer createDefaultDragGestureRecognizer(Component c, int actions, DragGestureListener dgl)
public DragGestureRecognizer createDragGestureRecognizer(Class recognizerClass, Component c, int actions, DragGestureListener dgl)

These methods can be used to create DragGestureRecognizer objects for your drag-capable component (c). Again, the actions argument comes from DnDConstants and dictates the types of actions (move, copy, link) that are acceptable. You can give a null listener for the dgl argument and attach one to the recognizer later. The second version of this method uses recognizerClass as a prototype for the recognizer. The recognizerClass argument should be a subclass of DragGestureRecognizer.

protected DragSourceContext createDragSourceContext(DragSourceContextPeer dscp, DragGestureEvent dgl, Cursor dragCursor, Image dragImage, Point imageOffset, Transferable t, DragSourceListener dsl)

This protected method creates a new context object for the DragSource. As with other peer operations, this is not something you normally need to use. However, subclasses can override this to create context objects suited to a particular task, such as supplying a certain image to go with the drag operation.

24.4.1.6 Start methods

As 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:

public void startDrag(DragGestureEvent trigger, Cursor dragCursor, Transferable transferable, DragSourceListener dsl) throws InvalidDnDOperationException

The simplest of the start methods, this requires only a trigger event (trigger), an initial cursor to display (dragCursor), the data to be transferred (transferable), and a source listener (which can be null). If the system is not in a state in which a drag initiation is allowed (typically because a peer DragSourceContext cannot be created), it throws the InvalidDnDOperationException.

public void startDrag(DragGestureEvent trigger, Cursor dragCursor, Transferable transferable, DragSourceListener dsl, FlavorMap flavorMap) throws InvalidDnDOperationException

Similar to the previous method, this version allows you to specify your own flavor map.

public void startDrag(DragGestureEvent trigger, Cursor dragCursor, Image dragImage, Point dragOffset, Transferable transferable, DragSourceListener dsl) throws InvalidDnDOperationException

If your system supports drag images, you can specify the image and the offset for the cursor location in that image. Remember that not all systems support drag images.

public void startDrag(DragGestureEvent trigger, Cursor dragCursor, Image dragImage, Point imageOffset, Transferable transferable, DragSourceListener dsl, FlavorMap flavorMap) throws InvalidDnDOperationException

Similar to the other startDrag( ) methods, but you can specify both a drag image and a flavor map if you have them.

24.4.2 The DragSourceContext Class

As 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 Properties

The properties for DragSourceContext are shown in Table 24-16. They are all read-only.

Table 24-16. DragSourceContext properties

Property

Data type

get

is

set

Default value

component

Component

·

     

cursor

Cursor

·

     

dragSource

DragSource

·

     

sourceActions

int

·

     

transferable

Transferable

·

     

trigger

InputEvent

·

     

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 Events

The 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.)

public void addDragSourceListener(DragSourceListener dsl) throws TooManyListenersException
public void removeDragSourceListener(DragSourceListener dsl)

These methods add or remove a drag source listener for this context. Notice that this is a unicast event.

24.4.2.3 Protected constants

Table 24-17 defines four protected constants found in the DragSourceContext class.

Table 24-17. DragSourceContext constants

Constant

Data type

Description

CHANGED

int

The user action changed (usually between copy and move).

DEFAULT

int

Switches to the default cursor.

ENTER

int

The cursor entered a drop target.

OVER

int

The cursor is over a drop target.

These constants are used to identify cursor actions in the updateCurrentCursor( ) method, which is described later.

24.4.2.4 Constructors

You 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 methods

Like the DropTargetContext class, DragSourceContext implements the DragSourceList-ener interface itself.

public void dragEnter(DragSourceDragEvent dsde)
public void dragOver(DragSourceDragEvent dsde)
public void dragExit(DragSourceEvent dse)
public void dropActionChanged(DragSourceDragEvent dsde)
public void dragDropEnd(DragSourceDropEvent dsde)

These methods come from the DragSourceListener interface. They trap incoming events and, if a valid listener exists, the events are passed on. The cursor is then updated for you automatically.

24.4.2.6 Miscellaneous methods

Two other methods round out the functionality of the DragSourceContext class:

public void transferablesFlavorsChanged( )

This method can also be used to indicate that something has changed in the current drag process. If the data flavor for the Transferable object changes, this method can be called to notify the native peer of that change.

protected void updateCurrentCursor(int dropOp, int targetAct, int status)

Each of the previous event methods use this method to update the cursor as the user moves around over potential drop targets and other parts of the application. The dropOp argument is the current action the user has undertaken. The targetAction argument lists the acceptable drop actions for the current target, and status indicates the type of update for the current cursor. This can be any of the values from Table 24-17.

24.4.3 The DragSourceListener Interface

If 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 methods

The types of events presented here mimic the types we saw with the DropTargetListener interface:

public void dragEnter(DragSourceDragEvent dsde)

This method handles events generated as the user enters a viable drop target.

public void dragOver(DragSourceDragEvent dsde)

This method handles events that are generated continuously as the user moves around inside the bounds of a viable drop target.

public void dropActionChanged(DragSourceDragEvent dsde)

If the user changes from copy to move or vice versa, this method receives that event.

public void dragExit(DragSourceEvent dse)

This method handles the events generated when the user leaves the bounds of a viable target.

public void dragDropEnd(DragSourceDropEvent dsde)

Not found in the DropTargetListener interface, this method is notified when a drop has completed on a drop target. Notification does not imply success; you need to check the dsde event for that. The events are discussed in the next section.

24.4.4 The DragSourceMotionListener Interface

If 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 method

The event presented here is similar to the types found in the MouseMotionListener interface:

public void dragMouseMoved(DragSourceDragEvent dsde)

This method handles events generated as the user moves the mouse after starting a drag.

24.4.5 The DragSourceAdapter Class

As 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 Events

Not 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.

Table 24-18. DragSourceEvent property

Property

Data type

get

is

set

Default value

dragSourceContext

DragSourceContext

·

     

24.4.6.1 Constructors
public DragSourceEvent(DragSourceContext dsc)
public DragSourceEvent(DragSourceContext dsc, int x, int y)

If you have a valid DragSourceContext, you can build your own DragSourceEvent with this constructor. As of SDK 1.4, you can also specify (x,y) coordinates for the event.

24.4.7 The DragSourceDragEvent Class

The 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 Properties

The 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.

Table 24-19. DragSourceDragEvent properties

Property

Data type

get

is

set

Default value

dropAction

int

·

     

gestureModifiers

int

·

     

targetActions

int

·

     

userAction

int

·

     

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 Class

While 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 Properties

Table 24-20 shows the two properties available from a DragSourceDropEvent.

Table 24-20. DragSourceDropEvent properties

Property

Data type

get

is

set

Default value

dropAction

int

·

     

dropSuccess

boolean

·

     

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 Gesture

Now 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
figs/swng2.2406.gif

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.



Java Swing
Graphic Java 2: Mastering the Jfc, By Geary, 3Rd Edition, Volume 2: Swing
ISBN: 0130796670
EAN: 2147483647
Year: 2001
Pages: 289
Authors: David Geary

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net