Drag and Drop


When you use cut and paste to transmit information between two programs, the clipboard acts as an intermediary. The drag and drop metaphor cuts out the middleman and lets two programs communicate directly. The Java platform offers basic support for drag and drop. You can carry out drag and drop operations between Java applications and native applications. This section shows you how to write a Java application that is a drop target, and an application that is a drag source.

Before going deeper into the Java platform support for drag and drop, let us quickly look at the drag and drop user interface. We use the Windows Explorer and WordPad programs as exampleson another platform, you can experiment with locally available programs with drag and drop capabilities.

You initiate a drag operation with a gesture inside a drag sourceusually, by first selecting one or more elements and then dragging the selection away from its initial location (see Figure 7-51).

Figure 7-51. Initiating a drag operation


When you release the mouse button over a drop target that accepts the drop operation, the drop target queries the drag source for information about the dropped elements and initiates some operation. For example, if you drop a file icon from Windows Explorer to WordPad, then WordPad opens the file. However, if you drag a file icon on top of a directory icon in Windows Explorer, then Explorer moves the file into that directory.

If you hold down the SHIFT or CTRL key while dragging, then the type of the drop action changes from a move action to a copy action, and a copy of the file is placed into the directory. If you hold down both SHIFT and CTRL keys, then a link to the file is placed into the directory. (Other platforms may use other keyboard combinations for these operations.)

Thus, there are three types of drop actions with different gestures:

  • Move

  • Copy

  • Link

The intention of the link action is to establish a reference to the dropped element. Such links typically require support from the host operating system (such as symbolic links for files, or object linking for document components) and don't usually make a lot of sense in cross-platform programs. In this section, we focus on using drag and drop for copying and moving.

There is usually some visual feedback for the drag operation. Minimally, the cursor shape changes. As the cursor moves over possible drop targets, the cursor shape indicates whether the drop is possible or not. If a drop is possible, the cursor shape also indicates the type of the drop action. Figure 7-52 shows several cursor shapes over drop targets.

Figure 7-52. Cursor shapes over drop targets

Drop not allowed

Move

Copy

Link


You can also drag other elements besides file icons. For example, you can select text in WordPad and drag it. Try dropping text fragments into willing drop targets and see how they react.

NOTE

This experiment shows a disadvantage of drag and drop as a user interface mechanism. It can be difficult for users to anticipate what they can drag, where they can drop it, and what happens when they do. Because the default "move" action can remove the original, many users are understandably cautious about experimenting with drag and drop.


Drop Targets

In this section, we construct a simple Java application that is a drop target. The example program does nothing useful; it simply demonstrates how you can detect that a user would like to initiate a drop, how to accept the drop, and how to analyze the data that are being dropped.

You can designate any AWT component to be a drop target. To do so, you construct a DropTarget object and pass the component and a drop target listener to the constructor. The constructor registers the object with the drag and drop system.

 DropTarget target = new DropTarget(component, listener); 

You can activate or deactivate the target with the setActive method. By default, the target is active.

 target.setActive(b); 

You can call the setDefaultActions method to set the following drop operations that you want to accept by default:

 DndConstants.ACTION_COPY DndConstants.ACTION_MOVE DndConstants.ACTION_COPY_OR_MOVE DndConstants.ACTION_LINK 

By default, all operations are allowed.

Now you need to implement a drop target listener. The DropTargetListener interface has five methods:

 void dragEnter(DropTargetDragEvent event) void dragExit(DropTargetEvent event) void dragOver(DropTargetDragEvent event) void dropActionChanged(DropTargetDragEvent event) void drop(DropTargetDropEvent event) 

The dragEnter and dragExit methods are called when the cursor enters or exits the drop target component. In the dragEnter method, you can set the cursor shape to indicate whether the drop target is willing to accept the drop.

You don't usually worry about the dragExit method. However, if you built up some elaborate mechanism for visual feedback, then you can dispose of it in this method.

The dragOver method is called continuously as the user moves the mouse over the drop target component. You can use it to give detailed visual feedback about the effect of a drop. For example, if the drop target is a tree component, you can highlight the node under the cursor or even open up a subtree if the cursor hovers over a node.

The dropActionChanged method is called if the user changes the action gesture. For example, if the user presses or lifts the SHIFT or CTRL keys while moving the mouse over the drop target component, then this method is called. That gives you a chance to modify the visual feedback and match it to the changed action.

The most important method is the drop method. It is called when the user has committed to a drop by finishing the drop gesture, usually by releasing the mouse button. Note that this method is called whether or not you previously indicated that you would accept the drop.

Look carefully at the parameters of the DropTargetListener methods. Three of them are a DropTargetDragEvent. However, the drop method receives a DropTargetDropEvent, and the dragExit method receives a DropTargetEvent. The DropTargetEvent class is the superclass of the other two event classes. It has only one method, getdropTargetContext, which returns a class with no interesting public methods. Since the purpose of a dragExit method is to clean up, you probably won't even look at the parameter.

The DropTargetDragEvent and DropTargetDropEvent classes each have the following methods:

 int getDropAction() Point getLocation() DataFlavor[] getCurrentDataFlavors() boolean isDataFlavorSupported(DataFlavor flavor) 

You need these methods to test whether to encourage a drag or allow a drop, and to specify how to give visual feedback.

Unfortunately, because the methods are not available in the common superclass, you'll have to implement the test logic twice, once for the drag and then again for the drop.

If you don't want to encourage a drag, you call the rejectDrag method of the DropTargetDragEvent class in the dragEnter or dropActionChanged method. As a result, the cursor changes to a warning icon. If the user drops an item despite the warning, then you call the rejectDrop method of the DropTargetDropEvent class.

The getdropAction method returns the drop action that the user intends to carry out. In many drag and drop operations, you don't want the action taken literally. For example, if you move a file icon into WordPad, then you don't want the drag source to delete the file. But you also don't want the drop target to insist that the user hold down a key when dragging. In this situation, the drop target should accept either copy or move actions. In the drop method, call the acceptDrop method of the DropTargetDropEvent with the actual action. If you call

 event.acceptDrop(DnDConstants.ACTION_MOVE); // drag source deletes dragged items! 

then the drag source will delete the dragged items.

TIP

Are you certain that your users understand the distinction between move and copy operations and the role of the SHIFT and CTRL modifiers? Do they realize that the default drag gesture (without a modifier) deletes the dragged items from the source? If not, you should accept a drop as

 event.acceptDrop(DnDConstants.ACTION_COPY); 

On the other hand, if you really want to make a distinction between move and copy, simply call

 event.acceptDrop(event.getDropAction()). 


Here is an overview of a typical drop target listener:


class ADropTargetListener implements DropTargetListener
{
   // convenience methods
   public boolean isDragAcceptable(DropTargetDragEvent event)
   {
      look at drop action and available data flavors
   }

   public boolean isDropAcceptable(DropTargetDropEvent event)
   {
      carry out the same test as in isDragAcceptable
   }

   // listener methods
   public void dragEnter(DropTargetDragEvent event)
   {
      if (!isDragAcceptable(event))
      {
         event.rejectDrag();
         return;
      }
   }

   public void dragExit(DropTargetEvent event)
   {
   }

   public void dragOver(DropTargetDragEvent event)
   {
      // you can provide visual feedback here
   }

   public void dropActionChanged(DropTargetDragEvent event)
   {

      if (!isDragAcceptable(event))
      {
         event.rejectDrag();
         return;
      }
   }

   public void drop(DropTargetDropEvent event)
   {
      if (!isDropAcceptable(event))
      {
         event.rejectDrop();
         return;
      }
      event.acceptDrop(actual action);
      process data from drag source
      event.dropComplete(true);
   }
   . . .
}

Once you accept a drop, you need to analyze the data from the drag source. The gettransferable method of the DropTargetDropEvent class returns a reference to a transferable object. This is the same interface that is used for copy and paste.

One data type that is more commonly used for drag and drop than for copy and paste is the DataFlavor.javaFileListFlavor. A file list describes a set of file icons that was dropped onto the target. The transferable object yields an object of type java.util.List whose items are File objects. Here is the code for retrieving the files:


DataFlavor[] flavors = transferable.getTransferDataFlavors();
DataFlavor flavor = flavors[i];
if (flavor.equals(DataFlavor.javaFileListFlavor))
{
   java.util.List<File> fileList = (java.util.List<File>) transferable.getTransferData(flavor);
   Iterator iterator = fileList.iterator();
   for (File f : fileList)
   {
      do something with f;
   }
}

Another flavor that can be dropped is text. You can retrieve the text in various flavors. The most convenient is DataFlavor.stringFlavor. The other flavors have a MIME type of text/plain and a variety of representation classes, including InputStream and [B (byte array).

CAUTION

Earlier versions of the Java platform did not go through the effort of converting dragged text to Unicode and giving you a stringFlavor. Instead, you had to retrieve the text through an InputStream. The text/plain MIME type contains a charset parameter that indicates the character encoding. To compound the inconvenience, those Java platform versions also used character encoding names that were different from the names that the InputStreamReader constructor expects. In particular, you had to convert ascii to ISO-8859-1 and unicode to Unicode.

Under Windows, you ran into additional problems. The end of input was indicated by a null character, and you should not read past it. The Unicode data didn't start with a Unicode byte order marker that the InputStreamReader expects, resulting in a sun.io.MalformedInputException. Thus, programmers had to bypass the InputStreamReader and construct the Unicode characters from pairs of bytes.

Fortunately, these growing pains have been overcome in JDK 1.4.


Depending on the drag source, you might also find data in other formats such as

 text/html text/rtf 

To read the data in that format, pick a convenient flavor, for example, an input stream, and obtain the data like this:


if (flavor.isMimeTypeEqual("text/html") && flavor.getRepresentationClass() == InputStream.class)
{
   String charset = flavor.getParameter("charset");
   InputStreamReader in = new InputStreamReader(transferable.getTransferData(flavor), charset);
   read data from in
}

Our sample program does not attempt to do anything useful. It simply lets you drop items onto a text area. When you start dragging over the text area, the drop action is displayed. Once you initiate a drop, the dropped data are displayed. If the data are in text format, the program reads both ascii and unicode encodings.

In our sample program, we do not give any visual feedback of the dragging process beyond the change to a warning cursor that automatically happens when the rejectDrag method is called.

This program simply gives you a drop target for experimentation. Try dropping a selection of file names from Windows Explorer or a text fragment from WordPad (see Figure 7-53). Also see how a link attempt is rejected. If you press both the SHIFT and CTRL keys, then a warning icon appears when you drag an item over the text area.

Figure 7-53. The DropTargetTest program


Example 7-20 shows the complete program.

Example 7-20. DropTargetTest.java

[View full width]

   1. import java.awt.*;   2. import java.awt.datatransfer.*;   3. import java.awt.event.*;   4. import java.awt.dnd.*;   5. import java.io.*;   6. import java.util.*;   7. import javax.swing.*;   8.   9. /**  10.    This is a test class to test drag and drop behavior. Drop items into the text area  to see the  11.    MIME types of the drop target.  12. */  13. public class DropTargetTest  14. {  15.    public static void main(String[] args)  16.    {  17.       JFrame frame = new DropTargetFrame();  18.       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  19.       frame.setVisible(true);  20.    }  21. }  22.  23. /**  24.    This frame contains a text area that is a simple drop target.  25. */  26. class DropTargetFrame extends JFrame  27. {  28.    public DropTargetFrame()  29.    {  30.       setTitle("DropTarget");  31.       setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);  32.  33.       JTextArea textArea = new JTextArea("Drop items into this text area.\n");  34.  35.       new DropTarget(textArea, new TextDropTargetListener(textArea));  36.       add(new JScrollPane(textArea), "Center");  37.    }  38.  39.    private static final int DEFAULT_WIDTH = 300;  40.    private static final int DEFAULT_HEIGHT = 300;  41. }  42.  43. /**  44.    This listener displays the properties of a dropped object.  45. */  46. class TextDropTargetListener implements DropTargetListener  47. {  48.    /**  49.       Constructs a listener.  50.       @param aTextArea the text area in which to display the  51.       properties of the dropped object.  52.    */  53.    public TextDropTargetListener(JTextArea aTextArea)  54.    {  55.       textArea = aTextArea;  56.    }  57.  58.    public void dragEnter(DropTargetDragEvent event)  59.    {  60.       int a = event.getDropAction();  61.       if ((a & DnDConstants.ACTION_COPY) != 0)  62.          textArea.append("ACTION_COPY\n");  63.       if ((a & DnDConstants.ACTION_MOVE) != 0)  64.          textArea.append("ACTION_MOVE\n");  65.       if ((a & DnDConstants.ACTION_LINK) != 0)  66.          textArea.append("ACTION_LINK\n");  67.  68.       if (!isDragAcceptable(event))  69.       {  70.          event.rejectDrag();  71.          return;  72.       }  73.    }  74.  75.    public void dragExit(DropTargetEvent event)  76.    {  77.    }  78.  79.    public void dragOver(DropTargetDragEvent event)  80.    {  81.       // you can provide visual feedback here  82.    }  83.  84.    public void dropActionChanged(DropTargetDragEvent event)  85.    {  86.       if (!isDragAcceptable(event))  87.       {  88.          event.rejectDrag();  89.          return;  90.       }  91.    }  92.  93.    public void drop(DropTargetDropEvent event)  94.    {  95.       if (!isDropAcceptable(event))  96.       {  97.          event.rejectDrop();  98.          return;  99.       } 100. 101.       event.acceptDrop(DnDConstants.ACTION_COPY); 102. 103.       Transferable transferable = event.getTransferable(); 104. 105.       DataFlavor[] flavors = transferable.getTransferDataFlavors(); 106.       for (int i = 0; i < flavors.length; i++) 107.       { 108.          DataFlavor d = flavors[i]; 109.          textArea.append("MIME type=" + d.getMimeType() + "\n"); 110. 111.          try 112.          { 113.             if (d.equals(DataFlavor.javaFileListFlavor)) 114.             { 115.                java.util.List<File> fileList 116.                   = (java.util.List<File>) transferable.getTransferData(d); 117.                for (File f : fileList) 118.                { 119.                   textArea.append(f + "\n"); 120.                } 121.             } 122.             else if (d.equals(DataFlavor.stringFlavor)) 123.             { 124.                String s = (String) transferable.getTransferData(d); 125.                textArea.append(s + "\n"); 126.             } 127.          } 128.          catch (Exception e) 129.          { 130.             textArea.append(e + "\n"); 131.          } 132.       } 133.       textArea.append("\n"); 134.       event.dropComplete(true); 135.    } 136. 137.    public boolean isDragAcceptable(DropTargetDragEvent event) 138.    { 139.       // usually, you check the available data flavors here 140.       // in this program, we accept all flavors 141.       return (event.getDropAction() & DnDConstants.ACTION_COPY_OR_MOVE) != 0; 142.    } 143. 144.    public boolean isDropAcceptable(DropTargetDropEvent event) 145.    { 146.       // usually, you check the available data flavors here 147.       // in this program, we accept all flavors 148.       return (event.getDropAction() & DnDConstants.ACTION_COPY_OR_MOVE) != 0; 149.    } 150. 151.    private JTextArea textArea; 152. } 


 java.awt.dnd.DropTarget 1.2 

  • DropTarget(Component c, DropTargetListener listener)

    constructs a drop target that coordinates the drag and drop action onto a component.

    Parameters:

    c

    The drop target

     

    listener

    The listener to be notified in the drop process


  • void setActive(boolean b)

    activates or deactivates this drop target.

  • void setDefaultActions(int actions)

    sets the actions that are permissible by default for this drop target. actions is a bit mask composed of constants defined in the DnDConstants class such as ACTION_COPY, ACTION_MOVE, ACTION_COPY_OR_MOVE, or ACTION_LINK.


 java.awt.dnd.DropTargetListener 1.2 

  • void dragEnter(DropTargetDragEvent event)

    is called when the cursor enters the drop target.

  • void dragExit(DropTargetEvent event)

    is called when the cursor exits the drop target.

  • void dragOver(DropTargetDragEvent event)

    is called when the cursor moves over the drop target.

  • void dropActionChanged(DropTargetDragEvent event)

    is called when the user changes the drop action while the cursor is over the drop target.

  • void drop(DropTargetDropEvent event)

    is called when the user drops items into the drop target.


 java.awt.dnd.DropTargetDragEvent 1.2 

  • int getDropAction()

    gets the currently selected drop action. Possible values are defined in the DnDConstants class.

  • void acceptDrag(int action)

    should be called if the drop target wants to accept a drop action that is different from the currently selected action.

  • void rejectDrag()

    notifies the drag and drop mechanism that this component rejects the current drop attempt.

  • Point getLocation()

    returns the current location of the mouse over the drop target.

  • DataFlavor[] getCurrentDataFlavors()

    returns the data flavors that the drag source can deliver.

  • boolean isDataFlavorSupported(DataFlavor flavor)

    tests whether drag source supports the given flavor.

  • TRansferable getTransferable() 5.0

    gets the transferable object that represents the dragged value.


 java.awt.dnd.DropTargetDropEvent 1.2 

  • int getDropAction()

    gets the currently selected drop action. Possible values are defined in the DnDConstants class.

  • void acceptDrop(int action)

    should be called if the drop target has carried out a drop action that is different from the currently selected action.

  • void rejectDrop()

    notifies the drag and drop mechanism that this component rejects the drop.

  • void dropComplete(boolean success)

    notifies the drag source that the drop is complete and that it was or was not successful.

  • Point getLocation()

    returns the current location of the mouse over the drop target.

  • DataFlavor[] getCurrentDataFlavors()

    returns the data flavors that the drag source can deliver.

  • boolean isDataFlavorSupported(DataFlavor flavor)

    tests whether the drag source supports the given flavor.

Drag Sources

Now that you saw how to implement a program that contains a drop target, we show you how to implement a drag source.

The program in Example 7-21 fills a JList with all files in the current directory (see Figure 7-54). The list component is a drag source. You can drag file items from the list component to any drop target that is willing to accept a list of files.

Figure 7-54. The DragSourceTest program


To turn a component into a drag source, obtain a DragSource objectyou can simply call the static DragSource.getDefaultDragSource method. Then, call the createDefaultDragGestureRecognizer method and supply it with

  • The component that you want to turn into a drag source;

  • The drop actions that you want to allow; and

  • An object that implements the DragGestureListener interface.

For example,

 DragSource dragSource = DragSource.getDefaultDragSource(); dragSource.createDefaultDragGestureRecognizer(component,    DnDConstants.ACTION_COPY_OR_MOVE, dragGestureListener); 

The DragGestureListener interface has a single method, dragGestureRecognized. The gesture recognizer calls that method as soon as it has noticed that the user wants to initiate a drag operation. In that method, you build the transferable object that the drop target will ultimately read in its drop method. Once you have assembled the transferable object, you call the startDrag method of the DragGestureEvent class. You supply an optional cursor, or null if you want to use the default drag cursor, followed by the transferable object and an object that implements the DragSourceListener interface. For example,

 event.startDrag(null, transferable, dragSourceListener); 

You then do the usual busywork of defining a transferable wrappersee the code in the example program for details.

The drag source listener is notified repeatedly as the drag operation progresses. The interface has five methods:

 void dragEnter(DragSourceDragEvent event) void dragOver(DragSourceDragEvent event) void dragExit(DragSourceEvent event) void dropActionChanged(DragSourceDragEvent event) void dragDropEnd(DragSourceDropEvent event) 

You can use the first four methods to give the user visual feedback of the drag operation. However, generally, such feedback should be the role of the drop target. Only the last method, dragDropEnd, is important. This method is called when the drop method has finished. For a move operation, you check whether the drop has succeeded. In that case, you update the drag source. (For a copy operation, you probably don't have to do anything.)

NOTE

JDK 1.4 introduces a DragSourceAdapter helper class that implements all methods of the DragSourceListener interface as do-nothing methods.


Here is the dragDropEnd method for our example program. When a move has succeeded, we remove the moved items from the list model.

 public void dragDropEnd(DragSourceDropEvent event) {    if (event.getDropSuccess())    {       int action = event.getDropAction();       if (action == DnDConstants.ACTION_MOVE)       {          for (Object v : draggedValues)             model.removeElement(v);       }    } } 

In this method, we rely on the drop method to tell us what drop was actually carried out. Recall that the drop method can change a move action to a copy action if the source allowed both actions. The event.geTDropAction of the DragSourceDropEvent class returns the action that the drop target reported when calling the acceptDrop method of the DropTargetDropEvent.

Try out the program in Example 7-21 and drag file items to various drop targets, such as the program in Example 7-20 or a native program such as Windows Explorer or WordPad.

NOTE

When you try the dragging, be careful that the drag gesture doesn't interfere with the normal mouse effects of the list control. Select one or more items. Press the mouse button on a selected item and move the mouse sideways, until it leaves the list component. Now the drag gesture is recognized. After the mouse has left the list component, press the SHIFT or CTRL key to modify the drop action.


CAUTION

The default drop action is a move. If you drag a file item from the list component and drop it into Windows Explorer, then Explorer moves the file into the target folder.


As you have seen, support for the system clipboard and the drag and drop mechanism are still very much a work in progress. The basics work on all platforms, but future versions of the Java platform will, we hope, offer more robust and comprehensive support.

In this section, we have covered the basic mechanics of the drag and drop mechanism. For more information, particularly about programming visual feedback, we recommend Core Swing: Advanced Programming by Kim Topley [Prentice Hall 1999].

Example 7-21. DragSourceTest.java
   1. import java.awt.*;   2. import java.awt.datatransfer.*;   3. import java.awt.dnd.*;   4. import java.awt.event.*;   5. import java.io.*;   6. import java.util.*;   7. import java.util.List;   8. import javax.swing.*;   9.  10.  11. /**  12.    This is a sample drag source for testing purposes. It consists of a list of files  13.    in the current directory.  14. */  15. public class DragSourceTest  16. {  17.    public static void main(String[] args)  18.    {  19.       JFrame frame = new DragSourceFrame();  20.       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  21.       frame.setVisible(true);  22.    }  23. }  24.  25. /**  26.    This frame contains a list of files in the current  27.    directory with support for dragging files to a drop target.  28.    Moved files are removed from the list.  29. */  30. class DragSourceFrame extends JFrame  31. {  32.    public DragSourceFrame()  33.    {  34.       setTitle("DragSourceTest");  35.       setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);  36.  37.       File f = new File(".").getAbsoluteFile();  38.       File[] files = f.listFiles();  39.       model = new DefaultListModel();  40.       for (File file : files)  41.          try  42.          {  43.             model.addElement(file.getCanonicalFile());  44.          }  45.          catch (IOException e)  46.          {  47.             JOptionPane.showMessageDialog(this, e);  48.          }  49.       fileList = new JList(model);  50.       add(new JScrollPane(fileList), BorderLayout.CENTER);  51.       add(new JLabel("Drag files from this list"), BorderLayout.NORTH);  52.  53.       DragSource dragSource = DragSource.getDefaultDragSource();  54.       dragSource.createDefaultDragGestureRecognizer(fileList,  55.          DnDConstants.ACTION_COPY_OR_MOVE, new  56.             DragGestureListener()  57.             {  58.                public void dragGestureRecognized(DragGestureEvent event)  59.                {  60.                   draggedValues = fileList.getSelectedValues();  61.                   Transferable transferable = new FileListTransferable(draggedValues);  62.                   event.startDrag(null, transferable, new FileListDragSourceListener());  63.                }  64.             });  65.    }  66.  67.    /**  68.       A drag source listener that removes moved files from the file list.  69.    */  70.    private class FileListDragSourceListener  71.       extends DragSourceAdapter  72.    {  73.       public void dragDropEnd(DragSourceDropEvent event)  74.       {  75.          if (event.getDropSuccess())  76.          {  77.             int action = event.getDropAction();  78.             if (action == DnDConstants.ACTION_MOVE)  79.             {  80.                for (Object v : draggedValues)  81.                   model.removeElement(v);  82.             }  83.          }  84.       }  85.    }  86.  87.    private JList fileList;  88.    private DefaultListModel model;  89.    private Object[] draggedValues;  90.    private static final int DEFAULT_WIDTH = 300;  91.    private static final int DEFAULT_HEIGHT = 200;  92. }  93.  94. class FileListTransferable implements Transferable  95. {  96.    public FileListTransferable(Object[] files)  97.    {  98.       fileList = new ArrayList<Object>(Arrays.asList(files));  99.    } 100. 101.    public DataFlavor[] getTransferDataFlavors() 102.    { 103.       return flavors; 104.    } 105. 106.    public boolean isDataFlavorSupported(DataFlavor flavor) 107.    { 108.       return Arrays.asList(flavors).contains(flavor); 109.    } 110. 111.    public Object getTransferData(DataFlavor flavor) 112.       throws UnsupportedFlavorException 113.    { 114.       if(flavor.equals(DataFlavor.javaFileListFlavor)) 115.          return fileList; 116.       else if(flavor.equals(DataFlavor.stringFlavor)) 117.          return fileList.toString(); 118.       else 119.          throw new UnsupportedFlavorException(flavor); 120.    } 121. 122.    private static DataFlavor[] flavors = 123.    { 124.       DataFlavor.javaFileListFlavor, 125.       DataFlavor.stringFlavor 126.    }; 127. 128.    private java.util.List<Object> fileList; 129. } 


 java.awt.dnd.DragSource 1.2 

  • static DragSource getDefaultDragSource()

    gets a DragSource object to coordinate drag actions on components.

  • DragGestureRecognizer createDefaultDragGestureRecognizer(Component component, int actions, DragGestureListener listener)

    creates a drag gesture recognizer.

    Parameters:

    component

    The drag source

     

    actions

    The permissible drop actions

     

    listener

    The listener to be notified when a drag gesture has been recognized



 java.awt.dnd.DragGestureListener 1.2 

  • void dragGestureRecognized(DragGestureEvent event)

    is called when the drag gesture recognizer has recognized a gesture.


 java.awt.dnd.DragGestureEvent 1.2 

  • void startDrag(Cursor dragCursor, Transferable transferable, DragSourceListener listener)

    starts the drag action.

    Parameters:

    dragCursor

    An optional cursor to use for the drag; may be null, in which case a default cursor is used

     

    transferable

    The data to be transferred to the drop target

     

    listener

    The listener to be notified of the drag process



 java.awt.dnd.DragSourceListener 1.2 

  • void dragEnter(DragSourceDragEvent event)

    is called when the drag cursor enters the drag source.

  • void dragExit(DragSourceEvent event)

    is called when the drag cursor exits the drag source.

  • void dragOver(DragSourceDragEvent event)

    is called when the drag cursor moves over the drag source.

  • void dropActionChanged(DragSourceDragEvent event)

    is called when the user changes the drop action.

  • void dragDropEnd(DragSourceDropEvent event)

    is called after the drag and drop operation is completed or canceled.


 java.awt.dnd.DragSourceDropEvent 1.2 

  • boolean getDropSuccess()

    returns true if the drop target reported a successful drop.

  • int getDropAction()

    returns the action that the drop target actually carried out.

Data Transfer Support in Swing

Starting with JDK 1.4, Swing components have built-in support for data transfer. That frees programmers from much of the burden of implementing copy and paste or drag and drop.

For example, start the TableSelectionTest program from Chapter 6 and highlight a range of cells. Then press CTRL+C and paste the clipboard contents into a text editor. The result is HTML-formatted text like this:

 <html> <table> <tr>   <th id=2>C   <th id=3>D   <th id=4>E   <th id=5>F <tr id=3>   <td>12   <td>16   <td>20   <td>24 . . . </table> </html> 

If you add the line

 table.setDragEnabled(true); 

after the table constructor and recompile the program, then you can drag the selection area to drop targets. The drop target receives the table selection as HTML-formatted data.

Table 7-6 summarizes the Swing components that are sources and targets for data transfer. The standard Cut, Copy, and Paste keyboard shortcuts are enabled for all components except the JColorChooser. Dragging is not enabled by default. You must call the setDragEnabled method to activate it.

Table 7-6. Data Transfer Support in Swing Components

Component

Transfer Source

Transfer Target

JFileChooser

Exports file list

N/A

JColorChooser

Exports local reference to color object

Accepts any color object

 JTextField JFormattedTextField 

Exports selected text

Accepts text

JPasswordField

N/A (for security)

Accepts text

 JTextArea JTextPane JEditorPane 

Exports selected text

Accepts text and file lists. Text is inserted. Files are opened.

 JList JTable JTree 

Exports HTML description of selection

N/A


The Swing package provides a potentially useful mechanism to quickly turn a component into a drop target. If the component has a method


void setName(Type t)

then you turn it into a drop target for data flavors with representation class Type simply by calling


component.setTransferHandler(new TransferHandler("name"));

When a drop occurs, then the transfer handler checks whether one of the data flavors has representation class Type. If so, it invokes the setName method.

NOTE

In JavaBeans terminology, the transfer handler sets the value of the name property. JavaBeans component properties are covered in Chapter 8.


For example, suppose you want to use drag and drop to change the background color of a text field. You need a transfer handler that invokes the method

 void setBackground(Color c) 

when a Color object is dragged onto the text field. Simply call

 textField.setTransferHandler(new TransferHandler("background")); 

Example 7-22 demonstrates this behavior. As you can see in Figure 7-55, the top of the frame contains a color chooser, and the bottom, a text field with the text "Drag color here." You drag the color from the inside of the Preview panel, not from one of the color swatches. When you drag it onto the text field, its background color changes.

Figure 7-55. The Swing drag and drop test program


CAUTION

By installing this transfer handler into the text field, you disable the standard transfer handler. You can no longer cut, copy, paste, drag, or drop text in the text field. A Swing component can have only one transfer handler.


Example 7-22. SwingDnDTest.java
  1. import java.awt.*;  2. import javax.swing.*;  3.  4. /**  5.    This program demonstrates how to easily add data transfer  6.    capabilities to Swing components. Drag a color from the  7.    "Preview" panel of the color chooser into the text field.  8. */  9. public class SwingDnDTest 10. { 11.    public static void main(String[] args) 12.    { 13.       JFrame frame = new SwingDnDFrame(); 14.       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 15.       frame.setVisible(true); 16.    } 17. } 18. 19. /** 20.    This frame contains a color chooser and a text field. Dragging 21.    a color into the text field changes its background color. 22. */ 23. class SwingDnDFrame extends JFrame 24. { 25.    public SwingDnDFrame() 26.    { 27.       setTitle("SwingDnDTest"); 28. 29.       JColorChooser chooser = new JColorChooser(); 30.       chooser.setDragEnabled(true); 31.       add(chooser, BorderLayout.CENTER); 32.       JTextField textField = new JTextField("Drag color here"); 33.       textField.setDragEnabled(true); 34.       textField.setTransferHandler(new TransferHandler("background")); 35.       add(textField, BorderLayout.SOUTH); 36.       pack(); 37.    } 38. } 


 javax.swing.JComponent 1.2 

  • void setTransferHandler(TransferHandler handler) 1.4

    sets a transfer handler to handle data transfer operations (cut, copy, paste, drag, drop).


 javax.swing.TransferHandler 1.4 

  • transferHandler(String propertyName)

    constructs a transfer handler that reads or writes the JavaBeans component property with the given name when a data transfer operation is executed.


 javx.swing.JFileChooser 1.2 


 javax.swing.JColorChooser 1.2 


 javax.swing.JTextComponent 1.2 


 javax.swing.JList 1.2 


 javax.swing.JTable 1.2 


 javax.swing.JTree 1.2 

  • void setDragEnabled(boolean b) 1.4

    enables or disables dragging of data out of this component.



    Core JavaT 2 Volume II - Advanced Features
    Building an On Demand Computing Environment with IBM: How to Optimize Your Current Infrastructure for Today and Tomorrow (MaxFacts Guidebook series)
    ISBN: 193164411X
    EAN: 2147483647
    Year: 2003
    Pages: 156
    Authors: Jim Hoskins

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